From d145fa6f792d6c44da2feec90507adb94e40323e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 31 Jul 2011 03:59:16 +0000 Subject: got everything building using the template Makefile svn path=/trunk/externals/unauthorized/; revision=15173 --- analyze-100.pd | 41 + audience~-help.pd | 60 + audience~.c | 1064 ++++++++++++++++++ audience~.h | 44 + audience~.tcl | 90 ++ audience~/INSTALL | 15 - audience~/audience~-help.pd | 60 - audience~/audience~.c | 1063 ------------------ audience~/audience~.h | 44 - audience~/audience~.tk | 90 -- audience~/audience~.tk2c | 69 -- audience~/speaker.gif | Bin 83 -> 0 bytes audience~/wanderer.gif | Bin 962 -> 0 bytes beatify~-help.pd | 36 + beatify~.c | 177 +++ beatify~/INSTALL | 15 - beatify~/beatify~-help.pd | 36 - beatify~/beatify~.c | 177 --- blinkenlights-help.pd | 156 +++ blinkenlights.c | 869 +++++++++++++++ blinkenlights/INSTALL | 15 - blinkenlights/blinkenlights-help.pd | 156 --- blinkenlights/blinkenlights.c | 869 --------------- compressor~-help.pd | 14 + compressor~.c | 104 ++ compressor~/INSTALL | 15 - compressor~/compressor~-help.pd | 14 - compressor~/compressor~.c | 104 -- cooled~-help.pd | 144 +++ cooled~.c | 1394 +++++++++++++++++++++++ cooled~.tcl | 87 ++ cooled~/INSTALL | 15 - cooled~/cooled~-help.pd | 144 --- cooled~/cooled~.c | 1387 ----------------------- cooled~/cooled~.tk | 87 -- cooled~/cooled~.tk2c | 65 -- cooled~/tk2c.bash | 24 - countund-help.pd | 17 + countund.c | 115 ++ countund/INSTALL | 7 - countund/countund-help.pd | 17 - countund/countund.c | 115 -- disto~-help.pd | 73 ++ disto~.c | 490 ++++++++ disto~/INSTALL | 15 - disto~/disto~-help.pd | 73 -- disto~/disto~.c | 490 -------- disto~/rs-disto~.pd | 349 ------ examples/speaker.gif | Bin 0 -> 83 bytes examples/wanderer.gif | Bin 0 -> 962 bytes examples/yesterday.txt | 34 + exciter-help.pd | 71 ++ exciter.c | 823 ++++++++++++++ exciter.h | 34 + exciter.tcl | 123 +++ exciter/INSTALL | 15 - exciter/exciter-help.pd | 71 -- exciter/exciter.c | 822 -------------- exciter/exciter.h | 34 - exciter/exciter.tk | 123 --- exciter/exciter.tk2c | 94 -- exciter/timeval.h | 76 -- exciter/tk2c.bash | 24 - filterbank~-help.pd | 199 ++++ filterbank~.c | 670 +++++++++++ filterbank~.h | 85 ++ filterbank~.tcl | 77 ++ filterbank~/INSTALL | 15 - filterbank~/analyze-100.pd | 41 - filterbank~/filterbank~-help.pd | 199 ---- filterbank~/filterbank~.c | 668 ----------- filterbank~/filterbank~.h | 85 -- filterbank~/filterbank~.tk | 77 -- filterbank~/filterbank~.tk2c | 58 - filterbank~/resynth-64.pd | 285 ----- filterbank~/setosc.pd | 21 - filterbank~/tk2c.bash | 24 - filters.c | 49 + formant~-help.pd | 56 + formant~.c | 253 +++++ formant~/INSTALL | 9 - formant~/formant~-help.pd | 56 - formant~/formant~.c | 253 ----- g_grid.h | 37 + graphic-mp3amp~-help.pd | 52 + grid-help.pd | 201 ++++ grid.c | 717 ++++++++++++ grid.tcl | 204 ++++ grid/INSTALL | 15 - grid/g_grid.h | 37 - grid/grid-help.pd | 201 ---- grid/grid.c | 715 ------------ grid/grid.tk | 204 ---- grid/grid.tk2c | 164 --- grid/tk2c.bash | 24 - interface.h | 32 + lpc.c | 252 +++++ mp3amp~-help.pd | 53 + mp3amp~.c | 1262 +++++++++++++++++++++ mp3amp~/INSTALL | 19 - mp3amp~/graphic-mp3amp~-help.pd | 52 - mp3amp~/interface.h | 32 - mp3amp~/mp3amp~-help.pd | 53 - mp3amp~/mp3amp~.c | 1262 --------------------- mp3amp~/mpglib.h | 65 -- mp3cast~-help.pd | 65 ++ mp3cast~.c | 970 ++++++++++++++++ mp3cast~/INSTALL | 15 - mp3cast~/interface.h | 32 - mp3cast~/mp3cast~-help.pd | 65 -- mp3cast~/mp3cast~.c | 970 ---------------- mp3cast~/mpglib.h | 65 -- mp3fileout~.c | 558 ++++++++++ mp3live~-help.pd | 118 ++ mp3live~/INSTALL | 21 - mp3live~/interface.h | 32 - mp3live~/mp3fileout~.c | 558 ---------- mp3live~/mp3live~-help.pd | 118 -- mp3live~/mp3streamin~.c | 671 ----------- mp3live~/mp3streamout~.c | 617 ----------- mp3live~/mpglib.h | 65 -- mp3live~/test-streaming-mp3.pd | 96 -- mp3streamin~.c | 671 +++++++++++ mp3streamout~.c | 617 +++++++++++ mp3write~-help.pd | 43 + mp3write~.c | 608 ++++++++++ mp3write~/INSTALL | 15 - mp3write~/interface.h | 32 - mp3write~/mp3write~-help.pd | 43 - mp3write~/mp3write~.c | 608 ---------- mp3write~/mpglib.h | 65 -- mpglib.h | 65 ++ mrandtab.pd | 6 + pianoroll-help.pd | 80 ++ pianoroll.c | 817 ++++++++++++++ pianoroll.h | 40 + pianoroll.tcl | 164 +++ pianoroll/INSTALL | 15 - pianoroll/pianoroll-help.pd | 80 -- pianoroll/pianoroll.c | 815 -------------- pianoroll/pianoroll.h | 40 - pianoroll/pianoroll.tk | 164 --- pianoroll/pianoroll.tk2c | 131 --- pianoroll/tk2c.bash | 24 - playlist-help.pd | 64 ++ playlist.c | 1074 ++++++++++++++++++ playlist.tcl | 154 +++ playlist/INSTALL | 15 - playlist/playlist-help.pd | 64 -- playlist/playlist.c | 1072 ------------------ playlist/playlist.tk | 154 --- playlist/playlist.tk2c | 123 --- playlist/tk2c.bash | 24 - playlist/xmms.pd | 144 --- probalizer-help.pd | 53 + probalizer.c | 706 ++++++++++++ probalizer.h | 26 + probalizer.tcl | 113 ++ probalizer/INSTALL | 14 - probalizer/probalizer-help.pd | 53 - probalizer/probalizer.c | 703 ------------ probalizer/probalizer.h | 26 - probalizer/probalizer.tk | 113 -- probalizer/probalizer.tk2c | 87 -- probalizer/tk2c.bash | 24 - randomblock~-help.pd | 15 + randomblock~.c | 115 ++ randomblock~/INSTALL | 7 - randomblock~/mrandtab.pd | 6 - randomblock~/randomblock~-help.pd | 15 - randomblock~/randomblock~.c | 115 -- randomblock~/randtab.pd | 43 - randtab.pd | 43 + resynth-64.pd | 285 +++++ rs-disto~.pd | 349 ++++++ rs-scratcher~.pd | 103 ++ rs-sonogram~.pd | 311 ++++++ rs-sonograph~.pd | 217 ++++ rs-vocoder~.pd | 13 + rs-wahwah~.pd | 348 ++++++ samplebox~-help.pd | 145 +++ samplebox~.c | 530 +++++++++ samplebox~/INSTALL | 9 - samplebox~/samplebox~-help.pd | 145 --- samplebox~/samplebox~.c | 530 --------- scratcher~-help.pd | 7 + scratcher~.c | 820 ++++++++++++++ scratcher~.tcl | 77 ++ scratcher~/INSTALL | 15 - scratcher~/rs-scratcher~.pd | 103 -- scratcher~/scratcher~-help.pd | 7 - scratcher~/scratcher~.c | 817 -------------- scratcher~/scratcher~.tk | 77 -- scratcher~/scratcher~.tk2c | 58 - scratcher~/timeval.h | 76 -- scratcher~/tk2c.bash | 24 - scrolllist-help.pd | 123 +++ scrolllist.c | 1041 +++++++++++++++++ scrolllist.tcl | 141 +++ scrolllist/INSTALL | 14 - scrolllist/ave-lucifer.txt | 35 - scrolllist/scrolllist-help.pd | 124 --- scrolllist/scrolllist.c | 1039 ----------------- scrolllist/scrolllist.tk | 141 --- scrolllist/scrolllist.tk2c | 112 -- scrolllist/tk2c.bash | 24 - scrolllist/yesterday.txt | 34 - setosc.pd | 21 + sonogram~-help.pd | 10 + sonogram~.c | 2088 +++++++++++++++++++++++++++++++++++ sonogram~/INSTALL | 15 - sonogram~/rs-sonogram~.pd | 311 ------ sonogram~/rs-sonograph~.pd | 217 ---- sonogram~/sonogram~-help.pd | 10 - sonogram~/sonogram~-joge.c | 2044 ---------------------------------- sonogram~/sonogram~-yves.c | 2017 --------------------------------- sonogram~/sonogram~.c | 2088 ----------------------------------- sonogram~/sonograph~-help.pd | 10 - sonograph~-help.pd | 10 + speexin~.c | 612 ++++++++++ speexout~.c | 455 ++++++++ speex~-help.pd | 68 ++ speex~/INSTALL | 18 - speex~/speexin~.c | 612 ---------- speex~/speexout~.c | 455 -------- speex~/speex~-help.pd | 68 -- spigot~-help.pd | 14 + spigot~.c | 74 ++ spigot~/INSTALL | 15 - spigot~/spigot~-help.pd | 14 - spigot~/spigot~.c | 74 -- tables.c | 311 ++++++ test-streaming-mp3.pd | 96 ++ timeval.h | 76 ++ tk2c.bash | 24 - vocoder~-help.pd | 55 + vocoder~.c | 163 +++ vocoder~/INSTALL | 15 - vocoder~/filters.c | 49 - vocoder~/lpc.c | 252 ----- vocoder~/rs-vocoder~.pd | 13 - vocoder~/tables.c | 311 ------ vocoder~/vocoder~-help.pd | 55 - vocoder~/vocoder~.c | 163 --- wahwah~-help.pd | 48 + wahwah~.c | 408 +++++++ wahwah~/INSTALL | 15 - wahwah~/rs-wahwah~.pd | 348 ------ wahwah~/wahwah~-help.pd | 48 - wahwah~/wahwah~.c | 408 ------- xmms.pd | 144 +++ 251 files changed, 26607 insertions(+), 32635 deletions(-) create mode 100644 analyze-100.pd create mode 100644 audience~-help.pd create mode 100644 audience~.c create mode 100644 audience~.h create mode 100644 audience~.tcl delete mode 100644 audience~/INSTALL delete mode 100644 audience~/audience~-help.pd delete mode 100644 audience~/audience~.c delete mode 100644 audience~/audience~.h delete mode 100644 audience~/audience~.tk delete mode 100644 audience~/audience~.tk2c delete mode 100644 audience~/speaker.gif delete mode 100644 audience~/wanderer.gif create mode 100644 beatify~-help.pd create mode 100644 beatify~.c delete mode 100644 beatify~/INSTALL delete mode 100644 beatify~/beatify~-help.pd delete mode 100644 beatify~/beatify~.c create mode 100644 blinkenlights-help.pd create mode 100644 blinkenlights.c delete mode 100644 blinkenlights/INSTALL delete mode 100644 blinkenlights/blinkenlights-help.pd delete mode 100644 blinkenlights/blinkenlights.c create mode 100644 compressor~-help.pd create mode 100644 compressor~.c delete mode 100644 compressor~/INSTALL delete mode 100644 compressor~/compressor~-help.pd delete mode 100644 compressor~/compressor~.c create mode 100644 cooled~-help.pd create mode 100644 cooled~.c create mode 100644 cooled~.tcl delete mode 100644 cooled~/INSTALL delete mode 100644 cooled~/cooled~-help.pd delete mode 100644 cooled~/cooled~.c delete mode 100644 cooled~/cooled~.tk delete mode 100755 cooled~/cooled~.tk2c delete mode 100755 cooled~/tk2c.bash create mode 100644 countund-help.pd create mode 100644 countund.c delete mode 100644 countund/INSTALL delete mode 100644 countund/countund-help.pd delete mode 100644 countund/countund.c create mode 100644 disto~-help.pd create mode 100644 disto~.c delete mode 100644 disto~/INSTALL delete mode 100644 disto~/disto~-help.pd delete mode 100644 disto~/disto~.c delete mode 100644 disto~/rs-disto~.pd create mode 100644 examples/speaker.gif create mode 100644 examples/wanderer.gif create mode 100644 examples/yesterday.txt create mode 100644 exciter-help.pd create mode 100644 exciter.c create mode 100644 exciter.h create mode 100644 exciter.tcl delete mode 100644 exciter/INSTALL delete mode 100644 exciter/exciter-help.pd delete mode 100644 exciter/exciter.c delete mode 100644 exciter/exciter.h delete mode 100644 exciter/exciter.tk delete mode 100755 exciter/exciter.tk2c delete mode 100644 exciter/timeval.h delete mode 100755 exciter/tk2c.bash create mode 100644 filterbank~-help.pd create mode 100644 filterbank~.c create mode 100644 filterbank~.h create mode 100644 filterbank~.tcl delete mode 100644 filterbank~/INSTALL delete mode 100644 filterbank~/analyze-100.pd delete mode 100644 filterbank~/filterbank~-help.pd delete mode 100644 filterbank~/filterbank~.c delete mode 100644 filterbank~/filterbank~.h delete mode 100644 filterbank~/filterbank~.tk delete mode 100755 filterbank~/filterbank~.tk2c delete mode 100644 filterbank~/resynth-64.pd delete mode 100644 filterbank~/setosc.pd delete mode 100755 filterbank~/tk2c.bash create mode 100644 filters.c create mode 100644 formant~-help.pd create mode 100644 formant~.c delete mode 100644 formant~/INSTALL delete mode 100644 formant~/formant~-help.pd delete mode 100644 formant~/formant~.c create mode 100644 g_grid.h create mode 100644 graphic-mp3amp~-help.pd create mode 100644 grid-help.pd create mode 100644 grid.c create mode 100644 grid.tcl delete mode 100644 grid/INSTALL delete mode 100644 grid/g_grid.h delete mode 100644 grid/grid-help.pd delete mode 100644 grid/grid.c delete mode 100644 grid/grid.tk delete mode 100644 grid/grid.tk2c delete mode 100755 grid/tk2c.bash create mode 100644 interface.h create mode 100644 lpc.c create mode 100644 mp3amp~-help.pd create mode 100644 mp3amp~.c delete mode 100644 mp3amp~/INSTALL delete mode 100644 mp3amp~/graphic-mp3amp~-help.pd delete mode 100644 mp3amp~/interface.h delete mode 100644 mp3amp~/mp3amp~-help.pd delete mode 100644 mp3amp~/mp3amp~.c delete mode 100644 mp3amp~/mpglib.h create mode 100644 mp3cast~-help.pd create mode 100644 mp3cast~.c delete mode 100644 mp3cast~/INSTALL delete mode 100644 mp3cast~/interface.h delete mode 100644 mp3cast~/mp3cast~-help.pd delete mode 100644 mp3cast~/mp3cast~.c delete mode 100644 mp3cast~/mpglib.h create mode 100644 mp3fileout~.c create mode 100644 mp3live~-help.pd delete mode 100644 mp3live~/INSTALL delete mode 100644 mp3live~/interface.h delete mode 100644 mp3live~/mp3fileout~.c delete mode 100644 mp3live~/mp3live~-help.pd delete mode 100644 mp3live~/mp3streamin~.c delete mode 100644 mp3live~/mp3streamout~.c delete mode 100644 mp3live~/mpglib.h delete mode 100644 mp3live~/test-streaming-mp3.pd create mode 100644 mp3streamin~.c create mode 100644 mp3streamout~.c create mode 100644 mp3write~-help.pd create mode 100644 mp3write~.c delete mode 100644 mp3write~/INSTALL delete mode 100644 mp3write~/interface.h delete mode 100644 mp3write~/mp3write~-help.pd delete mode 100644 mp3write~/mp3write~.c delete mode 100644 mp3write~/mpglib.h create mode 100644 mpglib.h create mode 100644 mrandtab.pd create mode 100644 pianoroll-help.pd create mode 100644 pianoroll.c create mode 100644 pianoroll.h create mode 100644 pianoroll.tcl delete mode 100644 pianoroll/INSTALL delete mode 100644 pianoroll/pianoroll-help.pd delete mode 100644 pianoroll/pianoroll.c delete mode 100644 pianoroll/pianoroll.h delete mode 100644 pianoroll/pianoroll.tk delete mode 100755 pianoroll/pianoroll.tk2c delete mode 100755 pianoroll/tk2c.bash create mode 100644 playlist-help.pd create mode 100644 playlist.c create mode 100644 playlist.tcl delete mode 100644 playlist/INSTALL delete mode 100644 playlist/playlist-help.pd delete mode 100644 playlist/playlist.c delete mode 100644 playlist/playlist.tk delete mode 100644 playlist/playlist.tk2c delete mode 100755 playlist/tk2c.bash delete mode 100644 playlist/xmms.pd create mode 100644 probalizer-help.pd create mode 100644 probalizer.c create mode 100644 probalizer.h create mode 100644 probalizer.tcl delete mode 100644 probalizer/INSTALL delete mode 100644 probalizer/probalizer-help.pd delete mode 100644 probalizer/probalizer.c delete mode 100644 probalizer/probalizer.h delete mode 100644 probalizer/probalizer.tk delete mode 100755 probalizer/probalizer.tk2c delete mode 100755 probalizer/tk2c.bash create mode 100644 randomblock~-help.pd create mode 100644 randomblock~.c delete mode 100644 randomblock~/INSTALL delete mode 100644 randomblock~/mrandtab.pd delete mode 100644 randomblock~/randomblock~-help.pd delete mode 100644 randomblock~/randomblock~.c delete mode 100644 randomblock~/randtab.pd create mode 100644 randtab.pd create mode 100644 resynth-64.pd create mode 100644 rs-disto~.pd create mode 100644 rs-scratcher~.pd create mode 100644 rs-sonogram~.pd create mode 100644 rs-sonograph~.pd create mode 100644 rs-vocoder~.pd create mode 100644 rs-wahwah~.pd create mode 100644 samplebox~-help.pd create mode 100644 samplebox~.c delete mode 100644 samplebox~/INSTALL delete mode 100644 samplebox~/samplebox~-help.pd delete mode 100644 samplebox~/samplebox~.c create mode 100644 scratcher~-help.pd create mode 100644 scratcher~.c create mode 100644 scratcher~.tcl delete mode 100644 scratcher~/INSTALL delete mode 100644 scratcher~/rs-scratcher~.pd delete mode 100644 scratcher~/scratcher~-help.pd delete mode 100644 scratcher~/scratcher~.c delete mode 100644 scratcher~/scratcher~.tk delete mode 100755 scratcher~/scratcher~.tk2c delete mode 100644 scratcher~/timeval.h delete mode 100755 scratcher~/tk2c.bash create mode 100755 scrolllist-help.pd create mode 100644 scrolllist.c create mode 100755 scrolllist.tcl delete mode 100755 scrolllist/INSTALL delete mode 100644 scrolllist/ave-lucifer.txt delete mode 100755 scrolllist/scrolllist-help.pd delete mode 100644 scrolllist/scrolllist.c delete mode 100755 scrolllist/scrolllist.tk delete mode 100644 scrolllist/scrolllist.tk2c delete mode 100755 scrolllist/tk2c.bash delete mode 100644 scrolllist/yesterday.txt create mode 100644 setosc.pd create mode 100644 sonogram~-help.pd create mode 100644 sonogram~.c delete mode 100644 sonogram~/INSTALL delete mode 100644 sonogram~/rs-sonogram~.pd delete mode 100644 sonogram~/rs-sonograph~.pd delete mode 100644 sonogram~/sonogram~-help.pd delete mode 100644 sonogram~/sonogram~-joge.c delete mode 100644 sonogram~/sonogram~-yves.c delete mode 100644 sonogram~/sonogram~.c delete mode 100644 sonogram~/sonograph~-help.pd create mode 100644 sonograph~-help.pd create mode 100644 speexin~.c create mode 100644 speexout~.c create mode 100644 speex~-help.pd delete mode 100644 speex~/INSTALL delete mode 100644 speex~/speexin~.c delete mode 100644 speex~/speexout~.c delete mode 100644 speex~/speex~-help.pd create mode 100644 spigot~-help.pd create mode 100644 spigot~.c delete mode 100644 spigot~/INSTALL delete mode 100644 spigot~/spigot~-help.pd delete mode 100644 spigot~/spigot~.c create mode 100644 tables.c create mode 100644 test-streaming-mp3.pd create mode 100644 timeval.h delete mode 100755 tk2c.bash create mode 100644 vocoder~-help.pd create mode 100644 vocoder~.c delete mode 100644 vocoder~/INSTALL delete mode 100644 vocoder~/filters.c delete mode 100644 vocoder~/lpc.c delete mode 100644 vocoder~/rs-vocoder~.pd delete mode 100644 vocoder~/tables.c delete mode 100644 vocoder~/vocoder~-help.pd delete mode 100644 vocoder~/vocoder~.c create mode 100644 wahwah~-help.pd create mode 100644 wahwah~.c delete mode 100644 wahwah~/INSTALL delete mode 100644 wahwah~/rs-wahwah~.pd delete mode 100644 wahwah~/wahwah~-help.pd delete mode 100644 wahwah~/wahwah~.c create mode 100644 xmms.pd diff --git a/analyze-100.pd b/analyze-100.pd new file mode 100644 index 0000000..132876b --- /dev/null +++ b/analyze-100.pd @@ -0,0 +1,41 @@ +#N canvas 112 -6 970 685 10; +#X obj 236 283 filterbank~ 0 2000 100; +#X obj 31 62 t s b; +#X obj 80 68 float \$0; +#X text 31 1 Step 1 : Load a sound file; +#X obj 31 83 route float; +#X msg 336 250 bang; +#X obj 125 250 tabplay~ \$0-filterbank-sample; +#X obj 31 104 makefilename %d-filterbank-sample; +#X obj 32 137 pack s s; +#X msg 32 158 read -resize \$1 \$2; +#X msg 239 220 bang; +#X obj 28 220 tabplay~ \$0-filterbank-sample; +#X obj 365 149 table \$0-filterbank-sample; +#X msg 440 223 randomize 1; +#X msg 442 246 randomize 0; +#X obj 32 180 soundfiler; +#X obj 719 55 playlist all 200 200; +#X msg 484 52 location /Samples; +#X obj 484 25 loadbang; +#X obj 391 369 dac~; +#X connect 0 8 19 0; +#X connect 0 15 19 1; +#X connect 0 28 19 1; +#X connect 1 0 8 0; +#X connect 1 1 2 0; +#X connect 2 0 4 0; +#X connect 4 0 7 0; +#X connect 5 0 6 0; +#X connect 6 0 0 0; +#X connect 7 0 8 1; +#X connect 8 0 9 0; +#X connect 9 0 15 0; +#X connect 10 0 11 0; +#X connect 11 0 19 1; +#X connect 11 0 19 0; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 16 0 1 0; +#X connect 17 0 16 0; +#X connect 18 0 17 0; diff --git a/audience~-help.pd b/audience~-help.pd new file mode 100644 index 0000000..ee90caf --- /dev/null +++ b/audience~-help.pd @@ -0,0 +1,60 @@ +#N canvas 207 7 763 647 10; +#X text 370 378 * Width : graphical x size; +#X text 371 393 * Height : graphical y size; +#X text 358 456 bugs and comments @ ydegoyon@free.fr [-_-]; +#X obj 91 492 *~ 1; +#X obj 177 491 *~ 1; +#X obj 134 458 / 100; +#X floatatom 134 428 5 0 0; +#X floatatom 174 129 5 0 0; +#X floatatom 254 128 5 0 0; +#X floatatom 332 128 5 0 0; +#X floatatom 405 128 5 0 0; +#X text 332 210 audience~ is a moving audience simulation; +#X text 334 236 within a 2d space; +#X text 332 223 Each sound input and each listener can be moved; +#X text 371 407 * Nb Listeners : number of listeners; +#X obj 129 523 dac~; +#X msg 42 89 attenuation 0; +#X msg 42 64 attenuation 0.1; +#X msg 42 40 attenuation 1; +#X obj 406 153 osc~ 10000; +#X text 8 14 Sound attenuation per meter ( default = 0.01 ); +#X text 338 306 Example : audience~ 200 200 4 1 0.01 0; +#X text 339 349 (invoke with Properties ); +#X text 342 339 You can set the following properties :; +#X text 341 527 Note : the number of inputs + outputs is limited to +10; +#X text 341 540 ( can be easily changed in the code ); +#X obj 254 154 osc~ 500; +#X obj 331 154 osc~ 3000; +#X text 337 278 Constructor : audience~ + | audience~; +#X obj 175 155 osc~ 50; +#X obj 70 196 audience~ 200 200 4 2 0.01 0 0 0 193 188 126 118 145 +72 20 182 10 0; +#X msg 165 66 delay 0; +#X msg 165 91 delay 1; +#X text 296 41 ( due to the distance between speaker and listener ) +; +#X text 163 40 Apply delay option; +#X connect 3 0 15 0; +#X connect 4 0 15 1; +#X connect 5 0 3 1; +#X connect 5 0 4 1; +#X connect 6 0 5 0; +#X connect 7 0 29 0; +#X connect 8 0 26 0; +#X connect 9 0 27 0; +#X connect 10 0 19 0; +#X connect 16 0 30 0; +#X connect 17 0 30 0; +#X connect 18 0 30 0; +#X connect 19 0 30 4; +#X connect 26 0 30 2; +#X connect 27 0 30 3; +#X connect 29 0 30 1; +#X connect 30 0 3 0; +#X connect 30 1 4 0; +#X connect 31 0 30 0; +#X connect 32 0 30 0; diff --git a/audience~.c b/audience~.c new file mode 100644 index 0000000..1c32c28 --- /dev/null +++ b/audience~.c @@ -0,0 +1,1064 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* audience.c written by Yves Degoyon 2002 */ +/* 2-dimensional audience simulation */ +/* ( simulates spatialization and interferences ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* Shalaby Effect -- Instrumentals */ +/* Honey Bane -- I Wish I Could Be Me */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + +#include "audience~.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define DEFAULT_AUDIENCE_WIDTH 200 +#define DEFAULT_AUDIENCE_HEIGHT 200 +#define DEFAULT_AUDIENCE_NBINPUTS 4 +#define DEFAULT_AUDIENCE_NBOUTPUTS 2 +#define DEFAULT_AUDIENCE_ATTENUATION 0.01 + +#define LISTENER_WIDTH 15 +#define LISTENER_HEIGHT 20 +#define SPEAKER_WIDTH 15 +#define SPEAKER_HEIGHT 20 + +// sound propagates at the speed of 340 m/s, isn't it ?? +#define SOUNDSPEED 340.0 + +// a pixel is 0.1 meter +#define PIXELSIZE 0.1 + +static char *audience_version = "audience : 2d audience simulation, version 0.7 (ydegoyon@free.fr)"; + +t_widgetbehavior audience_widgetbehavior; +static t_class *audience_class_tilde; + +static int guidebug=0; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h );\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +/* drawing functions */ +static void audience_draw_update(t_audience_tilde *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ei; + + for ( ei=0; eix_nbinputs; ei++ ) + { + SYS_VGUI6(".x%x.c coords %xISPEAKER%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] + ); + SYS_VGUI6(".x%x.c coords %xSPEAKERNUM%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2 + ); + } + for ( ei=0; eix_nboutputs; ei++ ) + { + SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + ); + SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2 + ); + } +} + +static void audience_draw_new(t_audience_tilde *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int ei; + + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #EAF1E2 -tags %xAAUDIENCE\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x); + // create captions + SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0m\" -tags %xBLCAPTION\n", + canvas, text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); + SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%dm\" -tags %xBRCAPTION\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_width + 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10, x->x_width, x ); + SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%dm\" -tags %xULCAPTION\n", + canvas, text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist), x->x_height, x ); + + // draw all outlets + if ( x->x_nboutputs > 1 ) + { + for ( ei=0; eix_nboutputs; ei++ ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", + canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x, ei); + } + } + else + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", + canvas, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x, 0); + } + // draw all inlets + for ( ei=0; eix_nbinputs+1; ei++ ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN%d\n", + canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs) + 5, + text_ypix(&x->x_obj, glist), + x, ei); + } + // create speaker images + for ( ei=0; eix_nbinputs; ei++ ) + { + SYS_VGUI6("image create photo %xSPEAKER%d -file %s/examples/speaker.gif -format gif -width %d -height %d\n", + x, ei, audience_class_tilde->c_externdir->s_name, SPEAKER_WIDTH, SPEAKER_HEIGHT ); + SYS_VGUI8(".x%x.c create image %d %d -image %xSPEAKER%d -tags %xISPEAKER%d\n", + canvas, + text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei], + x, ei, x, ei ); + SYS_VGUI7(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"s%d\" -tags %xSPEAKERNUM%d\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2, ei+1, x, ei ); + } + // create listener images + for ( ei=0; eix_nboutputs; ei++ ) + { + SYS_VGUI6("image create photo %xLISTENER%d -file %s/examples/wanderer.gif -format gif -width %d -height %d\n", + x, ei, audience_class_tilde->c_externdir->s_name, LISTENER_WIDTH, LISTENER_HEIGHT ); + SYS_VGUI8(".x%x.c create image %d %d -image %xLISTENER%d -tags %xILISTENER%d\n", + canvas, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei], + x, ei, x, ei ); + SYS_VGUI7(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"l%d\" -tags %xLISTENERNUM%d\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2, ei+1, x, ei ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void audience_draw_move(t_audience_tilde *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ei; + + SYS_VGUI7(".x%x.c coords %xAAUDIENCE %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height); + SYS_VGUI5(".x%x.c coords %xBLCAPTION %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10); + SYS_VGUI5(".x%x.c coords %xBRCAPTION %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist) + x->x_width + 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10 ); + SYS_VGUI5(".x%x.c coords %xULCAPTION %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) ); + + for ( ei=0; eix_nbinputs+1; ei++ ) + { + SYS_VGUI8(".x%x.c coords %xIN%d %d %d %d %d\n", + canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs) + 5, + text_ypix(&x->x_obj, glist) + ); + } + for ( ei=0; eix_nbinputs+1; ei++ ) + { + SYS_VGUI6(".x%x.c coords %xISPEAKER%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] + ); + SYS_VGUI6(".x%x.c coords %xSPEAKERNUM%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2 + ); + } + if ( x->x_nboutputs > 1 ) + { + for ( ei=0; eix_nboutputs; ei++ ) + { + SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + ); + SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2 + ); + } + } + else + { + SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, 0, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", + canvas, x, 0, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[0], + text_ypix(&x->x_obj, glist) + x->x_outputs_y[0] + ); + SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", + canvas, x, 0, + text_xpix(&x->x_obj, glist) + x->x_outputs_x[0] + LISTENER_WIDTH/2, + text_ypix(&x->x_obj, glist) + x->x_outputs_y[0] + LISTENER_HEIGHT/2 + ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void audience_draw_erase(t_audience_tilde* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int ei; + + SYS_VGUI3(".x%x.c delete %xAAUDIENCE\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xBLCAPTION\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xBRCAPTION\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xULCAPTION\n", canvas, x); + for ( ei=0; eix_nbinputs+1; ei++ ) + { + SYS_VGUI4(".x%x.c delete %xIN%d\n", canvas, x, ei ); + } + for ( ei=0; eix_nbinputs; ei++ ) + { + SYS_VGUI4(".x%x.c delete %xISPEAKER%d\n", canvas, x, ei ); + SYS_VGUI4(".x%x.c delete %xSPEAKERNUM%d\n", canvas, x, ei ); + // SYS_VGUI3("image delete %xSPEAKER%d\n", x, ei ); + } + for ( ei=0; eix_nboutputs; ei++ ) + { + SYS_VGUI4(".x%x.c delete %xOUT%d\n", canvas, x, ei ); + SYS_VGUI4(".x%x.c delete %xILISTENER%d\n", canvas, x, ei ); + SYS_VGUI4(".x%x.c delete %xLISTENERNUM%d\n", canvas, x, ei ); + // SYS_VGUI3("image delete %xLISTENER%d\n", x, ei ); + } +} + +static void audience_draw_select(t_audience_tilde* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xAAUDIENCE -outline #0000FF\n", canvas, x); + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xAAUDIENCE -outline #000000\n", canvas, x); + } +} + +/* ------------------------ audience widgetbehaviour----------------------------- */ + + +static void audience_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_audience_tilde* x = (t_audience_tilde*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void audience_save(t_gobj *z, t_binbuf *b) +{ + t_audience_tilde *x = (t_audience_tilde *)z; + t_int ii; + + binbuf_addv(b, "ssiisiiiifi", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_width, x->x_height, + x->x_nbinputs, x->x_nboutputs, x->x_attenuation, x->x_applydelay ); + for ( ii=0; iix_nbinputs; ii++ ) + { + binbuf_addv(b, "ii", x->x_inputs_x[ii], x->x_inputs_y[ii] ); + } + for ( ii=0; iix_nboutputs; ii++ ) + { + binbuf_addv(b, "ii", x->x_outputs_x[ii], x->x_outputs_y[ii] ); + } + binbuf_addv(b, ";"); +} + +static void audience_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_audience_tilde *x=(t_audience_tilde *)z; + + sprintf(buf, "pdtk_audience_dialog %%s %d %d %d\n", + x->x_width, x->x_height, x->x_nboutputs + ); + // post("audience_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void audience_select(t_gobj *z, t_glist *glist, int selected) +{ + t_audience_tilde *x = (t_audience_tilde *)z; + + x->x_selected = selected; + audience_draw_select( x, glist ); +} + +static void audience_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_audience_tilde *x = (t_audience_tilde *)z; + + // post( "audience~ : vis : %d", vis ); + if (vis) + { + audience_draw_new( x, glist ); + } + else + { + audience_draw_erase( x, glist ); + } +} + +static void audience_dialog(t_audience_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + t_int onbinputs = x->x_nbinputs; + t_int onboutputs = x->x_nboutputs; + t_int owidth = x->x_width; + t_int oheight = x->x_height; + t_int bi, ei; + t_int dspstate; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( !x ) { + post( "audience~ : error :tried to set properties on an unexisting object" ); + } + if ( argc != 3 ) + { + post( "audience : error in the number of arguments ( %d instead of 3 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT ) { + post( "audience~ : wrong arguments" ); + return; + } + + dspstate = canvas_suspend_dsp(); + audience_draw_erase(x, x->x_glist); + + x->x_width = (int)argv[0].a_w.w_float; + if ( x->x_width < 10 ) x->x_width = 10; + x->x_height = (int)argv[1].a_w.w_float; + if ( x->x_height < 10 ) x->x_height = 10; + x->x_nboutputs = (int)argv[2].a_w.w_float; + if ( x->x_nboutputs < 1 ) x->x_nboutputs = 1; + + // re-allocate audio buffers if needed + if ( ( owidth != x->x_width ) || ( oheight != x->x_height ) ) + { + if ( x->x_audiobuffer ) + { + for ( ei=0; eix_audiobuffer[ei], x->x_audiobuffersize*sizeof(t_float) ); + } + freebytes( x->x_audiobuffer, onbinputs*sizeof(t_float*) ); + } + // allocate audio buffer + x->x_audiobuffer = (t_float **) getbytes( x->x_nbinputs*sizeof(t_float *) ); + if ( !x->x_audiobuffer ) + { + post( "audience~ : could not allocate audio buffer" ); + return; + } + x->x_audiobuffersize = ( t_int ) ( ( ( ( t_float ) sqrt( pow( x->x_width, 2 ) + + pow( x->x_height, 2 ) ) ) / SOUNDSPEED ) + * ( (float ) sys_getsr() ) ); + post( "audience~ : audio buffer size : %d samples", x->x_audiobuffersize ); + for ( bi=0; bix_nbinputs; bi++ ) + { + x->x_audiobuffer[bi] = (t_float *) getbytes( x->x_audiobuffersize*sizeof(t_float) ); + if ( !x->x_audiobuffer[bi] ) + { + post( "audience~ : could not allocate audio buffer" ); + return; + } + } + x->x_audiowritepos = 0; + } + + // re-allocate inlets : CRASHES PD,I GUESS IT'S NOT SUPPORTED + if ( onbinputs != x->x_nbinputs ) + { + // post( "audience~ : cleaning up old inlets" ); + if ( x->x_inputs ) + { + for ( ei=0; eix_inputs[ei] ); + } + freebytes( x->x_inputs, onbinputs*sizeof(t_inlet*) ); + } + if ( x->x_inputs_x ) + { + freebytes( x->x_inputs_x, onbinputs*sizeof(t_int) ); + } + if ( x->x_inputs_y ) + { + freebytes( x->x_inputs_y, onbinputs*sizeof(t_int) ); + } + // post( "audience~ : creating new ones" ); + x->x_inputs = (t_inlet **) getbytes( x->x_nbinputs*sizeof(t_inlet *) ); + x->x_inputs_x = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); + x->x_inputs_y = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); + if ( !x->x_inputs || !x->x_inputs_x || !x->x_inputs_y ) + { + error( "audience~ : fatal : could not create new object" ); + return; + } + for ( bi=0; bix_nbinputs; bi++ ) + { + // post( "audience~ : allocating input ! %d", bi ); + x->x_inputs[bi] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + } + } + + // re-allocate outlets + if ( onboutputs != x->x_nboutputs ) + { + // post( "audience~ : cleaning up old outlets" ); + if ( x->x_outputs ) + { + for ( ei=0; eix_outputs[ei] ); + // outlet_free( x->x_outputs[ei] ); + } + freebytes( x->x_outputs, onboutputs*sizeof(t_outlet*) ); + } + if ( x->x_outputs_x ) + { + freebytes( x->x_outputs_x, onboutputs*sizeof(t_int) ); + } + if ( x->x_outputs_y ) + { + freebytes( x->x_outputs_y, onboutputs*sizeof(t_int) ); + } + // post( "audience~ : creating new ones" ); + x->x_outputs = (t_outlet **) getbytes( x->x_nboutputs*sizeof(t_outlet *) ); + x->x_outputs_x = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); + x->x_outputs_y = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); + if ( !x->x_outputs || !x->x_outputs_x || !x->x_outputs_y ) + { + // error( "audience~ : fatal : could not create new object" ); + return; + } + for ( bi=0; bix_nboutputs; bi++ ) + { + x->x_outputs[bi] = outlet_new( &x->x_obj, &s_signal ); + } + // set default coordinates + if ( x->x_nboutputs > 1 ) + { + for ( ei=0; eix_nboutputs; ei++ ) + { + x->x_outputs_x[ei] = ei * (x->x_width - 5) / ( x->x_nboutputs - 1 ); + x->x_outputs_y[ei] = x->x_height - LISTENER_HEIGHT/2; + } + } + else + { + x->x_outputs_x[0] = x->x_width; + x->x_outputs_y[0] = x->x_height - LISTENER_HEIGHT/2; + } + } + + canvas_fixlinesfor( canvas, (t_text*)x ); + audience_draw_new(x, x->x_glist); + canvas_resume_dsp(dspstate); +} + +static void audience_delete(t_gobj *z, t_glist *glist) +{ + t_audience_tilde *x = (t_audience_tilde *)z; + + // post( "audience~ : delete" ); + audience_draw_erase( x, glist ); + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void audience_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_audience_tilde *x = (t_audience_tilde *)z; + int xold = text_xpix(&x->x_obj, glist); + int yold = text_ypix(&x->x_obj, glist); + + // post( "audience_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) + { + audience_draw_move(x, x->x_glist); + } +} + +static void audience_motion(t_audience_tilde *x, t_floatarg dx, t_floatarg dy) +{ + // post( "audience_motion dx=%f dy=%f", dx, dy ); + + switch( x->x_type_selected ) + { + case AUDIENCE_INPUT: + x->x_inputs_x[ x->x_nselected ] += dx; + if ( x->x_inputs_x[ x->x_nselected ] < 0 ) x->x_inputs_x[ x->x_nselected ] = 0; + if ( x->x_inputs_x[ x->x_nselected ] > x->x_width ) x->x_inputs_x[ x->x_nselected ] = x->x_width; + x->x_inputs_y[ x->x_nselected ] += dy; + if ( x->x_inputs_y[ x->x_nselected ] < 0 ) x->x_inputs_y[ x->x_nselected ] = 0; + if ( x->x_inputs_y[ x->x_nselected ] > x->x_height ) x->x_inputs_y[ x->x_nselected ] = x->x_height; + break; + case AUDIENCE_OUTPUT: + x->x_outputs_x[ x->x_nselected ] += dx; + if ( x->x_outputs_x[ x->x_nselected ] < 0 ) x->x_outputs_x[ x->x_nselected ] = 0; + if ( x->x_outputs_x[ x->x_nselected ] > x->x_width ) x->x_outputs_x[ x->x_nselected ] = x->x_width; + x->x_outputs_y[ x->x_nselected ] += dy; + if ( x->x_outputs_y[ x->x_nselected ] < 0 ) x->x_outputs_y[ x->x_nselected ] = 0; + if ( x->x_outputs_y[ x->x_nselected ] > x->x_height ) x->x_outputs_y[ x->x_nselected ] = x->x_height; + break; + } + + audience_draw_update(x, x->x_glist); +} + +static int audience_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_audience_tilde* x = (t_audience_tilde *)z; + t_int bi; + + // post( "audience_click doit=%d x=%d y=%d", doit, xpix, ypix ); + if ( doit) + { + t_int relx = xpix-text_xpix(&x->x_obj, glist); + t_int rely = ypix-text_ypix(&x->x_obj, glist); + + // post( "audience~ : relx : %d : rely : %d", relx, rely ); + x->x_type_selected = AUDIENCE_NONE; + x->x_nselected = -1; + for ( bi=0; bix_nbinputs; bi++ ) + { + if ( ( abs( relx - x->x_inputs_x[bi] ) < SPEAKER_WIDTH ) && + ( abs( rely - x->x_inputs_y[bi] ) < SPEAKER_HEIGHT ) ) { + x->x_type_selected = AUDIENCE_INPUT; + x->x_nselected = bi; + break; + } + } + if ( x->x_type_selected == AUDIENCE_NONE ) + { + for ( bi=0; bix_nboutputs; bi++ ) + { + if ( ( abs( relx - x->x_outputs_x[bi] ) < LISTENER_WIDTH ) && + ( abs( rely - x->x_outputs_y[bi] ) < LISTENER_HEIGHT ) ) { + x->x_type_selected = AUDIENCE_OUTPUT; + x->x_nselected = bi; + break; + } + } + } + audience_draw_update(x, glist); + glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)audience_motion, + 0, xpix, ypix); + } + return (1); +} + +static t_audience_tilde *audience_new(t_symbol *s, int argc, t_atom *argv) +{ + t_int bi, ei; + t_audience_tilde *x; + t_pd *x2; + char *str; + + // post( "audience_new : create : %s argc =%d", s->s_name, argc ); + + x = (t_audience_tilde *)pd_new(audience_class_tilde); + // new audience created from the gui + if ( argc != 0 ) + { + if ( argc < 5 ) + { + post( "audience~ : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) { + post( "audience~ : wrong arguments" ); + return NULL; + } + + x->x_width = (int)argv[0].a_w.w_float; + if ( x->x_width < 10 ) x->x_width = 10; + x->x_height = (int)argv[1].a_w.w_float; + if ( x->x_height < 10 ) x->x_height = 10; + x->x_nbinputs = (int)argv[2].a_w.w_float; + if ( x->x_nbinputs < 1 ) x->x_nbinputs = 1; + x->x_nboutputs = (int)argv[3].a_w.w_float; + if ( x->x_nboutputs < 1 ) x->x_nboutputs = 1; + x->x_attenuation = argv[4].a_w.w_float; + if ( x->x_attenuation < 0 ) x->x_attenuation = 0; + x->x_applydelay = argv[5].a_w.w_float; + } + else + { + x->x_width = DEFAULT_AUDIENCE_WIDTH; + x->x_height = DEFAULT_AUDIENCE_HEIGHT; + x->x_nbinputs = DEFAULT_AUDIENCE_NBINPUTS; + x->x_nboutputs = DEFAULT_AUDIENCE_NBOUTPUTS; + x->x_attenuation = DEFAULT_AUDIENCE_ATTENUATION; + x->x_applydelay = 0; + } + + // create inlets and outlets + x->x_outputs = (t_outlet **) getbytes( x->x_nboutputs*sizeof(t_outlet *) ); + x->x_outputs_x = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); + x->x_outputs_y = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); + if ( !x->x_outputs || !x->x_outputs_x || !x->x_outputs_y ) + { + post( "audience~ : could not allocate outputs" ); + return NULL; + } + for ( bi=0; bix_nboutputs; bi++ ) + { + x->x_outputs[bi] = outlet_new( &x->x_obj, &s_signal ); + } + x->x_inputs = (t_inlet **) getbytes( x->x_nbinputs*sizeof(t_inlet *) ); + x->x_inputs_x = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); + x->x_inputs_y = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); + if ( !x->x_inputs || !x->x_inputs_x || !x->x_inputs_y ) + { + post( "audience~ : could not allocate inputs" ); + return NULL; + } + for ( bi=0; bix_nbinputs; bi++ ) + { + x->x_inputs[bi] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + } + + // allocate audio buffer + x->x_audiowritepos = 0; + x->x_audiobuffer = (t_float **) getbytes( x->x_nbinputs*sizeof(t_float *) ); + if ( !x->x_audiobuffer ) + { + post( "audience~ : could not allocate audio buffer" ); + return NULL; + } + x->x_audiobuffersize = ( t_int ) ( ( ( ( t_float ) sqrt( pow( x->x_width, 2 ) + + pow( x->x_height, 2 ) ) ) / SOUNDSPEED ) + * ( (float ) sys_getsr() ) ); + post( "audience~ : audio buffer size : %d samples", x->x_audiobuffersize ); + for ( bi=0; bix_nbinputs; bi++ ) + { + x->x_audiobuffer[bi] = (t_float *) getbytes( x->x_audiobuffersize*sizeof(t_float) ); + if ( !x->x_audiobuffer[bi] ) + { + post( "audience~ : could not allocate audio buffer" ); + return NULL; + } + } + + if ( argc == 0 ) + { + // set default coordinates + if ( x->x_nbinputs > 1 ) + { + for ( ei=0; eix_nbinputs; ei++ ) + { + x->x_inputs_x[ei] = (ei+1) * (x->x_width - 5) / x->x_nbinputs; + x->x_inputs_y[ei] = SPEAKER_HEIGHT/2; + } + } + else + { + x->x_inputs_x[0] = x->x_width; + x->x_inputs_y[0] = SPEAKER_HEIGHT/2; + } + + if ( x->x_nboutputs > 1 ) + { + for ( ei=0; eix_nboutputs; ei++ ) + { + x->x_outputs_x[ei] = ei * (x->x_width - 5) / ( x->x_nboutputs - 1 ); + x->x_outputs_y[ei] = x->x_height - LISTENER_HEIGHT/2; + } + } + else + { + x->x_outputs_x[0] = x->x_width; + x->x_outputs_y[0] = x->x_height - LISTENER_HEIGHT/2; + } + } + else + { + t_int ai = 6; + + // restore coordinates from arguments + for ( ei=0; eix_nbinputs; ei++ ) + { + x->x_inputs_x[ei] = argv[ai++].a_w.w_float; + x->x_inputs_y[ei] = argv[ai++].a_w.w_float; + } + for ( ei=0; eix_nboutputs; ei++ ) + { + x->x_outputs_x[ei] = argv[ai++].a_w.w_float; + x->x_outputs_y[ei] = argv[ai++].a_w.w_float; + } + } + + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_type_selected = AUDIENCE_NONE; + x->x_nselected = -1; + + // post( "audience~ : new object : inlets : %d : outlets : %d : attenuation : %f", x->x_nbinputs, x->x_nboutputs, x->x_attenuation ); + return (x); +} + +static void audience_free(t_audience_tilde *x) +{ + t_int ei; + + if ( x->x_outputs ) + { + for ( ei=0; eix_nboutputs; ei++ ) + { + outlet_free( x->x_outputs[ei] ); + } + freebytes( x->x_outputs, x->x_nboutputs*sizeof(t_outlet*) ); + } + if ( x->x_inputs ) + { + for ( ei=0; eix_nbinputs; ei++ ) + { + inlet_free( x->x_inputs[ei] ); + } + freebytes( x->x_inputs, x->x_nbinputs*sizeof(t_outlet*) ); + } + if ( x->x_audiobuffer ) + { + for ( ei=0; eix_nbinputs; ei++ ) + { + freebytes( x->x_audiobuffer[ei], x->x_audiobuffersize*sizeof(t_float) ); + } + freebytes( x->x_audiobuffer, x->x_nbinputs*sizeof(t_float*) ); + } +} + +static t_int *audience_perform(t_int *w) +{ + t_int ii, oi, op; + t_audience_tilde *x = (t_audience_tilde*)(w[1]); + t_int bsize = w[2]; + + { + // save input sounds in the audio buffer + for ( ii=0; iix_nbinputs; ii++ ) + { + t_float* isound = (t_float*)w[ii+3]; + + if ( x->x_audiobuffer[ii] ) + { + op = 0; + while ( op < bsize ) + { + *(x->x_audiobuffer[ii] + x->x_audiowritepos + op ) = *(isound + op); + op++; + } + } + } + + // set outputs + for ( oi=0; oix_nboutputs; oi++ ) + { + t_float* osound = (t_float*)w[oi+3+x->x_nbinputs]; + + // zeroing output + memset( osound, 0x00, bsize*sizeof( t_float ) ); + + for ( ii=0; iix_nbinputs; ii++ ) + { + t_int delay; + t_int dist; + t_int readpos; + t_int maxwritepos; + + maxwritepos = ( x->x_audiobuffersize / bsize ) * bsize; + dist = sqrt( pow( (x->x_outputs_x[oi] - x->x_inputs_x[ii]), 2 ) + + pow( (x->x_outputs_y[oi] - x->x_inputs_y[ii]), 2 ) ); + delay = ( t_int ) ( ( ( ( t_float ) dist ) * ( (float ) sys_getsr() ) ) / SOUNDSPEED ); + delay = ( delay / bsize ) * bsize; // set a block frontier + if ( x->x_applydelay ) + { + if ( x->x_audiowritepos >= delay ) + { + readpos = x->x_audiowritepos - delay; + } + else + { + readpos = maxwritepos - delay + x->x_audiowritepos; + } + } + else + { + readpos = x->x_audiowritepos; + } + // if ( ii == 0 ) + // { + // post( "audience~ : dist : %d : delay : %d : readpos : %d : writepos : %d", + // dist, delay, readpos, x->x_audiowritepos ); + // } + + op = 0; + while ( op < bsize ) + { + if ( ( readpos < x->x_audiobuffersize ) && ( readpos >= 0 ) ) + { + if ( 1.0-x->x_attenuation*dist < 0 ) + { + *(osound+op) += 0.0; + } + else + { + *(osound+op) += *(x->x_audiobuffer[ii] + readpos + op)*(1.0-x->x_attenuation*dist); + } + } + else + { + error( "audience~ : delay : %d : wrong readpos !!! : %d >= %d or < 0", delay, readpos, x->x_audiobuffersize ); + } + op++; + } + } + } + + // update write position + if ( x->x_audiowritepos + bsize > x->x_audiobuffersize - bsize ) + { + // post( "audience~ : write back to zero @ %d", x->x_audiowritepos ); + x->x_audiowritepos = 0; + } + else + { + x->x_audiowritepos += bsize; + } + + } + + return (w+x->x_nbinputs+x->x_nboutputs+3); +} + +static void audience_dsp(t_audience_tilde *x, t_signal **sp) +{ + switch ( x->x_nbinputs+x->x_nboutputs ) + { + case 2 : + dsp_add(audience_perform, 4, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec ); + break; + + case 3 : + dsp_add(audience_perform, 5, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec ); + break; + + case 4 : + dsp_add(audience_perform, 6, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec ); + break; + + case 5 : + dsp_add(audience_perform, 7, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec ); + break; + + case 6 : + dsp_add(audience_perform, 8, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, + sp[5]->s_vec, sp[6]->s_vec ); + break; + + case 7 : + dsp_add(audience_perform, 9, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, + sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec ); + break; + + case 8 : + dsp_add(audience_perform, 10, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, + sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec ); + break; + + case 9 : + dsp_add(audience_perform, 11, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, + sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, sp[9]->s_vec ); + break; + + case 10 : + dsp_add(audience_perform, 12, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, + sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, + sp[9]->s_vec, sp[10]->s_vec ); + break; + + default : + post( "audience~ : number of inlets/outlets not supported" ); + break; + } +} + +// set attenuation +static void audience_attenuation(t_audience_tilde *x, t_floatarg fattenuation ) +{ + if ( fattenuation < 0 ) + { + post( "audience~ : error : wrong attenuation : %f", fattenuation ); + return; + } + x->x_attenuation = fattenuation; +} + +// set delay +static void audience_delay(t_audience_tilde *x, t_floatarg fdelay ) +{ + if ( fdelay == 0. ) + { + x->x_applydelay = 0; + } + else + { + x->x_applydelay = 1; + } +} + +void audience_tilde_setup(void) +{ + post( audience_version ); + audience_class_tilde = class_new(gensym("audience~"), (t_newmethod)audience_new, + (t_method)audience_free, sizeof(t_audience_tilde), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN( audience_class_tilde, t_audience_tilde, x_f ); + class_addmethod(audience_class_tilde, (t_method)audience_dsp, gensym("dsp"), 0); + class_addmethod(audience_class_tilde, (t_method)audience_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(audience_class_tilde, (t_method)audience_attenuation, gensym("attenuation"), A_DEFFLOAT, 0); + class_addmethod(audience_class_tilde, (t_method)audience_delay, gensym("delay"), A_DEFFLOAT, 0); + audience_widgetbehavior.w_getrectfn = audience_getrect; + audience_widgetbehavior.w_displacefn = audience_displace; + audience_widgetbehavior.w_selectfn = audience_select; + audience_widgetbehavior.w_activatefn = NULL; + audience_widgetbehavior.w_deletefn = audience_delete; + audience_widgetbehavior.w_visfn = audience_vis; + audience_widgetbehavior.w_clickfn = audience_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(audience_class_tilde, audience_properties); + class_setsavefn(audience_class_tilde, audience_save); +#else + audience_widgetbehavior.w_propertiesfn = audience_properties; + audience_widgetbehavior.w_savefn = audience_save; +#endif + + class_setwidget(audience_class_tilde, &audience_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + audience_class_tilde->c_externdir->s_name, audience_class_tilde->c_name->s_name); +} diff --git a/audience~.h b/audience~.h new file mode 100644 index 0000000..b02d1b2 --- /dev/null +++ b/audience~.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2002 Yves Degoyon +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* a header for 2d_space which enables to spatialize +* several sound inputs with the mouse +*/ + +#ifndef __G_2D_SPACE_H +#define __G_2D_SPACE_H + +#define AUDIENCE_NONE 0 +#define AUDIENCE_INPUT 1 +#define AUDIENCE_OUTPUT 2 + +typedef struct _audience_tilde +{ + t_object x_obj; + t_glist *x_glist; + t_int x_nbinputs; + t_int x_nboutputs; + t_int *x_inputs_x; + t_int *x_inputs_y; + t_int *x_outputs_x; + t_int *x_outputs_y; + t_inlet **x_inputs; + t_outlet **x_outputs; + t_int x_allocate; /* indicates that audio buffer is */ + /* beeing reallocated */ + t_int x_audiobuffersize; /* audio buffer size */ + t_int x_audiowritepos; /* audio writing position */ + t_float **x_audiobuffer; /* audio buffer */ + t_int x_type_selected; /* type of selected object */ + /* e.g. inpout or output or none */ + t_int x_nselected; /* index of item selected */ + t_int x_height; /* height of the 2d_space object */ + t_int x_width; /* width of the 2d_space object */ + t_int x_selected; /* stores selected state */ + t_float x_attenuation; /* sound attenuation per meter */ + t_int x_applydelay; /* optional delay due to the distance */ + t_float x_f; /* classical float for signal input */ +} t_audience_tilde; + +#endif diff --git a/audience~.tcl b/audience~.tcl new file mode 100644 index 0000000..fcf7458 --- /dev/null +++ b/audience~.tcl @@ -0,0 +1,90 @@ +############ audience procedures -- ydegoyon@free.fr ######### + +proc audience_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nboutputs [concat graph_nboutputs_$vid] + global $var_graph_nboutputs + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_nboutputs] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc audience_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc audience_ok {id} { + audience_apply $id + audience_cancel $id +} + +proc pdtk_audience_dialog {id width height nboutputs} { + set vid [string trimleft $id .] + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nboutputs [concat graph_nboutputs_$vid] + global $var_graph_nboutputs + + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_nboutputs $nboutputs + + toplevel $id + wm title $id {audience} + wm protocol $id WM_DELETE_WINDOW [concat audience_cancel $id] + + label $id.label -text {2$ SPACE PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "audience_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "audience_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "audience_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lnboutputs -text "Nb Listeners :" + entry $id.3rangef.nboutputs -textvariable $var_graph_nboutputs -width 7 + pack $id.3rangef.lnboutputs $id.3rangef.nboutputs -side left + + bind $id.1rangef.width [concat audience_ok $id] + bind $id.2rangef.height [concat audience_ok $id] + bind $id.3rangef.nboutputs [concat audience_ok $id] + focus $id.1rangef.width +} + +############ audience procedures END -- ydegoyon@free.fr ######### diff --git a/audience~/INSTALL b/audience~/INSTALL deleted file mode 100644 index a1a03e0..0000000 --- a/audience~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/audience~ - -make clean - -make - -make install - -open help-audience~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/audience~/audience~-help.pd b/audience~/audience~-help.pd deleted file mode 100644 index ee90caf..0000000 --- a/audience~/audience~-help.pd +++ /dev/null @@ -1,60 +0,0 @@ -#N canvas 207 7 763 647 10; -#X text 370 378 * Width : graphical x size; -#X text 371 393 * Height : graphical y size; -#X text 358 456 bugs and comments @ ydegoyon@free.fr [-_-]; -#X obj 91 492 *~ 1; -#X obj 177 491 *~ 1; -#X obj 134 458 / 100; -#X floatatom 134 428 5 0 0; -#X floatatom 174 129 5 0 0; -#X floatatom 254 128 5 0 0; -#X floatatom 332 128 5 0 0; -#X floatatom 405 128 5 0 0; -#X text 332 210 audience~ is a moving audience simulation; -#X text 334 236 within a 2d space; -#X text 332 223 Each sound input and each listener can be moved; -#X text 371 407 * Nb Listeners : number of listeners; -#X obj 129 523 dac~; -#X msg 42 89 attenuation 0; -#X msg 42 64 attenuation 0.1; -#X msg 42 40 attenuation 1; -#X obj 406 153 osc~ 10000; -#X text 8 14 Sound attenuation per meter ( default = 0.01 ); -#X text 338 306 Example : audience~ 200 200 4 1 0.01 0; -#X text 339 349 (invoke with Properties ); -#X text 342 339 You can set the following properties :; -#X text 341 527 Note : the number of inputs + outputs is limited to -10; -#X text 341 540 ( can be easily changed in the code ); -#X obj 254 154 osc~ 500; -#X obj 331 154 osc~ 3000; -#X text 337 278 Constructor : audience~ - | audience~; -#X obj 175 155 osc~ 50; -#X obj 70 196 audience~ 200 200 4 2 0.01 0 0 0 193 188 126 118 145 -72 20 182 10 0; -#X msg 165 66 delay 0; -#X msg 165 91 delay 1; -#X text 296 41 ( due to the distance between speaker and listener ) -; -#X text 163 40 Apply delay option; -#X connect 3 0 15 0; -#X connect 4 0 15 1; -#X connect 5 0 3 1; -#X connect 5 0 4 1; -#X connect 6 0 5 0; -#X connect 7 0 29 0; -#X connect 8 0 26 0; -#X connect 9 0 27 0; -#X connect 10 0 19 0; -#X connect 16 0 30 0; -#X connect 17 0 30 0; -#X connect 18 0 30 0; -#X connect 19 0 30 4; -#X connect 26 0 30 2; -#X connect 27 0 30 3; -#X connect 29 0 30 1; -#X connect 30 0 3 0; -#X connect 30 1 4 0; -#X connect 31 0 30 0; -#X connect 32 0 30 0; diff --git a/audience~/audience~.c b/audience~/audience~.c deleted file mode 100644 index b14b139..0000000 --- a/audience~/audience~.c +++ /dev/null @@ -1,1063 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* audience.c written by Yves Degoyon 2002 */ -/* 2-dimensional audience simulation */ -/* ( simulates spatialization and interferences ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* Shalaby Effect -- Instrumentals */ -/* Honey Bane -- I Wish I Could Be Me */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - -#include "audience~.h" - -#ifdef NT -#include -#else -#include -#endif - -#define DEFAULT_AUDIENCE_WIDTH 200 -#define DEFAULT_AUDIENCE_HEIGHT 200 -#define DEFAULT_AUDIENCE_NBINPUTS 4 -#define DEFAULT_AUDIENCE_NBOUTPUTS 2 -#define DEFAULT_AUDIENCE_ATTENUATION 0.01 - -#define LISTENER_WIDTH 15 -#define LISTENER_HEIGHT 20 -#define SPEAKER_WIDTH 15 -#define SPEAKER_HEIGHT 20 - -// sound propagates at the speed of 340 m/s, isn't it ?? -#define SOUNDSPEED 340.0 - -// a pixel is 0.1 meter -#define PIXELSIZE 0.1 - -static char *audience_version = "audience : 2d audience simulation, version 0.7 (ydegoyon@free.fr)"; - -t_widgetbehavior audience_widgetbehavior; -static t_class *audience_class_tilde; - -static int guidebug=0; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h );\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -/* drawing functions */ -static void audience_draw_update(t_audience_tilde *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ei; - - for ( ei=0; eix_nbinputs; ei++ ) - { - SYS_VGUI6(".x%x.c coords %xISPEAKER%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - ); - SYS_VGUI6(".x%x.c coords %xSPEAKERNUM%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2 - ); - } - for ( ei=0; eix_nboutputs; ei++ ) - { - SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] - ); - SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2 - ); - } -} - -static void audience_draw_new(t_audience_tilde *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int ei; - - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #EAF1E2 -tags %xAAUDIENCE\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, - x); - // create captions - SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0m\" -tags %xBLCAPTION\n", - canvas, text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); - SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%dm\" -tags %xBRCAPTION\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_width + 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10, x->x_width, x ); - SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%dm\" -tags %xULCAPTION\n", - canvas, text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist), x->x_height, x ); - - // draw all outlets - if ( x->x_nboutputs > 1 ) - { - for ( ei=0; eix_nboutputs; ei++ ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", - canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x, ei); - } - } - else - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", - canvas, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x, 0); - } - // draw all inlets - for ( ei=0; eix_nbinputs+1; ei++ ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN%d\n", - canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs) + 5, - text_ypix(&x->x_obj, glist), - x, ei); - } - // create speaker images - for ( ei=0; eix_nbinputs; ei++ ) - { - SYS_VGUI5("image create photo %xSPEAKER%d -file /tmp/speaker.gif -format gif -width %d -height %d\n", - x, ei, SPEAKER_WIDTH, SPEAKER_HEIGHT ); - SYS_VGUI8(".x%x.c create image %d %d -image %xSPEAKER%d -tags %xISPEAKER%d\n", - canvas, - text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei], - x, ei, x, ei ); - SYS_VGUI7(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"s%d\" -tags %xSPEAKERNUM%d\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2, ei+1, x, ei ); - } - // create listener images - for ( ei=0; eix_nboutputs; ei++ ) - { - SYS_VGUI5("image create photo %xLISTENER%d -file /tmp/wanderer.gif -format gif -width %d -height %d\n", - x, ei, LISTENER_WIDTH, LISTENER_HEIGHT ); - SYS_VGUI8(".x%x.c create image %d %d -image %xLISTENER%d -tags %xILISTENER%d\n", - canvas, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei], - x, ei, x, ei ); - SYS_VGUI7(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"l%d\" -tags %xLISTENERNUM%d\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2, ei+1, x, ei ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void audience_draw_move(t_audience_tilde *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ei; - - SYS_VGUI7(".x%x.c coords %xAAUDIENCE %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height); - SYS_VGUI5(".x%x.c coords %xBLCAPTION %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10); - SYS_VGUI5(".x%x.c coords %xBRCAPTION %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist) + x->x_width + 10 , text_ypix(&x->x_obj, glist) + x->x_height + 10 ); - SYS_VGUI5(".x%x.c coords %xULCAPTION %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist) - 10 , text_ypix(&x->x_obj, glist) ); - - for ( ei=0; eix_nbinputs+1; ei++ ) - { - SYS_VGUI8(".x%x.c coords %xIN%d %d %d %d %d\n", - canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbinputs) + 5, - text_ypix(&x->x_obj, glist) - ); - } - for ( ei=0; eix_nbinputs+1; ei++ ) - { - SYS_VGUI6(".x%x.c coords %xISPEAKER%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - ); - SYS_VGUI6(".x%x.c coords %xSPEAKERNUM%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_inputs_x[ei] - SPEAKER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_inputs_y[ei] - SPEAKER_HEIGHT/2 - ); - } - if ( x->x_nboutputs > 1 ) - { - for ( ei=0; eix_nboutputs; ei++ ) - { - SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", - canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nboutputs-1) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei], - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] - ); - SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[ei] + LISTENER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_outputs_y[ei] + LISTENER_HEIGHT/2 - ); - } - } - else - { - SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", - canvas, x, 0, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - SYS_VGUI6(".x%x.c coords %xILISTENER%d %d %d\n", - canvas, x, 0, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[0], - text_ypix(&x->x_obj, glist) + x->x_outputs_y[0] - ); - SYS_VGUI6(".x%x.c coords %xLISTENERNUM%d %d %d\n", - canvas, x, 0, - text_xpix(&x->x_obj, glist) + x->x_outputs_x[0] + LISTENER_WIDTH/2, - text_ypix(&x->x_obj, glist) + x->x_outputs_y[0] + LISTENER_HEIGHT/2 - ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void audience_draw_erase(t_audience_tilde* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int ei; - - SYS_VGUI3(".x%x.c delete %xAAUDIENCE\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xBLCAPTION\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xBRCAPTION\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xULCAPTION\n", canvas, x); - for ( ei=0; eix_nbinputs+1; ei++ ) - { - SYS_VGUI4(".x%x.c delete %xIN%d\n", canvas, x, ei ); - } - for ( ei=0; eix_nbinputs; ei++ ) - { - SYS_VGUI4(".x%x.c delete %xISPEAKER%d\n", canvas, x, ei ); - SYS_VGUI4(".x%x.c delete %xSPEAKERNUM%d\n", canvas, x, ei ); - // SYS_VGUI3("image delete %xSPEAKER%d\n", x, ei ); - } - for ( ei=0; eix_nboutputs; ei++ ) - { - SYS_VGUI4(".x%x.c delete %xOUT%d\n", canvas, x, ei ); - SYS_VGUI4(".x%x.c delete %xILISTENER%d\n", canvas, x, ei ); - SYS_VGUI4(".x%x.c delete %xLISTENERNUM%d\n", canvas, x, ei ); - // SYS_VGUI3("image delete %xLISTENER%d\n", x, ei ); - } -} - -static void audience_draw_select(t_audience_tilde* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xAAUDIENCE -outline #0000FF\n", canvas, x); - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xAAUDIENCE -outline #000000\n", canvas, x); - } -} - -/* ------------------------ audience widgetbehaviour----------------------------- */ - - -static void audience_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_audience_tilde* x = (t_audience_tilde*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void audience_save(t_gobj *z, t_binbuf *b) -{ - t_audience_tilde *x = (t_audience_tilde *)z; - t_int ii; - - binbuf_addv(b, "ssiisiiiifi", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_width, x->x_height, - x->x_nbinputs, x->x_nboutputs, x->x_attenuation, x->x_applydelay ); - for ( ii=0; iix_nbinputs; ii++ ) - { - binbuf_addv(b, "ii", x->x_inputs_x[ii], x->x_inputs_y[ii] ); - } - for ( ii=0; iix_nboutputs; ii++ ) - { - binbuf_addv(b, "ii", x->x_outputs_x[ii], x->x_outputs_y[ii] ); - } - binbuf_addv(b, ";"); -} - -static void audience_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_audience_tilde *x=(t_audience_tilde *)z; - - sprintf(buf, "pdtk_audience_dialog %%s %d %d %d\n", - x->x_width, x->x_height, x->x_nboutputs - ); - // post("audience_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void audience_select(t_gobj *z, t_glist *glist, int selected) -{ - t_audience_tilde *x = (t_audience_tilde *)z; - - x->x_selected = selected; - audience_draw_select( x, glist ); -} - -static void audience_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_audience_tilde *x = (t_audience_tilde *)z; - - // post( "audience~ : vis : %d", vis ); - if (vis) - { - audience_draw_new( x, glist ); - } - else - { - audience_draw_erase( x, glist ); - } -} - -static void audience_dialog(t_audience_tilde *x, t_symbol *s, int argc, t_atom *argv) -{ - t_int onbinputs = x->x_nbinputs; - t_int onboutputs = x->x_nboutputs; - t_int owidth = x->x_width; - t_int oheight = x->x_height; - t_int bi, ei; - t_int dspstate; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( !x ) { - post( "audience~ : error :tried to set properties on an unexisting object" ); - } - if ( argc != 3 ) - { - post( "audience : error in the number of arguments ( %d instead of 3 )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT ) { - post( "audience~ : wrong arguments" ); - return; - } - - dspstate = canvas_suspend_dsp(); - audience_draw_erase(x, x->x_glist); - - x->x_width = (int)argv[0].a_w.w_float; - if ( x->x_width < 10 ) x->x_width = 10; - x->x_height = (int)argv[1].a_w.w_float; - if ( x->x_height < 10 ) x->x_height = 10; - x->x_nboutputs = (int)argv[2].a_w.w_float; - if ( x->x_nboutputs < 1 ) x->x_nboutputs = 1; - - // re-allocate audio buffers if needed - if ( ( owidth != x->x_width ) || ( oheight != x->x_height ) ) - { - if ( x->x_audiobuffer ) - { - for ( ei=0; eix_audiobuffer[ei], x->x_audiobuffersize*sizeof(t_float) ); - } - freebytes( x->x_audiobuffer, onbinputs*sizeof(t_float*) ); - } - // allocate audio buffer - x->x_audiobuffer = (t_float **) getbytes( x->x_nbinputs*sizeof(t_float *) ); - if ( !x->x_audiobuffer ) - { - post( "audience~ : could not allocate audio buffer" ); - return; - } - x->x_audiobuffersize = ( t_int ) ( ( ( ( t_float ) sqrt( pow( x->x_width, 2 ) - + pow( x->x_height, 2 ) ) ) / SOUNDSPEED ) - * ( (float ) sys_getsr() ) ); - post( "audience~ : audio buffer size : %d samples", x->x_audiobuffersize ); - for ( bi=0; bix_nbinputs; bi++ ) - { - x->x_audiobuffer[bi] = (t_float *) getbytes( x->x_audiobuffersize*sizeof(t_float) ); - if ( !x->x_audiobuffer[bi] ) - { - post( "audience~ : could not allocate audio buffer" ); - return; - } - } - x->x_audiowritepos = 0; - } - - // re-allocate inlets : CRASHES PD,I GUESS IT'S NOT SUPPORTED - if ( onbinputs != x->x_nbinputs ) - { - // post( "audience~ : cleaning up old inlets" ); - if ( x->x_inputs ) - { - for ( ei=0; eix_inputs[ei] ); - } - freebytes( x->x_inputs, onbinputs*sizeof(t_inlet*) ); - } - if ( x->x_inputs_x ) - { - freebytes( x->x_inputs_x, onbinputs*sizeof(t_int) ); - } - if ( x->x_inputs_y ) - { - freebytes( x->x_inputs_y, onbinputs*sizeof(t_int) ); - } - // post( "audience~ : creating new ones" ); - x->x_inputs = (t_inlet **) getbytes( x->x_nbinputs*sizeof(t_inlet *) ); - x->x_inputs_x = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); - x->x_inputs_y = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); - if ( !x->x_inputs || !x->x_inputs_x || !x->x_inputs_y ) - { - error( "audience~ : fatal : could not create new object" ); - return; - } - for ( bi=0; bix_nbinputs; bi++ ) - { - // post( "audience~ : allocating input ! %d", bi ); - x->x_inputs[bi] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - } - } - - // re-allocate outlets - if ( onboutputs != x->x_nboutputs ) - { - // post( "audience~ : cleaning up old outlets" ); - if ( x->x_outputs ) - { - for ( ei=0; eix_outputs[ei] ); - // outlet_free( x->x_outputs[ei] ); - } - freebytes( x->x_outputs, onboutputs*sizeof(t_outlet*) ); - } - if ( x->x_outputs_x ) - { - freebytes( x->x_outputs_x, onboutputs*sizeof(t_int) ); - } - if ( x->x_outputs_y ) - { - freebytes( x->x_outputs_y, onboutputs*sizeof(t_int) ); - } - // post( "audience~ : creating new ones" ); - x->x_outputs = (t_outlet **) getbytes( x->x_nboutputs*sizeof(t_outlet *) ); - x->x_outputs_x = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); - x->x_outputs_y = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); - if ( !x->x_outputs || !x->x_outputs_x || !x->x_outputs_y ) - { - // error( "audience~ : fatal : could not create new object" ); - return; - } - for ( bi=0; bix_nboutputs; bi++ ) - { - x->x_outputs[bi] = outlet_new( &x->x_obj, &s_signal ); - } - // set default coordinates - if ( x->x_nboutputs > 1 ) - { - for ( ei=0; eix_nboutputs; ei++ ) - { - x->x_outputs_x[ei] = ei * (x->x_width - 5) / ( x->x_nboutputs - 1 ); - x->x_outputs_y[ei] = x->x_height - LISTENER_HEIGHT/2; - } - } - else - { - x->x_outputs_x[0] = x->x_width; - x->x_outputs_y[0] = x->x_height - LISTENER_HEIGHT/2; - } - } - - canvas_fixlinesfor( canvas, (t_text*)x ); - audience_draw_new(x, x->x_glist); - canvas_resume_dsp(dspstate); -} - -static void audience_delete(t_gobj *z, t_glist *glist) -{ - t_audience_tilde *x = (t_audience_tilde *)z; - - // post( "audience~ : delete" ); - audience_draw_erase( x, glist ); - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void audience_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_audience_tilde *x = (t_audience_tilde *)z; - int xold = text_xpix(&x->x_obj, glist); - int yold = text_ypix(&x->x_obj, glist); - - // post( "audience_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) - { - audience_draw_move(x, x->x_glist); - } -} - -static void audience_motion(t_audience_tilde *x, t_floatarg dx, t_floatarg dy) -{ - // post( "audience_motion dx=%f dy=%f", dx, dy ); - - switch( x->x_type_selected ) - { - case AUDIENCE_INPUT: - x->x_inputs_x[ x->x_nselected ] += dx; - if ( x->x_inputs_x[ x->x_nselected ] < 0 ) x->x_inputs_x[ x->x_nselected ] = 0; - if ( x->x_inputs_x[ x->x_nselected ] > x->x_width ) x->x_inputs_x[ x->x_nselected ] = x->x_width; - x->x_inputs_y[ x->x_nselected ] += dy; - if ( x->x_inputs_y[ x->x_nselected ] < 0 ) x->x_inputs_y[ x->x_nselected ] = 0; - if ( x->x_inputs_y[ x->x_nselected ] > x->x_height ) x->x_inputs_y[ x->x_nselected ] = x->x_height; - break; - case AUDIENCE_OUTPUT: - x->x_outputs_x[ x->x_nselected ] += dx; - if ( x->x_outputs_x[ x->x_nselected ] < 0 ) x->x_outputs_x[ x->x_nselected ] = 0; - if ( x->x_outputs_x[ x->x_nselected ] > x->x_width ) x->x_outputs_x[ x->x_nselected ] = x->x_width; - x->x_outputs_y[ x->x_nselected ] += dy; - if ( x->x_outputs_y[ x->x_nselected ] < 0 ) x->x_outputs_y[ x->x_nselected ] = 0; - if ( x->x_outputs_y[ x->x_nselected ] > x->x_height ) x->x_outputs_y[ x->x_nselected ] = x->x_height; - break; - } - - audience_draw_update(x, x->x_glist); -} - -static int audience_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_audience_tilde* x = (t_audience_tilde *)z; - t_int bi; - - // post( "audience_click doit=%d x=%d y=%d", doit, xpix, ypix ); - if ( doit) - { - t_int relx = xpix-text_xpix(&x->x_obj, glist); - t_int rely = ypix-text_ypix(&x->x_obj, glist); - - // post( "audience~ : relx : %d : rely : %d", relx, rely ); - x->x_type_selected = AUDIENCE_NONE; - x->x_nselected = -1; - for ( bi=0; bix_nbinputs; bi++ ) - { - if ( ( abs( relx - x->x_inputs_x[bi] ) < SPEAKER_WIDTH ) && - ( abs( rely - x->x_inputs_y[bi] ) < SPEAKER_HEIGHT ) ) { - x->x_type_selected = AUDIENCE_INPUT; - x->x_nselected = bi; - break; - } - } - if ( x->x_type_selected == AUDIENCE_NONE ) - { - for ( bi=0; bix_nboutputs; bi++ ) - { - if ( ( abs( relx - x->x_outputs_x[bi] ) < LISTENER_WIDTH ) && - ( abs( rely - x->x_outputs_y[bi] ) < LISTENER_HEIGHT ) ) { - x->x_type_selected = AUDIENCE_OUTPUT; - x->x_nselected = bi; - break; - } - } - } - audience_draw_update(x, glist); - glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)audience_motion, - 0, xpix, ypix); - } - return (1); -} - -static t_audience_tilde *audience_new(t_symbol *s, int argc, t_atom *argv) -{ - t_int bi, ei; - t_audience_tilde *x; - t_pd *x2; - char *str; - - // post( "audience_new : create : %s argc =%d", s->s_name, argc ); - - x = (t_audience_tilde *)pd_new(audience_class_tilde); - // new audience created from the gui - if ( argc != 0 ) - { - if ( argc < 5 ) - { - post( "audience~ : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) { - post( "audience~ : wrong arguments" ); - return NULL; - } - - x->x_width = (int)argv[0].a_w.w_float; - if ( x->x_width < 10 ) x->x_width = 10; - x->x_height = (int)argv[1].a_w.w_float; - if ( x->x_height < 10 ) x->x_height = 10; - x->x_nbinputs = (int)argv[2].a_w.w_float; - if ( x->x_nbinputs < 1 ) x->x_nbinputs = 1; - x->x_nboutputs = (int)argv[3].a_w.w_float; - if ( x->x_nboutputs < 1 ) x->x_nboutputs = 1; - x->x_attenuation = argv[4].a_w.w_float; - if ( x->x_attenuation < 0 ) x->x_attenuation = 0; - x->x_applydelay = argv[5].a_w.w_float; - } - else - { - x->x_width = DEFAULT_AUDIENCE_WIDTH; - x->x_height = DEFAULT_AUDIENCE_HEIGHT; - x->x_nbinputs = DEFAULT_AUDIENCE_NBINPUTS; - x->x_nboutputs = DEFAULT_AUDIENCE_NBOUTPUTS; - x->x_attenuation = DEFAULT_AUDIENCE_ATTENUATION; - x->x_applydelay = 0; - } - - // create inlets and outlets - x->x_outputs = (t_outlet **) getbytes( x->x_nboutputs*sizeof(t_outlet *) ); - x->x_outputs_x = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); - x->x_outputs_y = (t_int *) getbytes( x->x_nboutputs*sizeof(t_int) ); - if ( !x->x_outputs || !x->x_outputs_x || !x->x_outputs_y ) - { - post( "audience~ : could not allocate outputs" ); - return NULL; - } - for ( bi=0; bix_nboutputs; bi++ ) - { - x->x_outputs[bi] = outlet_new( &x->x_obj, &s_signal ); - } - x->x_inputs = (t_inlet **) getbytes( x->x_nbinputs*sizeof(t_inlet *) ); - x->x_inputs_x = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); - x->x_inputs_y = (t_int *) getbytes( x->x_nbinputs*sizeof(t_int) ); - if ( !x->x_inputs || !x->x_inputs_x || !x->x_inputs_y ) - { - post( "audience~ : could not allocate inputs" ); - return NULL; - } - for ( bi=0; bix_nbinputs; bi++ ) - { - x->x_inputs[bi] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - } - - // allocate audio buffer - x->x_audiowritepos = 0; - x->x_audiobuffer = (t_float **) getbytes( x->x_nbinputs*sizeof(t_float *) ); - if ( !x->x_audiobuffer ) - { - post( "audience~ : could not allocate audio buffer" ); - return NULL; - } - x->x_audiobuffersize = ( t_int ) ( ( ( ( t_float ) sqrt( pow( x->x_width, 2 ) - + pow( x->x_height, 2 ) ) ) / SOUNDSPEED ) - * ( (float ) sys_getsr() ) ); - post( "audience~ : audio buffer size : %d samples", x->x_audiobuffersize ); - for ( bi=0; bix_nbinputs; bi++ ) - { - x->x_audiobuffer[bi] = (t_float *) getbytes( x->x_audiobuffersize*sizeof(t_float) ); - if ( !x->x_audiobuffer[bi] ) - { - post( "audience~ : could not allocate audio buffer" ); - return NULL; - } - } - - if ( argc == 0 ) - { - // set default coordinates - if ( x->x_nbinputs > 1 ) - { - for ( ei=0; eix_nbinputs; ei++ ) - { - x->x_inputs_x[ei] = (ei+1) * (x->x_width - 5) / x->x_nbinputs; - x->x_inputs_y[ei] = SPEAKER_HEIGHT/2; - } - } - else - { - x->x_inputs_x[0] = x->x_width; - x->x_inputs_y[0] = SPEAKER_HEIGHT/2; - } - - if ( x->x_nboutputs > 1 ) - { - for ( ei=0; eix_nboutputs; ei++ ) - { - x->x_outputs_x[ei] = ei * (x->x_width - 5) / ( x->x_nboutputs - 1 ); - x->x_outputs_y[ei] = x->x_height - LISTENER_HEIGHT/2; - } - } - else - { - x->x_outputs_x[0] = x->x_width; - x->x_outputs_y[0] = x->x_height - LISTENER_HEIGHT/2; - } - } - else - { - t_int ai = 6; - - // restore coordinates from arguments - for ( ei=0; eix_nbinputs; ei++ ) - { - x->x_inputs_x[ei] = argv[ai++].a_w.w_float; - x->x_inputs_y[ei] = argv[ai++].a_w.w_float; - } - for ( ei=0; eix_nboutputs; ei++ ) - { - x->x_outputs_x[ei] = argv[ai++].a_w.w_float; - x->x_outputs_y[ei] = argv[ai++].a_w.w_float; - } - } - - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_type_selected = AUDIENCE_NONE; - x->x_nselected = -1; - - // post( "audience~ : new object : inlets : %d : outlets : %d : attenuation : %f", x->x_nbinputs, x->x_nboutputs, x->x_attenuation ); - return (x); -} - -static void audience_free(t_audience_tilde *x) -{ - t_int ei; - - if ( x->x_outputs ) - { - for ( ei=0; eix_nboutputs; ei++ ) - { - outlet_free( x->x_outputs[ei] ); - } - freebytes( x->x_outputs, x->x_nboutputs*sizeof(t_outlet*) ); - } - if ( x->x_inputs ) - { - for ( ei=0; eix_nbinputs; ei++ ) - { - inlet_free( x->x_inputs[ei] ); - } - freebytes( x->x_inputs, x->x_nbinputs*sizeof(t_outlet*) ); - } - if ( x->x_audiobuffer ) - { - for ( ei=0; eix_nbinputs; ei++ ) - { - freebytes( x->x_audiobuffer[ei], x->x_audiobuffersize*sizeof(t_float) ); - } - freebytes( x->x_audiobuffer, x->x_nbinputs*sizeof(t_float*) ); - } -} - -static t_int *audience_perform(t_int *w) -{ - t_int ii, oi, op; - t_audience_tilde *x = (t_audience_tilde*)(w[1]); - t_int bsize = w[2]; - - { - // save input sounds in the audio buffer - for ( ii=0; iix_nbinputs; ii++ ) - { - t_float* isound = (t_float*)w[ii+3]; - - if ( x->x_audiobuffer[ii] ) - { - op = 0; - while ( op < bsize ) - { - *(x->x_audiobuffer[ii] + x->x_audiowritepos + op ) = *(isound + op); - op++; - } - } - } - - // set outputs - for ( oi=0; oix_nboutputs; oi++ ) - { - t_float* osound = (t_float*)w[oi+3+x->x_nbinputs]; - - // zeroing output - memset( osound, 0x00, bsize*sizeof( t_float ) ); - - for ( ii=0; iix_nbinputs; ii++ ) - { - t_int delay; - t_int dist; - t_int readpos; - t_int maxwritepos; - - maxwritepos = ( x->x_audiobuffersize / bsize ) * bsize; - dist = sqrt( pow( (x->x_outputs_x[oi] - x->x_inputs_x[ii]), 2 ) - + pow( (x->x_outputs_y[oi] - x->x_inputs_y[ii]), 2 ) ); - delay = ( t_int ) ( ( ( ( t_float ) dist ) * ( (float ) sys_getsr() ) ) / SOUNDSPEED ); - delay = ( delay / bsize ) * bsize; // set a block frontier - if ( x->x_applydelay ) - { - if ( x->x_audiowritepos >= delay ) - { - readpos = x->x_audiowritepos - delay; - } - else - { - readpos = maxwritepos - delay + x->x_audiowritepos; - } - } - else - { - readpos = x->x_audiowritepos; - } - // if ( ii == 0 ) - // { - // post( "audience~ : dist : %d : delay : %d : readpos : %d : writepos : %d", - // dist, delay, readpos, x->x_audiowritepos ); - // } - - op = 0; - while ( op < bsize ) - { - if ( ( readpos < x->x_audiobuffersize ) && ( readpos >= 0 ) ) - { - if ( 1.0-x->x_attenuation*dist < 0 ) - { - *(osound+op) += 0.0; - } - else - { - *(osound+op) += *(x->x_audiobuffer[ii] + readpos + op)*(1.0-x->x_attenuation*dist); - } - } - else - { - error( "audience~ : delay : %d : wrong readpos !!! : %d >= %d or < 0", delay, readpos, x->x_audiobuffersize ); - } - op++; - } - } - } - - // update write position - if ( x->x_audiowritepos + bsize > x->x_audiobuffersize - bsize ) - { - // post( "audience~ : write back to zero @ %d", x->x_audiowritepos ); - x->x_audiowritepos = 0; - } - else - { - x->x_audiowritepos += bsize; - } - - } - - return (w+x->x_nbinputs+x->x_nboutputs+3); -} - -static void audience_dsp(t_audience_tilde *x, t_signal **sp) -{ - switch ( x->x_nbinputs+x->x_nboutputs ) - { - case 2 : - dsp_add(audience_perform, 4, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec ); - break; - - case 3 : - dsp_add(audience_perform, 5, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec ); - break; - - case 4 : - dsp_add(audience_perform, 6, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec ); - break; - - case 5 : - dsp_add(audience_perform, 7, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec ); - break; - - case 6 : - dsp_add(audience_perform, 8, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, - sp[5]->s_vec, sp[6]->s_vec ); - break; - - case 7 : - dsp_add(audience_perform, 9, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, - sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec ); - break; - - case 8 : - dsp_add(audience_perform, 10, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, - sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec ); - break; - - case 9 : - dsp_add(audience_perform, 11, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, - sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, sp[9]->s_vec ); - break; - - case 10 : - dsp_add(audience_perform, 12, x, sp[1]->s_n, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, - sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, - sp[9]->s_vec, sp[10]->s_vec ); - break; - - default : - post( "audience~ : number of inlets/outlets not supported" ); - break; - } -} - -// set attenuation -static void audience_attenuation(t_audience_tilde *x, t_floatarg fattenuation ) -{ - if ( fattenuation < 0 ) - { - post( "audience~ : error : wrong attenuation : %f", fattenuation ); - return; - } - x->x_attenuation = fattenuation; -} - -// set delay -static void audience_delay(t_audience_tilde *x, t_floatarg fdelay ) -{ - if ( fdelay == 0. ) - { - x->x_applydelay = 0; - } - else - { - x->x_applydelay = 1; - } -} - -void audience_tilde_setup(void) -{ - post( audience_version ); -#include "audience~.tk2c" - audience_class_tilde = class_new(gensym("audience~"), (t_newmethod)audience_new, - (t_method)audience_free, sizeof(t_audience_tilde), 0, A_GIMME, 0); - CLASS_MAINSIGNALIN( audience_class_tilde, t_audience_tilde, x_f ); - class_addmethod(audience_class_tilde, (t_method)audience_dsp, gensym("dsp"), 0); - class_addmethod(audience_class_tilde, (t_method)audience_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(audience_class_tilde, (t_method)audience_attenuation, gensym("attenuation"), A_DEFFLOAT, 0); - class_addmethod(audience_class_tilde, (t_method)audience_delay, gensym("delay"), A_DEFFLOAT, 0); - audience_widgetbehavior.w_getrectfn = audience_getrect; - audience_widgetbehavior.w_displacefn = audience_displace; - audience_widgetbehavior.w_selectfn = audience_select; - audience_widgetbehavior.w_activatefn = NULL; - audience_widgetbehavior.w_deletefn = audience_delete; - audience_widgetbehavior.w_visfn = audience_vis; - audience_widgetbehavior.w_clickfn = audience_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(audience_class_tilde, audience_properties); - class_setsavefn(audience_class_tilde, audience_save); -#else - audience_widgetbehavior.w_propertiesfn = audience_properties; - audience_widgetbehavior.w_savefn = audience_save; -#endif - - class_setwidget(audience_class_tilde, &audience_widgetbehavior); - -} diff --git a/audience~/audience~.h b/audience~/audience~.h deleted file mode 100644 index b02d1b2..0000000 --- a/audience~/audience~.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* a header for 2d_space which enables to spatialize -* several sound inputs with the mouse -*/ - -#ifndef __G_2D_SPACE_H -#define __G_2D_SPACE_H - -#define AUDIENCE_NONE 0 -#define AUDIENCE_INPUT 1 -#define AUDIENCE_OUTPUT 2 - -typedef struct _audience_tilde -{ - t_object x_obj; - t_glist *x_glist; - t_int x_nbinputs; - t_int x_nboutputs; - t_int *x_inputs_x; - t_int *x_inputs_y; - t_int *x_outputs_x; - t_int *x_outputs_y; - t_inlet **x_inputs; - t_outlet **x_outputs; - t_int x_allocate; /* indicates that audio buffer is */ - /* beeing reallocated */ - t_int x_audiobuffersize; /* audio buffer size */ - t_int x_audiowritepos; /* audio writing position */ - t_float **x_audiobuffer; /* audio buffer */ - t_int x_type_selected; /* type of selected object */ - /* e.g. inpout or output or none */ - t_int x_nselected; /* index of item selected */ - t_int x_height; /* height of the 2d_space object */ - t_int x_width; /* width of the 2d_space object */ - t_int x_selected; /* stores selected state */ - t_float x_attenuation; /* sound attenuation per meter */ - t_int x_applydelay; /* optional delay due to the distance */ - t_float x_f; /* classical float for signal input */ -} t_audience_tilde; - -#endif diff --git a/audience~/audience~.tk b/audience~/audience~.tk deleted file mode 100644 index fcf7458..0000000 --- a/audience~/audience~.tk +++ /dev/null @@ -1,90 +0,0 @@ -############ audience procedures -- ydegoyon@free.fr ######### - -proc audience_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nboutputs [concat graph_nboutputs_$vid] - global $var_graph_nboutputs - - set cmd [concat $id dialog \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_nboutputs] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc audience_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc audience_ok {id} { - audience_apply $id - audience_cancel $id -} - -proc pdtk_audience_dialog {id width height nboutputs} { - set vid [string trimleft $id .] - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nboutputs [concat graph_nboutputs_$vid] - global $var_graph_nboutputs - - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_nboutputs $nboutputs - - toplevel $id - wm title $id {audience} - wm protocol $id WM_DELETE_WINDOW [concat audience_cancel $id] - - label $id.label -text {2$ SPACE PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "audience_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "audience_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "audience_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lwidth -text "Width :" - entry $id.1rangef.width -textvariable $var_graph_width -width 7 - pack $id.1rangef.lwidth $id.1rangef.width -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lheight -text "Height :" - entry $id.2rangef.height -textvariable $var_graph_height -width 7 - pack $id.2rangef.lheight $id.2rangef.height -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lnboutputs -text "Nb Listeners :" - entry $id.3rangef.nboutputs -textvariable $var_graph_nboutputs -width 7 - pack $id.3rangef.lnboutputs $id.3rangef.nboutputs -side left - - bind $id.1rangef.width [concat audience_ok $id] - bind $id.2rangef.height [concat audience_ok $id] - bind $id.3rangef.nboutputs [concat audience_ok $id] - focus $id.1rangef.width -} - -############ audience procedures END -- ydegoyon@free.fr ######### diff --git a/audience~/audience~.tk2c b/audience~/audience~.tk2c deleted file mode 100644 index ea3a7a3..0000000 --- a/audience~/audience~.tk2c +++ /dev/null @@ -1,69 +0,0 @@ -// ########### audience procedures -- ydegoyon@free.fr ######### -sys_gui("proc audience_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nboutputs [concat graph_nboutputs_$vid]\n"); -sys_gui("global $var_graph_nboutputs\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_nboutputs] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc audience_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc audience_ok {id} {\n"); -sys_gui("audience_apply $id\n"); -sys_gui("audience_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_audience_dialog {id width height nboutputs} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nboutputs [concat graph_nboutputs_$vid]\n"); -sys_gui("global $var_graph_nboutputs\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_nboutputs $nboutputs\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {audience}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat audience_cancel $id]\n"); -sys_gui("label $id.label -text {2$ SPACE PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"audience_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"audience_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"audience_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.1rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.1rangef.lwidth $id.1rangef.width -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.2rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.2rangef.lheight $id.2rangef.height -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lnboutputs -text \"Nb Listeners :\"\n"); -sys_gui("entry $id.3rangef.nboutputs -textvariable $var_graph_nboutputs -width 7\n"); -sys_gui("pack $id.3rangef.lnboutputs $id.3rangef.nboutputs -side left\n"); -sys_gui("bind $id.1rangef.width [concat audience_ok $id]\n"); -sys_gui("bind $id.2rangef.height [concat audience_ok $id]\n"); -sys_gui("bind $id.3rangef.nboutputs [concat audience_ok $id]\n"); -sys_gui("focus $id.1rangef.width\n"); -sys_gui("}\n"); -// ########### audience procedures END -- ydegoyon@free.fr ######### diff --git a/audience~/speaker.gif b/audience~/speaker.gif deleted file mode 100644 index 6dd9fd4..0000000 Binary files a/audience~/speaker.gif and /dev/null differ diff --git a/audience~/wanderer.gif b/audience~/wanderer.gif deleted file mode 100644 index b2a9f8c..0000000 Binary files a/audience~/wanderer.gif and /dev/null differ diff --git a/beatify~-help.pd b/beatify~-help.pd new file mode 100644 index 0000000..16577a0 --- /dev/null +++ b/beatify~-help.pd @@ -0,0 +1,36 @@ +#N canvas 45 57 695 405 10; +#X obj 86 268 dac~; +#X text 288 313 comments & bugs @ ydegoyon.free.fr; +#X floatatom 143 104 5 -100 500; +#X text 244 42 musiscript \, an excellent sound generation tool; +#X text 245 53 by David Piott ( http://musicscript.sourceforge.net +); +#X text 243 32 The idea was borrowed from; +#X floatatom 171 129 5 -100 500; +#X floatatom 194 156 5 -100 500; +#X floatatom 210 183 5 0 0; +#X floatatom 277 211 5 -100 500; +#X obj 233 213 / 100; +#X obj 108 41 osc~ 400; +#X text 268 273 Note : the default values are tuned for the osc~ input +; +#X text 268 286 You might need to set other values for your source +; +#X text 188 103 attack [ min=1.0 \, default= 10 ]; +#X text 215 128 sustain [ min=0.0 \, default=2.0 ]; +#X text 238 155 decay [ min=1.0 \, default = 50 ]; +#X text 254 182 size [ min=1.0 \, default = 700 ]; +#X text 321 210 global amplitude [ min=0.0 \, max=1.0 \, default=0.5] +; +#X obj 107 237 beatify~ -------------; +#X text 244 19 Beatify~ : an audio amplitude modulator [ ADSR + loop +size ]; +#X connect 2 0 19 1; +#X connect 6 0 19 2; +#X connect 7 0 19 3; +#X connect 8 0 19 4; +#X connect 9 0 10 0; +#X connect 10 0 19 5; +#X connect 11 0 19 0; +#X connect 19 0 0 0; +#X connect 19 0 0 1; diff --git a/beatify~.c b/beatify~.c new file mode 100644 index 0000000..69c2dd0 --- /dev/null +++ b/beatify~.c @@ -0,0 +1,177 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "COPYING" in this distribution. */ +/* */ +/* beatify~ -- modulates an audio signal amplitude, */ +/* making it sounding like drums (sometimes) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* "We wanted succes" */ +/* "We got lost into the night" */ +/* "Take life as it comes" */ +/* PJ Harvey -- We Float */ +/* ---------------------------------------------------------------------------- */ + +#include "m_pd.h" +#include +#include + +static char *beatify_version = "beatify~: an audio beatify, version 0.1 (ydegoyon@free.fr)"; + +typedef struct _beatify +{ + t_object x_obj; + t_float x_attack; + t_float x_sustain; + t_float x_decay; + t_float x_size; + t_float x_gamplitude; + t_float x_vol; + t_int x_current; + t_float x_f; +} t_beatify; + +static t_class *beatify_class; + +static void beatify_attack(t_beatify *x, t_floatarg fattack ) +{ + if (fattack < 1.0) + { + x->x_attack = 1.0; + } + else + { + x->x_attack = fattack; + } +} + +static void beatify_sustain(t_beatify *x, t_floatarg fsustain ) +{ + if (fsustain < 0.0) + { + x->x_sustain = 0.0; + } + else + { + x->x_sustain = fsustain; + } +} + +static void beatify_decay(t_beatify *x, t_floatarg fdecay ) +{ + if (fdecay < 1.0) + { + x->x_decay = 1.0; + } + else + { + x->x_decay = fdecay; + } +} + +static void beatify_size(t_beatify *x, t_floatarg fsize ) +{ + if (fsize < 100.0) + { + x->x_size = 100.0; + } + else + { + x->x_size = fsize; + } +} + +static void beatify_gamplitude(t_beatify *x, t_floatarg fgamplitude ) +{ + if (fgamplitude < 0.0) { + x->x_gamplitude = 0.0; + } else if (fgamplitude > 1.0) { + x->x_gamplitude = 1.0; + } else { + x->x_gamplitude = fgamplitude; + } +} + +static void *beatify_new(void) +{ + t_beatify *x = (t_beatify *)pd_new(beatify_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("attack")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("sustain")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("decay")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("size")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("gamplitude")); + x->x_attack = 10; + x->x_decay = 50; + x->x_sustain = 2; + x->x_size = 700; + x->x_gamplitude = 0.5; + x->x_current = x->x_size; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static t_int *beatify_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_int n = (int)(w[3]); + t_beatify *x = (t_beatify*)(w[4]); + t_float adelta = 0., ddelta = 0.; + + while (n--) { + if ( x->x_current>=x->x_size ) + { + adelta = (x->x_gamplitude-x->x_vol)/x->x_attack; + ddelta = x->x_gamplitude/x->x_decay; + x->x_current = 0; + } + if ( x->x_currentx_attack ) x->x_vol+= adelta; + if ( x->x_current>x->x_attack+x->x_sustain && x->x_currentx_attack+x->x_sustain+x->x_decay ) + { + x->x_vol-= ddelta; + } + x->x_current++; + + *(out) = *(in)*x->x_vol; + out++; in++; + } + return (w+5); +} + +static void beatify_dsp(t_beatify *x, t_signal **sp) +{ + dsp_add(beatify_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); +} + +void beatify_tilde_setup(void) +{ + post( beatify_version ); + beatify_class = class_new(gensym("beatify~"), (t_newmethod)beatify_new, 0, + sizeof(t_beatify), 0, 0); + CLASS_MAINSIGNALIN( beatify_class, t_beatify, x_f ); + class_addmethod(beatify_class, (t_method)beatify_dsp, gensym("dsp"), 0); + class_addmethod(beatify_class, (t_method)beatify_attack, gensym("attack"), A_FLOAT, 0); + class_addmethod(beatify_class, (t_method)beatify_sustain, gensym("sustain"), A_FLOAT, 0); + class_addmethod(beatify_class, (t_method)beatify_decay, gensym("decay"), A_FLOAT, 0); + class_addmethod(beatify_class, (t_method)beatify_size, gensym("size"), A_FLOAT, 0); + class_addmethod(beatify_class, (t_method)beatify_gamplitude, gensym("gamplitude"), A_FLOAT, 0); +} diff --git a/beatify~/INSTALL b/beatify~/INSTALL deleted file mode 100644 index db33979..0000000 --- a/beatify~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/beatify~ - -make clean - -make - -make install - -open help-beatify~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/beatify~/beatify~-help.pd b/beatify~/beatify~-help.pd deleted file mode 100644 index 16577a0..0000000 --- a/beatify~/beatify~-help.pd +++ /dev/null @@ -1,36 +0,0 @@ -#N canvas 45 57 695 405 10; -#X obj 86 268 dac~; -#X text 288 313 comments & bugs @ ydegoyon.free.fr; -#X floatatom 143 104 5 -100 500; -#X text 244 42 musiscript \, an excellent sound generation tool; -#X text 245 53 by David Piott ( http://musicscript.sourceforge.net -); -#X text 243 32 The idea was borrowed from; -#X floatatom 171 129 5 -100 500; -#X floatatom 194 156 5 -100 500; -#X floatatom 210 183 5 0 0; -#X floatatom 277 211 5 -100 500; -#X obj 233 213 / 100; -#X obj 108 41 osc~ 400; -#X text 268 273 Note : the default values are tuned for the osc~ input -; -#X text 268 286 You might need to set other values for your source -; -#X text 188 103 attack [ min=1.0 \, default= 10 ]; -#X text 215 128 sustain [ min=0.0 \, default=2.0 ]; -#X text 238 155 decay [ min=1.0 \, default = 50 ]; -#X text 254 182 size [ min=1.0 \, default = 700 ]; -#X text 321 210 global amplitude [ min=0.0 \, max=1.0 \, default=0.5] -; -#X obj 107 237 beatify~ -------------; -#X text 244 19 Beatify~ : an audio amplitude modulator [ ADSR + loop -size ]; -#X connect 2 0 19 1; -#X connect 6 0 19 2; -#X connect 7 0 19 3; -#X connect 8 0 19 4; -#X connect 9 0 10 0; -#X connect 10 0 19 5; -#X connect 11 0 19 0; -#X connect 19 0 0 0; -#X connect 19 0 0 1; diff --git a/beatify~/beatify~.c b/beatify~/beatify~.c deleted file mode 100644 index 69c2dd0..0000000 --- a/beatify~/beatify~.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "COPYING" in this distribution. */ -/* */ -/* beatify~ -- modulates an audio signal amplitude, */ -/* making it sounding like drums (sometimes) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* "We wanted succes" */ -/* "We got lost into the night" */ -/* "Take life as it comes" */ -/* PJ Harvey -- We Float */ -/* ---------------------------------------------------------------------------- */ - -#include "m_pd.h" -#include -#include - -static char *beatify_version = "beatify~: an audio beatify, version 0.1 (ydegoyon@free.fr)"; - -typedef struct _beatify -{ - t_object x_obj; - t_float x_attack; - t_float x_sustain; - t_float x_decay; - t_float x_size; - t_float x_gamplitude; - t_float x_vol; - t_int x_current; - t_float x_f; -} t_beatify; - -static t_class *beatify_class; - -static void beatify_attack(t_beatify *x, t_floatarg fattack ) -{ - if (fattack < 1.0) - { - x->x_attack = 1.0; - } - else - { - x->x_attack = fattack; - } -} - -static void beatify_sustain(t_beatify *x, t_floatarg fsustain ) -{ - if (fsustain < 0.0) - { - x->x_sustain = 0.0; - } - else - { - x->x_sustain = fsustain; - } -} - -static void beatify_decay(t_beatify *x, t_floatarg fdecay ) -{ - if (fdecay < 1.0) - { - x->x_decay = 1.0; - } - else - { - x->x_decay = fdecay; - } -} - -static void beatify_size(t_beatify *x, t_floatarg fsize ) -{ - if (fsize < 100.0) - { - x->x_size = 100.0; - } - else - { - x->x_size = fsize; - } -} - -static void beatify_gamplitude(t_beatify *x, t_floatarg fgamplitude ) -{ - if (fgamplitude < 0.0) { - x->x_gamplitude = 0.0; - } else if (fgamplitude > 1.0) { - x->x_gamplitude = 1.0; - } else { - x->x_gamplitude = fgamplitude; - } -} - -static void *beatify_new(void) -{ - t_beatify *x = (t_beatify *)pd_new(beatify_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("attack")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("sustain")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("decay")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("size")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("gamplitude")); - x->x_attack = 10; - x->x_decay = 50; - x->x_sustain = 2; - x->x_size = 700; - x->x_gamplitude = 0.5; - x->x_current = x->x_size; - outlet_new(&x->x_obj, &s_signal); - return (x); -} - -static t_int *beatify_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *out = (t_float *)(w[2]); - t_int n = (int)(w[3]); - t_beatify *x = (t_beatify*)(w[4]); - t_float adelta = 0., ddelta = 0.; - - while (n--) { - if ( x->x_current>=x->x_size ) - { - adelta = (x->x_gamplitude-x->x_vol)/x->x_attack; - ddelta = x->x_gamplitude/x->x_decay; - x->x_current = 0; - } - if ( x->x_currentx_attack ) x->x_vol+= adelta; - if ( x->x_current>x->x_attack+x->x_sustain && x->x_currentx_attack+x->x_sustain+x->x_decay ) - { - x->x_vol-= ddelta; - } - x->x_current++; - - *(out) = *(in)*x->x_vol; - out++; in++; - } - return (w+5); -} - -static void beatify_dsp(t_beatify *x, t_signal **sp) -{ - dsp_add(beatify_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); -} - -void beatify_tilde_setup(void) -{ - post( beatify_version ); - beatify_class = class_new(gensym("beatify~"), (t_newmethod)beatify_new, 0, - sizeof(t_beatify), 0, 0); - CLASS_MAINSIGNALIN( beatify_class, t_beatify, x_f ); - class_addmethod(beatify_class, (t_method)beatify_dsp, gensym("dsp"), 0); - class_addmethod(beatify_class, (t_method)beatify_attack, gensym("attack"), A_FLOAT, 0); - class_addmethod(beatify_class, (t_method)beatify_sustain, gensym("sustain"), A_FLOAT, 0); - class_addmethod(beatify_class, (t_method)beatify_decay, gensym("decay"), A_FLOAT, 0); - class_addmethod(beatify_class, (t_method)beatify_size, gensym("size"), A_FLOAT, 0); - class_addmethod(beatify_class, (t_method)beatify_gamplitude, gensym("gamplitude"), A_FLOAT, 0); -} diff --git a/blinkenlights-help.pd b/blinkenlights-help.pd new file mode 100644 index 0000000..32baca0 --- /dev/null +++ b/blinkenlights-help.pd @@ -0,0 +1,156 @@ +#N canvas 484 81 885 735 10; +#X text 334 640 Part of unauthorized PD; +#X text 480 570 blinkenlights is a blinkenlights movies player; +#X text 480 584 but it's also a pixel grid than you can use for ASCII +art...; +#X text 480 600 Constructor : blinkenlights ; +#X msg 125 10 create; +#X msg 182 10 destroy; +#X text 274 11 Create/destroy the window; +#X msg 125 129 background 78 34 12; +#X text 275 131 Set the background color [RGB]; +#X text 275 154 Set the foreground color [RGB]; +#X msg 121 223 pixon \$1 \$2; +#X msg 284 222 bang; +#X msg 285 266 bang; +#X msg 122 267 pixoff \$1 \$2; +#X obj 87 618 blinkenlights 18 8 32 32; +#X msg 125 152 foreground 124 78 89; +#X obj 347 277 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 336 250 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X text 355 257 Set a pixel off; +#X text 352 213 Set a pixel on; +#X obj 346 232 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 1600 1; +#X obj 335 205 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 1400 1; +#X msg 338 309 bang; +#X obj 400 320 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 389 293 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X text 410 303 Set a pixel in a particular color; +#X msg 118 310 pixel \$1 \$2 34 23 109; +#X obj 120 338 + 1; +#X obj 217 338 + 1; +#X obj 316 338 random 255; +#X obj 395 338 random 255; +#X obj 470 338 random 255; +#X msg 118 360 pixel \$1 \$2 \$3 \$4 \$5; +#X obj 267 359 pack f f f f f; +#X obj 464 360 t b b b b b; +#X msg 593 339 stop; +#X text 634 342 Random drawing; +#X msg 547 339 bang; +#X obj 548 360 metro 10; +#X obj 146 338 random 32; +#X obj 246 337 random 32; +#X msg 125 107 clear; +#X text 274 105 Clear the area; +#X text 122 187 ============================================ Pixel +Functions; +#X text 552 187 ========================================; +#X text 550 -6 ========================================; +#X text 539 472 ========================================; +#X text 112 472 =========================================== Movies +Functions; +#X text 122 -6 =========================================== Grid Actions +; +#X obj 214 222 pack f f; +#X obj 215 266 pack f f; +#X obj 275 310 pack f f; +#X msg 125 81 xsize 32; +#X msg 192 81 ysize 32; +#X text 274 79 Set the pixel x & y size; +#X msg 127 33 width 24; +#X msg 125 58 height 24; +#X text 275 37 Set the width ( number of pixels ); +#X text 275 56 Set the height ( number of pixels ); +#X msg 127 495 open ./blm/ascii_people.blm; +#X msg 335 495 play; +#X msg 377 495 stop; +#X msg 127 522 open \$1; +#X msg 418 495 next; +#X obj 458 494 metro 100; +#X msg 531 495 bang; +#X msg 571 494 stop; +#X obj 188 521 openpanel; +#X obj 261 522 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 615 495 5 0 0 0 - - -; +#X text 534 401 ========================================; +#X text 116 400 =============================================== VJ +function; +#X msg 132 444 vj \$1; +#X msg 363 444 goto \$1; +#X obj 366 423 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 5600 1; +#X obj 132 424 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X text 507 420 <- look! you can also scratch the film!; +#X text 530 434 be sure the window is created first....; +#X text 154 420 <- switch to the scratch mode; +#X text 333 654 Comments and bugs @ ydegoyon@free.fr and chun@goto10.org +; +#X connect 4 0 14 0; +#X connect 5 0 14 0; +#X connect 7 0 14 0; +#X connect 10 0 14 0; +#X connect 11 0 49 0; +#X connect 12 0 50 0; +#X connect 13 0 14 0; +#X connect 15 0 14 0; +#X connect 16 0 50 0; +#X connect 17 0 12 0; +#X connect 17 0 50 1; +#X connect 20 0 49 0; +#X connect 21 0 11 0; +#X connect 21 0 49 1; +#X connect 22 0 51 0; +#X connect 23 0 51 0; +#X connect 24 0 22 0; +#X connect 24 0 51 1; +#X connect 26 0 14 0; +#X connect 27 0 33 0; +#X connect 28 0 33 1; +#X connect 29 0 33 2; +#X connect 30 0 33 3; +#X connect 31 0 33 4; +#X connect 32 0 14 0; +#X connect 33 0 32 0; +#X connect 34 0 39 0; +#X connect 34 1 40 0; +#X connect 34 2 29 0; +#X connect 34 3 30 0; +#X connect 34 4 31 0; +#X connect 35 0 38 0; +#X connect 37 0 38 0; +#X connect 38 0 34 0; +#X connect 39 0 27 0; +#X connect 40 0 28 0; +#X connect 41 0 14 0; +#X connect 49 0 10 0; +#X connect 50 0 13 0; +#X connect 51 0 26 0; +#X connect 52 0 14 0; +#X connect 53 0 14 0; +#X connect 55 0 14 0; +#X connect 56 0 14 0; +#X connect 59 0 14 0; +#X connect 60 0 14 0; +#X connect 61 0 14 0; +#X connect 62 0 14 0; +#X connect 63 0 14 0; +#X connect 64 0 63 0; +#X connect 65 0 64 0; +#X connect 66 0 64 0; +#X connect 67 0 62 0; +#X connect 68 0 67 0; +#X connect 69 0 64 1; +#X connect 72 0 14 0; +#X connect 73 0 14 0; +#X connect 74 0 73 0; +#X connect 75 0 72 0; diff --git a/blinkenlights.c b/blinkenlights.c new file mode 100644 index 0000000..03abda9 --- /dev/null +++ b/blinkenlights.c @@ -0,0 +1,869 @@ +/* ---------------------- blinkenlights~ -------------------------------------- */ +/* */ +/* Blinkenlights is a BL movies player but also a pixel grid */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Currently listening : */ +/* Pop Group : We Are All Prostitutes */ +/* Culturcide : Bruce */ +/* ---------------------------------------------------------------------------- */ + +//added functions: +//"static void blinkenlights_findframes(t_blinkenlights *x)" +//this is to remember the frame positions in the .blm file + +//"static void blinkenlights_goto(t_blinkenlights* x, t_float frame)" +//with a "goto $1" message, you can stratch the blm film. note that the +//range of $1 is 0 to 1 + + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#include +#include +#include + +#include "m_pd.h" /* standard pd stuff */ +#include "g_canvas.h" /* some pd's graphical functions */ + +static char *blinkenlights_version = "blinkenlights: a blinkenlights movies player version 0.2 ( bugs @ ydegoyon@free.fr and chun@goto10.org )"; + +static int guidebug=0; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i);\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j);\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define BL_BACKGROUND_COLOR "#000000" +#define BL_FOREGROUND_COLOR "#00FF00" +#define BL_MAX_LENGTH 1024 + +static t_class *blinkenlights_class; + +typedef struct _blinkenlights +{ + t_object x_obj; + t_int x_width; /* number of pixels ( width ) */ + t_int x_height; /* number of pixels ( height) */ + t_int x_xsize; /* x size of each pixel */ + t_int x_ysize; /* y size of each pixel */ + char *x_background; /* color of the background #RRGGBB */ + char *x_foreground; /* color of the foreground #RRGGBB */ + t_int x_ecanvas; /* flag that indicates if the canvas has been created */ + t_glist *x_glist; /* graphic context */ + FILE *x_filed; /* file descriptor */ + t_int x_timer; /* timer read from bl movie */ + t_int *x_frame; /* frame contents */ + t_clock *x_clock; /* clock used for reading frames */ + t_outlet *outlet_bang; + t_int frame_no; + t_int frame_pos[BL_MAX_LENGTH]; + t_clock *x_clock2; + t_int x_timer2; + t_float frame_inc; + +} t_blinkenlights; + +static void blinkenlights_close(t_blinkenlights *x); + + /* clean up */ +static void blinkenlights_free(t_blinkenlights *x) +{ + post( "blinkenlights : freeing colors" ); + if ( x->x_background ) freebytes( x->x_background, 8 ); + if ( x->x_foreground ) freebytes( x->x_foreground, 8 ); + post( "blinkenlights : closing file" ); + blinkenlights_close(x); + post( "blinkenlights : cancelling clock" ); + if ( x->x_clock != NULL ) + { + clock_unset( x->x_clock ); + clock_free( x->x_clock ); + } + if ( x->x_clock2 != NULL ) + { + clock_unset( x->x_clock2 ); + clock_free( x->x_clock2 ); + } + post( "blinkenlights : done" ); +} + +static void *blinkenlights_new(t_float fwidth, t_float fheight, t_float fxpixsize, t_float fypixsize ) +{ + t_blinkenlights *x = (t_blinkenlights *)pd_new(blinkenlights_class); + if ( fwidth <= 0 ) { + post( "blinkenlights: wrong creation argument : width : %f", fwidth ); + return NULL; + } + if ( fheight <= 0 ) { + post( "blinkenlights: wrong creation argument : height : %f", fheight ); + return NULL; + } + if ( fxpixsize <= 0 ) { + post( "blinkenlights: wrong creation argument : x pixel size : %f", fxpixsize ); + return NULL; + } + if ( fypixsize <= 0 ) { + post( "blinkenlights: wrong creation argument : y pixel size : %f", fypixsize ); + return NULL; + } + x->x_width = (int) fwidth; + x->x_height = (int) fheight; + x->x_xsize = (int) fxpixsize; + x->x_ysize = (int) fypixsize; + x->x_ecanvas = 0; + x->x_filed = NULL; + x->x_frame = NULL; + x->x_clock = NULL; + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_background = (char*) getbytes( 8 ); + strncpy( x->x_background, BL_BACKGROUND_COLOR, 7 ); + x->x_background[7] = '\0'; + x->x_foreground = (char*) getbytes( 8 ); + strncpy( x->x_foreground, BL_FOREGROUND_COLOR, 7 ); + x->x_foreground[7] = '\0'; + x->x_timer2 = 40; + x->frame_inc = 0; + + x->outlet_bang = outlet_new(&x->x_obj, &s_bang); + + return(x); +} + +static void blinkenlights_draw_new(t_blinkenlights* x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int xi, yi; + + SYS_VGUI4("toplevel .x%x -width %d -height %d -borderwidth 0 -background #000000\n", x, + x->x_width*x->x_xsize, x->x_height*x->x_ysize ); + SYS_VGUI2("frame .x%x.m -relief raised -bd 2\n", x); + SYS_VGUI2("wm title .x%x blinkenlights\n", x); + + SYS_VGUI4("canvas .x%x.c -width %d -height %d\n", + x, + x->x_width*x->x_xsize, x->x_height*x->x_ysize ); + x->x_ecanvas = 1; + + for ( xi=1; xi<=x->x_width; xi++ ) + { + for ( yi=1; yi<=x->x_height; yi++ ) + { + SYS_VGUI10(".x%x.c create rectangle %d %d %d %d -fill %s -outline #555555 -tags %xPIX%.5d%.5d\n", + x, + (xi-1)*x->x_xsize, (yi-1)*x->x_ysize, + xi*x->x_xsize, yi*x->x_ysize, + x->x_background, + x, xi, yi); + } + } + + SYS_VGUI2("pack .x%x.c -side left -expand 1 -fill both\n", x); + SYS_VGUI2("pack .x%x.m -side top -fill x\n", x); + SYS_VGUI2("wm geometry .x%x +0+0\n", x); + SYS_VGUI2("wm geometry .x%x +0+0\n", x); + +} + +static void blinkenlights_create(t_blinkenlights* x) +{ + + if ( x->x_ecanvas ) + { + post("blinkenlights : create : canvas already exists" ); + return; + } + + blinkenlights_draw_new(x); + +} + +static void blinkenlights_erase(t_blinkenlights* x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int xi, yi; + + for ( xi=1; xi<=x->x_width; xi++ ) + { + for ( yi=1; yi<=x->x_height; yi++ ) + { + SYS_VGUI5(".x%x.c delete %xPIX%.5d%.5d\n", x, x, xi, yi); + } + } + SYS_VGUI2("destroy .x%x\n", x); + x->x_ecanvas=0; +} + +static void blinkenlights_destroy(t_blinkenlights* x) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : destroy : canvas does not exist" ); + return; + } + + blinkenlights_erase(x); +} + +static void blinkenlights_width(t_blinkenlights* x, t_float fwidth) +{ + if ( fwidth <= 0 ) { + post( "blinkenlights~: wrong width : ignored" ); + return; + } else { + if ( x->x_width == (int)fwidth ) return; + x->x_width=(int)fwidth; + } + if (x->x_ecanvas) blinkenlights_erase( x ); + blinkenlights_draw_new( x ); +} + +static void blinkenlights_height(t_blinkenlights* x, t_float fheight) +{ + if ( fheight <= 0 ) { + post( "blinkenlights~: wrong height : ignored" ); + return; + } else { + if ( x->x_height == (int)fheight ) return; + x->x_height=(int)fheight; + } + if (x->x_ecanvas) blinkenlights_erase( x ); + blinkenlights_draw_new( x ); +} + +static void blinkenlights_xsize(t_blinkenlights* x, t_float fxsize) +{ + if ( fxsize <= 0 ) { + post( "blinkenlights~: wrong x pixel size : ignored" ); + return; + } else { + if ( x->x_xsize == (int)fxsize ) return; + x->x_xsize=(int)fxsize; + } + if (x->x_ecanvas) blinkenlights_erase( x ); + blinkenlights_draw_new( x ); +} + +static void blinkenlights_ysize(t_blinkenlights* x, t_float fysize) +{ + if ( fysize <= 0 ) { + post( "blinkenlights~: wrong y pixel size : ignored" ); + return; + } else { + if ( x->x_ysize == (int)fysize ) return; + x->x_ysize=(int)fysize; + } + if (x->x_ecanvas) blinkenlights_erase( x ); + blinkenlights_draw_new( x ); +} + +static void blinkenlights_background(t_blinkenlights* x, t_float fR, t_float fG, t_float fB) +{ + if ( fR <0 || fR>255 ) + { + post("blinkenlights : wrong color component : fR : %d", fR); + return; + } + if ( fG <0 || fG>255 ) + { + post("blinkenlights : wrong color component : fG : %d", fG); + return; + } + if ( fB <0 || fB>255 ) + { + post("blinkenlights : wrong color component : fB : %d", fB); + return; + } + sprintf( x->x_background, "#%.2x%.2x%.2x", (int)fR, (int)fG, (int)fB ); + post("blinkenlights : background color set to : %s", x->x_background ); +} + +static void blinkenlights_foreground(t_blinkenlights* x, t_float fR, t_float fG, t_float fB) +{ + if ( fR <0 || fR>255 ) + { + post("blinkenlights : wrong color component : fR : %d", fR); + return; + } + if ( fG <0 || fG>255 ) + { + post("blinkenlights : wrong color component : fG : %d", fG); + return; + } + if ( fB <0 || fB>255 ) + { + post("blinkenlights : wrong color component : fB : %d", fB); + return; + } + sprintf( x->x_foreground, "#%.2x%.2x%.2x", (int)fR, (int)fG, (int)fB ); + post("blinkenlights : foreground color set to : %s", x->x_foreground ); +} + +static void blinkenlights_pixon(t_blinkenlights* x, t_float fX, t_float fY) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : pixon : canvas does not exist" ); + return; + } + if ( fX<1 || fX>x->x_width ) + { + post("blinkenlights : pixon : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); + return; + } + if ( fY<1 || fY>x->x_height ) + { + post("blinkenlights : pixon : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); + return; + } + SYS_VGUI6(".x%x.c itemconfigure %xPIX%.5d%.5d -fill %s\n", x, x, (int)fX, (int)fY, x->x_foreground ); +} + +static void blinkenlights_pixoff(t_blinkenlights* x, t_float fX, t_float fY) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : pixoff : canvas does not exist" ); + return; + } + if ( fX<1 || fX>x->x_width ) + { + post("blinkenlights : pixoff : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); + return; + } + if ( fY<1 || fY>x->x_height ) + { + post("blinkenlights : pixoff : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); + return; + } + SYS_VGUI6(".x%x.c itemconfigure %xPIX%.5d%.5d -fill %s\n", x, x, (int)fX, (int)fY, x->x_background ); +} + +static void blinkenlights_pixel(t_blinkenlights* x, t_float fX, t_float fY, t_float fR, t_float fG, t_float fB) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : pixel : canvas does not exist" ); + return; + } + if ( fX<1 || fX>x->x_width ) + { + post("blinkenlights : pixel : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); + return; + } + if ( fY<1 || fY>x->x_height ) + { + post("blinkenlights : pixel : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); + return; + } + if ( fR <0 || fR>255 ) + { + post("blinkenlights : pixel : wrong color component : fR : %d", fR); + return; + } + if ( fG <0 || fG>255 ) + { + post("blinkenlights : pixel : wrong color component : fG : %d", fG); + return; + } + if ( fB <0 || fB>255 ) + { + post("blinkenlights : pixel : wrong color component : fB : %d", fB); + return; + } + SYS_VGUI8(".x%x.c itemconfigure %xPIX%.5d%.5d -fill #%.2X%.2X%.2X\n", x, x, (int)fX, (int)fY, (int)fR, (int)fG, (int)fB ); +} + +static void blinkenlights_clear(t_blinkenlights* x) +{ + t_int xi, yi; + + for ( xi=1; xi<=x->x_width; xi++ ) + { + for ( yi=1; yi<=x->x_height; yi++ ) + { + blinkenlights_pixoff( x, xi, yi ); + } + } +} + + /* close the current movie */ +static void blinkenlights_close(t_blinkenlights *x) +{ + /* closing previous file descriptor */ + if ( x->x_filed != NULL ) { + if(fclose(x->x_filed) < 0) + { + perror( "blinkenlights : closing file" ); + } + x->x_filed = NULL; + } + if ( x->x_frame ) + { + freebytes( x->x_frame, x->x_width*x->x_height*sizeof(t_int) ); + x->x_frame = NULL; + } +} + + /* read the next frame */ +static void blinkenlights_readframe(t_blinkenlights *x) +{ + char *lineread = (char*) getbytes( BL_MAX_LENGTH ); + t_int flineno = 0; + t_int width, height, nwidth; + + //post( "blinkenlights: being readframe:>%s<", lineread ); + + if ( !x->x_ecanvas ) + { + post("blinkenlights : next : canvas does not exist" ); + return; + } + + if ( x->x_filed == NULL ) + { + post( "blinkenlights : no file is opened for reading a frame" ); + blinkenlights_close(x); + return; + } + + // skip header and empty lines + while ( lineread[0] == '#' || lineread[0] == '\n' || lineread[0] == '\0' ) + { + + //post( "blinkenlights : skipped line : >%s<", lineread ); + if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == 0 ) + { + post( "blinkenlights : end of file detected : looping..." ); + fseek( x->x_filed, 0L, SEEK_SET ); + outlet_bang(x->outlet_bang); + } + } + + if ( lineread[0] != '@' ) + { + post( "blinkenlights : format error : should find a time lime here : @XXX : got : >%s<", lineread ); + blinkenlights_close(x); + return; + } + else + { + x->x_timer = atoi( lineread+1 ); + // post( "blinkenlights : setting timer to %d", x->x_timer ); + } + + // read the contents of one frame + + // when reading first frame the height and width are read from the file + height = 0; + width = 0; + while ( 1 ) + { + + if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == NULL ) + { + post( "blinkenlights : EOF not expected here !!! "); + blinkenlights_close(x); + return; + } + else + { + if ( (lineread[0] == '\0') || (lineread[0] == '#') || (lineread[0] == '\n') ) break; + // post( "blinkenlights : lineread : %s", lineread ); + + nwidth = strlen( lineread )-1; // because of the carriage return + flineno++; + height = flineno; + if ( ( nwidth != width ) && ( width != 0 ) ) + { + post( "blinkenlights : weird file : width has changed (nwidth=%d) (width=%d)", nwidth, width ); + blinkenlights_close( x ); + return; + } + width = nwidth; + if ( x->x_frame != NULL ) + { + t_int pint = 0; + t_int newvalue; + + while ( pint < width ) + { + newvalue = (int) *(lineread+pint) - 48 /* ascii value for '0' */; + if ( newvalue != *(x->x_frame+(flineno-1)*x->x_width+pint ) ) + { + *(x->x_frame+(flineno-1)*x->x_width+pint ) = newvalue; + switch ( newvalue ) + { + case 0: + // post( "pixoff %d %d", pint+1, flineno ); + blinkenlights_pixoff( x, pint+1, flineno ); + break; + case 1: + // post( "pixon %d %d", pint+1, flineno ); + blinkenlights_pixon( x, pint+1, flineno ); + break; + default: + // post("blinkenlights : wrong value found for pixel : %d (c=%c)", newvalue, *(lineread+pint) ); + break; + } + } + pint++; + } + } + if ( x->x_frame == NULL ) x->x_height++; + } + } + if ( x->x_frame == NULL ) + { + if ( x->x_filed != NULL ) if ( fseek(x->x_filed, 0L, SEEK_SET) < 0 ) + { + post( "blinkenlights : could not rewind file" ); + blinkenlights_close( x ); + return; + } + blinkenlights_width(x, width); + blinkenlights_height(x, height); + x->x_frame = ( t_int* ) getbytes( x->x_width*x->x_height*sizeof(t_int) ); + blinkenlights_readframe(x); + } + + if ( lineread ) freebytes( lineread, BL_MAX_LENGTH ); +} +//------------------------------------------------------------------------- +//--chun's functions begin here... +//------------------------------------------------------------------------- +/* remember all the frame positions */ +static void blinkenlights_findframes(t_blinkenlights *x) +{ + int i =0; + + x->frame_no = 0; + + for(i=0;;i++) + { + char *lineread = (char*) getbytes( BL_MAX_LENGTH ); + + fgets( lineread, BL_MAX_LENGTH, x->x_filed ); + if(strlen(lineread) == 0) break; + + if(lineread[0] == '@') + { + x->frame_pos[x->frame_no] = ftell(x->x_filed); + x->frame_no++; + } + if (lineread) freebytes( lineread, BL_MAX_LENGTH ); + } + fseek( x->x_filed, 0L, SEEK_SET ); + post("the end:: %d frames!", x->frame_no); +} + +//------------------------------------------------------------------------- +static void blinkenlights_goto(t_blinkenlights* x) +{ + //char *lineread = (char*) getbytes( BL_MAX_LENGTH ); + char lineread[BL_MAX_LENGTH]; + int current_frame = x->frame_pos[(int)(x->frame_inc * (x->frame_no-1))]; + int i, n, width, newvalue, height, nwidth; + + t_int flineno = 0; + + fseek(x->x_filed, current_frame, SEEK_SET); + + height = 0; + width = 0; + while ( 1 ) + { + + if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == NULL ) + { + post( "blinkenlights : EOF not expected here !!! "); + blinkenlights_close(x); + return; + } + else + { + if ( (lineread[0] == '\0') || (lineread[0] == '#') || (lineread[0] == '\n') ) break; + // post( "blinkenlights : lineread : %s", lineread ); + + nwidth = strlen( lineread )-1; // because of the carriage return + flineno++; + height = flineno; + if ( ( nwidth != width ) && ( width != 0 ) ) + { + post( "blinkenlights : weird file : width has changed (nwidth=%d) (width=%d)", nwidth, width ); + blinkenlights_close( x ); + return; + } + width = nwidth; + if ( x->x_frame != NULL ) + { + t_int pint = 0; + t_int newvalue; + + while ( pint < width ) + { + newvalue = (int) *(lineread+pint) - 48 /* ascii value for '0' */; + if ( newvalue != *(x->x_frame+(flineno-1)*x->x_width+pint ) ) + { + *(x->x_frame+(flineno-1)*x->x_width+pint ) = newvalue; + switch ( newvalue ) + { + case 0: + // post( "pixoff %d %d", pint+1, flineno ); + blinkenlights_pixoff( x, pint+1, flineno ); + break; + case 1: + // post( "pixon %d %d", pint+1, flineno ); + blinkenlights_pixon( x, pint+1, flineno ); + break; + default: + // post("blinkenlights : wrong value found for pixel : %d (c=%c)", newvalue, *(lineread+pint) ); + break; + } + } + pint++; + } + } + if ( x->x_frame == NULL ) x->x_height++; + } + } + if ( x->x_frame == NULL ) + { + if ( x->x_filed != NULL ) if ( fseek(x->x_filed, 0L, SEEK_SET) < 0 ) + { + post( "blinkenlights : could not rewind file" ); + blinkenlights_close( x ); + return; + } + blinkenlights_width(x, width); + blinkenlights_height(x, height); + x->x_frame = ( t_int* ) getbytes( x->x_width*x->x_height*sizeof(t_int) ); + blinkenlights_readframe(x); + } + +} + +static void blinkenlights_frame_pos(t_blinkenlights* x, t_float pos) +{ + if(pos > 1 | pos < 0) post ("dude, don't be crazy!"); + else x->frame_inc = pos;; + //post("frame %d", x->frame_inc); +} + +static void blinkenlights_timer2(t_blinkenlights* x, t_float timer) +{ + x->x_timer2 = timer; + //post("frame %d", x->frame_inc); +} + + /* open movie */ +static void blinkenlights_open(t_blinkenlights *x, t_symbol *sfile) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : open : canvas does not exist" ); + return; + } + + //---------------------------------- + /* closing previous file descriptor */ + if ( x->x_filed != NULL ) { + if(fclose(x->x_filed) < 0) + { + perror( "blinkenlights : closing file" ); + } + x->x_filed = NULL; + } + if ( x->x_frame ) + { + blinkenlights_clear(x); + } + + //-------------------------------- + + if ( ( x->x_filed = fopen( sfile->s_name, "r" ) ) == NULL ) + { + error( "blinkenlights : cannot open >%s<", sfile->s_name); + return; + } + post( "blinkenlights : opened >%s<", sfile->s_name); + // don't read the first frame when open.. + //blinkenlights_readframe(x); + blinkenlights_findframes(x); +} + + /* play frames */ +static void blinkenlights_playframes(t_blinkenlights *x) +{ + blinkenlights_readframe( x ); + clock_delay( x->x_clock, (double)x->x_timer ); +} + +/* play frames2 */ +static void blinkenlights_playframes2(t_blinkenlights *x) +{ + blinkenlights_goto(x); + clock_delay( x->x_clock2, (double)x->x_timer2 ); +} + + /* play movie */ +static void blinkenlights_play(t_blinkenlights *x) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : play : canvas does not exist" ); + return; + } + + if ( x->x_filed == NULL ) + { + post( "blinkenlights : no file is opened for playing" ); + blinkenlights_close(x); + return; + } + + if ( x->x_clock == NULL ) x->x_clock = clock_new( x, (t_method)blinkenlights_playframes); + clock_delay( x->x_clock, (double)x->x_timer ); +} + + /* vj movie */ +static void blinkenlights_vj(t_blinkenlights *x, t_float start_vj) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : play : canvas does not exist" ); + return; + } + + if ( x->x_filed == NULL ) + { + post( "blinkenlights : no file is opened for playing" ); + blinkenlights_close(x); + return; + } + + if(start_vj) + { + if ( x->x_clock2 == NULL ) x->x_clock2 = clock_new( x, (t_method)blinkenlights_playframes2); + clock_delay( x->x_clock2, (double)x->x_timer2 ); + } + else + { + clock_unset( x->x_clock2 ); + } +} + + /* stop movie */ +static void blinkenlights_stop(t_blinkenlights *x) +{ + if ( !x->x_ecanvas ) + { + post("blinkenlights : play : canvas does not exist" ); + return; + } + + if ( x->x_filed == NULL ) + { + post( "blinkenlights : no file is opened for playing" ); + blinkenlights_close(x); + return; + } + + if ( x->x_clock != NULL ) + { + clock_unset( x->x_clock ); + } +} + + /* jump to next frame */ +static void blinkenlights_next(t_blinkenlights *x) +{ + blinkenlights_readframe(x); +} + +void blinkenlights_setup(void) +{ + post(blinkenlights_version); + blinkenlights_class = class_new(gensym("blinkenlights"), (t_newmethod)blinkenlights_new, + (t_method)blinkenlights_free, + sizeof(t_blinkenlights), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_width, gensym("width"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_height, gensym("height"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_xsize, gensym("xsize"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_ysize, gensym("ysize"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_open, gensym("open"), A_SYMBOL, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_create, gensym("create"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_destroy, gensym("destroy"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_next, gensym("next"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_play, gensym("play"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_stop, gensym("stop"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_frame_pos, gensym("goto"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_vj, gensym("vj"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_timer2, gensym("timer2"), A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_background, gensym("background"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_foreground, gensym("foreground"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_destroy, gensym("destroy"), 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixon, gensym("pixon"), A_FLOAT, A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixoff, gensym("pixoff"), A_FLOAT, A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixel, gensym("pixel"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod( blinkenlights_class, (t_method)blinkenlights_clear, gensym("clear"), 0); +} diff --git a/blinkenlights/INSTALL b/blinkenlights/INSTALL deleted file mode 100644 index 218e125..0000000 --- a/blinkenlights/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/blinkenlights - -make clean - -make - -make install - -open help-blinkenlights.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/blinkenlights/blinkenlights-help.pd b/blinkenlights/blinkenlights-help.pd deleted file mode 100644 index 32baca0..0000000 --- a/blinkenlights/blinkenlights-help.pd +++ /dev/null @@ -1,156 +0,0 @@ -#N canvas 484 81 885 735 10; -#X text 334 640 Part of unauthorized PD; -#X text 480 570 blinkenlights is a blinkenlights movies player; -#X text 480 584 but it's also a pixel grid than you can use for ASCII -art...; -#X text 480 600 Constructor : blinkenlights ; -#X msg 125 10 create; -#X msg 182 10 destroy; -#X text 274 11 Create/destroy the window; -#X msg 125 129 background 78 34 12; -#X text 275 131 Set the background color [RGB]; -#X text 275 154 Set the foreground color [RGB]; -#X msg 121 223 pixon \$1 \$2; -#X msg 284 222 bang; -#X msg 285 266 bang; -#X msg 122 267 pixoff \$1 \$2; -#X obj 87 618 blinkenlights 18 8 32 32; -#X msg 125 152 foreground 124 78 89; -#X obj 347 277 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X obj 336 250 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 0 1; -#X text 355 257 Set a pixel off; -#X text 352 213 Set a pixel on; -#X obj 346 232 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 1600 1; -#X obj 335 205 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 1400 1; -#X msg 338 309 bang; -#X obj 400 320 hsl 32 8 1 32 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X obj 389 293 vsl 8 32 1 32 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 0 1; -#X text 410 303 Set a pixel in a particular color; -#X msg 118 310 pixel \$1 \$2 34 23 109; -#X obj 120 338 + 1; -#X obj 217 338 + 1; -#X obj 316 338 random 255; -#X obj 395 338 random 255; -#X obj 470 338 random 255; -#X msg 118 360 pixel \$1 \$2 \$3 \$4 \$5; -#X obj 267 359 pack f f f f f; -#X obj 464 360 t b b b b b; -#X msg 593 339 stop; -#X text 634 342 Random drawing; -#X msg 547 339 bang; -#X obj 548 360 metro 10; -#X obj 146 338 random 32; -#X obj 246 337 random 32; -#X msg 125 107 clear; -#X text 274 105 Clear the area; -#X text 122 187 ============================================ Pixel -Functions; -#X text 552 187 ========================================; -#X text 550 -6 ========================================; -#X text 539 472 ========================================; -#X text 112 472 =========================================== Movies -Functions; -#X text 122 -6 =========================================== Grid Actions -; -#X obj 214 222 pack f f; -#X obj 215 266 pack f f; -#X obj 275 310 pack f f; -#X msg 125 81 xsize 32; -#X msg 192 81 ysize 32; -#X text 274 79 Set the pixel x & y size; -#X msg 127 33 width 24; -#X msg 125 58 height 24; -#X text 275 37 Set the width ( number of pixels ); -#X text 275 56 Set the height ( number of pixels ); -#X msg 127 495 open ./blm/ascii_people.blm; -#X msg 335 495 play; -#X msg 377 495 stop; -#X msg 127 522 open \$1; -#X msg 418 495 next; -#X obj 458 494 metro 100; -#X msg 531 495 bang; -#X msg 571 494 stop; -#X obj 188 521 openpanel; -#X obj 261 522 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X floatatom 615 495 5 0 0 0 - - -; -#X text 534 401 ========================================; -#X text 116 400 =============================================== VJ -function; -#X msg 132 444 vj \$1; -#X msg 363 444 goto \$1; -#X obj 366 423 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 5600 1; -#X obj 132 424 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X text 507 420 <- look! you can also scratch the film!; -#X text 530 434 be sure the window is created first....; -#X text 154 420 <- switch to the scratch mode; -#X text 333 654 Comments and bugs @ ydegoyon@free.fr and chun@goto10.org -; -#X connect 4 0 14 0; -#X connect 5 0 14 0; -#X connect 7 0 14 0; -#X connect 10 0 14 0; -#X connect 11 0 49 0; -#X connect 12 0 50 0; -#X connect 13 0 14 0; -#X connect 15 0 14 0; -#X connect 16 0 50 0; -#X connect 17 0 12 0; -#X connect 17 0 50 1; -#X connect 20 0 49 0; -#X connect 21 0 11 0; -#X connect 21 0 49 1; -#X connect 22 0 51 0; -#X connect 23 0 51 0; -#X connect 24 0 22 0; -#X connect 24 0 51 1; -#X connect 26 0 14 0; -#X connect 27 0 33 0; -#X connect 28 0 33 1; -#X connect 29 0 33 2; -#X connect 30 0 33 3; -#X connect 31 0 33 4; -#X connect 32 0 14 0; -#X connect 33 0 32 0; -#X connect 34 0 39 0; -#X connect 34 1 40 0; -#X connect 34 2 29 0; -#X connect 34 3 30 0; -#X connect 34 4 31 0; -#X connect 35 0 38 0; -#X connect 37 0 38 0; -#X connect 38 0 34 0; -#X connect 39 0 27 0; -#X connect 40 0 28 0; -#X connect 41 0 14 0; -#X connect 49 0 10 0; -#X connect 50 0 13 0; -#X connect 51 0 26 0; -#X connect 52 0 14 0; -#X connect 53 0 14 0; -#X connect 55 0 14 0; -#X connect 56 0 14 0; -#X connect 59 0 14 0; -#X connect 60 0 14 0; -#X connect 61 0 14 0; -#X connect 62 0 14 0; -#X connect 63 0 14 0; -#X connect 64 0 63 0; -#X connect 65 0 64 0; -#X connect 66 0 64 0; -#X connect 67 0 62 0; -#X connect 68 0 67 0; -#X connect 69 0 64 1; -#X connect 72 0 14 0; -#X connect 73 0 14 0; -#X connect 74 0 73 0; -#X connect 75 0 72 0; diff --git a/blinkenlights/blinkenlights.c b/blinkenlights/blinkenlights.c deleted file mode 100644 index 03abda9..0000000 --- a/blinkenlights/blinkenlights.c +++ /dev/null @@ -1,869 +0,0 @@ -/* ---------------------- blinkenlights~ -------------------------------------- */ -/* */ -/* Blinkenlights is a BL movies player but also a pixel grid */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Currently listening : */ -/* Pop Group : We Are All Prostitutes */ -/* Culturcide : Bruce */ -/* ---------------------------------------------------------------------------- */ - -//added functions: -//"static void blinkenlights_findframes(t_blinkenlights *x)" -//this is to remember the frame positions in the .blm file - -//"static void blinkenlights_goto(t_blinkenlights* x, t_float frame)" -//with a "goto $1" message, you can stratch the blm film. note that the -//range of $1 is 0 to 1 - - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#include -#include -#include - -#include "m_pd.h" /* standard pd stuff */ -#include "g_canvas.h" /* some pd's graphical functions */ - -static char *blinkenlights_version = "blinkenlights: a blinkenlights movies player version 0.2 ( bugs @ ydegoyon@free.fr and chun@goto10.org )"; - -static int guidebug=0; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i);\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j);\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define BL_BACKGROUND_COLOR "#000000" -#define BL_FOREGROUND_COLOR "#00FF00" -#define BL_MAX_LENGTH 1024 - -static t_class *blinkenlights_class; - -typedef struct _blinkenlights -{ - t_object x_obj; - t_int x_width; /* number of pixels ( width ) */ - t_int x_height; /* number of pixels ( height) */ - t_int x_xsize; /* x size of each pixel */ - t_int x_ysize; /* y size of each pixel */ - char *x_background; /* color of the background #RRGGBB */ - char *x_foreground; /* color of the foreground #RRGGBB */ - t_int x_ecanvas; /* flag that indicates if the canvas has been created */ - t_glist *x_glist; /* graphic context */ - FILE *x_filed; /* file descriptor */ - t_int x_timer; /* timer read from bl movie */ - t_int *x_frame; /* frame contents */ - t_clock *x_clock; /* clock used for reading frames */ - t_outlet *outlet_bang; - t_int frame_no; - t_int frame_pos[BL_MAX_LENGTH]; - t_clock *x_clock2; - t_int x_timer2; - t_float frame_inc; - -} t_blinkenlights; - -static void blinkenlights_close(t_blinkenlights *x); - - /* clean up */ -static void blinkenlights_free(t_blinkenlights *x) -{ - post( "blinkenlights : freeing colors" ); - if ( x->x_background ) freebytes( x->x_background, 8 ); - if ( x->x_foreground ) freebytes( x->x_foreground, 8 ); - post( "blinkenlights : closing file" ); - blinkenlights_close(x); - post( "blinkenlights : cancelling clock" ); - if ( x->x_clock != NULL ) - { - clock_unset( x->x_clock ); - clock_free( x->x_clock ); - } - if ( x->x_clock2 != NULL ) - { - clock_unset( x->x_clock2 ); - clock_free( x->x_clock2 ); - } - post( "blinkenlights : done" ); -} - -static void *blinkenlights_new(t_float fwidth, t_float fheight, t_float fxpixsize, t_float fypixsize ) -{ - t_blinkenlights *x = (t_blinkenlights *)pd_new(blinkenlights_class); - if ( fwidth <= 0 ) { - post( "blinkenlights: wrong creation argument : width : %f", fwidth ); - return NULL; - } - if ( fheight <= 0 ) { - post( "blinkenlights: wrong creation argument : height : %f", fheight ); - return NULL; - } - if ( fxpixsize <= 0 ) { - post( "blinkenlights: wrong creation argument : x pixel size : %f", fxpixsize ); - return NULL; - } - if ( fypixsize <= 0 ) { - post( "blinkenlights: wrong creation argument : y pixel size : %f", fypixsize ); - return NULL; - } - x->x_width = (int) fwidth; - x->x_height = (int) fheight; - x->x_xsize = (int) fxpixsize; - x->x_ysize = (int) fypixsize; - x->x_ecanvas = 0; - x->x_filed = NULL; - x->x_frame = NULL; - x->x_clock = NULL; - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_background = (char*) getbytes( 8 ); - strncpy( x->x_background, BL_BACKGROUND_COLOR, 7 ); - x->x_background[7] = '\0'; - x->x_foreground = (char*) getbytes( 8 ); - strncpy( x->x_foreground, BL_FOREGROUND_COLOR, 7 ); - x->x_foreground[7] = '\0'; - x->x_timer2 = 40; - x->frame_inc = 0; - - x->outlet_bang = outlet_new(&x->x_obj, &s_bang); - - return(x); -} - -static void blinkenlights_draw_new(t_blinkenlights* x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int xi, yi; - - SYS_VGUI4("toplevel .x%x -width %d -height %d -borderwidth 0 -background #000000\n", x, - x->x_width*x->x_xsize, x->x_height*x->x_ysize ); - SYS_VGUI2("frame .x%x.m -relief raised -bd 2\n", x); - SYS_VGUI2("wm title .x%x blinkenlights\n", x); - - SYS_VGUI4("canvas .x%x.c -width %d -height %d\n", - x, - x->x_width*x->x_xsize, x->x_height*x->x_ysize ); - x->x_ecanvas = 1; - - for ( xi=1; xi<=x->x_width; xi++ ) - { - for ( yi=1; yi<=x->x_height; yi++ ) - { - SYS_VGUI10(".x%x.c create rectangle %d %d %d %d -fill %s -outline #555555 -tags %xPIX%.5d%.5d\n", - x, - (xi-1)*x->x_xsize, (yi-1)*x->x_ysize, - xi*x->x_xsize, yi*x->x_ysize, - x->x_background, - x, xi, yi); - } - } - - SYS_VGUI2("pack .x%x.c -side left -expand 1 -fill both\n", x); - SYS_VGUI2("pack .x%x.m -side top -fill x\n", x); - SYS_VGUI2("wm geometry .x%x +0+0\n", x); - SYS_VGUI2("wm geometry .x%x +0+0\n", x); - -} - -static void blinkenlights_create(t_blinkenlights* x) -{ - - if ( x->x_ecanvas ) - { - post("blinkenlights : create : canvas already exists" ); - return; - } - - blinkenlights_draw_new(x); - -} - -static void blinkenlights_erase(t_blinkenlights* x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int xi, yi; - - for ( xi=1; xi<=x->x_width; xi++ ) - { - for ( yi=1; yi<=x->x_height; yi++ ) - { - SYS_VGUI5(".x%x.c delete %xPIX%.5d%.5d\n", x, x, xi, yi); - } - } - SYS_VGUI2("destroy .x%x\n", x); - x->x_ecanvas=0; -} - -static void blinkenlights_destroy(t_blinkenlights* x) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : destroy : canvas does not exist" ); - return; - } - - blinkenlights_erase(x); -} - -static void blinkenlights_width(t_blinkenlights* x, t_float fwidth) -{ - if ( fwidth <= 0 ) { - post( "blinkenlights~: wrong width : ignored" ); - return; - } else { - if ( x->x_width == (int)fwidth ) return; - x->x_width=(int)fwidth; - } - if (x->x_ecanvas) blinkenlights_erase( x ); - blinkenlights_draw_new( x ); -} - -static void blinkenlights_height(t_blinkenlights* x, t_float fheight) -{ - if ( fheight <= 0 ) { - post( "blinkenlights~: wrong height : ignored" ); - return; - } else { - if ( x->x_height == (int)fheight ) return; - x->x_height=(int)fheight; - } - if (x->x_ecanvas) blinkenlights_erase( x ); - blinkenlights_draw_new( x ); -} - -static void blinkenlights_xsize(t_blinkenlights* x, t_float fxsize) -{ - if ( fxsize <= 0 ) { - post( "blinkenlights~: wrong x pixel size : ignored" ); - return; - } else { - if ( x->x_xsize == (int)fxsize ) return; - x->x_xsize=(int)fxsize; - } - if (x->x_ecanvas) blinkenlights_erase( x ); - blinkenlights_draw_new( x ); -} - -static void blinkenlights_ysize(t_blinkenlights* x, t_float fysize) -{ - if ( fysize <= 0 ) { - post( "blinkenlights~: wrong y pixel size : ignored" ); - return; - } else { - if ( x->x_ysize == (int)fysize ) return; - x->x_ysize=(int)fysize; - } - if (x->x_ecanvas) blinkenlights_erase( x ); - blinkenlights_draw_new( x ); -} - -static void blinkenlights_background(t_blinkenlights* x, t_float fR, t_float fG, t_float fB) -{ - if ( fR <0 || fR>255 ) - { - post("blinkenlights : wrong color component : fR : %d", fR); - return; - } - if ( fG <0 || fG>255 ) - { - post("blinkenlights : wrong color component : fG : %d", fG); - return; - } - if ( fB <0 || fB>255 ) - { - post("blinkenlights : wrong color component : fB : %d", fB); - return; - } - sprintf( x->x_background, "#%.2x%.2x%.2x", (int)fR, (int)fG, (int)fB ); - post("blinkenlights : background color set to : %s", x->x_background ); -} - -static void blinkenlights_foreground(t_blinkenlights* x, t_float fR, t_float fG, t_float fB) -{ - if ( fR <0 || fR>255 ) - { - post("blinkenlights : wrong color component : fR : %d", fR); - return; - } - if ( fG <0 || fG>255 ) - { - post("blinkenlights : wrong color component : fG : %d", fG); - return; - } - if ( fB <0 || fB>255 ) - { - post("blinkenlights : wrong color component : fB : %d", fB); - return; - } - sprintf( x->x_foreground, "#%.2x%.2x%.2x", (int)fR, (int)fG, (int)fB ); - post("blinkenlights : foreground color set to : %s", x->x_foreground ); -} - -static void blinkenlights_pixon(t_blinkenlights* x, t_float fX, t_float fY) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : pixon : canvas does not exist" ); - return; - } - if ( fX<1 || fX>x->x_width ) - { - post("blinkenlights : pixon : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); - return; - } - if ( fY<1 || fY>x->x_height ) - { - post("blinkenlights : pixon : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); - return; - } - SYS_VGUI6(".x%x.c itemconfigure %xPIX%.5d%.5d -fill %s\n", x, x, (int)fX, (int)fY, x->x_foreground ); -} - -static void blinkenlights_pixoff(t_blinkenlights* x, t_float fX, t_float fY) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : pixoff : canvas does not exist" ); - return; - } - if ( fX<1 || fX>x->x_width ) - { - post("blinkenlights : pixoff : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); - return; - } - if ( fY<1 || fY>x->x_height ) - { - post("blinkenlights : pixoff : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); - return; - } - SYS_VGUI6(".x%x.c itemconfigure %xPIX%.5d%.5d -fill %s\n", x, x, (int)fX, (int)fY, x->x_background ); -} - -static void blinkenlights_pixel(t_blinkenlights* x, t_float fX, t_float fY, t_float fR, t_float fG, t_float fB) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : pixel : canvas does not exist" ); - return; - } - if ( fX<1 || fX>x->x_width ) - { - post("blinkenlights : pixel : wrong x coordinate : %d : should be in [1,%d]", (int)fX, x->x_width ); - return; - } - if ( fY<1 || fY>x->x_height ) - { - post("blinkenlights : pixel : wrong y coordinate : %d : should be in [1,%d]", (int)fY, x->x_height ); - return; - } - if ( fR <0 || fR>255 ) - { - post("blinkenlights : pixel : wrong color component : fR : %d", fR); - return; - } - if ( fG <0 || fG>255 ) - { - post("blinkenlights : pixel : wrong color component : fG : %d", fG); - return; - } - if ( fB <0 || fB>255 ) - { - post("blinkenlights : pixel : wrong color component : fB : %d", fB); - return; - } - SYS_VGUI8(".x%x.c itemconfigure %xPIX%.5d%.5d -fill #%.2X%.2X%.2X\n", x, x, (int)fX, (int)fY, (int)fR, (int)fG, (int)fB ); -} - -static void blinkenlights_clear(t_blinkenlights* x) -{ - t_int xi, yi; - - for ( xi=1; xi<=x->x_width; xi++ ) - { - for ( yi=1; yi<=x->x_height; yi++ ) - { - blinkenlights_pixoff( x, xi, yi ); - } - } -} - - /* close the current movie */ -static void blinkenlights_close(t_blinkenlights *x) -{ - /* closing previous file descriptor */ - if ( x->x_filed != NULL ) { - if(fclose(x->x_filed) < 0) - { - perror( "blinkenlights : closing file" ); - } - x->x_filed = NULL; - } - if ( x->x_frame ) - { - freebytes( x->x_frame, x->x_width*x->x_height*sizeof(t_int) ); - x->x_frame = NULL; - } -} - - /* read the next frame */ -static void blinkenlights_readframe(t_blinkenlights *x) -{ - char *lineread = (char*) getbytes( BL_MAX_LENGTH ); - t_int flineno = 0; - t_int width, height, nwidth; - - //post( "blinkenlights: being readframe:>%s<", lineread ); - - if ( !x->x_ecanvas ) - { - post("blinkenlights : next : canvas does not exist" ); - return; - } - - if ( x->x_filed == NULL ) - { - post( "blinkenlights : no file is opened for reading a frame" ); - blinkenlights_close(x); - return; - } - - // skip header and empty lines - while ( lineread[0] == '#' || lineread[0] == '\n' || lineread[0] == '\0' ) - { - - //post( "blinkenlights : skipped line : >%s<", lineread ); - if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == 0 ) - { - post( "blinkenlights : end of file detected : looping..." ); - fseek( x->x_filed, 0L, SEEK_SET ); - outlet_bang(x->outlet_bang); - } - } - - if ( lineread[0] != '@' ) - { - post( "blinkenlights : format error : should find a time lime here : @XXX : got : >%s<", lineread ); - blinkenlights_close(x); - return; - } - else - { - x->x_timer = atoi( lineread+1 ); - // post( "blinkenlights : setting timer to %d", x->x_timer ); - } - - // read the contents of one frame - - // when reading first frame the height and width are read from the file - height = 0; - width = 0; - while ( 1 ) - { - - if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == NULL ) - { - post( "blinkenlights : EOF not expected here !!! "); - blinkenlights_close(x); - return; - } - else - { - if ( (lineread[0] == '\0') || (lineread[0] == '#') || (lineread[0] == '\n') ) break; - // post( "blinkenlights : lineread : %s", lineread ); - - nwidth = strlen( lineread )-1; // because of the carriage return - flineno++; - height = flineno; - if ( ( nwidth != width ) && ( width != 0 ) ) - { - post( "blinkenlights : weird file : width has changed (nwidth=%d) (width=%d)", nwidth, width ); - blinkenlights_close( x ); - return; - } - width = nwidth; - if ( x->x_frame != NULL ) - { - t_int pint = 0; - t_int newvalue; - - while ( pint < width ) - { - newvalue = (int) *(lineread+pint) - 48 /* ascii value for '0' */; - if ( newvalue != *(x->x_frame+(flineno-1)*x->x_width+pint ) ) - { - *(x->x_frame+(flineno-1)*x->x_width+pint ) = newvalue; - switch ( newvalue ) - { - case 0: - // post( "pixoff %d %d", pint+1, flineno ); - blinkenlights_pixoff( x, pint+1, flineno ); - break; - case 1: - // post( "pixon %d %d", pint+1, flineno ); - blinkenlights_pixon( x, pint+1, flineno ); - break; - default: - // post("blinkenlights : wrong value found for pixel : %d (c=%c)", newvalue, *(lineread+pint) ); - break; - } - } - pint++; - } - } - if ( x->x_frame == NULL ) x->x_height++; - } - } - if ( x->x_frame == NULL ) - { - if ( x->x_filed != NULL ) if ( fseek(x->x_filed, 0L, SEEK_SET) < 0 ) - { - post( "blinkenlights : could not rewind file" ); - blinkenlights_close( x ); - return; - } - blinkenlights_width(x, width); - blinkenlights_height(x, height); - x->x_frame = ( t_int* ) getbytes( x->x_width*x->x_height*sizeof(t_int) ); - blinkenlights_readframe(x); - } - - if ( lineread ) freebytes( lineread, BL_MAX_LENGTH ); -} -//------------------------------------------------------------------------- -//--chun's functions begin here... -//------------------------------------------------------------------------- -/* remember all the frame positions */ -static void blinkenlights_findframes(t_blinkenlights *x) -{ - int i =0; - - x->frame_no = 0; - - for(i=0;;i++) - { - char *lineread = (char*) getbytes( BL_MAX_LENGTH ); - - fgets( lineread, BL_MAX_LENGTH, x->x_filed ); - if(strlen(lineread) == 0) break; - - if(lineread[0] == '@') - { - x->frame_pos[x->frame_no] = ftell(x->x_filed); - x->frame_no++; - } - if (lineread) freebytes( lineread, BL_MAX_LENGTH ); - } - fseek( x->x_filed, 0L, SEEK_SET ); - post("the end:: %d frames!", x->frame_no); -} - -//------------------------------------------------------------------------- -static void blinkenlights_goto(t_blinkenlights* x) -{ - //char *lineread = (char*) getbytes( BL_MAX_LENGTH ); - char lineread[BL_MAX_LENGTH]; - int current_frame = x->frame_pos[(int)(x->frame_inc * (x->frame_no-1))]; - int i, n, width, newvalue, height, nwidth; - - t_int flineno = 0; - - fseek(x->x_filed, current_frame, SEEK_SET); - - height = 0; - width = 0; - while ( 1 ) - { - - if ( fgets( lineread, BL_MAX_LENGTH, x->x_filed ) == NULL ) - { - post( "blinkenlights : EOF not expected here !!! "); - blinkenlights_close(x); - return; - } - else - { - if ( (lineread[0] == '\0') || (lineread[0] == '#') || (lineread[0] == '\n') ) break; - // post( "blinkenlights : lineread : %s", lineread ); - - nwidth = strlen( lineread )-1; // because of the carriage return - flineno++; - height = flineno; - if ( ( nwidth != width ) && ( width != 0 ) ) - { - post( "blinkenlights : weird file : width has changed (nwidth=%d) (width=%d)", nwidth, width ); - blinkenlights_close( x ); - return; - } - width = nwidth; - if ( x->x_frame != NULL ) - { - t_int pint = 0; - t_int newvalue; - - while ( pint < width ) - { - newvalue = (int) *(lineread+pint) - 48 /* ascii value for '0' */; - if ( newvalue != *(x->x_frame+(flineno-1)*x->x_width+pint ) ) - { - *(x->x_frame+(flineno-1)*x->x_width+pint ) = newvalue; - switch ( newvalue ) - { - case 0: - // post( "pixoff %d %d", pint+1, flineno ); - blinkenlights_pixoff( x, pint+1, flineno ); - break; - case 1: - // post( "pixon %d %d", pint+1, flineno ); - blinkenlights_pixon( x, pint+1, flineno ); - break; - default: - // post("blinkenlights : wrong value found for pixel : %d (c=%c)", newvalue, *(lineread+pint) ); - break; - } - } - pint++; - } - } - if ( x->x_frame == NULL ) x->x_height++; - } - } - if ( x->x_frame == NULL ) - { - if ( x->x_filed != NULL ) if ( fseek(x->x_filed, 0L, SEEK_SET) < 0 ) - { - post( "blinkenlights : could not rewind file" ); - blinkenlights_close( x ); - return; - } - blinkenlights_width(x, width); - blinkenlights_height(x, height); - x->x_frame = ( t_int* ) getbytes( x->x_width*x->x_height*sizeof(t_int) ); - blinkenlights_readframe(x); - } - -} - -static void blinkenlights_frame_pos(t_blinkenlights* x, t_float pos) -{ - if(pos > 1 | pos < 0) post ("dude, don't be crazy!"); - else x->frame_inc = pos;; - //post("frame %d", x->frame_inc); -} - -static void blinkenlights_timer2(t_blinkenlights* x, t_float timer) -{ - x->x_timer2 = timer; - //post("frame %d", x->frame_inc); -} - - /* open movie */ -static void blinkenlights_open(t_blinkenlights *x, t_symbol *sfile) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : open : canvas does not exist" ); - return; - } - - //---------------------------------- - /* closing previous file descriptor */ - if ( x->x_filed != NULL ) { - if(fclose(x->x_filed) < 0) - { - perror( "blinkenlights : closing file" ); - } - x->x_filed = NULL; - } - if ( x->x_frame ) - { - blinkenlights_clear(x); - } - - //-------------------------------- - - if ( ( x->x_filed = fopen( sfile->s_name, "r" ) ) == NULL ) - { - error( "blinkenlights : cannot open >%s<", sfile->s_name); - return; - } - post( "blinkenlights : opened >%s<", sfile->s_name); - // don't read the first frame when open.. - //blinkenlights_readframe(x); - blinkenlights_findframes(x); -} - - /* play frames */ -static void blinkenlights_playframes(t_blinkenlights *x) -{ - blinkenlights_readframe( x ); - clock_delay( x->x_clock, (double)x->x_timer ); -} - -/* play frames2 */ -static void blinkenlights_playframes2(t_blinkenlights *x) -{ - blinkenlights_goto(x); - clock_delay( x->x_clock2, (double)x->x_timer2 ); -} - - /* play movie */ -static void blinkenlights_play(t_blinkenlights *x) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : play : canvas does not exist" ); - return; - } - - if ( x->x_filed == NULL ) - { - post( "blinkenlights : no file is opened for playing" ); - blinkenlights_close(x); - return; - } - - if ( x->x_clock == NULL ) x->x_clock = clock_new( x, (t_method)blinkenlights_playframes); - clock_delay( x->x_clock, (double)x->x_timer ); -} - - /* vj movie */ -static void blinkenlights_vj(t_blinkenlights *x, t_float start_vj) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : play : canvas does not exist" ); - return; - } - - if ( x->x_filed == NULL ) - { - post( "blinkenlights : no file is opened for playing" ); - blinkenlights_close(x); - return; - } - - if(start_vj) - { - if ( x->x_clock2 == NULL ) x->x_clock2 = clock_new( x, (t_method)blinkenlights_playframes2); - clock_delay( x->x_clock2, (double)x->x_timer2 ); - } - else - { - clock_unset( x->x_clock2 ); - } -} - - /* stop movie */ -static void blinkenlights_stop(t_blinkenlights *x) -{ - if ( !x->x_ecanvas ) - { - post("blinkenlights : play : canvas does not exist" ); - return; - } - - if ( x->x_filed == NULL ) - { - post( "blinkenlights : no file is opened for playing" ); - blinkenlights_close(x); - return; - } - - if ( x->x_clock != NULL ) - { - clock_unset( x->x_clock ); - } -} - - /* jump to next frame */ -static void blinkenlights_next(t_blinkenlights *x) -{ - blinkenlights_readframe(x); -} - -void blinkenlights_setup(void) -{ - post(blinkenlights_version); - blinkenlights_class = class_new(gensym("blinkenlights"), (t_newmethod)blinkenlights_new, - (t_method)blinkenlights_free, - sizeof(t_blinkenlights), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_width, gensym("width"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_height, gensym("height"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_xsize, gensym("xsize"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_ysize, gensym("ysize"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_open, gensym("open"), A_SYMBOL, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_create, gensym("create"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_destroy, gensym("destroy"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_next, gensym("next"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_play, gensym("play"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_stop, gensym("stop"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_frame_pos, gensym("goto"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_vj, gensym("vj"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_timer2, gensym("timer2"), A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_background, gensym("background"), A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_foreground, gensym("foreground"), A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_destroy, gensym("destroy"), 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixon, gensym("pixon"), A_FLOAT, A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixoff, gensym("pixoff"), A_FLOAT, A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_pixel, gensym("pixel"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod( blinkenlights_class, (t_method)blinkenlights_clear, gensym("clear"), 0); -} diff --git a/compressor~-help.pd b/compressor~-help.pd new file mode 100644 index 0000000..0b5d277 --- /dev/null +++ b/compressor~-help.pd @@ -0,0 +1,14 @@ +#N canvas 251 75 572 506 10; +#X obj 149 202 dac~; +#X obj 150 128 compressor~; +#X text 290 253 comments & bugs @ ydegoyon.free.fr; +#X text 243 19 Compressor~ : an audio compressor; +#X floatatom 259 86 5 -100 500; +#X obj 108 41 osc~ 250; +#X text 305 83 strength [ min : -1 \; max = 5 \; default = 0 ]; +#X obj 215 88 / 100; +#X connect 1 0 0 0; +#X connect 1 0 0 1; +#X connect 4 0 7 0; +#X connect 5 0 1 0; +#X connect 7 0 1 1; diff --git a/compressor~.c b/compressor~.c new file mode 100644 index 0000000..01204f3 --- /dev/null +++ b/compressor~.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* compressor~ -- compresses audio signal according to a factor */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* "I can't get you out of my head" */ +/* "Na, na, na, na, na, na, na, na, na, ...." */ +/* Kylie Minogue ( without Nick Cave ) */ +/* ---------------------------------------------------------------------------- */ + +#include "m_pd.h" +#include +#include + +static char *compressor_version = "compressor~: an audio compressor, version 0.1 (ydegoyon@free.fr)"; + +typedef struct _compressor +{ + t_object x_obj; + t_float x_strength; + t_float x_pifactor; + t_float x_f; +} t_compressor; + +static t_class *compressor_class; + +static void compressor_strength(t_compressor *x, t_floatarg fstrength ) +{ + if (fstrength < -1.0) + { + x->x_strength = -1.0; + } + else if (fstrength > 5) + { + x->x_strength = 5; + } + else + { + x->x_strength = fstrength; + } + x->x_pifactor = pow( M_PI, x->x_strength ); +} + +static void *compressor_new(void) +{ + t_compressor *x = (t_compressor *)pd_new(compressor_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("strength")); + x->x_strength = 0.; + x->x_pifactor = pow( M_PI, x->x_strength ); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static t_int *compressor_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); + t_compressor *x = (t_compressor*)(w[4]); + t_float isample_fact = x->x_pifactor; + t_float osample_fact = 2.0 / M_PI; + + while (n--) { + *out = atan (*in * isample_fact) * osample_fact; + out++; in++; + } + return (w+5); +} + +static void compressor_dsp(t_compressor *x, t_signal **sp) +{ + dsp_add(compressor_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); +} + +void compressor_tilde_setup(void) +{ + post( compressor_version ); + compressor_class = class_new(gensym("compressor~"), (t_newmethod)compressor_new, 0, + sizeof(t_compressor), 0, 0); + CLASS_MAINSIGNALIN( compressor_class, t_compressor, x_f ); + class_addmethod(compressor_class, (t_method)compressor_dsp, gensym("dsp"), 0); + class_addmethod(compressor_class, (t_method)compressor_strength, gensym("strength"), A_FLOAT, 0); +} diff --git a/compressor~/INSTALL b/compressor~/INSTALL deleted file mode 100644 index 8139fba..0000000 --- a/compressor~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/compressor~ - -make clean - -make - -make install - -open help-compressor~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/compressor~/compressor~-help.pd b/compressor~/compressor~-help.pd deleted file mode 100644 index 0b5d277..0000000 --- a/compressor~/compressor~-help.pd +++ /dev/null @@ -1,14 +0,0 @@ -#N canvas 251 75 572 506 10; -#X obj 149 202 dac~; -#X obj 150 128 compressor~; -#X text 290 253 comments & bugs @ ydegoyon.free.fr; -#X text 243 19 Compressor~ : an audio compressor; -#X floatatom 259 86 5 -100 500; -#X obj 108 41 osc~ 250; -#X text 305 83 strength [ min : -1 \; max = 5 \; default = 0 ]; -#X obj 215 88 / 100; -#X connect 1 0 0 0; -#X connect 1 0 0 1; -#X connect 4 0 7 0; -#X connect 5 0 1 0; -#X connect 7 0 1 1; diff --git a/compressor~/compressor~.c b/compressor~/compressor~.c deleted file mode 100644 index 01204f3..0000000 --- a/compressor~/compressor~.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* compressor~ -- compresses audio signal according to a factor */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* "I can't get you out of my head" */ -/* "Na, na, na, na, na, na, na, na, na, ...." */ -/* Kylie Minogue ( without Nick Cave ) */ -/* ---------------------------------------------------------------------------- */ - -#include "m_pd.h" -#include -#include - -static char *compressor_version = "compressor~: an audio compressor, version 0.1 (ydegoyon@free.fr)"; - -typedef struct _compressor -{ - t_object x_obj; - t_float x_strength; - t_float x_pifactor; - t_float x_f; -} t_compressor; - -static t_class *compressor_class; - -static void compressor_strength(t_compressor *x, t_floatarg fstrength ) -{ - if (fstrength < -1.0) - { - x->x_strength = -1.0; - } - else if (fstrength > 5) - { - x->x_strength = 5; - } - else - { - x->x_strength = fstrength; - } - x->x_pifactor = pow( M_PI, x->x_strength ); -} - -static void *compressor_new(void) -{ - t_compressor *x = (t_compressor *)pd_new(compressor_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("strength")); - x->x_strength = 0.; - x->x_pifactor = pow( M_PI, x->x_strength ); - outlet_new(&x->x_obj, &s_signal); - return (x); -} - -static t_int *compressor_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *out = (t_float *)(w[2]); - int n = (int)(w[3]); - t_compressor *x = (t_compressor*)(w[4]); - t_float isample_fact = x->x_pifactor; - t_float osample_fact = 2.0 / M_PI; - - while (n--) { - *out = atan (*in * isample_fact) * osample_fact; - out++; in++; - } - return (w+5); -} - -static void compressor_dsp(t_compressor *x, t_signal **sp) -{ - dsp_add(compressor_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); -} - -void compressor_tilde_setup(void) -{ - post( compressor_version ); - compressor_class = class_new(gensym("compressor~"), (t_newmethod)compressor_new, 0, - sizeof(t_compressor), 0, 0); - CLASS_MAINSIGNALIN( compressor_class, t_compressor, x_f ); - class_addmethod(compressor_class, (t_method)compressor_dsp, gensym("dsp"), 0); - class_addmethod(compressor_class, (t_method)compressor_strength, gensym("strength"), A_FLOAT, 0); -} diff --git a/cooled~-help.pd b/cooled~-help.pd new file mode 100644 index 0000000..19a6d67 --- /dev/null +++ b/cooled~-help.pd @@ -0,0 +1,144 @@ +#N canvas 29 25 986 675 10; +#X msg 30 628 \; pd dsp 1; +#X msg 104 629 \; pd dsp 0; +#X obj 122 567 dac~; +#X obj 29 599 loadbang; +#X obj 115 531 *~ 1; +#X obj 156 530 *~ 1; +#X floatatom 204 531 5 0 0; +#X text 557 36 Cooled~ : a micro sound editor; +#X text 555 48 it supports selection and cut/paste modifications; +#X text 686 645 Comments and bugs @ ydegoyon@noos.fr; +#X obj 277 506 print recend; +#X obj 362 540 print playend; +#X msg 28 31 bang; +#X obj 27 53 openpanel; +#X msg 62 226 resize \$1; +#X obj 27 73 t s b; +#X obj 76 73 float \$0; +#X text 27 6 Step 1 : Load a sound file; +#X obj 27 96 route float; +#X text 95 25 ( a small one ); +#X msg 208 218 record; +#X msg 315 10 bang; +#X text 355 9 Step 2 : Record the sound; +#X obj 63 163 pack s s s; +#X obj 19 117 makefilename %d-right-channel; +#X obj 23 140 makefilename %d-left-channel; +#X obj 180 611 table \$0-right-channel; +#X obj 181 636 table \$0-left-channel; +#X msg 62 184 read -resize \$1 \$2 \$3; +#X obj 289 41 tabplay~ \$0-right-channel; +#X obj 288 67 tabplay~ \$0-left-channel; +#X msg 18 298 refresh; +#X msg 23 467 play; +#X msg 22 445 bang; +#X text 11 494 Step 3 : Play it back; +#X obj 146 249 cooled~ 81839 400 200 1; +#X obj 397 157 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 397 179 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 400 131 Reading positions; +#X text 539 153 Start; +#X text 538 179 End; +#X msg 301 106 readspeed \$1; +#X floatatom 438 106 5 0 0; +#X obj 397 106 / 100; +#X msg 489 106 100; +#X text 521 105 Reading speed; +#X msg 18 328 zoom 2; +#X msg 19 357 zoom 1; +#X msg 361 179 100; +#X obj 297 179 loadbang; +#X obj 600 187 random 100; +#X msg 660 137 bang; +#X obj 681 186 random 100; +#X text 641 114 Random play; +#X obj 602 164 metro 1000; +#X text 601 507 Mouse modifications :; +#X text 601 522 : erase selection; +#X text 601 537 : replace by selection; +#X text 418 612 The red area is the selection; +#X text 419 596 point for paste and replace; +#X text 420 581 Note : the blue line is the insertion; +#X msg 361 155 0; +#X text 600 552 : add selection [ noize ]; +#X text 706 429 (invoke with Properties ); +#X text 709 419 You can set the following properties :; +#X text 733 460 * Width : graphical x size; +#X text 733 476 * Height : graphical y size; +#X msg 704 138 stop; +#X text 686 631 Part of unauthorized PD; +#X obj 683 163 metro 1000; +#X msg 23 391 stereo; +#X text 19 413 Map to stereo; +#X floatatom 448 481 8 0 0; +#X floatatom 521 481 8 0 0; +#X text 447 502 start; +#X text 510 503 end; +#X text 469 518 Selection; +#X msg 460 219 loop *2; +#X msg 401 218 loop /2; +#X msg 342 218 loop <1; +#X obj 62 206 soundfiler; +#X msg 282 218 loop >1; +#X text 520 220 loop operators ( accept any float value ); +#X connect 3 0 0 0; +#X connect 4 0 2 0; +#X connect 5 0 2 1; +#X connect 6 0 4 1; +#X connect 6 0 5 1; +#X connect 12 0 13 0; +#X connect 13 0 15 0; +#X connect 14 0 35 0; +#X connect 15 0 23 0; +#X connect 15 1 16 0; +#X connect 16 0 18 0; +#X connect 18 0 24 0; +#X connect 18 0 25 0; +#X connect 20 0 35 0; +#X connect 21 0 20 0; +#X connect 21 0 29 0; +#X connect 21 0 30 0; +#X connect 23 0 28 0; +#X connect 24 0 23 1; +#X connect 25 0 23 2; +#X connect 28 0 80 0; +#X connect 29 0 35 0; +#X connect 30 0 35 1; +#X connect 31 0 35 0; +#X connect 32 0 35 0; +#X connect 33 0 32 0; +#X connect 35 0 4 0; +#X connect 35 1 5 0; +#X connect 35 2 10 0; +#X connect 35 3 11 0; +#X connect 35 3 32 0; +#X connect 35 4 72 0; +#X connect 35 5 73 0; +#X connect 36 0 35 2; +#X connect 37 0 35 3; +#X connect 41 0 35 0; +#X connect 42 0 43 0; +#X connect 43 0 41 0; +#X connect 44 0 42 0; +#X connect 46 0 35 0; +#X connect 47 0 35 0; +#X connect 48 0 37 0; +#X connect 49 0 48 0; +#X connect 50 0 35 2; +#X connect 51 0 54 0; +#X connect 51 0 69 0; +#X connect 52 0 35 3; +#X connect 54 0 50 0; +#X connect 61 0 36 0; +#X connect 67 0 54 0; +#X connect 67 0 69 0; +#X connect 69 0 52 0; +#X connect 70 0 35 0; +#X connect 77 0 35 0; +#X connect 78 0 35 0; +#X connect 79 0 35 0; +#X connect 80 0 14 0; +#X connect 81 0 35 0; diff --git a/cooled~.c b/cooled~.c new file mode 100644 index 0000000..ed5b4b8 --- /dev/null +++ b/cooled~.c @@ -0,0 +1,1394 @@ +/*------------------------ cooled~ -------------------------------------------- */ +/* */ +/* cooled~ : display sound, play parts and modify it with cut and paste */ +/* constructor : cooled~ | cooled~ */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "I am the fly in the ointment" -- Wire + 154 */ +/* Komet -- Instrumentals */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +# include +#else +# include +#endif + +#ifdef _WIN32 +# define M_PI 3.14159265358979323846 +#else +# include +#endif + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + + +static int guidebug=0; +static int ignorevisible=1; // ignore visible test + // because this seems to lead to bad refresh + // wait for a fix + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h );\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +#define THREAD_SLEEP_TIME 10000 // 10000 us = 10 ms +#define COOLED_BGCOLOR "#000000" +#define COOLED_FGCOLOR "#34E112" +#define COOLED_FRCOLOR "#FFFFFF" + +#define COOLED_DEFAULT_SIZE 1024 +#define COOLED_DEFAULT_WIDTH 400 +#define COOLED_DEFAULT_HEIGHT 200 + +static char *cooled_version = "cooled~: version 0.13, written by Yves Degoyon (ydegoyon@free.fr)"; + +static t_class *cooled_class; +t_widgetbehavior cooled_widgetbehavior; + +typedef struct _cooled +{ + t_object x_obj; + + int x_size; /* size of the stored sound */ + t_float x_readpos; /* data's playing position */ + int x_writepos; /* data's recording position */ + t_float x_readstart; /* data's starting position for reading */ + t_float x_readend; /* data's ending position for reading */ + int x_play; /* playing on/off flag */ + t_float x_readspeed; /* speed increment */ + t_float x_record; /* flag to start recording process */ + t_float x_allocate; /* flag to indicate pending allocation */ + t_float x_empty; /* flag to indicate it's a brand new sound */ + t_float *x_rdata; /* table containing right channel samples */ + t_float *x_ldata; /* table containing leftt channel samples */ + t_outlet *x_end; /* outlet for end of restitution */ + t_outlet *x_recend; /* outlet for end of recording */ + t_outlet *x_sampstart; /* outlet for sample number [ start ] when selecting */ + t_outlet *x_sampend; /* outlet for sample number [ end ] when selecting */ + t_float *x_rsemp; /* temporary sample buffer ( right ) */ + t_float *x_lsemp; /* temporary sample buffer ( left ) */ + char* x_gifdata; /* buffer to store graphic data */ + char* x_guicommand; /* buffer to store gui command */ + int x_draw; /* drawing option */ + + /* graphical data block */ + int x_width; /* graphical width */ + int x_height; /* graphical height */ + int x_selected; /* flag to remember if we are seleted or not */ + int x_erase; /* flag used when an erase is needed */ + int x_redraw; /* flag used when drawing is needed */ + t_glist *x_glist; /* keep graphic context for various operations */ + int x_zoom; /* zoom factor */ + pthread_t x_updatechild; /* thread id for the update child */ + int x_updatestart; /* starting position for update */ + int x_updateend; /* ending position for update */ + int x_xpos; /* stuck x position */ + int x_ypos; /* stuck y position */ + int x_shifted; /* remember shift state from last click */ + int x_alted; /* remember alt state from last click */ + int x_xdraw; /* x drawing position */ + int x_edraw; /* end of drawing */ + + t_float x_f; /* float needed for signal input */ + +} t_cooled; + +/* ------------------------ drawing functions ---------------------------- */ + +static void cooled_update_block(t_cooled *x, t_glist *glist, int bnumber) +{ + int hi, i=0; + t_float fspectrum=0.0; + int phase=0; + char color[8]; + + memset( x->x_gifdata, 0x0, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + + // update cooled~ + for ( hi=x->x_height-1; hi>=0; hi-- ) + { + if ( ( hi == x->x_height/4) || ( hi == 3*x->x_height/4) ) + { + sprintf( color, "%s ", COOLED_FGCOLOR ); + } + else if ( hi == x->x_height/2) + { + sprintf( color, "%s ", COOLED_FRCOLOR ); + } + else + { + sprintf( color, "%s ", COOLED_BGCOLOR ); + } + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+(hi*x->x_zoom+i)*8, color, 8 ); + } + } + + // set all points + { + int fsamp = ( bnumber * x->x_size ) / x->x_width; + int lsamp = ( ( bnumber+1) * x->x_size ) / x->x_width; + int si; + + // post ( "cooled~ : updating samples [%d,%d]", fsamp, lsamp ); + + for ( si=fsamp;six_height/4 + ( *(x->x_rdata+si) * (x->x_height/4) ) - 1; + + if ( rind > x->x_height - 1 ) rind = x->x_height - 1; + if ( rind < x->x_height/2 ) rind = x->x_height/2; + + sprintf( color, "%s ", COOLED_FGCOLOR ); + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+(rind*x->x_zoom+i)*8, color, 8 ); + } + } + + // calculate left channel index + { + int lind = x->x_height/4 + ( *(x->x_ldata+si) * (x->x_height/4) ) - 1; + + if ( lind > x->x_height/2 - 1 ) lind = x->x_height/2 - 1; + if ( lind < 0 ) lind = 0; + + sprintf( color, "%s ", COOLED_FGCOLOR ); + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+(lind*x->x_zoom+i)*8, color, 8 ); + } + } + } + } + + for ( i=0; ix_zoom; i++ ) + { + sprintf( x->x_guicommand, "COOLEDIMAGE%x put {%s} -to %d 0\n", x, x->x_gifdata, (bnumber*x->x_zoom)+i ); + if ( glist_isvisible( x->x_glist ) ) + sys_gui( x->x_guicommand ); + } + +} + +static void cooled_erase_block(t_cooled *x, t_glist *glist, int sample ) +{ + t_canvas *canvas=glist_getcanvas(glist); + int hi; + t_float fspectrum=0.0; + char fillColor[ 16 ]; + + for ( hi=0; hix_height; hi++) + { + { + int i; + + for ( i=0; ix_zoom; i++ ) + { + strcpy( x->x_gifdata+i*sizeof("#FFFFFF "), strcat( COOLED_BGCOLOR, " ") ); + } + if ( glist_isvisible( x->x_glist ) ) + SYS_VGUI5("COOLEDIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, + sample*x->x_zoom, (x->x_height-hi)*x->x_zoom ); + } + } +} + +static void *cooled_do_update_part(void *tdata) +{ + t_cooled *x = (t_cooled*) tdata; + t_canvas *canvas=glist_getcanvas(x->x_glist); + int si; + int nbpoints = 0; + t_float percentage = 0, opercentage = 0; + + // loose synchro + usleep( THREAD_SLEEP_TIME ); + + // check bounds + if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; + if ( x->x_updatestart < 0 ) x->x_updatestart = 0; + + post("cooled~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); + + if ( x->x_erase ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + cooled_erase_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "cooled~ : erase part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + percentage = opercentage = nbpoints = 0; + + if ( x->x_redraw ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + cooled_update_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "cooled~ : update part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + canvas, x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + canvas, x->x_xpos+(int)(x->x_readstart*(x->x_width)/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*(x->x_width)/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + // set borders in black + SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #000000\n", canvas, x); + } + + post("cooled~ : child thread %d ended", (int)x->x_updatechild ); + x->x_updatechild = 0; + return NULL; +} + +static void cooled_update_part(t_cooled *x, t_glist *glist, int bstart, int bend, + int erase, int redraw, int keepframe) +{ + pthread_attr_t update_child_attr; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( x->x_updatechild != 0 ) + { + // post( "cooled~ : error : no update is possible for now" ); + return; + } + x->x_updatestart = bstart; + x->x_updateend = bend; + if ( !keepframe ) + { + x->x_erase = 0; + } + else + { + x->x_erase = erase; + } + x->x_redraw = redraw; + // recreate the square if needed + if ( glist_isvisible( x->x_glist ) ) + { + if ( ( bstart == 0 ) && ( bend == x->x_width-1 ) && !keepframe ) + { + SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", canvas, x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", + canvas, x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", + canvas, x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom, + x); + SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); + SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", canvas, x ); + SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", + x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); + SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); + SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", + canvas, + x->x_xpos+(x->x_width*x->x_zoom)/2, + x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); + canvas_fixlinesfor( canvas, (t_text*)x ); + } + // set borders in red + SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #FF0000\n", canvas, x); + } + + // launch update thread + if ( pthread_attr_init( &update_child_attr ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_attr_init" ); + return; + } + if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_attr_setdetachstate" ); + return; + } + if ( pthread_create( &x->x_updatechild, &update_child_attr, cooled_do_update_part, x ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_create" ); + return; + } + else + { + // post( "cooled~ : drawing thread %d launched", (int)x->x_updatechild ); + } +} + +static void cooled_draw_new(t_cooled *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + x->x_xpos=text_xpix(&x->x_obj, glist); + x->x_ypos=text_ypix(&x->x_obj, glist); + x->x_xdraw=text_xpix(&x->x_obj, glist); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", + canvas, x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", + canvas, x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom, + x); + SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", + x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); + SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); + SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", + canvas, + x->x_xpos+(x->x_width*x->x_zoom)/2, + x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void cooled_draw_delete(t_cooled *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( glist ) ) + { + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", canvas, x); + } + SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", canvas, x ); + SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", canvas, x ); + SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); + } +} + +static void cooled_draw_move(t_cooled *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI7(".x%x.c coords %xCOOLEDR %d %d %d %d\n", + canvas, x, + x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom); + SYS_VGUI7(".x%x.c coords %xCOOLEDL %d %d %d %d\n", + canvas, x, + x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom ); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7(".x%x.c coords %xCLIPZONE %d %d %d %d\n", + canvas, x, + x->x_xpos+(int)(x->x_readstart*(x->x_width)/100*x->x_zoom ), + x->x_ypos, + x->x_xpos+(int)(x->x_readend*(x->x_width)/100*x->x_zoom ), + x->x_ypos+x->x_height*x->x_zoom ); + } + SYS_VGUI7(".x%x.c coords %xINSERTHERE %d %d %d %d\n", + canvas, x, + x->x_xdraw, + x->x_ypos, + x->x_xdraw, + x->x_ypos+x->x_height*x->x_zoom ); + SYS_VGUI5(".x%x.c coords ICOOLEDIMAGE%x %d %d\n", + canvas, x, + x->x_xpos+((x->x_width*x->x_zoom)/2), + (x->x_ypos+((x->x_height*x->x_zoom)/2)) ); + canvas_fixlinesfor( canvas, (t_text*)x ); + } +} + +static void cooled_draw_select(t_cooled* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( x->x_glist ) ) + { + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #0000FF\n", canvas, x); + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #0000FF\n", canvas, x); + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #000000\n", canvas, x); + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #000000\n", canvas, x); + } + } +} + +/* ------------------------ widget callbacks ----------------------------- */ + + + /* setting the starting point for reading ( in percent ) */ +static void cooled_readstart(t_cooled *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + x->x_readstart = startpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + canvas, x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + canvas, x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + } + outlet_float( x->x_sampstart, (x->x_readstart*x->x_size)/100 ); +} + + /* setting the ending point for reading ( in percent ) */ +static void cooled_readend(t_cooled *x, t_floatarg fend) +{ + t_float endpoint = fend; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + x->x_readend = endpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + canvas, x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + canvas, + x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + } + outlet_float( x->x_sampend, (x->x_readend*x->x_size)/100 ); +} + +static void cooled_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_cooled* x = (t_cooled*)z; + + *xp1 = x->x_xpos; + *yp1 = x->x_ypos; + *xp2 = x->x_xpos+x->x_width*x->x_zoom; + *yp2 = x->x_ypos+x->x_height*x->x_zoom+1; +} + +static void cooled_save(t_gobj *z, t_binbuf *b) +{ + t_cooled *x = (t_cooled *)z; + + binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), + (int)x->x_obj.te_xpix, (int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_size, x->x_width, x->x_height, x->x_draw ); + binbuf_addv(b, ";"); +} + +static void cooled_select(t_gobj *z, t_glist *glist, int selected) +{ + t_cooled *x = (t_cooled *)z; + + x->x_selected = selected; + cooled_draw_select( x, glist ); +} + +static void cooled_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_cooled *x = (t_cooled *)z; + t_rtext *y; + + if (vis) + { + cooled_draw_new( x, glist ); + } + else + { + // erase all points + cooled_draw_delete( x, glist ); + } +} + +static void cooled_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void cooled_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_cooled *x = (t_cooled *)z; + int xold = x->x_xpos; + int yold = x->x_ypos; + + x->x_xpos += dx; + x->x_ypos += dy; + + if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) + { + cooled_draw_move( x, glist ); + } + +} + +static void cooled_motion(t_cooled *x, t_floatarg dx, t_floatarg dy) +{ + // post( "cooled_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); + if ( dx != 0 ) + { + cooled_readstart( x, ((t_float)( x->x_xdraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); + x->x_edraw += dx; + cooled_readend( x, ((t_float)( x->x_edraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); + } +} + + /* erase data form readstart to readend */ +static void cooled_erase( t_cooled *x ) +{ + int startsamp, endsamp, si; + int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot erase while re-allocation" ); + return; + } + // post( "cooled~ : erase" ); + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + for ( si=startsamp; si<=endsamp; si++ ) + { + *(x->x_rdata+si) = 0.; + *(x->x_ldata+si) = 0.; + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, startsamp*x->x_width/x->x_size, endsamp*(x->x_width-1)/x->x_size, 0, 1, 1); +} + /* paste data form readstart to readend */ +static void cooled_paste( t_cooled *x ) +{ + int startsamp, endsamp, si, inssamp, hlimit, csize; + int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot paste while re-allocation" ); + return; + } + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + // insert data at insertion point + inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); + // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); + csize=endsamp-startsamp; + for ( si=0; si<=csize; si++ ) + { + if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; + *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); + *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); + } + hlimit = si; + for ( si=0 ; si<=hlimit; si++ ) + { + *(x->x_rdata+inssamp+si) += *(x->x_rsemp+si); + *(x->x_ldata+inssamp+si) += *(x->x_lsemp+si); + } + + // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); + if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); +} + /* replace data form readstart to readend */ +static void cooled_replace( t_cooled *x ) +{ + int startsamp, endsamp, si, inssamp, hlimit, csize; + int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot replace while re-allocation" ); + return; + } + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + // insert data at insertion point + inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); + // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); + csize=endsamp-startsamp; + for ( si=0; si<=csize; si++ ) + { + if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; + *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); + *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); + } + hlimit = si; + for ( si=0 ; si<=hlimit; si++ ) + { + *(x->x_rdata+inssamp+si) = *(x->x_rsemp+si); + *(x->x_ldata+inssamp+si) = *(x->x_lsemp+si); + } + + // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); + if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); + +} + + /* call editor's property dialog */ +static void cooled_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_cooled *x=(t_cooled *)z; + + sprintf(buf, "pdtk_cooled_dialog %%s %d %d %d\n", + x->x_width, x->x_height, x->x_draw); + // post("cooled_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + + /* handle properties change */ +static void cooled_dialog(t_cooled *x, t_symbol *s, int argc, t_atom *argv) +{ + if ( !x ) { + post( "cooled~ : error :tried to set properties on an unexisting object" ); + } + if ( argc != 3 ) + { + post( "cooled~ : error in the number of arguments ( %d instead of 3 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || argv[2].a_type != A_FLOAT ) { + post( "cooled~ : wrong arguments" ); + return; + } + cooled_draw_delete(x, x->x_glist); + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } + x->x_width = (int)argv[0].a_w.w_float; + if ( x->x_width < 0 ) x->x_width = 100; + x->x_height = (int)argv[1].a_w.w_float; + if ( x->x_height < 0 ) x->x_height = 100; + x->x_draw = (int)argv[2].a_w.w_float; + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + cooled_draw_new(x, x->x_glist); +} + + /* handle clicks */ +static int cooled_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_cooled* x = (t_cooled *)z; + int pipos; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + // post( "cooled_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); + if ( doit ) + { + if ( shift && alt ) + { + cooled_paste(x); + } + else if ( shift ) + { + cooled_replace(x); + } + else if ( alt ) + { + cooled_erase(x); + } + else + { + x->x_xdraw = xpix; + x->x_edraw = xpix; + x->x_shifted = shift; + x->x_alted = alt; + // activate motion callback + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)cooled_motion, + 0, xpix, ypix ); + + // draw insertion line + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", + canvas, x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #00FFFF -tags %xINSERTHERE -width 2\n", + canvas, x->x_xdraw, + x->x_ypos, x->x_xdraw, + x->x_ypos+x->x_height*x->x_zoom, x ); + } + + } + + } + else + { + // nothing + } + return (1); + +} + + /* clean up */ +static void cooled_free(t_cooled *x) +{ + if ( x->x_rdata != NULL ) { + freebytes(x->x_rdata, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_rdata = NULL; + } + if ( x->x_ldata != NULL ) { + freebytes(x->x_ldata, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_ldata = NULL; + } + if ( x->x_rsemp != NULL ) { + freebytes(x->x_rsemp, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_rsemp = NULL; + } + if ( x->x_lsemp != NULL ) { + freebytes(x->x_lsemp, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_lsemp = NULL; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } +} + + /* allocate tables for storing sound and temporary copy */ +static int cooled_allocate(t_cooled *x) +{ + int fi; + + if ( !(x->x_rdata = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_ldata = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_rsemp = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_lsemp = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + + return 0; +} + + /* allocate tables for storing sound and temporary copy */ +static int cooled_reallocate(t_cooled *x, int ioldsize, int inewsize) +{ + int fi, csize; + t_float *prdata=x->x_rdata, *pldata=x->x_ldata, *prsemp=x->x_rsemp, *plsemp=x->x_lsemp; + + if ( !(x->x_rdata = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_ldata = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_rsemp = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_lsemp = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + + if ( ioldsize <= inewsize ) + { + csize = ioldsize; + } + else + { + csize = inewsize; + } + memcpy( x->x_rdata, prdata, csize*sizeof(float) ); + memcpy( x->x_ldata, pldata, csize*sizeof(float) ); + memcpy( x->x_rsemp, prsemp, csize*sizeof(float) ); + memcpy( x->x_lsemp, plsemp, csize*sizeof(float) ); + + if ( prdata != NULL ) { + freebytes(prdata, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( pldata != NULL ) { + freebytes(pldata, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( prsemp != NULL ) { + freebytes(prsemp, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( plsemp != NULL ) { + freebytes(plsemp, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + + return 0; +} + + /* records and playback the sound */ +static t_int *cooled_perform(t_int *w) +{ + t_float *lin = (t_float *)(w[1]); + t_float *rin = (t_float *)(w[2]); + t_float *rout = (t_float *)(w[3]); + t_float *lout = (t_float *)(w[4]); + int is; + int n = (int)(w[5]); /* number of samples */ + int startsamp, endsamp; + t_cooled *x = (t_cooled *)(w[6]); + int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + while (n--) + { + // eventually records input + if ( x->x_record ) { + *(x->x_ldata+x->x_writepos)=*(lin); + *(x->x_rdata+x->x_writepos)=*(rin); + x->x_writepos++; + if ( x->x_writepos >= x->x_size ) { + x->x_record=0; + x->x_writepos=0; + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); + outlet_bang(x->x_recend); + if ( x->x_empty ) x->x_empty = 0; + // post( "cooled~ : stopped recording" ); + } + } + // set outputs + *rout = 0.0; + *lout = 0.0; + if ( x->x_play) { + is=0; + *lout = *(x->x_ldata+(int)x->x_readpos); + *rout = *(x->x_rdata+(int)x->x_readpos); + x->x_readpos+=x->x_readspeed; + // post( "xreadpos : %f (added %f) %d", x->x_readpos, x->x_readspeed, x->x_readend ); + if ( ( x->x_readspeed >= 0 ) && ( x->x_readpos >= endsamp ) ) { + x->x_play=0; + x->x_readpos=(float)(startsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + if ( ( x->x_readspeed < 0 ) && ( x->x_readpos <= startsamp ) ) { + x->x_play=0; + x->x_readpos = (float)(endsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + } + rout++;lout++; + rin++;lin++; + } + // post( "cooled~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); + return (w+7); +} + +static void cooled_dsp(t_cooled *x, t_signal **sp) +{ + dsp_add(cooled_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); +} + + /* record the cooled */ +static void cooled_record(t_cooled *x) +{ + if (x->x_allocate) { + post( "cooled~ : error : cannot record while re-allocation" ); + return; + } + x->x_record=1; + x->x_writepos=0; + post( "cooled~ : recording on" ); +} + + /* map to stereo */ +static void cooled_stereo(t_cooled *x) +{ + int si; + + if (x->x_allocate) { + post( "cooled~ : error : cannot map to stereo while re-allocation" ); + return; + } + for ( si=0; six_size; si++ ) + { + *(x->x_rdata+si) = *(x->x_ldata+si); + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); +} + + /* play the cooled */ +static void cooled_play(t_cooled *x) +{ + x->x_play=1; + // post( "cooled~ : playing on" ); +} + + /* sets the reading speed */ +static void cooled_readspeed(t_cooled *x, t_floatarg freadspeed) +{ + x->x_readspeed=freadspeed; +} + + /* resize cooled */ +static void cooled_resize(t_cooled *x, t_floatarg fnewsize ) +{ + if (fnewsize <= 0) { + post( "cooled~ : error : wrong size" ); + return; + } + if (x->x_allocate) { + post( "cooled~ : error : cannot resize while re-allocation" ); + return; + } + if (x->x_updatechild > 0) { + post( "cooled~ : can't resize now, an update is pending." ); + return; + } + post( "cooled~ : reallocating tables" ); + x->x_allocate = 1; + x->x_play = 0; + x->x_record = 0; + cooled_readstart( x, 0); + cooled_readend( x, 100); + cooled_reallocate(x, x->x_size, fnewsize); + x->x_size = fnewsize; + x->x_empty = 1; + if ( x->x_readstart <= x->x_readend ) + { + x->x_readpos = (x->x_readstart*x->x_size)/100; + } + else + { + x->x_readpos = (x->x_readend*x->x_size)/100; + } + // erase all points, as data is zero no drawing is needed + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, !x->x_empty, 1); + x->x_allocate = 0; +} + + /* set zoom factor */ +static void cooled_zoom(t_cooled *x, t_floatarg fzoom ) +{ + if (fzoom < 1) { + post( "cooled~ : error : wrong zoom factor" ); + return; + } + if (x->x_allocate) { + post( "cooled~ : error : cannot zoom while re-allocation" ); + return; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } + x->x_zoom = (int)fzoom; + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); + canvas_fixlinesfor(x->x_glist, (t_text*)x ); +} + + /* modify the loop positions */ +static void cooled_loop(t_cooled *x, t_symbol *soperator ) +{ + char *operator = soperator->s_name; + int ci; + t_float fvalue, freadstart = x->x_readstart, freadend = x->x_readend; + + if ( (soperator->s_name[0] != '*') && + (soperator->s_name[0] != '/') && + (soperator->s_name[0] != '>') && + (soperator->s_name[0] != '<') ) { + post( "cooled~ : error : wrong operator argument : should be *|/|>|<" ); + return; + } + for ( ci=1; ci<(int)strlen( soperator->s_name ); ci++ ) + { + if ( !(isdigit(soperator->s_name[ci])||(soperator->s_name[ci]=='.')) ) { + post( "cooled~ : error : wrong operation value : %s : should be in a float format", soperator->s_name+1 ); + return; + } + } + if ( sscanf( soperator->s_name+1, "%f", &fvalue ) != 1 ) { + post( "cooled~ : error : can't get operation value" ); + return; + } + switch( soperator->s_name[0] ) + { + case '*' : + freadend = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); + break; + + case '/' : + if ( fvalue != 0 ) { freadend = x->x_readstart + (x->x_readend-x->x_readstart)/fvalue; }; + break; + + case '>' : + freadstart = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); + freadend = x->x_readend + fvalue*(x->x_readend-x->x_readstart); + break; + + case '<' : + freadstart = x->x_readstart - fvalue*(x->x_readend-x->x_readstart); + freadend = x->x_readend - fvalue*(x->x_readend-x->x_readstart); + break; + } + if ( freadstart < 0.0 ) freadstart = 0.0; + if ( freadend < 0.0 ) freadend = 0.0; + if ( freadstart > 100.0 ) freadstart = 100.0; + if ( freadend > 100.0 ) freadend = 100.0; + cooled_readstart( x, freadstart); + cooled_readend( x, freadend); +} + + /* refresh data */ +static void cooled_refresh(t_cooled *x) +{ + if (x->x_allocate) { + post( "cooled~ : error : cannot refresh while re-allocation" ); + return; + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 1); +} + +static void *cooled_new(t_symbol *s, int argc, t_atom *argv) +{ + t_cooled *x = (t_cooled *)pd_new(cooled_class); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_recend = outlet_new(&x->x_obj, &s_bang ); + x->x_end = outlet_new(&x->x_obj, &s_bang ); + x->x_sampstart = outlet_new(&x->x_obj, &s_float ); + x->x_sampend = outlet_new(&x->x_obj, &s_float ); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); + + if ( argc != 0 ) + { + if ( argc < 3 ) + { + post( "audience~ : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT ) { + post( "audience~ : wrong arguments" ); + return NULL; + } + x->x_size = (int)argv[0].a_w.w_float; + if ( x->x_size < 1 ) x->x_size = 1; + x->x_width = (int)argv[1].a_w.w_float; + if ( x->x_width < 10 ) x->x_width = 10; + x->x_height = (int)argv[2].a_w.w_float; + if ( x->x_height < 10 ) x->x_height = 10; + if ( argc == 3 ) + x->x_draw = 1; + else + x->x_draw = (int)argv[3].a_w.w_float; + } + else + { + x->x_size = COOLED_DEFAULT_SIZE; + x->x_width = COOLED_DEFAULT_WIDTH; + x->x_height = COOLED_DEFAULT_HEIGHT; + x->x_draw = 1; + } + + // activate graphical callbacks + class_setwidget(cooled_class, &cooled_widgetbehavior); + + x->x_play = 0; + x->x_readspeed = 1.; + x->x_record = 0; + x->x_allocate = 0; + x->x_readpos = 0.; + x->x_writepos = 0; + x->x_rdata = NULL; + x->x_ldata = NULL; + x->x_empty = 1; + x->x_xpos = -1; + x->x_ypos = -1; + /* graphic data */ + x->x_selected = 0; + x->x_zoom = 1; + x->x_updatechild = 0; + x->x_glist = (t_glist*)canvas_getcurrent(); + // post( "cooled~ : new : readend=%d", x->x_readend ); + cooled_readstart( x, 0); + cooled_readend( x, 100); + + if ( cooled_allocate(x) <0 ) { + return NULL; + } else { + return(x); + } + +} + +void cooled_tilde_setup(void) +{ + post(cooled_version); + cooled_class = class_new(gensym("cooled~"), (t_newmethod)cooled_new, (t_method)cooled_free, + sizeof(t_cooled), 0, A_GIMME, 0); + + + // set callbacks + cooled_widgetbehavior.w_getrectfn = cooled_getrect; + cooled_widgetbehavior.w_displacefn = cooled_displace; + cooled_widgetbehavior.w_selectfn = cooled_select; + cooled_widgetbehavior.w_activatefn = NULL; + cooled_widgetbehavior.w_deletefn = cooled_delete; + cooled_widgetbehavior.w_visfn = cooled_vis; + cooled_widgetbehavior.w_clickfn = cooled_click; + + class_setpropertiesfn(cooled_class, cooled_properties); + class_setsavefn(cooled_class, cooled_save); + + CLASS_MAINSIGNALIN( cooled_class, t_cooled, x_f ); + class_addmethod(cooled_class, (t_method)cooled_dsp, gensym("dsp"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_record, gensym("record"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_resize, gensym("resize"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_zoom, gensym("zoom"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_play, gensym("play"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_refresh, gensym("refresh"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readstart, gensym("readstart"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_stereo, gensym("stereo"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readend, gensym("readend"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_loop, gensym("loop"), A_SYMBOL, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_dialog, gensym("dialog"), A_GIMME, 0); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + cooled_class->c_externdir->s_name, cooled_class->c_name->s_name); +} diff --git a/cooled~.tcl b/cooled~.tcl new file mode 100644 index 0000000..ebd7699 --- /dev/null +++ b/cooled~.tcl @@ -0,0 +1,87 @@ +############ cooled procedures -- ydegoyon@free.fr ######### + +proc cooled_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_draw [concat graph_draw_$vid] + global $var_graph_draw + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_draw] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc cooled_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc cooled_ok {id} { + cooled_apply $id + cooled_cancel $id +} + +proc pdtk_cooled_dialog {id width height draw} { + set vid [string trimleft $id .] + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_draw [concat graph_draw_$vid] + global $var_graph_draw + + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_draw $draw + + toplevel $id + wm title $id {cooled} + wm protocol $id WM_DELETE_WINDOW [concat cooled_cancel $id] + + label $id.label -text {EDITOR PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "cooled_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "cooled_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "cooled_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + checkbutton $id.draw -text {Draw Sample} -variable $var_graph_draw \ + -anchor w + pack $id.draw -side top + + bind $id.1rangef.width [concat cooled_ok $id] + bind $id.2rangef.height [concat cooled_ok $id] + focus $id.1rangef.width +} + +############ cooled procedures END -- ydegoyon@free.fr ######### diff --git a/cooled~/INSTALL b/cooled~/INSTALL deleted file mode 100644 index 411a1c3..0000000 --- a/cooled~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/cooled~ - -make clean - -make - -make install - -open help-cooled~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/cooled~/cooled~-help.pd b/cooled~/cooled~-help.pd deleted file mode 100644 index 19a6d67..0000000 --- a/cooled~/cooled~-help.pd +++ /dev/null @@ -1,144 +0,0 @@ -#N canvas 29 25 986 675 10; -#X msg 30 628 \; pd dsp 1; -#X msg 104 629 \; pd dsp 0; -#X obj 122 567 dac~; -#X obj 29 599 loadbang; -#X obj 115 531 *~ 1; -#X obj 156 530 *~ 1; -#X floatatom 204 531 5 0 0; -#X text 557 36 Cooled~ : a micro sound editor; -#X text 555 48 it supports selection and cut/paste modifications; -#X text 686 645 Comments and bugs @ ydegoyon@noos.fr; -#X obj 277 506 print recend; -#X obj 362 540 print playend; -#X msg 28 31 bang; -#X obj 27 53 openpanel; -#X msg 62 226 resize \$1; -#X obj 27 73 t s b; -#X obj 76 73 float \$0; -#X text 27 6 Step 1 : Load a sound file; -#X obj 27 96 route float; -#X text 95 25 ( a small one ); -#X msg 208 218 record; -#X msg 315 10 bang; -#X text 355 9 Step 2 : Record the sound; -#X obj 63 163 pack s s s; -#X obj 19 117 makefilename %d-right-channel; -#X obj 23 140 makefilename %d-left-channel; -#X obj 180 611 table \$0-right-channel; -#X obj 181 636 table \$0-left-channel; -#X msg 62 184 read -resize \$1 \$2 \$3; -#X obj 289 41 tabplay~ \$0-right-channel; -#X obj 288 67 tabplay~ \$0-left-channel; -#X msg 18 298 refresh; -#X msg 23 467 play; -#X msg 22 445 bang; -#X text 11 494 Step 3 : Play it back; -#X obj 146 249 cooled~ 81839 400 200 1; -#X obj 397 157 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 397 179 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 400 131 Reading positions; -#X text 539 153 Start; -#X text 538 179 End; -#X msg 301 106 readspeed \$1; -#X floatatom 438 106 5 0 0; -#X obj 397 106 / 100; -#X msg 489 106 100; -#X text 521 105 Reading speed; -#X msg 18 328 zoom 2; -#X msg 19 357 zoom 1; -#X msg 361 179 100; -#X obj 297 179 loadbang; -#X obj 600 187 random 100; -#X msg 660 137 bang; -#X obj 681 186 random 100; -#X text 641 114 Random play; -#X obj 602 164 metro 1000; -#X text 601 507 Mouse modifications :; -#X text 601 522 : erase selection; -#X text 601 537 : replace by selection; -#X text 418 612 The red area is the selection; -#X text 419 596 point for paste and replace; -#X text 420 581 Note : the blue line is the insertion; -#X msg 361 155 0; -#X text 600 552 : add selection [ noize ]; -#X text 706 429 (invoke with Properties ); -#X text 709 419 You can set the following properties :; -#X text 733 460 * Width : graphical x size; -#X text 733 476 * Height : graphical y size; -#X msg 704 138 stop; -#X text 686 631 Part of unauthorized PD; -#X obj 683 163 metro 1000; -#X msg 23 391 stereo; -#X text 19 413 Map to stereo; -#X floatatom 448 481 8 0 0; -#X floatatom 521 481 8 0 0; -#X text 447 502 start; -#X text 510 503 end; -#X text 469 518 Selection; -#X msg 460 219 loop *2; -#X msg 401 218 loop /2; -#X msg 342 218 loop <1; -#X obj 62 206 soundfiler; -#X msg 282 218 loop >1; -#X text 520 220 loop operators ( accept any float value ); -#X connect 3 0 0 0; -#X connect 4 0 2 0; -#X connect 5 0 2 1; -#X connect 6 0 4 1; -#X connect 6 0 5 1; -#X connect 12 0 13 0; -#X connect 13 0 15 0; -#X connect 14 0 35 0; -#X connect 15 0 23 0; -#X connect 15 1 16 0; -#X connect 16 0 18 0; -#X connect 18 0 24 0; -#X connect 18 0 25 0; -#X connect 20 0 35 0; -#X connect 21 0 20 0; -#X connect 21 0 29 0; -#X connect 21 0 30 0; -#X connect 23 0 28 0; -#X connect 24 0 23 1; -#X connect 25 0 23 2; -#X connect 28 0 80 0; -#X connect 29 0 35 0; -#X connect 30 0 35 1; -#X connect 31 0 35 0; -#X connect 32 0 35 0; -#X connect 33 0 32 0; -#X connect 35 0 4 0; -#X connect 35 1 5 0; -#X connect 35 2 10 0; -#X connect 35 3 11 0; -#X connect 35 3 32 0; -#X connect 35 4 72 0; -#X connect 35 5 73 0; -#X connect 36 0 35 2; -#X connect 37 0 35 3; -#X connect 41 0 35 0; -#X connect 42 0 43 0; -#X connect 43 0 41 0; -#X connect 44 0 42 0; -#X connect 46 0 35 0; -#X connect 47 0 35 0; -#X connect 48 0 37 0; -#X connect 49 0 48 0; -#X connect 50 0 35 2; -#X connect 51 0 54 0; -#X connect 51 0 69 0; -#X connect 52 0 35 3; -#X connect 54 0 50 0; -#X connect 61 0 36 0; -#X connect 67 0 54 0; -#X connect 67 0 69 0; -#X connect 69 0 52 0; -#X connect 70 0 35 0; -#X connect 77 0 35 0; -#X connect 78 0 35 0; -#X connect 79 0 35 0; -#X connect 80 0 14 0; -#X connect 81 0 35 0; diff --git a/cooled~/cooled~.c b/cooled~/cooled~.c deleted file mode 100644 index 87cec0e..0000000 --- a/cooled~/cooled~.c +++ /dev/null @@ -1,1387 +0,0 @@ -/*------------------------ cooled~ -------------------------------------------- */ -/* */ -/* cooled~ : display sound, play parts and modify it with cut and paste */ -/* constructor : cooled~ | cooled~ */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "I am the fly in the ointment" -- Wire + 154 */ -/* Komet -- Instrumentals */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef UNIX -#include -#endif -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif -#include - -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - - -static int guidebug=0; -static int ignorevisible=1; // ignore visible test - // because this seems to lead to bad refresh - // wait for a fix - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h );\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define THREAD_SLEEP_TIME 10000 // 10000 us = 10 ms -#define COOLED_BGCOLOR "#000000" -#define COOLED_FGCOLOR "#34E112" -#define COOLED_FRCOLOR "#FFFFFF" - -#define COOLED_DEFAULT_SIZE 1024 -#define COOLED_DEFAULT_WIDTH 400 -#define COOLED_DEFAULT_HEIGHT 200 - -static char *cooled_version = "cooled~: version 0.13, written by Yves Degoyon (ydegoyon@free.fr)"; - -static t_class *cooled_class; -t_widgetbehavior cooled_widgetbehavior; - -typedef struct _cooled -{ - t_object x_obj; - - int x_size; /* size of the stored sound */ - t_float x_readpos; /* data's playing position */ - int x_writepos; /* data's recording position */ - t_float x_readstart; /* data's starting position for reading */ - t_float x_readend; /* data's ending position for reading */ - int x_play; /* playing on/off flag */ - t_float x_readspeed; /* speed increment */ - t_float x_record; /* flag to start recording process */ - t_float x_allocate; /* flag to indicate pending allocation */ - t_float x_empty; /* flag to indicate it's a brand new sound */ - t_float *x_rdata; /* table containing right channel samples */ - t_float *x_ldata; /* table containing leftt channel samples */ - t_outlet *x_end; /* outlet for end of restitution */ - t_outlet *x_recend; /* outlet for end of recording */ - t_outlet *x_sampstart; /* outlet for sample number [ start ] when selecting */ - t_outlet *x_sampend; /* outlet for sample number [ end ] when selecting */ - t_float *x_rsemp; /* temporary sample buffer ( right ) */ - t_float *x_lsemp; /* temporary sample buffer ( left ) */ - char* x_gifdata; /* buffer to store graphic data */ - char* x_guicommand; /* buffer to store gui command */ - int x_draw; /* drawing option */ - - /* graphical data block */ - int x_width; /* graphical width */ - int x_height; /* graphical height */ - int x_selected; /* flag to remember if we are seleted or not */ - int x_erase; /* flag used when an erase is needed */ - int x_redraw; /* flag used when drawing is needed */ - t_glist *x_glist; /* keep graphic context for various operations */ - int x_zoom; /* zoom factor */ - pthread_t x_updatechild; /* thread id for the update child */ - int x_updatestart; /* starting position for update */ - int x_updateend; /* ending position for update */ - int x_xpos; /* stuck x position */ - int x_ypos; /* stuck y position */ - int x_shifted; /* remember shift state from last click */ - int x_alted; /* remember alt state from last click */ - int x_xdraw; /* x drawing position */ - int x_edraw; /* end of drawing */ - - t_float x_f; /* float needed for signal input */ - -} t_cooled; - -/* ------------------------ drawing functions ---------------------------- */ - -static void cooled_update_block(t_cooled *x, t_glist *glist, int bnumber) -{ - int hi, i=0; - t_float fspectrum=0.0; - int phase=0; - char color[8]; - - memset( x->x_gifdata, 0x0, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - - // update cooled~ - for ( hi=x->x_height-1; hi>=0; hi-- ) - { - if ( ( hi == x->x_height/4) || ( hi == 3*x->x_height/4) ) - { - sprintf( color, "%s ", COOLED_FGCOLOR ); - } - else if ( hi == x->x_height/2) - { - sprintf( color, "%s ", COOLED_FRCOLOR ); - } - else - { - sprintf( color, "%s ", COOLED_BGCOLOR ); - } - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+(hi*x->x_zoom+i)*8, color, 8 ); - } - } - - // set all points - { - int fsamp = ( bnumber * x->x_size ) / x->x_width; - int lsamp = ( ( bnumber+1) * x->x_size ) / x->x_width; - int si; - - // post ( "cooled~ : updating samples [%d,%d]", fsamp, lsamp ); - - for ( si=fsamp;six_height/4 + ( *(x->x_rdata+si) * (x->x_height/4) ) - 1; - - if ( rind > x->x_height - 1 ) rind = x->x_height - 1; - if ( rind < x->x_height/2 ) rind = x->x_height/2; - - sprintf( color, "%s ", COOLED_FGCOLOR ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+(rind*x->x_zoom+i)*8, color, 8 ); - } - } - - // calculate left channel index - { - int lind = x->x_height/4 + ( *(x->x_ldata+si) * (x->x_height/4) ) - 1; - - if ( lind > x->x_height/2 - 1 ) lind = x->x_height/2 - 1; - if ( lind < 0 ) lind = 0; - - sprintf( color, "%s ", COOLED_FGCOLOR ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+(lind*x->x_zoom+i)*8, color, 8 ); - } - } - } - } - - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "COOLEDIMAGE%x put {%s} -to %d 0\n", x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - if ( glist_isvisible( x->x_glist ) ) - sys_gui( x->x_guicommand ); - } - -} - -static void cooled_erase_block(t_cooled *x, t_glist *glist, int sample ) -{ - t_canvas *canvas=glist_getcanvas(glist); - int hi; - t_float fspectrum=0.0; - char fillColor[ 16 ]; - - for ( hi=0; hix_height; hi++) - { - { - int i; - - for ( i=0; ix_zoom; i++ ) - { - strcpy( x->x_gifdata+i*sizeof("#FFFFFF "), strcat( COOLED_BGCOLOR, " ") ); - } - if ( glist_isvisible( x->x_glist ) ) - SYS_VGUI5("COOLEDIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom, (x->x_height-hi)*x->x_zoom ); - } - } -} - -static void *cooled_do_update_part(void *tdata) -{ - t_cooled *x = (t_cooled*) tdata; - t_canvas *canvas=glist_getcanvas(x->x_glist); - int si; - int nbpoints = 0; - t_float percentage = 0, opercentage = 0; - - // loose synchro - usleep( THREAD_SLEEP_TIME ); - - // check bounds - if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; - if ( x->x_updatestart < 0 ) x->x_updatestart = 0; - - post("cooled~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); - - if ( x->x_erase ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - cooled_erase_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "cooled~ : erase part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - percentage = opercentage = nbpoints = 0; - - if ( x->x_redraw ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - cooled_update_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "cooled~ : update part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - if ( glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", - canvas, x); - if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) - { - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", - canvas, x->x_xpos+(int)(x->x_readstart*(x->x_width)/100 ), - x->x_ypos, x->x_xpos+(int)(x->x_readend*(x->x_width)/100 ), - x->x_ypos+x->x_height*x->x_zoom, x ); - } - // set borders in black - SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #000000\n", canvas, x); - } - - post("cooled~ : child thread %d ended", (int)x->x_updatechild ); - x->x_updatechild = 0; - return NULL; -} - -static void cooled_update_part(t_cooled *x, t_glist *glist, int bstart, int bend, - int erase, int redraw, int keepframe) -{ - pthread_attr_t update_child_attr; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( x->x_updatechild != 0 ) - { - // post( "cooled~ : error : no update is possible for now" ); - return; - } - x->x_updatestart = bstart; - x->x_updateend = bend; - if ( !keepframe ) - { - x->x_erase = 0; - } - else - { - x->x_erase = erase; - } - x->x_redraw = redraw; - // recreate the square if needed - if ( glist_isvisible( x->x_glist ) ) - { - if ( ( bstart == 0 ) && ( bend == x->x_width-1 ) && !keepframe ) - { - SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", canvas, x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", - canvas, x->x_xpos, x->x_ypos, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height/2*x->x_zoom, - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", - canvas, x->x_xpos, - x->x_ypos + x->x_height/2*x->x_zoom, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height*x->x_zoom, - x); - SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", canvas, x ); - SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", - x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); - SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); - SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", - canvas, - x->x_xpos+(x->x_width*x->x_zoom)/2, - x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); - canvas_fixlinesfor( canvas, (t_text*)x ); - } - // set borders in red - SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #FF0000\n", canvas, x); - } - - // launch update thread - if ( pthread_attr_init( &update_child_attr ) < 0 ) { - post( "cooled~ : could not launch update thread" ); - perror( "pthread_attr_init" ); - return; - } - if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { - post( "cooled~ : could not launch update thread" ); - perror( "pthread_attr_setdetachstate" ); - return; - } - if ( pthread_create( &x->x_updatechild, &update_child_attr, cooled_do_update_part, x ) < 0 ) { - post( "cooled~ : could not launch update thread" ); - perror( "pthread_create" ); - return; - } - else - { - // post( "cooled~ : drawing thread %d launched", (int)x->x_updatechild ); - } -} - -static void cooled_draw_new(t_cooled *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - x->x_xpos=text_xpix(&x->x_obj, glist); - x->x_ypos=text_ypix(&x->x_obj, glist); - x->x_xdraw=text_xpix(&x->x_obj, glist); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", - canvas, x->x_xpos, x->x_ypos, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height/2*x->x_zoom, - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", - canvas, x->x_xpos, - x->x_ypos + x->x_height/2*x->x_zoom, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height*x->x_zoom, - x); - SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", - x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); - SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); - SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", - canvas, - x->x_xpos+(x->x_width*x->x_zoom)/2, - x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); - if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void cooled_draw_delete(t_cooled *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( glist_isvisible( glist ) ) - { - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); - if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) - { - SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", canvas, x); - } - SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", canvas, x ); - SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", canvas, x ); - SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); - } -} - -static void cooled_draw_move(t_cooled *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( glist_isvisible( x->x_glist ) ) - { - SYS_VGUI7(".x%x.c coords %xCOOLEDR %d %d %d %d\n", - canvas, x, - x->x_xpos, x->x_ypos, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height/2*x->x_zoom); - SYS_VGUI7(".x%x.c coords %xCOOLEDL %d %d %d %d\n", - canvas, x, - x->x_xpos, - x->x_ypos + x->x_height/2*x->x_zoom, - x->x_xpos + x->x_width*x->x_zoom, - x->x_ypos + x->x_height*x->x_zoom ); - if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) - { - SYS_VGUI7(".x%x.c coords %xCLIPZONE %d %d %d %d\n", - canvas, x, - x->x_xpos+(int)(x->x_readstart*(x->x_width)/100*x->x_zoom ), - x->x_ypos, - x->x_xpos+(int)(x->x_readend*(x->x_width)/100*x->x_zoom ), - x->x_ypos+x->x_height*x->x_zoom ); - } - SYS_VGUI7(".x%x.c coords %xINSERTHERE %d %d %d %d\n", - canvas, x, - x->x_xdraw, - x->x_ypos, - x->x_xdraw, - x->x_ypos+x->x_height*x->x_zoom ); - SYS_VGUI5(".x%x.c coords ICOOLEDIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_width*x->x_zoom)/2), - (x->x_ypos+((x->x_height*x->x_zoom)/2)) ); - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void cooled_draw_select(t_cooled* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( glist_isvisible( x->x_glist ) ) - { - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #0000FF\n", canvas, x); - SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #0000FF\n", canvas, x); - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #000000\n", canvas, x); - SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #000000\n", canvas, x); - } - } -} - -/* ------------------------ widget callbacks ----------------------------- */ - - - /* setting the starting point for reading ( in percent ) */ -static void cooled_readstart(t_cooled *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - x->x_readstart = startpoint; - // set readspeed sign - if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", - canvas, x); - if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) - { - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", - canvas, x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), - x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), - x->x_ypos+x->x_height*x->x_zoom, x ); - } - } - outlet_float( x->x_sampstart, (x->x_readstart*x->x_size)/100 ); -} - - /* setting the ending point for reading ( in percent ) */ -static void cooled_readend(t_cooled *x, t_floatarg fend) -{ - t_float endpoint = fend; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - x->x_readend = endpoint; - // set readspeed sign - if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", - canvas, x); - if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) - { - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", - canvas, - x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), - x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), - x->x_ypos+x->x_height*x->x_zoom, x ); - } - } - outlet_float( x->x_sampend, (x->x_readend*x->x_size)/100 ); -} - -static void cooled_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_cooled* x = (t_cooled*)z; - - *xp1 = x->x_xpos; - *yp1 = x->x_ypos; - *xp2 = x->x_xpos+x->x_width*x->x_zoom; - *yp2 = x->x_ypos+x->x_height*x->x_zoom+1; -} - -static void cooled_save(t_gobj *z, t_binbuf *b) -{ - t_cooled *x = (t_cooled *)z; - - binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), - (int)x->x_obj.te_xpix, (int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_size, x->x_width, x->x_height, x->x_draw ); - binbuf_addv(b, ";"); -} - -static void cooled_select(t_gobj *z, t_glist *glist, int selected) -{ - t_cooled *x = (t_cooled *)z; - - x->x_selected = selected; - cooled_draw_select( x, glist ); -} - -static void cooled_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_cooled *x = (t_cooled *)z; - t_rtext *y; - - if (vis) - { - cooled_draw_new( x, glist ); - } - else - { - // erase all points - cooled_draw_delete( x, glist ); - } -} - -static void cooled_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void cooled_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_cooled *x = (t_cooled *)z; - int xold = x->x_xpos; - int yold = x->x_ypos; - - x->x_xpos += dx; - x->x_ypos += dy; - - if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) - { - cooled_draw_move( x, glist ); - } - -} - -static void cooled_motion(t_cooled *x, t_floatarg dx, t_floatarg dy) -{ - // post( "cooled_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); - if ( dx != 0 ) - { - cooled_readstart( x, ((t_float)( x->x_xdraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); - x->x_edraw += dx; - cooled_readend( x, ((t_float)( x->x_edraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); - } -} - - /* erase data form readstart to readend */ -static void cooled_erase( t_cooled *x ) -{ - int startsamp, endsamp, si; - int lreadstart = x->x_readstart, lreadend = x->x_readend; - - if (x->x_allocate) { - post( "cooled~ : error : cannot erase while re-allocation" ); - return; - } - // post( "cooled~ : erase" ); - if ( lreadstart <= lreadend ) - { - startsamp = (lreadstart*x->x_size)/100; - endsamp = (lreadend*x->x_size)/100; - } - else - { - startsamp = (lreadend*x->x_size)/100; - endsamp = (lreadstart*x->x_size)/100; - } - - for ( si=startsamp; si<=endsamp; si++ ) - { - *(x->x_rdata+si) = 0.; - *(x->x_ldata+si) = 0.; - } - if ( x->x_draw ) cooled_update_part(x, x->x_glist, startsamp*x->x_width/x->x_size, endsamp*(x->x_width-1)/x->x_size, 0, 1, 1); -} - /* paste data form readstart to readend */ -static void cooled_paste( t_cooled *x ) -{ - int startsamp, endsamp, si, inssamp, hlimit, csize; - int lreadstart = x->x_readstart, lreadend = x->x_readend; - - if (x->x_allocate) { - post( "cooled~ : error : cannot paste while re-allocation" ); - return; - } - if ( lreadstart <= lreadend ) - { - startsamp = (lreadstart*x->x_size)/100; - endsamp = (lreadend*x->x_size)/100; - } - else - { - startsamp = (lreadend*x->x_size)/100; - endsamp = (lreadstart*x->x_size)/100; - } - - // insert data at insertion point - inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); - // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); - csize=endsamp-startsamp; - for ( si=0; si<=csize; si++ ) - { - if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; - *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); - *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); - } - hlimit = si; - for ( si=0 ; si<=hlimit; si++ ) - { - *(x->x_rdata+inssamp+si) += *(x->x_rsemp+si); - *(x->x_ldata+inssamp+si) += *(x->x_lsemp+si); - } - - // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); - if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); -} - /* replace data form readstart to readend */ -static void cooled_replace( t_cooled *x ) -{ - int startsamp, endsamp, si, inssamp, hlimit, csize; - int lreadstart = x->x_readstart, lreadend = x->x_readend; - - if (x->x_allocate) { - post( "cooled~ : error : cannot replace while re-allocation" ); - return; - } - if ( lreadstart <= lreadend ) - { - startsamp = (lreadstart*x->x_size)/100; - endsamp = (lreadend*x->x_size)/100; - } - else - { - startsamp = (lreadend*x->x_size)/100; - endsamp = (lreadstart*x->x_size)/100; - } - - // insert data at insertion point - inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); - // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); - csize=endsamp-startsamp; - for ( si=0; si<=csize; si++ ) - { - if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; - *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); - *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); - } - hlimit = si; - for ( si=0 ; si<=hlimit; si++ ) - { - *(x->x_rdata+inssamp+si) = *(x->x_rsemp+si); - *(x->x_ldata+inssamp+si) = *(x->x_lsemp+si); - } - - // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); - if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); - -} - - /* call editor's property dialog */ -static void cooled_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_cooled *x=(t_cooled *)z; - - sprintf(buf, "pdtk_cooled_dialog %%s %d %d %d\n", - x->x_width, x->x_height, x->x_draw); - // post("cooled_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - - /* handle properties change */ -static void cooled_dialog(t_cooled *x, t_symbol *s, int argc, t_atom *argv) -{ - if ( !x ) { - post( "cooled~ : error :tried to set properties on an unexisting object" ); - } - if ( argc != 3 ) - { - post( "cooled~ : error in the number of arguments ( %d instead of 3 )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || argv[2].a_type != A_FLOAT ) { - post( "cooled~ : wrong arguments" ); - return; - } - cooled_draw_delete(x, x->x_glist); - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } - x->x_width = (int)argv[0].a_w.w_float; - if ( x->x_width < 0 ) x->x_width = 100; - x->x_height = (int)argv[1].a_w.w_float; - if ( x->x_height < 0 ) x->x_height = 100; - x->x_draw = (int)argv[2].a_w.w_float; - if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return; - } else { - post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return; - } else { - post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - cooled_draw_new(x, x->x_glist); -} - - /* handle clicks */ -static int cooled_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_cooled* x = (t_cooled *)z; - int pipos; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - // post( "cooled_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); - if ( doit ) - { - if ( shift && alt ) - { - cooled_paste(x); - } - else if ( shift ) - { - cooled_replace(x); - } - else if ( alt ) - { - cooled_erase(x); - } - else - { - x->x_xdraw = xpix; - x->x_edraw = xpix; - x->x_shifted = shift; - x->x_alted = alt; - // activate motion callback - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)cooled_motion, - 0, xpix, ypix ); - - // draw insertion line - if ( glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", - canvas, x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #00FFFF -tags %xINSERTHERE -width 2\n", - canvas, x->x_xdraw, - x->x_ypos, x->x_xdraw, - x->x_ypos+x->x_height*x->x_zoom, x ); - } - - } - - } - else - { - // nothing - } - return (1); - -} - - /* clean up */ -static void cooled_free(t_cooled *x) -{ - if ( x->x_rdata != NULL ) { - freebytes(x->x_rdata, x->x_size*sizeof(float) ); - post( "Freed %d bytes", x->x_size*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_ldata != NULL ) { - freebytes(x->x_ldata, x->x_size*sizeof(float) ); - post( "Freed %d bytes", x->x_size*sizeof(float) ); - x->x_ldata = NULL; - } - if ( x->x_rsemp != NULL ) { - freebytes(x->x_rsemp, x->x_size*sizeof(float) ); - post( "Freed %d bytes", x->x_size*sizeof(float) ); - x->x_rsemp = NULL; - } - if ( x->x_lsemp != NULL ) { - freebytes(x->x_lsemp, x->x_size*sizeof(float) ); - post( "Freed %d bytes", x->x_size*sizeof(float) ); - x->x_lsemp = NULL; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } -} - - /* allocate tables for storing sound and temporary copy */ -static int cooled_allocate(t_cooled *x) -{ - int fi; - - if ( !(x->x_rdata = getbytes( x->x_size*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); - } - if ( !(x->x_ldata = getbytes( x->x_size*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); - } - if ( !(x->x_rsemp = getbytes( x->x_size*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); - } - if ( !(x->x_lsemp = getbytes( x->x_size*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); - } - if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - - return 0; -} - - /* allocate tables for storing sound and temporary copy */ -static int cooled_reallocate(t_cooled *x, int ioldsize, int inewsize) -{ - int fi, csize; - t_float *prdata=x->x_rdata, *pldata=x->x_ldata, *prsemp=x->x_rsemp, *plsemp=x->x_lsemp; - - if ( !(x->x_rdata = getbytes( inewsize*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); - } - if ( !(x->x_ldata = getbytes( inewsize*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); - } - if ( !(x->x_rsemp = getbytes( inewsize*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); - } - if ( !(x->x_lsemp = getbytes( inewsize*sizeof(float) ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return -1; - } else { - post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); - } - - if ( ioldsize <= inewsize ) - { - csize = ioldsize; - } - else - { - csize = inewsize; - } - memcpy( x->x_rdata, prdata, csize*sizeof(float) ); - memcpy( x->x_ldata, pldata, csize*sizeof(float) ); - memcpy( x->x_rsemp, prsemp, csize*sizeof(float) ); - memcpy( x->x_lsemp, plsemp, csize*sizeof(float) ); - - if ( prdata != NULL ) { - freebytes(prdata, ioldsize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*sizeof(float) ); - } - if ( pldata != NULL ) { - freebytes(pldata, ioldsize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*sizeof(float) ); - } - if ( prsemp != NULL ) { - freebytes(prsemp, ioldsize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*sizeof(float) ); - } - if ( plsemp != NULL ) { - freebytes(plsemp, ioldsize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*sizeof(float) ); - } - - return 0; -} - - /* records and playback the sound */ -static t_int *cooled_perform(t_int *w) -{ - t_float *lin = (t_float *)(w[1]); - t_float *rin = (t_float *)(w[2]); - t_float *rout = (t_float *)(w[3]); - t_float *lout = (t_float *)(w[4]); - int is; - int n = (int)(w[5]); /* number of samples */ - int startsamp, endsamp; - t_cooled *x = (t_cooled *)(w[6]); - int lreadstart = x->x_readstart, lreadend = x->x_readend; - - if ( lreadstart <= lreadend ) - { - startsamp = (lreadstart*x->x_size)/100; - endsamp = (lreadend*x->x_size)/100; - } - else - { - startsamp = (lreadend*x->x_size)/100; - endsamp = (lreadstart*x->x_size)/100; - } - - while (n--) - { - // eventually records input - if ( x->x_record ) { - *(x->x_ldata+x->x_writepos)=*(lin); - *(x->x_rdata+x->x_writepos)=*(rin); - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); - outlet_bang(x->x_recend); - if ( x->x_empty ) x->x_empty = 0; - // post( "cooled~ : stopped recording" ); - } - } - // set outputs - *rout = 0.0; - *lout = 0.0; - if ( x->x_play) { - is=0; - *lout = *(x->x_ldata+(int)x->x_readpos); - *rout = *(x->x_rdata+(int)x->x_readpos); - x->x_readpos+=x->x_readspeed; - // post( "xreadpos : %f (added %f) %d", x->x_readpos, x->x_readspeed, x->x_readend ); - if ( ( x->x_readspeed >= 0 ) && ( x->x_readpos >= endsamp ) ) { - x->x_play=0; - x->x_readpos=(float)(startsamp); - // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - if ( ( x->x_readspeed < 0 ) && ( x->x_readpos <= startsamp ) ) { - x->x_play=0; - x->x_readpos = (float)(endsamp); - // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - } - rout++;lout++; - rin++;lin++; - } - // post( "cooled~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); - return (w+7); -} - -static void cooled_dsp(t_cooled *x, t_signal **sp) -{ - dsp_add(cooled_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); -} - - /* record the cooled */ -static void cooled_record(t_cooled *x) -{ - if (x->x_allocate) { - post( "cooled~ : error : cannot record while re-allocation" ); - return; - } - x->x_record=1; - x->x_writepos=0; - post( "cooled~ : recording on" ); -} - - /* map to stereo */ -static void cooled_stereo(t_cooled *x) -{ - int si; - - if (x->x_allocate) { - post( "cooled~ : error : cannot map to stereo while re-allocation" ); - return; - } - for ( si=0; six_size; si++ ) - { - *(x->x_rdata+si) = *(x->x_ldata+si); - } - if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); -} - - /* play the cooled */ -static void cooled_play(t_cooled *x) -{ - x->x_play=1; - // post( "cooled~ : playing on" ); -} - - /* sets the reading speed */ -static void cooled_readspeed(t_cooled *x, t_floatarg freadspeed) -{ - x->x_readspeed=freadspeed; -} - - /* resize cooled */ -static void cooled_resize(t_cooled *x, t_floatarg fnewsize ) -{ - if (fnewsize <= 0) { - post( "cooled~ : error : wrong size" ); - return; - } - if (x->x_allocate) { - post( "cooled~ : error : cannot resize while re-allocation" ); - return; - } - if (x->x_updatechild > 0) { - post( "cooled~ : can't resize now, an update is pending." ); - return; - } - post( "cooled~ : reallocating tables" ); - x->x_allocate = 1; - x->x_play = 0; - x->x_record = 0; - cooled_readstart( x, 0); - cooled_readend( x, 100); - cooled_reallocate(x, x->x_size, fnewsize); - x->x_size = fnewsize; - x->x_empty = 1; - if ( x->x_readstart <= x->x_readend ) - { - x->x_readpos = (x->x_readstart*x->x_size)/100; - } - else - { - x->x_readpos = (x->x_readend*x->x_size)/100; - } - // erase all points, as data is zero no drawing is needed - if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, !x->x_empty, 1); - x->x_allocate = 0; -} - - /* set zoom factor */ -static void cooled_zoom(t_cooled *x, t_floatarg fzoom ) -{ - if (fzoom < 1) { - post( "cooled~ : error : wrong zoom factor" ); - return; - } - if (x->x_allocate) { - post( "cooled~ : error : cannot zoom while re-allocation" ); - return; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } - x->x_zoom = (int)fzoom; - if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return; - } else { - post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "cooled~ : error : could not allocate buffers" ); - return; - } else { - post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); -} - - /* modify the loop positions */ -static void cooled_loop(t_cooled *x, t_symbol *soperator ) -{ - char *operator = soperator->s_name; - int ci; - t_float fvalue, freadstart = x->x_readstart, freadend = x->x_readend; - - if ( (soperator->s_name[0] != '*') && - (soperator->s_name[0] != '/') && - (soperator->s_name[0] != '>') && - (soperator->s_name[0] != '<') ) { - post( "cooled~ : error : wrong operator argument : should be *|/|>|<" ); - return; - } - for ( ci=1; ci<(int)strlen( soperator->s_name ); ci++ ) - { - if ( !(isdigit(soperator->s_name[ci])||(soperator->s_name[ci]=='.')) ) { - post( "cooled~ : error : wrong operation value : %s : should be in a float format", soperator->s_name+1 ); - return; - } - } - if ( sscanf( soperator->s_name+1, "%f", &fvalue ) != 1 ) { - post( "cooled~ : error : can't get operation value" ); - return; - } - switch( soperator->s_name[0] ) - { - case '*' : - freadend = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); - break; - - case '/' : - if ( fvalue != 0 ) { freadend = x->x_readstart + (x->x_readend-x->x_readstart)/fvalue; }; - break; - - case '>' : - freadstart = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); - freadend = x->x_readend + fvalue*(x->x_readend-x->x_readstart); - break; - - case '<' : - freadstart = x->x_readstart - fvalue*(x->x_readend-x->x_readstart); - freadend = x->x_readend - fvalue*(x->x_readend-x->x_readstart); - break; - } - if ( freadstart < 0.0 ) freadstart = 0.0; - if ( freadend < 0.0 ) freadend = 0.0; - if ( freadstart > 100.0 ) freadstart = 100.0; - if ( freadend > 100.0 ) freadend = 100.0; - cooled_readstart( x, freadstart); - cooled_readend( x, freadend); -} - - /* refresh data */ -static void cooled_refresh(t_cooled *x) -{ - if (x->x_allocate) { - post( "cooled~ : error : cannot refresh while re-allocation" ); - return; - } - if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 1); -} - -static void *cooled_new(t_symbol *s, int argc, t_atom *argv) -{ - t_cooled *x = (t_cooled *)pd_new(cooled_class); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_recend = outlet_new(&x->x_obj, &s_bang ); - x->x_end = outlet_new(&x->x_obj, &s_bang ); - x->x_sampstart = outlet_new(&x->x_obj, &s_float ); - x->x_sampend = outlet_new(&x->x_obj, &s_float ); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); - - if ( argc != 0 ) - { - if ( argc < 3 ) - { - post( "audience~ : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT ) { - post( "audience~ : wrong arguments" ); - return NULL; - } - x->x_size = (int)argv[0].a_w.w_float; - if ( x->x_size < 1 ) x->x_size = 1; - x->x_width = (int)argv[1].a_w.w_float; - if ( x->x_width < 10 ) x->x_width = 10; - x->x_height = (int)argv[2].a_w.w_float; - if ( x->x_height < 10 ) x->x_height = 10; - if ( argc == 3 ) - x->x_draw = 1; - else - x->x_draw = (int)argv[3].a_w.w_float; - } - else - { - x->x_size = COOLED_DEFAULT_SIZE; - x->x_width = COOLED_DEFAULT_WIDTH; - x->x_height = COOLED_DEFAULT_HEIGHT; - x->x_draw = 1; - } - - // activate graphical callbacks - class_setwidget(cooled_class, &cooled_widgetbehavior); - - x->x_play = 0; - x->x_readspeed = 1.; - x->x_record = 0; - x->x_allocate = 0; - x->x_readpos = 0.; - x->x_writepos = 0; - x->x_rdata = NULL; - x->x_ldata = NULL; - x->x_empty = 1; - x->x_xpos = -1; - x->x_ypos = -1; - /* graphic data */ - x->x_selected = 0; - x->x_zoom = 1; - x->x_updatechild = 0; - x->x_glist = (t_glist*)canvas_getcurrent(); - // post( "cooled~ : new : readend=%d", x->x_readend ); - cooled_readstart( x, 0); - cooled_readend( x, 100); - - if ( cooled_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } - -} - -void cooled_tilde_setup(void) -{ -#include "cooled~.tk2c" - post(cooled_version); - cooled_class = class_new(gensym("cooled~"), (t_newmethod)cooled_new, (t_method)cooled_free, - sizeof(t_cooled), 0, A_GIMME, 0); - - - // set callbacks - cooled_widgetbehavior.w_getrectfn = cooled_getrect; - cooled_widgetbehavior.w_displacefn = cooled_displace; - cooled_widgetbehavior.w_selectfn = cooled_select; - cooled_widgetbehavior.w_activatefn = NULL; - cooled_widgetbehavior.w_deletefn = cooled_delete; - cooled_widgetbehavior.w_visfn = cooled_vis; - cooled_widgetbehavior.w_clickfn = cooled_click; - - class_setpropertiesfn(cooled_class, cooled_properties); - class_setsavefn(cooled_class, cooled_save); - - CLASS_MAINSIGNALIN( cooled_class, t_cooled, x_f ); - class_addmethod(cooled_class, (t_method)cooled_dsp, gensym("dsp"), A_NULL); - class_addmethod(cooled_class, (t_method)cooled_record, gensym("record"), A_NULL); - class_addmethod(cooled_class, (t_method)cooled_resize, gensym("resize"), A_FLOAT, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_zoom, gensym("zoom"), A_FLOAT, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_play, gensym("play"), A_NULL); - class_addmethod(cooled_class, (t_method)cooled_refresh, gensym("refresh"), A_NULL); - class_addmethod(cooled_class, (t_method)cooled_readstart, gensym("readstart"), A_FLOAT, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_stereo, gensym("stereo"), A_NULL); - class_addmethod(cooled_class, (t_method)cooled_readend, gensym("readend"), A_FLOAT, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_loop, gensym("loop"), A_SYMBOL, A_NULL); - class_addmethod(cooled_class, (t_method)cooled_dialog, gensym("dialog"), A_GIMME, 0); -} diff --git a/cooled~/cooled~.tk b/cooled~/cooled~.tk deleted file mode 100644 index ebd7699..0000000 --- a/cooled~/cooled~.tk +++ /dev/null @@ -1,87 +0,0 @@ -############ cooled procedures -- ydegoyon@free.fr ######### - -proc cooled_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_draw [concat graph_draw_$vid] - global $var_graph_draw - - set cmd [concat $id dialog \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_draw] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc cooled_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc cooled_ok {id} { - cooled_apply $id - cooled_cancel $id -} - -proc pdtk_cooled_dialog {id width height draw} { - set vid [string trimleft $id .] - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_draw [concat graph_draw_$vid] - global $var_graph_draw - - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_draw $draw - - toplevel $id - wm title $id {cooled} - wm protocol $id WM_DELETE_WINDOW [concat cooled_cancel $id] - - label $id.label -text {EDITOR PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "cooled_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "cooled_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "cooled_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lwidth -text "Width :" - entry $id.1rangef.width -textvariable $var_graph_width -width 7 - pack $id.1rangef.lwidth $id.1rangef.width -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lheight -text "Height :" - entry $id.2rangef.height -textvariable $var_graph_height -width 7 - pack $id.2rangef.lheight $id.2rangef.height -side left - - checkbutton $id.draw -text {Draw Sample} -variable $var_graph_draw \ - -anchor w - pack $id.draw -side top - - bind $id.1rangef.width [concat cooled_ok $id] - bind $id.2rangef.height [concat cooled_ok $id] - focus $id.1rangef.width -} - -############ cooled procedures END -- ydegoyon@free.fr ######### diff --git a/cooled~/cooled~.tk2c b/cooled~/cooled~.tk2c deleted file mode 100755 index 417c279..0000000 --- a/cooled~/cooled~.tk2c +++ /dev/null @@ -1,65 +0,0 @@ -// ########### cooled procedures -- ydegoyon@free.fr ######### -sys_gui("proc cooled_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_draw [concat graph_draw_$vid]\n"); -sys_gui("global $var_graph_draw\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_draw] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc cooled_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc cooled_ok {id} {\n"); -sys_gui("cooled_apply $id\n"); -sys_gui("cooled_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_cooled_dialog {id width height draw} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_draw [concat graph_draw_$vid]\n"); -sys_gui("global $var_graph_draw\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_draw $draw\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {cooled}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat cooled_cancel $id]\n"); -sys_gui("label $id.label -text {EDITOR PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"cooled_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"cooled_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"cooled_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.1rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.1rangef.lwidth $id.1rangef.width -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.2rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.2rangef.lheight $id.2rangef.height -side left\n"); -sys_gui("checkbutton $id.draw -text {Draw Sample} -variable $var_graph_draw -anchor w\n"); -sys_gui("pack $id.draw -side top\n"); -sys_gui("bind $id.1rangef.width [concat cooled_ok $id]\n"); -sys_gui("bind $id.2rangef.height [concat cooled_ok $id]\n"); -sys_gui("focus $id.1rangef.width\n"); -sys_gui("}\n"); -// ########### cooled procedures END -- ydegoyon@free.fr ######### diff --git a/cooled~/tk2c.bash b/cooled~/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/cooled~/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/countund-help.pd b/countund-help.pd new file mode 100644 index 0000000..89c1207 --- /dev/null +++ b/countund-help.pd @@ -0,0 +1,17 @@ +#N canvas 194 211 575 337 10; +#X floatatom 192 112 5 0 0; +#X msg 76 156 bang; +#X text 161 29 Count up to a limit and then down to zero; +#X text 160 41 Bugs and comments @ ydegoyon@free.fr; +#X text 194 88 Set upper limit; +#X obj 121 143 countund 100; +#X obj 118 113 metro 100; +#X msg 115 82 bang; +#X obj 121 179 print countund; +#X floatatom 223 179 5 0 0; +#X connect 0 0 5 1; +#X connect 1 0 8 0; +#X connect 5 0 8 0; +#X connect 5 0 9 0; +#X connect 6 0 5 0; +#X connect 7 0 6 0; diff --git a/countund.c b/countund.c new file mode 100644 index 0000000..976f79c --- /dev/null +++ b/countund.c @@ -0,0 +1,115 @@ +/* ------------------------ countund~ -------------------------------------- */ +/* */ +/* Count up to a value and then down to zero */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#include +#include +#include + +#include /* standard pd stuff */ + +static char *countund_version = "countund~: count up to a value and then down to zero : author : ydegoyon@free.fr"; + +static t_class *countund_class; + +typedef struct _countund +{ + t_object x_obj; + t_int x_limit; + t_int x_value; + t_int x_up; +} t_countund; + + /* clean up */ +static void countund_free(t_countund *x) +{ +} + +static void *countund_new(t_float flimit) +{ + t_countund *x = (t_countund *)pd_new(countund_class); + outlet_new(&x->x_obj, &s_float); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("limit")); + if ( flimit < 0 ) { + post( "countund~: wrong creation argument" ); + return NULL; + } + x->x_limit = (int) flimit; + x->x_value = 0; + x->x_up = 1; + return(x); +} + +static void *countund_limit(t_countund* x, t_float flimit) +{ + if ( flimit < 0 ) { + post( "countund~: wrong count limit" ); + return; + } else { + x->x_limit=(int)flimit; + } +} + +static void *countund_bang(t_countund *x) +{ + + if ( x->x_up ) { + x->x_value+=1; + if (x->x_value>x->x_limit) { + x->x_value=x->x_limit-1; + x->x_up=0; + } + } else { + x->x_value-=1; + if (x->x_value<0) { + x->x_value=1; + x->x_up=1; + } + } + outlet_float( x->x_obj.ob_outlet, x->x_value ); + return; +} + +void countund_setup(void) +{ + post(countund_version); + countund_class = class_new(gensym("countund"), (t_newmethod)countund_new, + (t_method)countund_free, + sizeof(t_countund), 0, A_DEFFLOAT, 0); + class_addmethod( countund_class, (t_method)countund_bang, &s_bang, 0); + class_addmethod( countund_class, (t_method)countund_limit, gensym("limit"), A_FLOAT, 0); +} diff --git a/countund/INSTALL b/countund/INSTALL deleted file mode 100644 index f2488de..0000000 --- a/countund/INSTALL +++ /dev/null @@ -1,7 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/extra/countund~ - -make - -you're set !! diff --git a/countund/countund-help.pd b/countund/countund-help.pd deleted file mode 100644 index 89c1207..0000000 --- a/countund/countund-help.pd +++ /dev/null @@ -1,17 +0,0 @@ -#N canvas 194 211 575 337 10; -#X floatatom 192 112 5 0 0; -#X msg 76 156 bang; -#X text 161 29 Count up to a limit and then down to zero; -#X text 160 41 Bugs and comments @ ydegoyon@free.fr; -#X text 194 88 Set upper limit; -#X obj 121 143 countund 100; -#X obj 118 113 metro 100; -#X msg 115 82 bang; -#X obj 121 179 print countund; -#X floatatom 223 179 5 0 0; -#X connect 0 0 5 1; -#X connect 1 0 8 0; -#X connect 5 0 8 0; -#X connect 5 0 9 0; -#X connect 6 0 5 0; -#X connect 7 0 6 0; diff --git a/countund/countund.c b/countund/countund.c deleted file mode 100644 index 976f79c..0000000 --- a/countund/countund.c +++ /dev/null @@ -1,115 +0,0 @@ -/* ------------------------ countund~ -------------------------------------- */ -/* */ -/* Count up to a value and then down to zero */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#include -#include -#include - -#include /* standard pd stuff */ - -static char *countund_version = "countund~: count up to a value and then down to zero : author : ydegoyon@free.fr"; - -static t_class *countund_class; - -typedef struct _countund -{ - t_object x_obj; - t_int x_limit; - t_int x_value; - t_int x_up; -} t_countund; - - /* clean up */ -static void countund_free(t_countund *x) -{ -} - -static void *countund_new(t_float flimit) -{ - t_countund *x = (t_countund *)pd_new(countund_class); - outlet_new(&x->x_obj, &s_float); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("limit")); - if ( flimit < 0 ) { - post( "countund~: wrong creation argument" ); - return NULL; - } - x->x_limit = (int) flimit; - x->x_value = 0; - x->x_up = 1; - return(x); -} - -static void *countund_limit(t_countund* x, t_float flimit) -{ - if ( flimit < 0 ) { - post( "countund~: wrong count limit" ); - return; - } else { - x->x_limit=(int)flimit; - } -} - -static void *countund_bang(t_countund *x) -{ - - if ( x->x_up ) { - x->x_value+=1; - if (x->x_value>x->x_limit) { - x->x_value=x->x_limit-1; - x->x_up=0; - } - } else { - x->x_value-=1; - if (x->x_value<0) { - x->x_value=1; - x->x_up=1; - } - } - outlet_float( x->x_obj.ob_outlet, x->x_value ); - return; -} - -void countund_setup(void) -{ - post(countund_version); - countund_class = class_new(gensym("countund"), (t_newmethod)countund_new, - (t_method)countund_free, - sizeof(t_countund), 0, A_DEFFLOAT, 0); - class_addmethod( countund_class, (t_method)countund_bang, &s_bang, 0); - class_addmethod( countund_class, (t_method)countund_limit, gensym("limit"), A_FLOAT, 0); -} diff --git a/disto~-help.pd b/disto~-help.pd new file mode 100644 index 0000000..593702b --- /dev/null +++ b/disto~-help.pd @@ -0,0 +1,73 @@ +#N canvas 45 57 817 573 10; +#X text 389 525 comments & bugs @ ydegoyon.free.fr; +#X obj 125 503 dac~; +#X obj 146 432 rs-disto~; +#X msg 94 62 bang; +#X obj 93 84 openpanel; +#X obj 93 104 t s b; +#X obj 150 106 float \$0; +#X text 101 39 Step 1 : Load a sound file; +#X obj 93 127 route float; +#X obj 94 219 soundfiler; +#X text 151 55 ( maybe \, a guitar sound ? ); +#X obj 582 374 table \$0-sample; +#X msg 94 197 read -resize \$1 \$2; +#X obj 95 176 pack s s; +#X msg 146 307 bang; +#X text 191 307 Step 2 : Start playing; +#X obj 59 288 adc~; +#X text 226 433 Step 3 : Modify parameters; +#X text 584 510 ( http://st.karelia.ru/~smlalx ); +#X text 391 496 a DOS guitar effects software that rocks; +#X obj 606 263 loadbang; +#X msg 608 293 \; pd dsp 1; +#X text 390 482 the algorithm is borrowed from Digital Effects \,; +#X text 35 266 Plug a guitar ??; +#X msg 228 330 stop; +#X obj 146 330 metro 250; +#X text 431 111 Disto~ : distortion with highpass and lowpass filters +; +#X obj 93 150 makefilename %d-sample; +#X obj 80 423 *~ 0; +#X obj 154 461 *~ 0; +#X msg 172 380 1; +#X msg 207 379 0; +#X text 287 382 Normal sound; +#X msg 242 380 bang; +#X msg 178 404 1; +#X msg 213 403 0; +#X msg 248 404 bang; +#X text 355 405 Distorted sound; +#X text 392 510 written by (c) Alexei Smoli; +#X obj 146 354 tabplay~ \$0-sample; +#X obj 287 404 loadbang; +#X connect 2 0 29 0; +#X connect 3 0 4 0; +#X connect 4 0 5 0; +#X connect 5 0 13 0; +#X connect 5 1 6 0; +#X connect 6 0 8 0; +#X connect 8 0 27 0; +#X connect 12 0 9 0; +#X connect 13 0 12 0; +#X connect 14 0 25 0; +#X connect 16 0 2 0; +#X connect 20 0 21 0; +#X connect 24 0 25 0; +#X connect 25 0 39 0; +#X connect 27 0 13 1; +#X connect 28 0 1 0; +#X connect 28 0 1 1; +#X connect 29 0 1 0; +#X connect 29 0 1 1; +#X connect 30 0 28 1; +#X connect 31 0 29 1; +#X connect 33 0 31 0; +#X connect 33 0 30 0; +#X connect 34 0 29 1; +#X connect 35 0 28 1; +#X connect 36 0 35 0; +#X connect 36 0 34 0; +#X connect 39 0 2 0; +#X connect 39 0 28 0; +#X connect 40 0 36 0; diff --git a/disto~.c b/disto~.c new file mode 100644 index 0000000..66865db --- /dev/null +++ b/disto~.c @@ -0,0 +1,490 @@ +/* Copyleft (c) 2002 Yves Degoyon. */ +/* Copyright (c) 2001 Alexei Smoli */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "COPYING" in this distribution. */ +/* */ +/* disto~ -- a kind of effect used in pop music */ +/* the algorithm was taken from Digital Effects (DISTORT3), */ +/* a guitar effects software for DOS which rocks, written by Alexey Smoli */ +/* ( http://st.karelia.ru/~smlalx/ ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* Bruce Gilbert -- Ab Ovo */ +/* Poison Girls -- Promenade Immortelle */ +/* */ +/* Special message for the french : */ +/* "Delay all your work...and go vote against national front" */ +/* ---------------------------------------------------------------------------- */ + +#include "m_pd.h" +#include +#include + +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif + +#define BFSZ 4096 /* main delay buffer */ +#define BLOCK_DELAY 10 /* number of blocks to delay */ +#define NA 0.0 /* param not applicable */ +#define NBEXPS 129 + +static char *disto_version = "disto~: distortion, version 0.1 (ydegoyon@free.fr)"; + +struct hipass { + /* few intermediate variables */ + double omega; + double sn,cs; + double alpha; + /* filter coefficients */ + double a0,a1,a2,b0,b1,b2; + double k0,k1,k2,k3,k4; + /* amplitudes */ + double x0,x1,x2; + double y0,y1,y2; +} hipass; + +struct lowpass { + /* few intermediate variables */ + double omega; + double sn,cs; + double alpha; + /* filter coefficients */ + double a0,a1,a2,b0,b1,b2; + double k0,k1,k2,k3,k4; + /* amplitudes */ + double x0,x1,x2; + double y0,y1,y2; +} lowpass; + +typedef struct _disto +{ + t_object x_obj; + double *x_buf; + t_int x_samplerate; + double x_drive; /* distortion drive */ /* 0<= <=25 */ + double x_drymix; /* dry (unaffected) signal mix */ /* -5<= <=5 */ + double x_wetmix; /* wet (affected) signal mix */ /* -5<= <=5 */ + double x_feedback; /* feedback */ /* -10<= <=10 */ + double x_volume; /* distortion volume */ /* 0=< <=5 */ + double x_hipassfreq; /* cutoff frequency for hi pass filter */ /* 0< exps[i]=exp((double)i*x->x_drive)*x->x_wetmix; + } + + x->HPF.omega = 2.0*M_PI*x->x_hipassfreq/(double)x->x_samplerate; + x->HPF.sn = sin(x->HPF.omega); + x->HPF.cs = cos(x->HPF.omega); + x->HPF.alpha = x->HPF.sn/(2.0*x->x_hipassQ); + x->HPF.b0 = (1.0 + x->HPF.cs)/2.0; + x->HPF.b1 = -(1.0 + x->HPF.cs) ; + x->HPF.b2 = (1.0 + x->HPF.cs)/2.0; + x->HPF.a0 = 1.0 + x->HPF.alpha ; + x->HPF.a1 = -2.0*x->HPF.cs ; + x->HPF.a2 = 1.0 - x->HPF.alpha ; + x->HPF.k0 = (x->HPF.b0/x->HPF.a0); + x->HPF.k1 = (x->HPF.b1/x->HPF.a0); + x->HPF.k2 = (x->HPF.b2/x->HPF.a0); + x->HPF.k3 = (x->HPF.a1/x->HPF.a0); + x->HPF.k4 = (x->HPF.a2/x->HPF.a0); + + x->LPF.omega = 2.0*M_PI*x->x_lowpassfreq/(double)x->x_samplerate; + x->LPF.sn = sin(x->LPF.omega); + x->LPF.cs = cos(x->LPF.omega); + x->LPF.alpha = x->LPF.sn/(2.0*x->x_lowpassQ); + x->LPF.b0 = (1.0 - x->LPF.cs)/2.0; + x->LPF.b1 = 1.0 - x->LPF.cs ; + x->LPF.b2 = (1.0 - x->LPF.cs)/2.0; + x->LPF.a0 = 1.0 + x->LPF.alpha ; + x->LPF.a1 = -2.0*x->LPF.cs ; + x->LPF.a2 = 1.0 - x->LPF.alpha ; + x->LPF.k0 = (x->LPF.b0/x->LPF.a0); + x->LPF.k1 = (x->LPF.b1/x->LPF.a0); + x->LPF.k2 = (x->LPF.b2/x->LPF.a0); + x->LPF.k3 = (x->LPF.a1/x->LPF.a0); + x->LPF.k4 = (x->LPF.a2/x->LPF.a0); +} + +static void disto_drive(t_disto *x, t_floatarg fdrive ) +{ + if ( fdrive > 25.0 ) + { + fdrive = 25.0; + } + if ( fdrive < 0.0 ) + { + fdrive = 0.0; + } + x->x_drive = fdrive; + // post( "disto~ : drive: %f", x->x_drive ); + disto_init_filters( x ); +} + +static void disto_drymix(t_disto *x, t_floatarg fdrymix ) +{ + if ( fdrymix > 5.0 ) + { + fdrymix = 5.0; + } + if ( fdrymix < -5.0 ) + { + fdrymix = -5.0; + } + x->x_drymix = fdrymix; + // post( "disto~ : drymix: %f", x->x_drymix ); + disto_init_filters( x ); +} + +static void disto_wetmix(t_disto *x, t_floatarg fwetmix ) +{ + if ( fwetmix > 5.0 ) + { + fwetmix = 5.0; + } + if ( fwetmix < -5.0 ) + { + fwetmix = -5.0; + } + x->x_wetmix = fwetmix; + // post( "disto~ : wetmix: %f", x->x_wetmix ); + disto_init_filters( x ); +} + +static void disto_feedback(t_disto *x, t_floatarg ffeedback ) +{ + if ( ffeedback > 10.0 ) + { + ffeedback = 10.0; + } + if ( ffeedback < -10.0 ) + { + ffeedback = -10.0; + } + x->x_feedback = ffeedback; + // post( "disto~ : feedback: %f", x->x_feedback ); + disto_init_filters( x ); +} + +static void disto_volume(t_disto *x, t_floatarg fvolume ) +{ + if ( fvolume > 5.0 ) + { + fvolume = 5.0; + } + if ( fvolume < 0.0 ) + { + fvolume = 0.0; + } + x->x_volume = fvolume; + // post( "disto~ : volume: %f", x->x_volume ); + disto_init_filters( x ); +} + +static void disto_hipassfreq(t_disto *x, t_floatarg fhipassfreq ) +{ + if ( fhipassfreq > x->x_samplerate/2 ) + { + fhipassfreq = x->x_samplerate/2; + } + if ( fhipassfreq < 0.0 ) + { + fhipassfreq = 0.0; + } + x->x_hipassfreq = fhipassfreq; + // post( "disto~ : hipassfreq: %f", x->x_hipassfreq ); + disto_init_filters( x ); +} + +static void disto_hipassQ(t_disto *x, t_floatarg fhipassQ ) +{ + if ( fhipassQ > 1.0 ) + { + fhipassQ = 1.0; + } + if ( fhipassQ < 0.1 ) + { + fhipassQ = 0.1; + } + x->x_hipassQ = fhipassQ; + // post( "disto~ : hipassQ: %f", x->x_hipassQ ); + disto_init_filters( x ); +} + +static void disto_lowpassfreq(t_disto *x, t_floatarg flowpassfreq ) +{ + if ( flowpassfreq > x->x_samplerate/2 ) + { + flowpassfreq = x->x_samplerate/2; + } + if ( flowpassfreq < 0.0 ) + { + flowpassfreq = 0.0; + } + x->x_lowpassfreq = flowpassfreq; + // post( "disto~ : lowpassfreq: %f", x->x_lowpassfreq ); + disto_init_filters( x ); +} + +static void disto_lowpassQ(t_disto *x, t_floatarg flowpassQ ) +{ + if ( flowpassQ > 1.0 ) + { + flowpassQ = 1.0; + } + if ( flowpassQ < 0.1 ) + { + flowpassQ = 0.1; + } + x->x_lowpassQ = flowpassQ; + // post( "disto~ : lowpassQ: %f", x->x_lowpassQ ); + disto_init_filters( x ); +} + +static t_int *disto_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_int n = (int)(w[3]); + t_disto *x = (t_disto*)(w[4]); + t_int i; + + for (i = 0; i < n; i++) + { + + x->HPF.x0 = *(in++); + x->HPF.y0 = (x->HPF.k0*x->HPF.x0+x->HPF.k1*x->HPF.x1+x->HPF.k2*x->HPF.x2-x->HPF.k3*x->HPF.y1-x->HPF.k4*x->HPF.y2); + x->HPF.y2 = x->HPF.y1; + x->HPF.y1 = x->HPF.y0; + x->HPF.x2 = x->HPF.x1; + x->HPF.x1 = x->HPF.x0; + x->data = (int)x->HPF.y0; + + if ((x->data-x->pred)>0) + x->outval += (x->data*x->x_drymix+ x->exps[abs(x->data)]); + else + if ((x->data-x->pred)<0) + x->outval += (x->data*x->x_drymix- x->exps[abs(x->data)]); + x->pred = x->data; + + x->LPF.x0 = *(out); + x->LPF.y0 = (x->LPF.k0*x->LPF.x0+x->LPF.k1*x->LPF.x1+x->LPF.k2*x->LPF.x2-x->LPF.k3*x->LPF.y1-x->LPF.k4*x->LPF.y2); + x->LPF.y2 = x->LPF.y1; + x->LPF.y1 = x->LPF.y0; + x->LPF.x2 = x->LPF.x1; + x->LPF.x1 = x->LPF.x0; + + x->outvol = x->LPF.y0*x->x_volume; + + if(x->outvol > 1.0) + x->data = 1.0; + else if(x->outvol < -1.0) + x->data = -1.0; + else + x->data = x->outvol; + + *(out++) = x->data; + + x->outval *= x->x_feedback; + + } + + return (w+5); +} + +static void disto_preset(t_disto *x, t_float pnumber) +{ + switch ( (int)pnumber ) + { + /* "Hard Distortion 100-10000Hz" */ + case 1: + x->x_drive = 1.5; + x->x_drymix = 1.0; + x->x_wetmix = 0.5; + x->x_feedback = 0.0; + x->x_volume = 1.0; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 0.5; + x->x_lowpassfreq = 10000.0; + x->x_lowpassQ = 0.5; + break; + + /* "Hard Distortion 100-6000Hz" */ + case 2: + x->x_drive = 1.5; + x->x_drymix = 1.0; + x->x_wetmix = 0.5; + x->x_feedback = 0.0; + x->x_volume = 1.0; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 0.5; + x->x_lowpassfreq = 2000.0; + x->x_lowpassQ = 0.5; + break; + + /* "Very Hard Distortion" */ + case 3: + x->x_drive = 2.0; + x->x_drymix = 0.0; + x->x_wetmix = 1.0; + x->x_feedback = 1.0; + x->x_volume = 5.0; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 0.5; + x->x_lowpassfreq = 6000.0; + x->x_lowpassQ = 0.5; + break; + + /* "Medium Distortion 0.2" */ + case 4: + x->x_drive = 0.2; + x->x_drymix = 1.0; + x->x_wetmix = 1.0; + x->x_feedback = 0.1; + x->x_volume = 1.0; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 0.5; + x->x_lowpassfreq = 6000.0; + x->x_lowpassQ = 0.5; + break; + + /* "Medium Distortion 0.8" */ + case 5: + x->x_drive = 0.8; + x->x_drymix = 1.0; + x->x_wetmix = 1.0; + x->x_feedback = 0.1; + x->x_volume = 1.0; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 1.0; + x->x_lowpassfreq = 6000.0; + x->x_lowpassQ = 0.5; + break; + + /* "Soft Distortion 0.8" */ + case 6: + x->x_drive = 0.8; + x->x_drymix = 0.4; + x->x_wetmix = 0.8; + x->x_feedback = 0.0; + x->x_volume = 0.5; + x->x_hipassfreq = 100.0; + x->x_hipassQ = 1.0; + x->x_lowpassfreq = 10000.0; + x->x_lowpassQ = 0.5; + break; + + default: + post( "disto~ : unknown preset requested : %d", pnumber ); + return; + break; + } + disto_init_filters( x ); +} + +static void disto_dsp(t_disto *x, t_signal **sp) +{ + dsp_add(disto_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); +} + + /* clean up */ +static void disto_free(t_disto *x) +{ + if ( x->x_buf != NULL ) { + freebytes(x->x_buf, BFSZ*sizeof( double ) ); + post( "Freed %d bytes", BFSZ*sizeof( double ) ); + x->x_buf = NULL; + } +} + +static void *disto_new(void) +{ + t_disto *x = (t_disto *)pd_new(disto_class); + outlet_new(&x->x_obj, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("drive")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("drymix")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("wetmix")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("feedback")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("volume")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("hipassfreq")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("hipassQ")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lowpassfreq")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lowpassQ")); + + x->x_samplerate = (int)sys_getsr(); + x->pred = 0.0; + x->data = 0.0; + + if ( !( x->x_buf = ( double* ) getbytes( BFSZ*sizeof( double ) ) ) ) + { + post ("disto~ : could not allocate buffer" ); + return NULL; + } + + // set default parameters + disto_preset( x, 3 ); + disto_init_filters( x ); + + return (x); +} + +void disto_tilde_setup(void) +{ + post( disto_version ); + disto_class = class_new(gensym("disto~"), (t_newmethod)disto_new, (t_method)disto_free, + sizeof(t_disto), 0, 0); + + CLASS_MAINSIGNALIN( disto_class, t_disto, x_f ); + class_addmethod(disto_class, (t_method)disto_drive, gensym("drive"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_drymix, gensym("drymix"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_wetmix, gensym("wetmix"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_feedback, gensym("feedback"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_volume, gensym("volume"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_hipassfreq, gensym("hipassfreq"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_hipassQ, gensym("hipassQ"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_lowpassfreq, gensym("lowpassfreq"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_lowpassQ, gensym("lowpassQ"), A_FLOAT, 0); + class_addmethod(disto_class, (t_method)disto_dsp, gensym("dsp"), 0); + class_addmethod(disto_class, (t_method)disto_preset, gensym("preset"), A_FLOAT, 0); +} diff --git a/disto~/INSTALL b/disto~/INSTALL deleted file mode 100644 index 319f22a..0000000 --- a/disto~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/disto~ - -make clean - -make - -make install - -open help-disto~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/disto~/disto~-help.pd b/disto~/disto~-help.pd deleted file mode 100644 index 593702b..0000000 --- a/disto~/disto~-help.pd +++ /dev/null @@ -1,73 +0,0 @@ -#N canvas 45 57 817 573 10; -#X text 389 525 comments & bugs @ ydegoyon.free.fr; -#X obj 125 503 dac~; -#X obj 146 432 rs-disto~; -#X msg 94 62 bang; -#X obj 93 84 openpanel; -#X obj 93 104 t s b; -#X obj 150 106 float \$0; -#X text 101 39 Step 1 : Load a sound file; -#X obj 93 127 route float; -#X obj 94 219 soundfiler; -#X text 151 55 ( maybe \, a guitar sound ? ); -#X obj 582 374 table \$0-sample; -#X msg 94 197 read -resize \$1 \$2; -#X obj 95 176 pack s s; -#X msg 146 307 bang; -#X text 191 307 Step 2 : Start playing; -#X obj 59 288 adc~; -#X text 226 433 Step 3 : Modify parameters; -#X text 584 510 ( http://st.karelia.ru/~smlalx ); -#X text 391 496 a DOS guitar effects software that rocks; -#X obj 606 263 loadbang; -#X msg 608 293 \; pd dsp 1; -#X text 390 482 the algorithm is borrowed from Digital Effects \,; -#X text 35 266 Plug a guitar ??; -#X msg 228 330 stop; -#X obj 146 330 metro 250; -#X text 431 111 Disto~ : distortion with highpass and lowpass filters -; -#X obj 93 150 makefilename %d-sample; -#X obj 80 423 *~ 0; -#X obj 154 461 *~ 0; -#X msg 172 380 1; -#X msg 207 379 0; -#X text 287 382 Normal sound; -#X msg 242 380 bang; -#X msg 178 404 1; -#X msg 213 403 0; -#X msg 248 404 bang; -#X text 355 405 Distorted sound; -#X text 392 510 written by (c) Alexei Smoli; -#X obj 146 354 tabplay~ \$0-sample; -#X obj 287 404 loadbang; -#X connect 2 0 29 0; -#X connect 3 0 4 0; -#X connect 4 0 5 0; -#X connect 5 0 13 0; -#X connect 5 1 6 0; -#X connect 6 0 8 0; -#X connect 8 0 27 0; -#X connect 12 0 9 0; -#X connect 13 0 12 0; -#X connect 14 0 25 0; -#X connect 16 0 2 0; -#X connect 20 0 21 0; -#X connect 24 0 25 0; -#X connect 25 0 39 0; -#X connect 27 0 13 1; -#X connect 28 0 1 0; -#X connect 28 0 1 1; -#X connect 29 0 1 0; -#X connect 29 0 1 1; -#X connect 30 0 28 1; -#X connect 31 0 29 1; -#X connect 33 0 31 0; -#X connect 33 0 30 0; -#X connect 34 0 29 1; -#X connect 35 0 28 1; -#X connect 36 0 35 0; -#X connect 36 0 34 0; -#X connect 39 0 2 0; -#X connect 39 0 28 0; -#X connect 40 0 36 0; diff --git a/disto~/disto~.c b/disto~/disto~.c deleted file mode 100644 index 66865db..0000000 --- a/disto~/disto~.c +++ /dev/null @@ -1,490 +0,0 @@ -/* Copyleft (c) 2002 Yves Degoyon. */ -/* Copyright (c) 2001 Alexei Smoli */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "COPYING" in this distribution. */ -/* */ -/* disto~ -- a kind of effect used in pop music */ -/* the algorithm was taken from Digital Effects (DISTORT3), */ -/* a guitar effects software for DOS which rocks, written by Alexey Smoli */ -/* ( http://st.karelia.ru/~smlalx/ ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* Bruce Gilbert -- Ab Ovo */ -/* Poison Girls -- Promenade Immortelle */ -/* */ -/* Special message for the french : */ -/* "Delay all your work...and go vote against national front" */ -/* ---------------------------------------------------------------------------- */ - -#include "m_pd.h" -#include -#include - -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif - -#define BFSZ 4096 /* main delay buffer */ -#define BLOCK_DELAY 10 /* number of blocks to delay */ -#define NA 0.0 /* param not applicable */ -#define NBEXPS 129 - -static char *disto_version = "disto~: distortion, version 0.1 (ydegoyon@free.fr)"; - -struct hipass { - /* few intermediate variables */ - double omega; - double sn,cs; - double alpha; - /* filter coefficients */ - double a0,a1,a2,b0,b1,b2; - double k0,k1,k2,k3,k4; - /* amplitudes */ - double x0,x1,x2; - double y0,y1,y2; -} hipass; - -struct lowpass { - /* few intermediate variables */ - double omega; - double sn,cs; - double alpha; - /* filter coefficients */ - double a0,a1,a2,b0,b1,b2; - double k0,k1,k2,k3,k4; - /* amplitudes */ - double x0,x1,x2; - double y0,y1,y2; -} lowpass; - -typedef struct _disto -{ - t_object x_obj; - double *x_buf; - t_int x_samplerate; - double x_drive; /* distortion drive */ /* 0<= <=25 */ - double x_drymix; /* dry (unaffected) signal mix */ /* -5<= <=5 */ - double x_wetmix; /* wet (affected) signal mix */ /* -5<= <=5 */ - double x_feedback; /* feedback */ /* -10<= <=10 */ - double x_volume; /* distortion volume */ /* 0=< <=5 */ - double x_hipassfreq; /* cutoff frequency for hi pass filter */ /* 0< exps[i]=exp((double)i*x->x_drive)*x->x_wetmix; - } - - x->HPF.omega = 2.0*M_PI*x->x_hipassfreq/(double)x->x_samplerate; - x->HPF.sn = sin(x->HPF.omega); - x->HPF.cs = cos(x->HPF.omega); - x->HPF.alpha = x->HPF.sn/(2.0*x->x_hipassQ); - x->HPF.b0 = (1.0 + x->HPF.cs)/2.0; - x->HPF.b1 = -(1.0 + x->HPF.cs) ; - x->HPF.b2 = (1.0 + x->HPF.cs)/2.0; - x->HPF.a0 = 1.0 + x->HPF.alpha ; - x->HPF.a1 = -2.0*x->HPF.cs ; - x->HPF.a2 = 1.0 - x->HPF.alpha ; - x->HPF.k0 = (x->HPF.b0/x->HPF.a0); - x->HPF.k1 = (x->HPF.b1/x->HPF.a0); - x->HPF.k2 = (x->HPF.b2/x->HPF.a0); - x->HPF.k3 = (x->HPF.a1/x->HPF.a0); - x->HPF.k4 = (x->HPF.a2/x->HPF.a0); - - x->LPF.omega = 2.0*M_PI*x->x_lowpassfreq/(double)x->x_samplerate; - x->LPF.sn = sin(x->LPF.omega); - x->LPF.cs = cos(x->LPF.omega); - x->LPF.alpha = x->LPF.sn/(2.0*x->x_lowpassQ); - x->LPF.b0 = (1.0 - x->LPF.cs)/2.0; - x->LPF.b1 = 1.0 - x->LPF.cs ; - x->LPF.b2 = (1.0 - x->LPF.cs)/2.0; - x->LPF.a0 = 1.0 + x->LPF.alpha ; - x->LPF.a1 = -2.0*x->LPF.cs ; - x->LPF.a2 = 1.0 - x->LPF.alpha ; - x->LPF.k0 = (x->LPF.b0/x->LPF.a0); - x->LPF.k1 = (x->LPF.b1/x->LPF.a0); - x->LPF.k2 = (x->LPF.b2/x->LPF.a0); - x->LPF.k3 = (x->LPF.a1/x->LPF.a0); - x->LPF.k4 = (x->LPF.a2/x->LPF.a0); -} - -static void disto_drive(t_disto *x, t_floatarg fdrive ) -{ - if ( fdrive > 25.0 ) - { - fdrive = 25.0; - } - if ( fdrive < 0.0 ) - { - fdrive = 0.0; - } - x->x_drive = fdrive; - // post( "disto~ : drive: %f", x->x_drive ); - disto_init_filters( x ); -} - -static void disto_drymix(t_disto *x, t_floatarg fdrymix ) -{ - if ( fdrymix > 5.0 ) - { - fdrymix = 5.0; - } - if ( fdrymix < -5.0 ) - { - fdrymix = -5.0; - } - x->x_drymix = fdrymix; - // post( "disto~ : drymix: %f", x->x_drymix ); - disto_init_filters( x ); -} - -static void disto_wetmix(t_disto *x, t_floatarg fwetmix ) -{ - if ( fwetmix > 5.0 ) - { - fwetmix = 5.0; - } - if ( fwetmix < -5.0 ) - { - fwetmix = -5.0; - } - x->x_wetmix = fwetmix; - // post( "disto~ : wetmix: %f", x->x_wetmix ); - disto_init_filters( x ); -} - -static void disto_feedback(t_disto *x, t_floatarg ffeedback ) -{ - if ( ffeedback > 10.0 ) - { - ffeedback = 10.0; - } - if ( ffeedback < -10.0 ) - { - ffeedback = -10.0; - } - x->x_feedback = ffeedback; - // post( "disto~ : feedback: %f", x->x_feedback ); - disto_init_filters( x ); -} - -static void disto_volume(t_disto *x, t_floatarg fvolume ) -{ - if ( fvolume > 5.0 ) - { - fvolume = 5.0; - } - if ( fvolume < 0.0 ) - { - fvolume = 0.0; - } - x->x_volume = fvolume; - // post( "disto~ : volume: %f", x->x_volume ); - disto_init_filters( x ); -} - -static void disto_hipassfreq(t_disto *x, t_floatarg fhipassfreq ) -{ - if ( fhipassfreq > x->x_samplerate/2 ) - { - fhipassfreq = x->x_samplerate/2; - } - if ( fhipassfreq < 0.0 ) - { - fhipassfreq = 0.0; - } - x->x_hipassfreq = fhipassfreq; - // post( "disto~ : hipassfreq: %f", x->x_hipassfreq ); - disto_init_filters( x ); -} - -static void disto_hipassQ(t_disto *x, t_floatarg fhipassQ ) -{ - if ( fhipassQ > 1.0 ) - { - fhipassQ = 1.0; - } - if ( fhipassQ < 0.1 ) - { - fhipassQ = 0.1; - } - x->x_hipassQ = fhipassQ; - // post( "disto~ : hipassQ: %f", x->x_hipassQ ); - disto_init_filters( x ); -} - -static void disto_lowpassfreq(t_disto *x, t_floatarg flowpassfreq ) -{ - if ( flowpassfreq > x->x_samplerate/2 ) - { - flowpassfreq = x->x_samplerate/2; - } - if ( flowpassfreq < 0.0 ) - { - flowpassfreq = 0.0; - } - x->x_lowpassfreq = flowpassfreq; - // post( "disto~ : lowpassfreq: %f", x->x_lowpassfreq ); - disto_init_filters( x ); -} - -static void disto_lowpassQ(t_disto *x, t_floatarg flowpassQ ) -{ - if ( flowpassQ > 1.0 ) - { - flowpassQ = 1.0; - } - if ( flowpassQ < 0.1 ) - { - flowpassQ = 0.1; - } - x->x_lowpassQ = flowpassQ; - // post( "disto~ : lowpassQ: %f", x->x_lowpassQ ); - disto_init_filters( x ); -} - -static t_int *disto_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *out = (t_float *)(w[2]); - t_int n = (int)(w[3]); - t_disto *x = (t_disto*)(w[4]); - t_int i; - - for (i = 0; i < n; i++) - { - - x->HPF.x0 = *(in++); - x->HPF.y0 = (x->HPF.k0*x->HPF.x0+x->HPF.k1*x->HPF.x1+x->HPF.k2*x->HPF.x2-x->HPF.k3*x->HPF.y1-x->HPF.k4*x->HPF.y2); - x->HPF.y2 = x->HPF.y1; - x->HPF.y1 = x->HPF.y0; - x->HPF.x2 = x->HPF.x1; - x->HPF.x1 = x->HPF.x0; - x->data = (int)x->HPF.y0; - - if ((x->data-x->pred)>0) - x->outval += (x->data*x->x_drymix+ x->exps[abs(x->data)]); - else - if ((x->data-x->pred)<0) - x->outval += (x->data*x->x_drymix- x->exps[abs(x->data)]); - x->pred = x->data; - - x->LPF.x0 = *(out); - x->LPF.y0 = (x->LPF.k0*x->LPF.x0+x->LPF.k1*x->LPF.x1+x->LPF.k2*x->LPF.x2-x->LPF.k3*x->LPF.y1-x->LPF.k4*x->LPF.y2); - x->LPF.y2 = x->LPF.y1; - x->LPF.y1 = x->LPF.y0; - x->LPF.x2 = x->LPF.x1; - x->LPF.x1 = x->LPF.x0; - - x->outvol = x->LPF.y0*x->x_volume; - - if(x->outvol > 1.0) - x->data = 1.0; - else if(x->outvol < -1.0) - x->data = -1.0; - else - x->data = x->outvol; - - *(out++) = x->data; - - x->outval *= x->x_feedback; - - } - - return (w+5); -} - -static void disto_preset(t_disto *x, t_float pnumber) -{ - switch ( (int)pnumber ) - { - /* "Hard Distortion 100-10000Hz" */ - case 1: - x->x_drive = 1.5; - x->x_drymix = 1.0; - x->x_wetmix = 0.5; - x->x_feedback = 0.0; - x->x_volume = 1.0; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 0.5; - x->x_lowpassfreq = 10000.0; - x->x_lowpassQ = 0.5; - break; - - /* "Hard Distortion 100-6000Hz" */ - case 2: - x->x_drive = 1.5; - x->x_drymix = 1.0; - x->x_wetmix = 0.5; - x->x_feedback = 0.0; - x->x_volume = 1.0; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 0.5; - x->x_lowpassfreq = 2000.0; - x->x_lowpassQ = 0.5; - break; - - /* "Very Hard Distortion" */ - case 3: - x->x_drive = 2.0; - x->x_drymix = 0.0; - x->x_wetmix = 1.0; - x->x_feedback = 1.0; - x->x_volume = 5.0; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 0.5; - x->x_lowpassfreq = 6000.0; - x->x_lowpassQ = 0.5; - break; - - /* "Medium Distortion 0.2" */ - case 4: - x->x_drive = 0.2; - x->x_drymix = 1.0; - x->x_wetmix = 1.0; - x->x_feedback = 0.1; - x->x_volume = 1.0; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 0.5; - x->x_lowpassfreq = 6000.0; - x->x_lowpassQ = 0.5; - break; - - /* "Medium Distortion 0.8" */ - case 5: - x->x_drive = 0.8; - x->x_drymix = 1.0; - x->x_wetmix = 1.0; - x->x_feedback = 0.1; - x->x_volume = 1.0; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 1.0; - x->x_lowpassfreq = 6000.0; - x->x_lowpassQ = 0.5; - break; - - /* "Soft Distortion 0.8" */ - case 6: - x->x_drive = 0.8; - x->x_drymix = 0.4; - x->x_wetmix = 0.8; - x->x_feedback = 0.0; - x->x_volume = 0.5; - x->x_hipassfreq = 100.0; - x->x_hipassQ = 1.0; - x->x_lowpassfreq = 10000.0; - x->x_lowpassQ = 0.5; - break; - - default: - post( "disto~ : unknown preset requested : %d", pnumber ); - return; - break; - } - disto_init_filters( x ); -} - -static void disto_dsp(t_disto *x, t_signal **sp) -{ - dsp_add(disto_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); -} - - /* clean up */ -static void disto_free(t_disto *x) -{ - if ( x->x_buf != NULL ) { - freebytes(x->x_buf, BFSZ*sizeof( double ) ); - post( "Freed %d bytes", BFSZ*sizeof( double ) ); - x->x_buf = NULL; - } -} - -static void *disto_new(void) -{ - t_disto *x = (t_disto *)pd_new(disto_class); - outlet_new(&x->x_obj, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("drive")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("drymix")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("wetmix")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("feedback")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("volume")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("hipassfreq")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("hipassQ")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lowpassfreq")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("lowpassQ")); - - x->x_samplerate = (int)sys_getsr(); - x->pred = 0.0; - x->data = 0.0; - - if ( !( x->x_buf = ( double* ) getbytes( BFSZ*sizeof( double ) ) ) ) - { - post ("disto~ : could not allocate buffer" ); - return NULL; - } - - // set default parameters - disto_preset( x, 3 ); - disto_init_filters( x ); - - return (x); -} - -void disto_tilde_setup(void) -{ - post( disto_version ); - disto_class = class_new(gensym("disto~"), (t_newmethod)disto_new, (t_method)disto_free, - sizeof(t_disto), 0, 0); - - CLASS_MAINSIGNALIN( disto_class, t_disto, x_f ); - class_addmethod(disto_class, (t_method)disto_drive, gensym("drive"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_drymix, gensym("drymix"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_wetmix, gensym("wetmix"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_feedback, gensym("feedback"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_volume, gensym("volume"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_hipassfreq, gensym("hipassfreq"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_hipassQ, gensym("hipassQ"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_lowpassfreq, gensym("lowpassfreq"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_lowpassQ, gensym("lowpassQ"), A_FLOAT, 0); - class_addmethod(disto_class, (t_method)disto_dsp, gensym("dsp"), 0); - class_addmethod(disto_class, (t_method)disto_preset, gensym("preset"), A_FLOAT, 0); -} diff --git a/disto~/rs-disto~.pd b/disto~/rs-disto~.pd deleted file mode 100644 index 981d235..0000000 --- a/disto~/rs-disto~.pd +++ /dev/null @@ -1,349 +0,0 @@ -#N canvas 97 16 837 658 10; -#X obj 87 469 outlet~; -#X msg 149 9 preset 1; -#X msg 149 31 preset 2; -#X msg 149 56 preset 3; -#X msg 149 80 preset 4; -#X msg 149 103 preset 5; -#X obj 53 307 inlet~; -#X obj 177 468 tabwrite~ odisto; -#N canvas 0 0 450 300 graph1 0; -#X array odisto 2000 float 1; -#A 0 -0.26708 -0.267659 -0.267773 -0.267663 -0.268063 -0.268941 -0.269679 --0.269954 -0.270085 -0.270558 -0.27125 -0.271575 -0.271187 -0.270388 --0.269913 -0.269957 -0.270104 -0.269923 -0.269085 -0.267836 -0.266711 --0.265669 -0.264553 -0.263606 -0.263061 -0.262861 -0.262675 -0.262145 --0.261336 -0.260573 -0.26004 -0.25979 -0.259776 -0.260007 -0.260453 --0.260904 -0.261228 -0.261418 -0.261567 -0.261693 -0.261452 -0.260715 --0.259912 -0.259345 -0.258913 -0.258407 -0.257621 -0.256502 -0.255412 --0.255096 -0.255742 -0.256443 -0.256694 -0.257092 -0.257969 -0.259069 --0.260196 -0.26123 -0.262196 -0.263298 -0.264522 -0.265454 -0.265789 --0.265929 -0.266428 -0.26689 -0.266694 -0.266317 -0.266395 -0.266645 --0.266675 -0.266611 -0.266736 -0.266962 -0.267 -0.266981 -0.267214 --0.267815 -0.268747 -0.2696 -0.269911 -0.269677 -0.269176 -0.268851 --0.268912 -0.268914 -0.268561 -0.26814 -0.267891 -0.267844 -0.267773 --0.267341 -0.266582 -0.265804 -0.265366 -0.265358 -0.265496 -0.265834 --0.26651 -0.267089 -0.267197 -0.266909 -0.266797 -0.267527 -0.268878 --0.270185 -0.27116 -0.271915 -0.272759 -0.273667 -0.274412 -0.275001 --0.27547 -0.275987 -0.276591 -0.276781 -0.276323 -0.275748 -0.275574 --0.275727 -0.275897 -0.275912 -0.275895 -0.276327 -0.277313 -0.277979 --0.277727 -0.277282 -0.277164 -0.276969 -0.276543 -0.276015 -0.2754 --0.274914 -0.274748 -0.274519 -0.273811 -0.2729 -0.272283 -0.272013 --0.271746 -0.271213 -0.270507 -0.269961 -0.269673 -0.269341 -0.268877 --0.268414 -0.267891 -0.267352 -0.266763 -0.266064 -0.265647 -0.265566 --0.265281 -0.264396 -0.262932 -0.261595 -0.260885 -0.260293 -0.25929 --0.257585 -0.255305 -0.253139 -0.251284 -0.249837 -0.249084 -0.248607 --0.247805 -0.246543 -0.245069 -0.243764 -0.242475 -0.240633 -0.237989 --0.234818 -0.231719 -0.229045 -0.226673 -0.224494 -0.222467 -0.220525 --0.218764 -0.217348 -0.216235 -0.214923 -0.212796 -0.209895 -0.206839 --0.204027 -0.201527 -0.199378 -0.197445 -0.19561 -0.193997 -0.192592 --0.191229 -0.189718 -0.187899 -0.185764 -0.183251 -0.180503 -0.177968 --0.175848 -0.173948 -0.171912 -0.16965 -0.167457 -0.165405 -0.163236 --0.160912 -0.158465 -0.155786 -0.153114 -0.150846 -0.148812 -0.146713 --0.144673 -0.142764 -0.140666 -0.13805 -0.135212 -0.132744 -0.130552 --0.128217 -0.1258 -0.123439 -0.120903 -0.117935 -0.114675 -0.111333 --0.107887 -0.10454 -0.101492 -0.0985705 -0.0956639 -0.092911 -0.0906006 --0.0887248 -0.0867019 -0.0840825 -0.0809534 -0.0775766 -0.0740247 -0.070271 --0.0665755 -0.0632598 -0.0602591 -0.0572601 -0.0539264 -0.0501022 -0.0462753 --0.0432218 -0.0408681 -0.0384562 -0.0356554 -0.0326975 -0.0297458 -0.0264714 --0.0226953 -0.0189905 -0.0158314 -0.0129583 -0.00992077 -0.006587 -0.00317483 --0.000170271 0.00229779 0.00464803 0.00721599 0.0100859 0.0130355 0.0159059 -0.0189153 0.022138 0.0254052 0.028593 0.0318781 0.0354225 0.0388125 -0.041718 0.0444737 0.0475818 0.0510936 0.054507 0.057465 0.0602617 -0.0631991 0.0661021 0.0689534 0.0719189 0.0750332 0.0784235 0.0819329 -0.0854564 0.0890724 0.0924396 0.0954562 0.098226 0.100836 0.103648 -0.106636 0.109676 0.112982 0.116417 0.119893 0.123406 0.126536 0.129097 -0.131271 0.133429 0.135833 0.138202 0.140347 0.14245 0.144688 0.147011 -0.149205 0.15138 0.153773 0.156286 0.158841 0.161446 0.164034 0.166742 -0.169614 0.172283 0.174349 0.17591 0.177754 0.180279 0.182867 0.185162 -0.187412 0.189872 0.192601 0.195232 0.197485 0.199546 0.201768 0.204144 -0.206174 0.207815 0.209428 0.211006 0.212441 0.213705 0.214928 0.216237 -0.217766 0.219741 0.221722 0.223089 0.224116 0.225337 0.226729 0.227758 -0.228216 0.228675 0.22939 0.230035 0.230542 0.231047 0.231827 0.233027 -0.234295 0.235417 0.236317 0.23679 0.236896 0.23694 0.237237 0.237881 -0.238629 0.239307 0.239995 0.240721 0.24144 0.242192 0.243171 0.244484 -0.245695 0.24654 0.247529 0.248852 0.250142 0.251325 0.252652 0.254384 -0.256341 0.25797 0.259165 0.260237 0.261247 0.262037 0.262577 0.263105 -0.263864 0.264588 0.264886 0.265002 0.265396 0.266151 0.267097 0.268057 -0.268906 0.269509 0.269879 0.270139 0.270324 0.270709 0.271559 0.272587 -0.273495 0.274237 0.274801 0.275454 0.276392 0.277454 0.278621 0.279744 -0.280669 0.281482 0.281956 0.282112 0.282319 0.28269 0.283387 0.28435 -0.285342 0.286491 0.287864 0.289279 0.290437 0.291215 0.291987 0.292999 -0.294054 0.29496 0.295644 0.296266 0.297002 0.297657 0.298119 0.298521 -0.299077 0.300061 0.301543 0.303172 0.304387 0.30505 0.305493 0.305954 -0.306373 0.306843 0.307805 0.309191 0.310435 0.311297 0.31185 0.312321 -0.312821 0.313274 0.313723 0.31416 0.314671 0.315332 0.315916 0.316495 -0.317263 0.318092 0.318635 0.318368 0.31737 0.316202 0.31487 0.313304 -0.311569 0.309675 0.307999 0.306836 0.306097 0.30543 0.304414 0.303255 -0.302409 0.301928 0.301785 0.301895 0.302158 0.30259 0.302976 0.302958 -0.302395 0.301419 0.300219 0.298894 0.297635 0.296575 0.29564 0.294797 -0.294115 0.293699 0.293627 0.293838 0.294015 0.293818 0.293335 0.292805 -0.292195 0.291567 0.290985 0.290239 0.289184 0.287888 0.286705 0.285863 -0.285138 0.28429 0.283133 0.281738 0.280465 0.279229 0.277755 0.276089 -0.274151 0.271899 0.269585 0.267458 0.265824 0.264746 0.263793 0.262516 -0.260886 0.259367 0.258111 0.256866 0.255784 0.25474 0.253198 0.251293 -0.249632 0.248461 0.247448 0.246263 0.244935 0.243536 0.242133 0.240709 -0.239106 0.237425 0.23605 0.235135 0.23424 0.232885 0.231229 0.229657 -0.228392 0.227415 0.226439 0.225406 0.224468 0.223602 0.222691 0.221352 -0.219332 0.216988 0.214684 0.212667 0.210812 0.208681 0.206372 0.203835 -0.200758 0.197397 0.194213 0.191612 0.189638 0.187898 0.186069 0.183983 -0.182057 0.180838 0.180003 0.179099 0.17805 0.176769 0.175117 0.172857 -0.169997 0.167006 0.164326 0.162073 0.160094 0.158136 0.156023 0.153598 -0.150921 0.148421 0.146236 0.144047 0.142044 0.140806 0.140162 0.139427 -0.138327 0.136841 0.134884 0.132719 0.130705 0.128635 0.126181 0.123419 -0.12071 0.11838 0.11634 0.114367 0.112656 0.111487 0.110742 0.109904 -0.108587 0.107225 0.106379 0.1059 0.10524 0.104039 0.102601 0.101234 -0.0994895 0.0971318 0.0944816 0.0916963 0.0888986 0.0859872 0.0826179 -0.0789733 0.0755323 0.072549 0.069849 0.0669985 0.0642158 0.062126 -0.0608327 0.0598513 0.0585596 0.0569368 0.0554447 0.0543066 0.0532107 -0.0514894 0.0489487 0.0463233 0.044406 0.0430643 0.0415634 0.0397923 -0.038182 0.0364309 0.0341317 0.0317625 0.0296438 0.027509 0.025305 -0.0233969 0.0219949 0.0207145 0.0191473 0.0172301 0.0151133 0.013269 -0.0119967 0.0109929 0.00987112 0.00847854 0.00662015 0.00422399 0.00178499 --4.51909e-05 -0.00127923 -0.00244447 -0.00409475 -0.00660254 -0.00976168 --0.0128603 -0.015249 -0.0169854 -0.0187953 -0.021044 -0.0235007 -0.0259382 --0.028343 -0.0309557 -0.0339662 -0.0371732 -0.0403194 -0.0434447 -0.0467169 --0.04999 -0.0529932 -0.055748 -0.0583544 -0.0609852 -0.0637931 -0.0666124 --0.0692497 -0.0717844 -0.0745041 -0.0774464 -0.0801579 -0.0823805 -0.0843732 --0.0864587 -0.0887887 -0.0912798 -0.0939585 -0.0971554 -0.100665 -0.103826 --0.106431 -0.108576 -0.110698 -0.113375 -0.1165 -0.119544 -0.122029 --0.124057 -0.126174 -0.128125 -0.12965 -0.13144 -0.133778 -0.136296 --0.138863 -0.141337 -0.143518 -0.14551 -0.14751 -0.149549 -0.151428 --0.153072 -0.15461 -0.155989 -0.157365 -0.159025 -0.160831 -0.162686 --0.164618 -0.166511 -0.168361 -0.170065 -0.171328 -0.172153 -0.172704 --0.173265 -0.174136 -0.175203 -0.176386 -0.177682 -0.178703 -0.179222 --0.179609 -0.180324 -0.181603 -0.183362 -0.185256 -0.187043 -0.188578 --0.189993 -0.191608 -0.193295 -0.19481 -0.196331 -0.198017 -0.199753 --0.20136 -0.202718 -0.203864 -0.204768 -0.205365 -0.205876 -0.206719 --0.20814 -0.209633 -0.210398 -0.210418 -0.210391 -0.211039 -0.212329 --0.213633 -0.214896 -0.21649 -0.21832 -0.220031 -0.221472 -0.222763 --0.224144 -0.225502 -0.226554 -0.227404 -0.228308 -0.229294 -0.230278 --0.231077 -0.23163 -0.232241 -0.232997 -0.233798 -0.234634 -0.23527 --0.235657 -0.236139 -0.236958 -0.238334 -0.240207 -0.241985 -0.243241 --0.243839 -0.244195 -0.244781 -0.245094 -0.245249 -0.245878 -0.24671 --0.247417 -0.247736 -0.247701 -0.247682 -0.247737 -0.248194 -0.249232 --0.250298 -0.251199 -0.252196 -0.25324 -0.253831 -0.253895 -0.254209 --0.254853 -0.255181 -0.255042 -0.254884 -0.254926 -0.254162 -0.252799 --0.252477 -0.252702 -0.252552 -0.25226 -0.251876 -0.25148 -0.251157 --0.251159 -0.25156 -0.251571 -0.251431 -0.252436 -0.253917 -0.254709 --0.255157 -0.25613 -0.25763 -0.258282 -0.258523 -0.259267 -0.259174 --0.258407 -0.257889 -0.257675 -0.257922 -0.257931 -0.257996 -0.258264 --0.25892 -0.261883 -0.26463 -0.264138 -0.26376 -0.264575 -0.265184 --0.266336 -0.267409 -0.267822 -0.266942 -0.266393 -0.267595 -0.266748 --0.264757 -0.263944 -0.263262 -0.265041 -0.268545 -0.269239 -0.266784 --0.264549 -0.264479 -0.263802 -0.26211 -0.263582 -0.267065 -0.269475 --0.270978 -0.270394 -0.269201 -0.270115 -0.271682 -0.272462 -0.270975 --0.268228 -0.267972 -0.268954 -0.269215 -0.267879 -0.265538 -0.265747 --0.26695 -0.265722 -0.262704 -0.261184 -0.262661 -0.263738 -0.262378 --0.261077 -0.261745 -0.26286 -0.262206 -0.260193 -0.256853 -0.253664 --0.254292 -0.254887 -0.253113 -0.252455 -0.252185 -0.252083 -0.251636 --0.250378 -0.250429 -0.251083 -0.251245 -0.250197 -0.248311 -0.248316 --0.250481 -0.25172 -0.25036 -0.248913 -0.24947 -0.250491 -0.249688 --0.247323 -0.246362 -0.246909 -0.247081 -0.247627 -0.248639 -0.249174 --0.248585 -0.246874 -0.245746 -0.246146 -0.247087 -0.247831 -0.247248 --0.244618 -0.242451 -0.24337 -0.24585 -0.246548 -0.24485 -0.242945 --0.242916 -0.244928 -0.246121 -0.243898 -0.241685 -0.241076 -0.239409 --0.238542 -0.239267 -0.23968 -0.239633 -0.238391 -0.238028 -0.239167 --0.238772 -0.239485 -0.241619 -0.240941 -0.239006 -0.23768 -0.237419 --0.238752 -0.23857 -0.236359 -0.234628 -0.234589 -0.236239 -0.236151 --0.234007; -#A 1000 -0.233151 -0.232566 -0.231177 -0.229258 -0.227183 -0.227228 --0.227617 -0.225116 -0.222538 -0.222347 -0.223857 -0.223895 -0.219827 --0.216547 -0.216368 -0.216054 -0.215722 -0.214559 -0.212003 -0.20963 --0.207424 -0.206119 -0.204874 -0.202757 -0.202116 -0.201593 -0.197969 --0.194809 -0.195558 -0.196154 -0.194239 -0.191265 -0.187853 -0.185618 --0.184496 -0.183492 -0.182305 -0.179041 -0.174603 -0.17044 -0.166358 --0.163546 -0.161854 -0.160624 -0.158786 -0.155308 -0.152192 -0.151414 --0.15124 -0.148396 -0.142697 -0.137792 -0.137038 -0.137641 -0.135005 --0.130929 -0.128258 -0.126764 -0.12501 -0.121357 -0.117967 -0.117197 --0.116285 -0.11336 -0.109174 -0.10519 -0.102996 -0.101146 -0.0986079 --0.096028 -0.0935584 -0.092103 -0.0909516 -0.0880864 -0.083206 -0.0781496 --0.0753894 -0.0735017 -0.0700775 -0.0666747 -0.06456 -0.0628634 -0.0596906 --0.05453 -0.0506355 -0.049393 -0.0486083 -0.0470291 -0.04386 -0.0400564 --0.0375559 -0.0354427 -0.0326462 -0.0284579 -0.0241831 -0.0231869 -0.0228954 --0.0193918 -0.0151974 -0.0131444 -0.0120789 -0.00885181 -0.00334882 --0.000488049 -0.00124724 -0.000826269 0.00269577 0.00816899 0.0125972 -0.0139505 0.015662 0.0197424 0.0238507 0.0261824 0.0274073 0.0296689 -0.0327018 0.0354039 0.0381678 0.0418735 0.0471356 0.0513068 0.0524804 -0.052739 0.0542056 0.0578076 0.0615656 0.0639498 0.0670369 0.0705633 -0.0735998 0.0770429 0.0802246 0.0831852 0.0858242 0.0876192 0.0902116 -0.0936297 0.0971528 0.10107 0.103717 0.104464 0.104406 0.10519 0.108577 -0.11268 0.11614 0.119239 0.121048 0.122739 0.124522 0.125989 0.128996 -0.133007 0.136894 0.140435 0.143467 0.146747 0.149152 0.150424 0.152439 -0.155326 0.158756 0.162286 0.165548 0.168342 0.169027 0.168369 0.169249 -0.171925 0.175741 0.180513 0.184524 0.186305 0.187594 0.191185 0.195745 -0.197635 0.198124 0.200597 0.204669 0.208345 0.211098 0.213641 0.216164 -0.217733 0.218783 0.220983 0.224042 0.227037 0.230287 0.233653 0.235084 -0.234313 0.235109 0.239012 0.242701 0.244361 0.246525 0.250272 0.25411 -0.255897 0.25524 0.255541 0.258263 0.262457 0.266652 0.269534 0.272847 -0.277157 0.279705 0.279503 0.278611 0.279129 0.281444 0.284939 0.288047 -0.289756 0.291121 0.292858 0.294858 0.297389 0.300696 0.304043 0.306559 -0.309312 0.313112 0.316137 0.317521 0.318532 0.319404 0.320956 0.323932 -0.326422 0.327967 0.328359 0.328234 0.330002 0.331075 0.330502 0.331551 -0.334164 0.336528 0.337502 0.339519 0.343138 0.343385 0.341942 0.345137 -0.350613 0.353263 0.355074 0.357987 0.360278 0.361003 0.360899 0.359697 -0.357073 0.357094 0.3612 0.364872 0.366239 0.367065 0.367359 0.367487 -0.370281 0.374995 0.377113 0.375402 0.373893 0.375784 0.378692 0.379707 -0.378632 0.376485 0.376255 0.378171 0.379984 0.381831 0.382382 0.38122 -0.380453 0.380165 0.38094 0.382664 0.382666 0.380171 0.377955 0.378977 -0.381425 0.382074 0.381313 0.380389 0.380109 0.380732 0.381984 0.383034 -0.382157 0.380766 0.380922 0.379459 0.375111 0.371841 0.370545 0.36898 -0.367916 0.369126 0.37053 0.36945 0.366917 0.364824 0.362867 0.361097 -0.360896 0.361417 0.360585 0.358882 0.357184 0.353876 0.348368 0.344413 -0.345112 0.345563 0.341402 0.337921 0.337485 0.336197 0.334123 0.332985 -0.331907 0.32895 0.325206 0.324924 0.326902 0.325753 0.321737 0.317587 -0.313514 0.310824 0.311441 0.31337 0.312221 0.308256 0.30576 0.305427 -0.304981 0.303626 0.300351 0.295198 0.291245 0.290881 0.293548 0.295234 -0.292051 0.285143 0.278155 0.273595 0.27235 0.273075 0.273481 0.27107 -0.26558 0.260761 0.258523 0.258636 0.259687 0.258633 0.255704 0.253178 -0.251565 0.250427 0.248592 0.244545 0.240821 0.238358 0.234409 0.232209 -0.232456 0.23026 0.225788 0.221606 0.218641 0.216768 0.216123 0.217035 -0.21832 0.217213 0.212238 0.206817 0.203371 0.201033 0.199994 0.199282 -0.197333 0.194419 0.191874 0.189577 0.186936 0.184725 0.182973 0.180792 -0.178151 0.176717 0.176135 0.173983 0.169511 0.163987 0.16068 0.161077 -0.162289 0.161645 0.159045 0.155913 0.153192 0.149358 0.144425 0.140544 -0.13728 0.13542 0.135981 0.13323 0.125881 0.122486 0.124123 0.12313 -0.118366 0.115432 0.115196 0.113423 0.109305 0.105931 0.104971 0.102352 -0.0964158 0.0939342 0.0956731 0.0938349 0.0886857 0.086643 0.0860824 -0.0835724 0.0809018 0.0784262 0.074743 0.0699358 0.0654743 0.0644693 -0.0670738 0.0667907 0.0608345 0.0560668 0.0550274 0.0517716 0.0470288 -0.0461094 0.0464903 0.0437995 0.0394189 0.0369743 0.035492 0.0316002 -0.0277853 0.0261807 0.0236398 0.0198325 0.0167765 0.0148441 0.0128608 -0.00970296 0.00703723 0.00583368 0.00380263 0.000473064 -0.00252255 --0.00541019 -0.00864094 -0.0111409 -0.0125186 -0.0135007 -0.0143205 --0.0146019 -0.0148482 -0.0171466 -0.020987 -0.0229116 -0.0231064 -0.0245996 --0.0276884 -0.0305513 -0.0327162 -0.0351196 -0.0376646 -0.0401182 -0.0426596 --0.0444322 -0.0457675 -0.0478584 -0.0497565 -0.0506464 -0.0513157 -0.052159 --0.0539484 -0.0561167 -0.0568429 -0.0573337 -0.0587494 -0.0603145 -0.0619514 --0.0639226 -0.0669022 -0.0707158 -0.0739696 -0.0772074 -0.0811309 -0.0844747 --0.0873654 -0.0907039 -0.0933156 -0.0941001 -0.0943444 -0.095617 -0.0974344 --0.099484 -0.1018 -0.102882 -0.103321 -0.105848 -0.110255 -0.114038 --0.115846 -0.116748 -0.118123 -0.119961 -0.122312 -0.124746 -0.126659 --0.128236 -0.127689 -0.125448 -0.126103 -0.12984 -0.133319 -0.134342 --0.133867 -0.135798 -0.139161 -0.141429 -0.144191 -0.145866 -0.145907 --0.147306 -0.149892 -0.153489 -0.155841 -0.155249 -0.15612 -0.158146 --0.157869 -0.156883 -0.157486 -0.159411 -0.160146 -0.160931 -0.164545 --0.167303 -0.166925 -0.167136 -0.170044 -0.17438 -0.177245 -0.177154 --0.176848 -0.177855 -0.179501 -0.182723 -0.187023 -0.189608 -0.189674 --0.188992 -0.189324 -0.191281 -0.193741 -0.195296 -0.195369 -0.193301 --0.191879 -0.194567 -0.198013 -0.199268 -0.199752 -0.199488 -0.199473 --0.201463 -0.204911 -0.208248 -0.208627 -0.205791 -0.203813 -0.205502 --0.209768 -0.213233 -0.213537 -0.211242 -0.209762 -0.210589 -0.212065 --0.214414 -0.217509 -0.218825 -0.21755 -0.216575 -0.218297 -0.220953 --0.221919 -0.222 -0.222716 -0.223324 -0.224083 -0.225504 -0.225747 --0.22421 -0.223129 -0.22334 -0.223363 -0.223819 -0.226083 -0.228188 --0.228343 -0.227315 -0.22695 -0.228393 -0.230022 -0.230815 -0.232001 --0.232692 -0.231958 -0.231828 -0.233017 -0.234158 -0.234324 -0.234582 --0.236492 -0.23755 -0.236831 -0.238344 -0.24147 -0.243434 -0.244738 --0.245636 -0.246112 -0.245377 -0.244503 -0.246052 -0.248095 -0.248097 --0.246671 -0.245189 -0.245102 -0.246481 -0.247893 -0.248335 -0.247514 --0.246449 -0.245922 -0.245682 -0.246598 -0.248263 -0.248967 -0.248829 --0.24816 -0.24748 -0.246923 -0.24558 -0.245254 -0.246168 -0.245029 --0.242549 -0.241186 -0.241762 -0.24368 -0.244018 -0.243866 -0.245271 --0.244062 -0.239965 -0.238904 -0.241356 -0.242091 -0.239899 -0.23877 --0.238927 -0.237334 -0.236052 -0.237747 -0.238291 -0.233767 -0.228659 --0.227553 -0.227043 -0.225269 -0.225544 -0.227385 -0.226236 -0.22154 --0.218968 -0.221037 -0.222556 -0.220614 -0.219152 -0.220012 -0.219519 --0.217602 -0.218801 -0.220957 -0.218647 -0.214792 -0.214112 -0.21522 --0.213766 -0.210293 -0.210031 -0.209338 -0.203426 -0.199947 -0.202385 --0.204352 -0.203511 -0.20268 -0.203071 -0.201417 -0.197239 -0.196734 --0.200169 -0.201207 -0.198635 -0.195482 -0.193122 -0.190594 -0.188472 --0.1884 -0.189048 -0.188209 -0.186508 -0.186198 -0.186368 -0.184437 --0.181724 -0.180083 -0.178512 -0.177677 -0.179502 -0.1818 -0.18054 --0.176895 -0.175291 -0.175508 -0.175358 -0.175918 -0.177403 -0.177107 --0.174243 -0.171687 -0.170536 -0.169344 -0.168906 -0.169992 -0.170334 --0.168262 -0.165975 -0.16621 -0.166189 -0.162635 -0.158982 -0.157627 --0.156921 -0.156462 -0.156192 -0.155766 -0.153264 -0.14937 -0.1486 --0.149288 -0.148866 -0.149764 -0.151418 -0.150841 -0.146987 -0.143179 --0.142844 -0.142361 -0.140405 -0.140584 -0.14176 -0.141941 -0.141421 --0.140756 -0.140163 -0.138007 -0.136409 -0.138076 -0.139307 -0.13895 --0.139289 -0.139026 -0.137142 -0.136061 -0.138299 -0.142194 -0.143127 --0.14174 -0.142156 -0.143001 -0.14211 -0.141021 -0.14012 -0.13871 -0.137428 --0.138223 -0.140831 -0.140916 -0.137712 -0.134516 -0.131997 -0.130671 --0.13108 -0.132343 -0.133538 -0.1325 -0.129983 -0.128205 -0.126336 --0.124934 -0.124084 -0.123517 -0.124253 -0.124134 -0.121727 -0.11916 --0.118518 -0.119372 -0.119263 -0.11808 -0.118028 -0.118947 -0.119155 --0.119376 -0.120386 -0.120797 -0.119504 -0.117742 -0.117604 -0.118196 --0.117564 -0.116427 -0.115047 -0.112277 -0.109151 -0.107823 -0.108153 --0.108001 -0.106851 -0.106133 -0.105341 -0.103449 -0.10225 -0.102543 --0.102643 -0.101744 -0.100163 -0.0989409 -0.0985816 -0.0983467 -0.0977372 --0.0962336 -0.0939372 -0.0920292 -0.0910775 -0.0912255 -0.0922101 -0.0922327 --0.0905764 -0.088414 -0.0861316 -0.0849861 -0.0859358 -0.0866984 -0.085469 --0.082363 -0.0791981 -0.0784002 -0.0789486 -0.0792314 -0.0791902 -0.0784253 --0.0780597 -0.0787439 -0.0790283 -0.0785446 -0.0774918 -0.0761877 -0.074771 --0.0732108 -0.0728679 -0.0734066 -0.0736221 -0.0735405 -0.0728323 -0.0720006 --0.0711169 -0.0703422 -0.0706587 -0.0712593 -0.0715813 -0.0713705 -0.0696971 --0.067587 -0.065892 -0.0648743 -0.0655384 -0.0659984 -0.0640801 -0.0604196 --0.0561824 -0.0529379 -0.051625 -0.0522934 -0.0530088 -0.0504143 -0.0461285 --0.0434267 -0.0418044 -0.0416196 -0.0432084 -0.0442318 -0.0422415 -0.0370414 --0.0328587 -0.0324699 -0.0334087 -0.0345388 -0.035246 -0.0336549 -0.0303687 --0.0274198 -0.0264446 -0.0272249 -0.0270482 -0.0256714 -0.0251707 -0.0246116 --0.0231644 -0.0228445 -0.024125 -0.0244141 -0.0223641 -0.0202823 -0.0195197 --0.0189773 -0.019408 -0.0209408 -0.0204265 -0.0171791 -0.0140059 -0.0129334 --0.0139812 -0.0153043 -0.0155131 -0.0147108 -0.012386 -0.00872585 -0.00597713 --0.00589554 -0.00785846 -0.00965299 -0.0102252 -0.00991027 -0.00770097 --0.00405239 -0.00314322 -0.00636492 -0.008773 -0.00656921 -0.00314961 --0.00142149 0.000355286 0.00157009 0.000652503 0.000665672 0.00507241 -0.0103608 0.0112021 0.00941616 0.00791777 0.00581629 0.00400531 0.00527335 -0.00874362 0.00976684 0.00734871 0.00608535; -#X coords 0 2 1999 -2 200 140 1; -#X restore 596 461 graph; -#X msg 177 446 bang; -#X obj 192 229 hsl 128 15 0 25 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 213 263 hsl 128 15 -5 5 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 256 330 hsl 128 15 -10 10 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 380 229 hsl 128 15 0 5 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 407 270 hsl 128 15 0 22500 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X text 256 168 Note : setting a parameter overrides presets; -#X msg 152 128 preset 6; -#X text 216 7 hard distortion 100-10000Hz; -#X text 217 31 hard distortion 100-6000Hz; -#X text 221 80 medium distortion 0.2; -#X text 221 104 medium distortion 0.8; -#X text 223 126 soft distortion 0.8; -#X text 208 247 Dry mix [ -5 - 5 ]; -#X obj 242 297 hsl 128 15 -5 5 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X text 237 279 Wet mix [ -5 - 5 ]; -#X text 402 253 Low pass frequency [ 0 - 22500 ]; -#X obj 441 307 hsl 128 15 0.1 1 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 482 344 hsl 128 15 0 22500 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X obj 517 379 hsl 128 15 0.1 1 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X text 477 327 High pass frequency [ 0 - 22500 ]; -#X text 133 543 Note : see file "distort3.txt" which explains parameters -; -#X text 375 212 Volume [ 0 - 5 ]; -#X text 193 208 Drive [ 0 - 25 ]; -#X text 512 362 High pass Q [ 0.1 - 1 ]; -#X text 436 290 Low pass Q [ 0.1 - 1 ]; -#X text 253 312 Feedback [ -10 - 10 ]; -#X text 218 56 very hard distortion ( default ); -#X obj 87 414 disto~ -------------------------------------------------- -; -#X connect 1 0 37 0; -#X connect 2 0 37 0; -#X connect 3 0 37 0; -#X connect 4 0 37 0; -#X connect 5 0 37 0; -#X connect 6 0 37 0; -#X connect 9 0 7 0; -#X connect 10 0 37 1; -#X connect 11 0 37 2; -#X connect 12 0 37 4; -#X connect 13 0 37 5; -#X connect 14 0 37 6; -#X connect 16 0 37 0; -#X connect 23 0 37 3; -#X connect 26 0 37 7; -#X connect 27 0 37 8; -#X connect 28 0 37 9; -#X connect 37 0 0 0; -#X connect 37 0 7 0; diff --git a/examples/speaker.gif b/examples/speaker.gif new file mode 100644 index 0000000..6dd9fd4 Binary files /dev/null and b/examples/speaker.gif differ diff --git a/examples/wanderer.gif b/examples/wanderer.gif new file mode 100644 index 0000000..b2a9f8c Binary files /dev/null and b/examples/wanderer.gif differ diff --git a/examples/yesterday.txt b/examples/yesterday.txt new file mode 100644 index 0000000..acbd1ed --- /dev/null +++ b/examples/yesterday.txt @@ -0,0 +1,34 @@ +Yesterday +All those backups seemed a waste of pay. +Now my database has gone away. +Oh I believe in yesterday. +Suddenly, +There's not half the files there used to be, +And there's a milestone +hanging over me +The system crashed so suddenly. +I pushed something wrong +What it was I could not say. +Now all my data's gone +and I long for yesterday-ay-ay-ay. +Yesterday, +The need for back-ups seemed so far away. +I knew my data was all here to stay, +Now I believe in yesterday. +Yesterday +All those backups seemed a waste of pay. +Now my database has gone away. +Oh I believe in yesterday. +Suddenly, +There's not half the files there used to be, +And there's a milestone +hanging over me +The system crashed so suddenly. +I pushed something wrong +What it was I could not say. +Now all my data's gone +and I long for yesterday-ay-ay-ay. +Yesterday, +The need for back-ups seemed so far away. +I knew my data was all here to stay, +Now I believe in yesterday. diff --git a/exciter-help.pd b/exciter-help.pd new file mode 100644 index 0000000..ab60831 --- /dev/null +++ b/exciter-help.pd @@ -0,0 +1,71 @@ +#N canvas 103 12 970 685 10; +#X text 457 89 (invoke with Properties ); +#X text 458 78 You can set the following properties :; +#X text 478 110 * Width : graphical x size; +#X text 478 121 * Height : graphical y size; +#X text 612 498 bugs and comments @ ydegoyon@free.fr; +#X msg 587 271 \; pd dsp 0; +#X msg 653 271 \; pd dsp 1; +#X obj 32 56 exciter 400 200 16 0.1 1 1 1 14 1 15 3 52 5 30 5 69 6 +8 8 20 9 32 9 74 10 79 11 14 11 74 12 79 13 40 13 79 15 78; +#X text 456 50 Exciter controls a list of bang-events scheduled in +time; +#X obj 22 282 print e1; +#X text 478 132 * Number of events : number of simultaneous events +; +#X text 477 155 * Loop : looping flag; +#X msg 193 29 reset; +#X msg 103 29 pause; +#X msg 31 29 start; +#X msg 145 29 resume; +#X msg 70 29 stop; +#X text 44 363 so that events are triggered; +#X obj 653 249 loadbang; +#X msg 239 30 clear; +#X text 102 389 Note 2 : the event happens in the center (?) of the +polygon; +#X msg 286 30 dump; +#X text 478 144 * Time Grain : time grain betweeen each event; +#X obj 80 283 print e3; +#X obj 137 284 print e5; +#X obj 194 283 print e7; +#X obj 252 284 print e9; +#X obj 308 284 print e11; +#X obj 366 284 print e13; +#X obj 429 285 print e15; +#X obj 45 307 print e2; +#X obj 103 308 print e4; +#X obj 217 308 print e8; +#X obj 275 309 print e10; +#X obj 335 310 print e12; +#X obj 396 309 print e14; +#X obj 457 309 print e16; +#X obj 160 309 print e6; +#X text 523 411 ( 10 ms ) \, it won't be processed properly; +#X text 523 399 WARNING : you can't set time grain below 1 clock tick +; +#X text 46 352 Note 1 : the dsp has to be on; +#X connect 7 0 9 0; +#X connect 7 1 30 0; +#X connect 7 2 23 0; +#X connect 7 3 31 0; +#X connect 7 4 24 0; +#X connect 7 5 37 0; +#X connect 7 6 25 0; +#X connect 7 7 32 0; +#X connect 7 8 26 0; +#X connect 7 9 33 0; +#X connect 7 10 27 0; +#X connect 7 11 34 0; +#X connect 7 12 28 0; +#X connect 7 13 35 0; +#X connect 7 14 29 0; +#X connect 7 15 36 0; +#X connect 12 0 7 0; +#X connect 13 0 7 0; +#X connect 14 0 7 0; +#X connect 15 0 7 0; +#X connect 16 0 7 0; +#X connect 18 0 6 0; +#X connect 19 0 7 0; +#X connect 21 0 7 0; diff --git a/exciter.c b/exciter.c new file mode 100644 index 0000000..cfbd365 --- /dev/null +++ b/exciter.c @@ -0,0 +1,823 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* exciter : a graphical object which enables */ +/* to schedule bang events on a time scale */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* "You're a maniac" */ +/* "To fullfill the emptyness" */ +/* Mecano ( no, not the spanish ones !!! ) - Escape The Human Myth */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + +#include "exciter.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* needed to create a exciter from PD's menu +void canvas_objtext(t_glist *gl, int xpos, int ypos, int selected, t_binbuf *b); +void canvas_startmotion(t_canvas *x); +*/ + +#define DEFAULT_EXCITER_WIDTH 200 +#define DEFAULT_EXCITER_HEIGHT 200 +#define DEFAULT_EXCITER_GRAIN 0.1 +#define DEFAULT_EXCITER_NBEVENTS 8 + +#define EXCITER_PIXEL_GRAIN 5 + +static char *exciter_version = "exciter: a bang-events sequencer, version 0.5 (ydegoyon@free.fr)"; + +t_widgetbehavior exciter_widgetbehavior; +static t_class *exciter_class; +static int excitercount=0; + +static int guidebug=0; +static int pointsize = 5; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i);\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI13(a,b,c,d,e,f,g,h,i,j,k,l,m) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k,l,m);\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k,l,m) + +/* drawing functions */ + +/* draw an event */ +static void exciter_draw_gem(t_exciter *x, t_glist *glist, t_int ix, t_int iy) +{ + t_int polyray = ( x->x_height / x->x_nbevents) / 2; + t_canvas *canvas=glist_getcanvas(glist); + + SYS_VGUI13(".x%x.c create polygon %d %d %d %d %d %d %d %d -outline #000000 -fill #FFFFFF -tags %xEVENT%.4d%.4d\n", + canvas, + text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN, + text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents + 2*polyray, + text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents + polyray, + text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + 2*polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents, + text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents - polyray, + x, ix, iy); +} + +/* delete an event */ +static void exciter_delete_gem(t_exciter *x, t_glist *glist, t_int ix, t_int iy) +{ + t_canvas *canvas=glist_getcanvas(glist); + + SYS_VGUI5(".x%x.c delete %xEVENT%.4d%.4d\n", canvas, x, ix, iy ); +} + +static void exciter_draw_update(t_exciter *x, t_glist *glist) +{ + int ei, gi; + + t_canvas *canvas=glist_getcanvas(glist); + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) == 1 ) + { + exciter_draw_gem(x, glist, gi, ei ); + } + else + { + exciter_delete_gem(x, glist, gi, ei ); + } + } + } +} + +static void exciter_draw_new(t_exciter *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ei; + + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #902181 -tags %xLINE\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height, + x); + SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0 s\" -tags %xLOWERCAPTION\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); + SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%.2f s\" -tags %xHIGHERCAPTION\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height + 10, + x->x_width/EXCITER_PIXEL_GRAIN*x->x_timegrain , x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN\n", + canvas, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) , + x); + if ( x->x_nbevents > 1 ) + { + for ( ei=0; eix_nbevents; ei++ ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", + canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x, ei); + } + } + else + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", + canvas, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x, 0); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void exciter_draw_move(t_exciter *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int polyray = ( x->x_height / x->x_nbevents) / 2; + t_int ei, gi; + + SYS_VGUI7(".x%x.c coords %xLINE %d %d %d %d \n", + canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height + ); + SYS_VGUI5(".x%x.c coords %xLOWERCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height + 10 ); + SYS_VGUI5(".x%x.c coords %xHIGHERCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height + 10); + SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + ); + if ( x->x_nbevents > 1 ) + { + for ( ei=0; eix_nbevents; ei++ ) + { + SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + } + } + else + { + SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, 0, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + } + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + SYS_VGUI13(".x%x.c coords %xEVENT%.4d%.4d %d %d %d %d %d %d %d %d\n", + canvas, x, gi, ei, + text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN, + text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents + 2*polyray, + text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents + polyray, + text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + 2*polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents, + text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + polyray, + text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents - polyray + ); + } + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void exciter_draw_erase(t_exciter* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int i, ei, gi; + + SYS_VGUI3(".x%x.c delete %xLINE\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xLOWERCAPTION\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xHIGHERCAPTION\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x ); + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) != 0 ) + { + exciter_delete_gem( x, glist, gi, ei ); + } + } + SYS_VGUI4(".x%x.c delete %xOUT%d\n", canvas, x, ei ); + } +} + +static void exciter_draw_select(t_exciter* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + /* sets the main item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xLINE -outline #0000FF\n", canvas, x); + + } + else + { + /* sets the main item in black */ + SYS_VGUI3(".x%x.c itemconfigure %xLINE -outline #000000\n", canvas, x); + } +} + +/* ------------------------ exciter widgetbehaviour----------------------------- */ + + +static void exciter_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_exciter* x = (t_exciter*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void exciter_save(t_gobj *z, t_binbuf *b) +{ + t_exciter *x = (t_exciter *)z; + int ei,gi; + + binbuf_addv(b, "ssiisiiifii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_width, x->x_height, + x->x_nbevents, x->x_timegrain, + x->x_loop, x->x_save + ); + if ( x->x_save ) + { + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) == 1 ) + { + // post( "exciter : saving ( %d, %d )", ei, gi ); + binbuf_addv(b, "ii", ei, gi ); + } + } + } + } + binbuf_addv(b, ";"); +} + +static void exciter_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_exciter *x=(t_exciter *)z; + + sprintf(buf, "pdtk_exciter_dialog %%s %d %d %d %.2f %d %d\n", + x->x_width, x->x_height, x->x_nbevents, x->x_timegrain, x->x_loop, x->x_save ); + // post("exciter_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void exciter_select(t_gobj *z, t_glist *glist, int selected) +{ + t_exciter *x = (t_exciter *)z; + + x->x_selected = selected; + exciter_draw_select( x, glist ); +} + +static void exciter_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_exciter *x = (t_exciter *)z; + + post("exciter_vis : %d", vis ); + if (vis) + { + exciter_draw_new( x, glist ); + exciter_draw_update( x, glist ); + } + else + { + exciter_draw_erase( x, glist ); + } +} + + /* resuming the triggering of events */ +static void exciter_resume(t_exciter *x) +{ + x->x_started = 1; +} + + /* pausing the triggering of events */ +static void exciter_pause(t_exciter *x) +{ + x->x_started = 0; +} + + /* trigger events -- no dsp processing */ +static void exciter_dialog(t_exciter *x, t_symbol *s, int argc, t_atom *argv) +{ + t_int onbevents, owidth, ei, gi, bi; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( !x ) { + post( "exciter : error :tried to set properties on an unexisting object" ); + } + onbevents = x->x_nbevents; + owidth = x->x_width; + exciter_draw_erase(x, x->x_glist); + if ( argc < 6 ) + { + post( "exciter : error in the number of arguments ( %d )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) + { + post( "exciter : wrong arguments" ); + return; + } + + exciter_pause( x ); + x->x_width = argv[0].a_w.w_float; + if ( x->x_width <= 0 ) x->x_width = 100; + x->x_height = argv[1].a_w.w_float; + if ( x->x_height <= 0 ) x->x_height = 100; + x->x_nbevents = argv[2].a_w.w_float; + if ( x->x_nbevents < 1 ) x->x_nbevents = 1; + x->x_timegrain = argv[3].a_w.w_float; + if ( x->x_timegrain < 0.01 ) + { + post ("exciter : incorrect time grain : forced to 1 tick ( 10 ms )" ); + x->x_timegrain = 0.01; + } + x->x_loop = argv[4].a_w.w_float; + x->x_save = argv[5].a_w.w_float; + x->x_started = 0; + x->x_reltime = 0L; + x->x_plooptime = 0L; + x->x_gindex = -1; + x->x_looplength = x->x_timegrain * x->x_width * 1000 / EXCITER_PIXEL_GRAIN; + + // re-allocate arrays and keep old events + post( "exciter : re-allocate events" ); + if ( onbevents != x->x_nbevents || owidth != x->x_width ) + { + t_int mevents = ( onbevents > x->x_nbevents ) ? x->x_nbevents : onbevents; + t_int mwidth = ( owidth > x->x_width ) ? x->x_width : owidth; + t_int *newbangs; + + newbangs = (t_int*) getbytes( x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + memset( newbangs, 0x0, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + for ( ei=0; eix_width/EXCITER_PIXEL_GRAIN)+gi ) = + *(x->x_sbangs+ei*(owidth/EXCITER_PIXEL_GRAIN)+gi ); + } + } + if ( x->x_sbangs ) + freebytes( x->x_sbangs, onbevents*owidth/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + x->x_sbangs = newbangs; + } + + // re-allocate outlets + post( "exciter : re-allocate outlets" ); + if ( onbevents != x->x_nbevents ) + { + post( "exciter : cleaning up old outlets" ); + if ( x->x_bangs ) + { + for ( ei=0; eix_bangs[ei] ); + } + freebytes( x->x_bangs, onbevents*sizeof(t_outlet*) ); + } + post( "exciter : creating new ones" ); + x->x_bangs = (t_outlet **) getbytes( x->x_nbevents*sizeof(t_outlet **) ); + for ( bi=0; bix_nbevents; bi++ ) + { + x->x_bangs[bi] = outlet_new( &x->x_obj, &s_bang ); + } + } + canvas_fixlinesfor( canvas, (t_text*)x ); + exciter_draw_new(x, x->x_glist); + exciter_draw_update(x, x->x_glist); + exciter_resume( x ); +} + +static void exciter_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void exciter_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_exciter *x = (t_exciter *)z; + t_int xold = text_xpix(&x->x_obj, glist); + t_int yold = text_ypix(&x->x_obj, glist); + + // post( "exciter_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) + { + exciter_draw_move(x, glist); + } +} + +static int exciter_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_exciter* x = (t_exciter *)z; + t_int nevent, npix; + + if ( doit) + { + nevent = ( 1 - ( ( ypix - ( (float)x->x_height / (float) x->x_nbevents / 2 ) + - text_ypix(&x->x_obj, glist)) / (float)x->x_height ) )*(x->x_nbevents-1); + npix = ( xpix - 1 - text_xpix(&x->x_obj, glist)) / EXCITER_PIXEL_GRAIN; + // post( "exciter : selected event (%d,%d)", nevent, npix ); + // set or unset event + { + if ( *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) == 1 ) + { + *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) = 0; + exciter_delete_gem( x, glist, npix, nevent ); + } + else + { + *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) = 1; + exciter_draw_gem( x, glist, npix, nevent ); + } + } + } + return (1); +} + +static t_exciter *exciter_new(t_symbol *s, int argc, t_atom *argv) +{ + int bi, i, ei, gi; + t_exciter *x; + t_pd *x2; + + // post( "exciter_new : create : %s argc =%d", s->s_name, argc ); + + x = (t_exciter *)pd_new(exciter_class); + x->x_glist = (t_glist *) canvas_getcurrent(); + // new exciter created from the gui + if ( argc != 0 ) + { + if ( argc < 6 ) + { + post( "exciter : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) + { + post( "exciter : wrong arguments" ); + return NULL; + } + + x->x_width = argv[0].a_w.w_float; + x->x_height = argv[1].a_w.w_float; + x->x_nbevents = argv[2].a_w.w_float; + if ( x->x_nbevents < 1 ) x->x_nbevents = 1; + x->x_timegrain = argv[3].a_w.w_float; + x->x_loop = argv[4].a_w.w_float; + x->x_save = argv[5].a_w.w_float; + } + else + { + x->x_width = DEFAULT_EXCITER_WIDTH; + x->x_height = DEFAULT_EXCITER_HEIGHT; + x->x_nbevents = DEFAULT_EXCITER_NBEVENTS; + x->x_timegrain = DEFAULT_EXCITER_GRAIN; + x->x_loop = 1; + x->x_save = 1; + + } + + // common fields for new and restored exciters + x->x_sbangs = (t_int*) getbytes( x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) = 0; + } + } + memset( x->x_sbangs, 0x0, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + x->x_selected = 0; + x->x_started = 0; + x->x_reltime = 0L; + x->x_plooptime = 0L; + x->x_gindex = -1; + x->x_looplength = x->x_timegrain * x->x_width * 1000 / EXCITER_PIXEL_GRAIN; + + x->x_bangs = (t_outlet **) getbytes( x->x_nbevents*sizeof(t_outlet **) ); + for ( bi=0; bix_nbevents; bi++ ) + { + x->x_bangs[bi] = outlet_new( &x->x_obj, &s_bang ); + } + + // post( "exciter : argc : %d", argc ); + if ( ( argc != 0 ) && ( x->x_save ) ) + { + int ai = 6; + int si = 0; + + while ( ai < argc - 1 ) + { + *(x->x_sbangs + +((int)argv[ai].a_w.w_float)*(x->x_width/EXCITER_PIXEL_GRAIN) + +(int)argv[ai+1].a_w.w_float) = 1; + ai += 2; + } + } + post( "exciter_new width: %d height : %d", x->x_width, x->x_height ); + + return (x); +} + +static void exciter_dump(t_exciter *x) +{ + t_int ei, gi; + + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) != 0 ) + { + post( "exciter : value ( %d, %d ) : %d", ei, gi, + *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) ); + } + } + } +} + + /* clearing all events */ +static void exciter_clear(t_exciter *x) +{ + t_int ei, gi; + + for ( ei=0; eix_nbevents; ei++ ) + { + for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) + { + *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) = 0; + } + } + exciter_draw_update( x, x->x_glist ); +} + + + /* starting the triggering of events */ +static void exciter_start(t_exciter *x) +{ + x->x_started = 1; + x->x_reltime = 0L; + x->x_plooptime = 0L; + x->x_gindex = -1; +} + + /* stop the triggering of events */ +static void exciter_stop(t_exciter *x) +{ + x->x_started = 0; +} + + /* reset the triggering of events */ +static void exciter_reset(t_exciter *x) +{ + x->x_reltime = 0L; + x->x_plooptime = 0L; + x->x_gindex = -1; +} + +static t_int *exciter_perform(t_int *w) +{ + t_int ei, gi; + t_int gstart, gend; + t_exciter* x = (t_exciter*)(w[1]); + struct timeval tv; + struct timezone tz; + long long looptime = 0L; + double preltime = x->x_reltime; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( x->x_started ) + { + // get current time in ms + gettimeofday( &tv, &tz ); + looptime = tv.tv_sec*1000 + tv.tv_usec/1000; + if ( x->x_plooptime == 0L ) + { + x->x_plooptime = looptime; + } + x->x_reltime += ( looptime - x->x_plooptime ); + if ( x->x_reltime > x->x_looplength ) + { + if ( x->x_loop ) + { + // post( "exciter : restarting loop" ); + x->x_reltime = 0; + preltime = 0; + x->x_gindex = -1; + } + else + { + // post( "exciter : end of the loop" ); + x->x_reltime = 0; + x->x_started = 0; + } + } + gstart = preltime/(x->x_timegrain*1000); + gend = x->x_reltime/(x->x_timegrain*1000); + + // prevent overflow due to long long precision + if ( gstart > x->x_width/EXCITER_PIXEL_GRAIN-1 ) gstart = x->x_width/EXCITER_PIXEL_GRAIN-1; + if ( gstart < 0 ) gstart = 0; + if ( gend > x->x_width/EXCITER_PIXEL_GRAIN-1 ) gend = x->x_width/EXCITER_PIXEL_GRAIN-1 ; + if ( gend < 0 ) gend = 0; + if ( gstart > x->x_gindex ) + { + // post( "exciter : focus slice : (%d,%d)", gstart, gend ); + for ( gi=x->x_gindex+1; gi<=gend; gi++ ) + { + for ( ei=0; eix_nbevents; ei++ ) + { + if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) == 1 ) + { + outlet_bang( x->x_bangs[ ei ] ); + SYS_VGUI5(".x%x.c itemconfigure %xEVENT%.4d%.4d -fill #00FF00\n", + canvas, x, gi, ei); + } + } + } + // unfocus previous events + if ( gstart >= x->x_width/EXCITER_PIXEL_GRAIN - 1) + gstart = x->x_width/EXCITER_PIXEL_GRAIN; // not too proud of this one + // post( "exciter : unfocus slice : (%d,%d)", x->x_gindex, gstart-1 ); + for ( gi=x->x_gindex; gix_nbevents; ei++ ) + { + if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) == 1 ) + { + SYS_VGUI5(".x%x.c itemconfigure %xEVENT%.4d%.4d -fill #FFFFFF\n", + canvas, x, gi, ei); + } + } + } + x->x_gindex = gend; + } + } + + x->x_plooptime = looptime; + return (w+2); +} + +static void exciter_dsp(t_exciter *x, t_signal **sp) +{ + dsp_add(exciter_perform, 1, x); +} + +static void exciter_free(t_exciter *x) +{ + t_int ei; + + // post( "exciter~: exciter_free" ); + if ( x->x_bangs ) + { + for ( ei=0; eix_nbevents; ei++ ) + { + outlet_free( x->x_bangs[ei] ); + } + freebytes( x->x_bangs, x->x_nbevents*sizeof(t_outlet*) ); + } + if ( x->x_sbangs ) + { + freebytes( x->x_sbangs, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); + } +} + +void exciter_setup(void) +{ + post( exciter_version ); + exciter_class = class_new(gensym("exciter"), (t_newmethod)exciter_new, + (t_method)exciter_free, sizeof(t_exciter), 0, A_GIMME, 0); + class_addmethod(exciter_class, (t_method)exciter_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(exciter_class, (t_method)exciter_dump, gensym("dump"), 0); + class_addmethod(exciter_class, (t_method)exciter_clear, gensym("clear"), 0); + class_addmethod(exciter_class, (t_method)exciter_start, gensym("start"), 0); + class_addmethod(exciter_class, (t_method)exciter_stop, gensym("stop"), 0); + class_addmethod(exciter_class, (t_method)exciter_reset, gensym("reset"), 0); + class_addmethod(exciter_class, (t_method)exciter_pause, gensym("pause"), 0); + class_addmethod(exciter_class, (t_method)exciter_resume, gensym("resume"), 0); + class_addmethod(exciter_class, (t_method)exciter_dsp, gensym("dsp"), A_NULL); + exciter_widgetbehavior.w_getrectfn = exciter_getrect; + exciter_widgetbehavior.w_displacefn = exciter_displace; + exciter_widgetbehavior.w_selectfn = exciter_select; + exciter_widgetbehavior.w_activatefn = NULL; + exciter_widgetbehavior.w_deletefn = exciter_delete; + exciter_widgetbehavior.w_visfn = exciter_vis; + exciter_widgetbehavior.w_clickfn = exciter_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(exciter_class, exciter_properties); + class_setsavefn(exciter_class, exciter_save); +#else + exciter_widgetbehavior.w_propertiesfn = exciter_properties; + exciter_widgetbehavior.w_savefn = exciter_save; +#endif + + class_setwidget(exciter_class, &exciter_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + exciter_class->c_externdir->s_name, exciter_class->c_name->s_name); +} diff --git a/exciter.h b/exciter.h new file mode 100644 index 0000000..81076a1 --- /dev/null +++ b/exciter.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2002 Yves Degoyon +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* a header for exciter which enables +* to trigger bang events scheduled with the mouse +*/ + +#ifndef __G_EXCITER_H +#define __G_EXCITER_H + +typedef struct _exciter +{ + t_object x_obj; + t_glist *x_glist; + t_outlet **x_bangs; + t_int x_height; /* height of the exciter */ + t_int x_width; /* width of the exciter */ + t_int x_nbevents; /* number of simultaneous events */ + t_float x_timegrain; /* time granularity for one pixel */ + t_int *x_sbangs; /* scheduled bangs */ + int x_selected; /* stores selected state */ + int x_loop; /* looping flag */ + int x_save; /* saving contents flag */ + + /* internal processing */ + long long x_plooptime; /* initial time */ + long long x_reltime; /* elapsed time since start */ + long long x_looplength; /* length of a loop */ + t_int x_started; /* start flag */ + t_int x_gindex; /* last scanned index */ +} t_exciter; + +#endif diff --git a/exciter.tcl b/exciter.tcl new file mode 100644 index 0000000..c0280e6 --- /dev/null +++ b/exciter.tcl @@ -0,0 +1,123 @@ +############ exciter procedures -- ydegoyon@free.fr ######### + +proc exciter_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nbevents [concat graph_nbevents_$vid] + global $var_graph_nbevents + set var_graph_timegrain [concat graph_timegrain_$vid] + global $var_graph_timegrain + set var_graph_loop [concat graph_loop_$vid] + global $var_graph_loop + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_nbevents] \ + [eval concat $$var_graph_timegrain] \ + [eval concat $$var_graph_loop] \ + [eval concat $$var_graph_save] \;] + #puts stderr $cmd + pd $cmd +} + +proc exciter_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc exciter_ok {id} { + exciter_apply $id + exciter_cancel $id +} + +proc pdtk_exciter_dialog {id width height nbevents timegrain loop save } { + set vid [string trimleft $id .] + + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nbevents [concat graph_nbevents_$vid] + global $var_graph_nbevents + set var_graph_timegrain [concat graph_timegrain_$vid] + global $var_graph_timegrain + set var_graph_loop [concat graph_loop_$vid] + global $var_graph_loop + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_nbevents $nbevents + set $var_graph_timegrain $timegrain + set $var_graph_loop $loop + set $var_graph_save $save + + toplevel $id + wm title $id {exciter} + wm protocol $id WM_DELETE_WINDOW [concat exciter_cancel $id] + + label $id.label -text {EXCITER PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "exciter_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "exciter_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "exciter_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lnbevents -text "Nb Events :" + entry $id.3rangef.nbevents -textvariable $var_graph_nbevents -width 7 + pack $id.3rangef.lnbevents $id.3rangef.nbevents -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.ltimegrain -text "Time Grain (seconds) :" + entry $id.4rangef.timegrain -textvariable $var_graph_timegrain -width 7 + pack $id.4rangef.ltimegrain $id.4rangef.timegrain -side left + + checkbutton $id.loop -text {Loop} -variable $var_graph_loop \ + -anchor w + pack $id.loop -side top + + checkbutton $id.save -text {Save contents} -variable $var_graph_save \ + -anchor w + pack $id.save -side top + + bind $id.1rangef.width [concat exciter_ok $id] + bind $id.2rangef.height [concat exciter_ok $id] + bind $id.3rangef.nbevents [concat exciter_ok $id] + bind $id.4rangef.timegrain [concat exciter_ok $id] + focus $id.1rangef.width +} + +############ exciter procedures END -- ydegoyon@free.fr ######### diff --git a/exciter/INSTALL b/exciter/INSTALL deleted file mode 100644 index 55894c3..0000000 --- a/exciter/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/exciter - -make clean - -make - -make install - -open help-exciter.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/exciter/exciter-help.pd b/exciter/exciter-help.pd deleted file mode 100644 index ab60831..0000000 --- a/exciter/exciter-help.pd +++ /dev/null @@ -1,71 +0,0 @@ -#N canvas 103 12 970 685 10; -#X text 457 89 (invoke with Properties ); -#X text 458 78 You can set the following properties :; -#X text 478 110 * Width : graphical x size; -#X text 478 121 * Height : graphical y size; -#X text 612 498 bugs and comments @ ydegoyon@free.fr; -#X msg 587 271 \; pd dsp 0; -#X msg 653 271 \; pd dsp 1; -#X obj 32 56 exciter 400 200 16 0.1 1 1 1 14 1 15 3 52 5 30 5 69 6 -8 8 20 9 32 9 74 10 79 11 14 11 74 12 79 13 40 13 79 15 78; -#X text 456 50 Exciter controls a list of bang-events scheduled in -time; -#X obj 22 282 print e1; -#X text 478 132 * Number of events : number of simultaneous events -; -#X text 477 155 * Loop : looping flag; -#X msg 193 29 reset; -#X msg 103 29 pause; -#X msg 31 29 start; -#X msg 145 29 resume; -#X msg 70 29 stop; -#X text 44 363 so that events are triggered; -#X obj 653 249 loadbang; -#X msg 239 30 clear; -#X text 102 389 Note 2 : the event happens in the center (?) of the -polygon; -#X msg 286 30 dump; -#X text 478 144 * Time Grain : time grain betweeen each event; -#X obj 80 283 print e3; -#X obj 137 284 print e5; -#X obj 194 283 print e7; -#X obj 252 284 print e9; -#X obj 308 284 print e11; -#X obj 366 284 print e13; -#X obj 429 285 print e15; -#X obj 45 307 print e2; -#X obj 103 308 print e4; -#X obj 217 308 print e8; -#X obj 275 309 print e10; -#X obj 335 310 print e12; -#X obj 396 309 print e14; -#X obj 457 309 print e16; -#X obj 160 309 print e6; -#X text 523 411 ( 10 ms ) \, it won't be processed properly; -#X text 523 399 WARNING : you can't set time grain below 1 clock tick -; -#X text 46 352 Note 1 : the dsp has to be on; -#X connect 7 0 9 0; -#X connect 7 1 30 0; -#X connect 7 2 23 0; -#X connect 7 3 31 0; -#X connect 7 4 24 0; -#X connect 7 5 37 0; -#X connect 7 6 25 0; -#X connect 7 7 32 0; -#X connect 7 8 26 0; -#X connect 7 9 33 0; -#X connect 7 10 27 0; -#X connect 7 11 34 0; -#X connect 7 12 28 0; -#X connect 7 13 35 0; -#X connect 7 14 29 0; -#X connect 7 15 36 0; -#X connect 12 0 7 0; -#X connect 13 0 7 0; -#X connect 14 0 7 0; -#X connect 15 0 7 0; -#X connect 16 0 7 0; -#X connect 18 0 6 0; -#X connect 19 0 7 0; -#X connect 21 0 7 0; diff --git a/exciter/exciter.c b/exciter/exciter.c deleted file mode 100644 index 009776f..0000000 --- a/exciter/exciter.c +++ /dev/null @@ -1,822 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* exciter : a graphical object which enables */ -/* to schedule bang events on a time scale */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* "You're a maniac" */ -/* "To fullfill the emptyness" */ -/* Mecano ( no, not the spanish ones !!! ) - Escape The Human Myth */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - -#include "exciter.h" - -#ifdef NT -#include -#else -#include -#endif - -/* needed to create a exciter from PD's menu -void canvas_objtext(t_glist *gl, int xpos, int ypos, int selected, t_binbuf *b); -void canvas_startmotion(t_canvas *x); -*/ - -#define DEFAULT_EXCITER_WIDTH 200 -#define DEFAULT_EXCITER_HEIGHT 200 -#define DEFAULT_EXCITER_GRAIN 0.1 -#define DEFAULT_EXCITER_NBEVENTS 8 - -#define EXCITER_PIXEL_GRAIN 5 - -static char *exciter_version = "exciter: a bang-events sequencer, version 0.5 (ydegoyon@free.fr)"; - -t_widgetbehavior exciter_widgetbehavior; -static t_class *exciter_class; -static int excitercount=0; - -static int guidebug=0; -static int pointsize = 5; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i);\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI13(a,b,c,d,e,f,g,h,i,j,k,l,m) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k,l,m);\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k,l,m) - -/* drawing functions */ - -/* draw an event */ -static void exciter_draw_gem(t_exciter *x, t_glist *glist, t_int ix, t_int iy) -{ - t_int polyray = ( x->x_height / x->x_nbevents) / 2; - t_canvas *canvas=glist_getcanvas(glist); - - SYS_VGUI13(".x%x.c create polygon %d %d %d %d %d %d %d %d -outline #000000 -fill #FFFFFF -tags %xEVENT%.4d%.4d\n", - canvas, - text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN, - text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents + 2*polyray, - text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents + polyray, - text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + 2*polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents, - text_xpix(&x->x_obj, glist) + ix*EXCITER_PIXEL_GRAIN + polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (iy+1)*x->x_height/x->x_nbevents - polyray, - x, ix, iy); -} - -/* delete an event */ -static void exciter_delete_gem(t_exciter *x, t_glist *glist, t_int ix, t_int iy) -{ - t_canvas *canvas=glist_getcanvas(glist); - - SYS_VGUI5(".x%x.c delete %xEVENT%.4d%.4d\n", canvas, x, ix, iy ); -} - -static void exciter_draw_update(t_exciter *x, t_glist *glist) -{ - int ei, gi; - - t_canvas *canvas=glist_getcanvas(glist); - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) == 1 ) - { - exciter_draw_gem(x, glist, gi, ei ); - } - else - { - exciter_delete_gem(x, glist, gi, ei ); - } - } - } -} - -static void exciter_draw_new(t_exciter *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ei; - - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #902181 -tags %xLINE\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height, - x); - SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0 s\" -tags %xLOWERCAPTION\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); - SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%.2f s\" -tags %xHIGHERCAPTION\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height + 10, - x->x_width/EXCITER_PIXEL_GRAIN*x->x_timegrain , x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN\n", - canvas, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) , - x); - if ( x->x_nbevents > 1 ) - { - for ( ei=0; eix_nbevents; ei++ ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", - canvas, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x, ei); - } - } - else - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT%d\n", - canvas, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x, 0); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void exciter_draw_move(t_exciter *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int polyray = ( x->x_height / x->x_nbevents) / 2; - t_int ei, gi; - - SYS_VGUI7(".x%x.c coords %xLINE %d %d %d %d \n", - canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height - ); - SYS_VGUI5(".x%x.c coords %xLOWERCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height + 10 ); - SYS_VGUI5(".x%x.c coords %xHIGHERCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height + 10); - SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) - ); - if ( x->x_nbevents > 1 ) - { - for ( ei=0; eix_nbevents; ei++ ) - { - SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", - canvas, x, ei, text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + ( ei * (x->x_width - 5) )/ (x->x_nbevents-1) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - } - } - else - { - SYS_VGUI8(".x%x.c coords %xOUT%d %d %d %d %d\n", - canvas, x, 0, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - } - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - SYS_VGUI13(".x%x.c coords %xEVENT%.4d%.4d %d %d %d %d %d %d %d %d\n", - canvas, x, gi, ei, - text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN, - text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents + 2*polyray, - text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents + polyray, - text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + 2*polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents, - text_xpix(&x->x_obj, glist) + gi*EXCITER_PIXEL_GRAIN + polyray, - text_ypix(&x->x_obj, glist) + x->x_height - (ei+1)*x->x_height/x->x_nbevents - polyray - ); - } - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void exciter_draw_erase(t_exciter* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int i, ei, gi; - - SYS_VGUI3(".x%x.c delete %xLINE\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xLOWERCAPTION\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xHIGHERCAPTION\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x ); - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) != 0 ) - { - exciter_delete_gem( x, glist, gi, ei ); - } - } - SYS_VGUI4(".x%x.c delete %xOUT%d\n", canvas, x, ei ); - } -} - -static void exciter_draw_select(t_exciter* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - /* sets the main item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xLINE -outline #0000FF\n", canvas, x); - - } - else - { - /* sets the main item in black */ - SYS_VGUI3(".x%x.c itemconfigure %xLINE -outline #000000\n", canvas, x); - } -} - -/* ------------------------ exciter widgetbehaviour----------------------------- */ - - -static void exciter_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_exciter* x = (t_exciter*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void exciter_save(t_gobj *z, t_binbuf *b) -{ - t_exciter *x = (t_exciter *)z; - int ei,gi; - - binbuf_addv(b, "ssiisiiifii", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_width, x->x_height, - x->x_nbevents, x->x_timegrain, - x->x_loop, x->x_save - ); - if ( x->x_save ) - { - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - if( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) == 1 ) - { - // post( "exciter : saving ( %d, %d )", ei, gi ); - binbuf_addv(b, "ii", ei, gi ); - } - } - } - } - binbuf_addv(b, ";"); -} - -static void exciter_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_exciter *x=(t_exciter *)z; - - sprintf(buf, "pdtk_exciter_dialog %%s %d %d %d %.2f %d %d\n", - x->x_width, x->x_height, x->x_nbevents, x->x_timegrain, x->x_loop, x->x_save ); - // post("exciter_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void exciter_select(t_gobj *z, t_glist *glist, int selected) -{ - t_exciter *x = (t_exciter *)z; - - x->x_selected = selected; - exciter_draw_select( x, glist ); -} - -static void exciter_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_exciter *x = (t_exciter *)z; - - post("exciter_vis : %d", vis ); - if (vis) - { - exciter_draw_new( x, glist ); - exciter_draw_update( x, glist ); - } - else - { - exciter_draw_erase( x, glist ); - } -} - - /* resuming the triggering of events */ -static void exciter_resume(t_exciter *x) -{ - x->x_started = 1; -} - - /* pausing the triggering of events */ -static void exciter_pause(t_exciter *x) -{ - x->x_started = 0; -} - - /* trigger events -- no dsp processing */ -static void exciter_dialog(t_exciter *x, t_symbol *s, int argc, t_atom *argv) -{ - t_int onbevents, owidth, ei, gi, bi; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( !x ) { - post( "exciter : error :tried to set properties on an unexisting object" ); - } - onbevents = x->x_nbevents; - owidth = x->x_width; - exciter_draw_erase(x, x->x_glist); - if ( argc < 6 ) - { - post( "exciter : error in the number of arguments ( %d )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) - { - post( "exciter : wrong arguments" ); - return; - } - - exciter_pause( x ); - x->x_width = argv[0].a_w.w_float; - if ( x->x_width <= 0 ) x->x_width = 100; - x->x_height = argv[1].a_w.w_float; - if ( x->x_height <= 0 ) x->x_height = 100; - x->x_nbevents = argv[2].a_w.w_float; - if ( x->x_nbevents < 1 ) x->x_nbevents = 1; - x->x_timegrain = argv[3].a_w.w_float; - if ( x->x_timegrain < 0.01 ) - { - post ("exciter : incorrect time grain : forced to 1 tick ( 10 ms )" ); - x->x_timegrain = 0.01; - } - x->x_loop = argv[4].a_w.w_float; - x->x_save = argv[5].a_w.w_float; - x->x_started = 0; - x->x_reltime = 0L; - x->x_plooptime = 0L; - x->x_gindex = -1; - x->x_looplength = x->x_timegrain * x->x_width * 1000 / EXCITER_PIXEL_GRAIN; - - // re-allocate arrays and keep old events - post( "exciter : re-allocate events" ); - if ( onbevents != x->x_nbevents || owidth != x->x_width ) - { - t_int mevents = ( onbevents > x->x_nbevents ) ? x->x_nbevents : onbevents; - t_int mwidth = ( owidth > x->x_width ) ? x->x_width : owidth; - t_int *newbangs; - - newbangs = (t_int*) getbytes( x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - memset( newbangs, 0x0, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - for ( ei=0; eix_width/EXCITER_PIXEL_GRAIN)+gi ) = - *(x->x_sbangs+ei*(owidth/EXCITER_PIXEL_GRAIN)+gi ); - } - } - if ( x->x_sbangs ) - freebytes( x->x_sbangs, onbevents*owidth/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - x->x_sbangs = newbangs; - } - - // re-allocate outlets - post( "exciter : re-allocate outlets" ); - if ( onbevents != x->x_nbevents ) - { - post( "exciter : cleaning up old outlets" ); - if ( x->x_bangs ) - { - for ( ei=0; eix_bangs[ei] ); - } - freebytes( x->x_bangs, onbevents*sizeof(t_outlet*) ); - } - post( "exciter : creating new ones" ); - x->x_bangs = (t_outlet **) getbytes( x->x_nbevents*sizeof(t_outlet **) ); - for ( bi=0; bix_nbevents; bi++ ) - { - x->x_bangs[bi] = outlet_new( &x->x_obj, &s_bang ); - } - } - canvas_fixlinesfor( canvas, (t_text*)x ); - exciter_draw_new(x, x->x_glist); - exciter_draw_update(x, x->x_glist); - exciter_resume( x ); -} - -static void exciter_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void exciter_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_exciter *x = (t_exciter *)z; - t_int xold = text_xpix(&x->x_obj, glist); - t_int yold = text_ypix(&x->x_obj, glist); - - // post( "exciter_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) - { - exciter_draw_move(x, glist); - } -} - -static int exciter_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_exciter* x = (t_exciter *)z; - t_int nevent, npix; - - if ( doit) - { - nevent = ( 1 - ( ( ypix - ( (float)x->x_height / (float) x->x_nbevents / 2 ) - - text_ypix(&x->x_obj, glist)) / (float)x->x_height ) )*(x->x_nbevents-1); - npix = ( xpix - 1 - text_xpix(&x->x_obj, glist)) / EXCITER_PIXEL_GRAIN; - // post( "exciter : selected event (%d,%d)", nevent, npix ); - // set or unset event - { - if ( *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) == 1 ) - { - *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) = 0; - exciter_delete_gem( x, glist, npix, nevent ); - } - else - { - *(x->x_sbangs+nevent*(x->x_width/EXCITER_PIXEL_GRAIN)+npix ) = 1; - exciter_draw_gem( x, glist, npix, nevent ); - } - } - } - return (1); -} - -static t_exciter *exciter_new(t_symbol *s, int argc, t_atom *argv) -{ - int bi, i, ei, gi; - t_exciter *x; - t_pd *x2; - - // post( "exciter_new : create : %s argc =%d", s->s_name, argc ); - - x = (t_exciter *)pd_new(exciter_class); - x->x_glist = (t_glist *) canvas_getcurrent(); - // new exciter created from the gui - if ( argc != 0 ) - { - if ( argc < 6 ) - { - post( "exciter : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT ) - { - post( "exciter : wrong arguments" ); - return NULL; - } - - x->x_width = argv[0].a_w.w_float; - x->x_height = argv[1].a_w.w_float; - x->x_nbevents = argv[2].a_w.w_float; - if ( x->x_nbevents < 1 ) x->x_nbevents = 1; - x->x_timegrain = argv[3].a_w.w_float; - x->x_loop = argv[4].a_w.w_float; - x->x_save = argv[5].a_w.w_float; - } - else - { - x->x_width = DEFAULT_EXCITER_WIDTH; - x->x_height = DEFAULT_EXCITER_HEIGHT; - x->x_nbevents = DEFAULT_EXCITER_NBEVENTS; - x->x_timegrain = DEFAULT_EXCITER_GRAIN; - x->x_loop = 1; - x->x_save = 1; - - } - - // common fields for new and restored exciters - x->x_sbangs = (t_int*) getbytes( x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi) = 0; - } - } - memset( x->x_sbangs, 0x0, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - x->x_selected = 0; - x->x_started = 0; - x->x_reltime = 0L; - x->x_plooptime = 0L; - x->x_gindex = -1; - x->x_looplength = x->x_timegrain * x->x_width * 1000 / EXCITER_PIXEL_GRAIN; - - x->x_bangs = (t_outlet **) getbytes( x->x_nbevents*sizeof(t_outlet **) ); - for ( bi=0; bix_nbevents; bi++ ) - { - x->x_bangs[bi] = outlet_new( &x->x_obj, &s_bang ); - } - - // post( "exciter : argc : %d", argc ); - if ( ( argc != 0 ) && ( x->x_save ) ) - { - int ai = 6; - int si = 0; - - while ( ai < argc - 1 ) - { - *(x->x_sbangs - +((int)argv[ai].a_w.w_float)*(x->x_width/EXCITER_PIXEL_GRAIN) - +(int)argv[ai+1].a_w.w_float) = 1; - ai += 2; - } - } - post( "exciter_new width: %d height : %d", x->x_width, x->x_height ); - - return (x); -} - -static void exciter_dump(t_exciter *x) -{ - t_int ei, gi; - - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) != 0 ) - { - post( "exciter : value ( %d, %d ) : %d", ei, gi, - *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) ); - } - } - } -} - - /* clearing all events */ -static void exciter_clear(t_exciter *x) -{ - t_int ei, gi; - - for ( ei=0; eix_nbevents; ei++ ) - { - for ( gi=0; gi<(x->x_width/EXCITER_PIXEL_GRAIN); gi++ ) - { - *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) = 0; - } - } - exciter_draw_update( x, x->x_glist ); -} - - - /* starting the triggering of events */ -static void exciter_start(t_exciter *x) -{ - x->x_started = 1; - x->x_reltime = 0L; - x->x_plooptime = 0L; - x->x_gindex = -1; -} - - /* stop the triggering of events */ -static void exciter_stop(t_exciter *x) -{ - x->x_started = 0; -} - - /* reset the triggering of events */ -static void exciter_reset(t_exciter *x) -{ - x->x_reltime = 0L; - x->x_plooptime = 0L; - x->x_gindex = -1; -} - -static t_int *exciter_perform(t_int *w) -{ - t_int ei, gi; - t_int gstart, gend; - t_exciter* x = (t_exciter*)(w[1]); - struct timeval tv; - struct timezone tz; - long long looptime = 0L; - double preltime = x->x_reltime; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( x->x_started ) - { - // get current time in ms - gettimeofday( &tv, &tz ); - looptime = tv.tv_sec*1000 + tv.tv_usec/1000; - if ( x->x_plooptime == 0L ) - { - x->x_plooptime = looptime; - } - x->x_reltime += ( looptime - x->x_plooptime ); - if ( x->x_reltime > x->x_looplength ) - { - if ( x->x_loop ) - { - // post( "exciter : restarting loop" ); - x->x_reltime = 0; - preltime = 0; - x->x_gindex = -1; - } - else - { - // post( "exciter : end of the loop" ); - x->x_reltime = 0; - x->x_started = 0; - } - } - gstart = preltime/(x->x_timegrain*1000); - gend = x->x_reltime/(x->x_timegrain*1000); - - // prevent overflow due to long long precision - if ( gstart > x->x_width/EXCITER_PIXEL_GRAIN-1 ) gstart = x->x_width/EXCITER_PIXEL_GRAIN-1; - if ( gstart < 0 ) gstart = 0; - if ( gend > x->x_width/EXCITER_PIXEL_GRAIN-1 ) gend = x->x_width/EXCITER_PIXEL_GRAIN-1 ; - if ( gend < 0 ) gend = 0; - if ( gstart > x->x_gindex ) - { - // post( "exciter : focus slice : (%d,%d)", gstart, gend ); - for ( gi=x->x_gindex+1; gi<=gend; gi++ ) - { - for ( ei=0; eix_nbevents; ei++ ) - { - if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) == 1 ) - { - outlet_bang( x->x_bangs[ ei ] ); - SYS_VGUI5(".x%x.c itemconfigure %xEVENT%.4d%.4d -fill #00FF00\n", - canvas, x, gi, ei); - } - } - } - // unfocus previous events - if ( gstart >= x->x_width/EXCITER_PIXEL_GRAIN - 1) - gstart = x->x_width/EXCITER_PIXEL_GRAIN; // not too proud of this one - // post( "exciter : unfocus slice : (%d,%d)", x->x_gindex, gstart-1 ); - for ( gi=x->x_gindex; gix_nbevents; ei++ ) - { - if ( *(x->x_sbangs+ei*(x->x_width/EXCITER_PIXEL_GRAIN)+gi ) == 1 ) - { - SYS_VGUI5(".x%x.c itemconfigure %xEVENT%.4d%.4d -fill #FFFFFF\n", - canvas, x, gi, ei); - } - } - } - x->x_gindex = gend; - } - } - - x->x_plooptime = looptime; - return (w+2); -} - -static void exciter_dsp(t_exciter *x, t_signal **sp) -{ - dsp_add(exciter_perform, 1, x); -} - -static void exciter_free(t_exciter *x) -{ - t_int ei; - - // post( "exciter~: exciter_free" ); - if ( x->x_bangs ) - { - for ( ei=0; eix_nbevents; ei++ ) - { - outlet_free( x->x_bangs[ei] ); - } - freebytes( x->x_bangs, x->x_nbevents*sizeof(t_outlet*) ); - } - if ( x->x_sbangs ) - { - freebytes( x->x_sbangs, x->x_nbevents*x->x_width/EXCITER_PIXEL_GRAIN*sizeof(t_int) ); - } -} - -void exciter_setup(void) -{ - post( exciter_version ); -#include "exciter.tk2c" - exciter_class = class_new(gensym("exciter"), (t_newmethod)exciter_new, - (t_method)exciter_free, sizeof(t_exciter), 0, A_GIMME, 0); - class_addmethod(exciter_class, (t_method)exciter_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(exciter_class, (t_method)exciter_dump, gensym("dump"), 0); - class_addmethod(exciter_class, (t_method)exciter_clear, gensym("clear"), 0); - class_addmethod(exciter_class, (t_method)exciter_start, gensym("start"), 0); - class_addmethod(exciter_class, (t_method)exciter_stop, gensym("stop"), 0); - class_addmethod(exciter_class, (t_method)exciter_reset, gensym("reset"), 0); - class_addmethod(exciter_class, (t_method)exciter_pause, gensym("pause"), 0); - class_addmethod(exciter_class, (t_method)exciter_resume, gensym("resume"), 0); - class_addmethod(exciter_class, (t_method)exciter_dsp, gensym("dsp"), A_NULL); - exciter_widgetbehavior.w_getrectfn = exciter_getrect; - exciter_widgetbehavior.w_displacefn = exciter_displace; - exciter_widgetbehavior.w_selectfn = exciter_select; - exciter_widgetbehavior.w_activatefn = NULL; - exciter_widgetbehavior.w_deletefn = exciter_delete; - exciter_widgetbehavior.w_visfn = exciter_vis; - exciter_widgetbehavior.w_clickfn = exciter_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(exciter_class, exciter_properties); - class_setsavefn(exciter_class, exciter_save); -#else - exciter_widgetbehavior.w_propertiesfn = exciter_properties; - exciter_widgetbehavior.w_savefn = exciter_save; -#endif - - class_setwidget(exciter_class, &exciter_widgetbehavior); - -} diff --git a/exciter/exciter.h b/exciter/exciter.h deleted file mode 100644 index 81076a1..0000000 --- a/exciter/exciter.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* a header for exciter which enables -* to trigger bang events scheduled with the mouse -*/ - -#ifndef __G_EXCITER_H -#define __G_EXCITER_H - -typedef struct _exciter -{ - t_object x_obj; - t_glist *x_glist; - t_outlet **x_bangs; - t_int x_height; /* height of the exciter */ - t_int x_width; /* width of the exciter */ - t_int x_nbevents; /* number of simultaneous events */ - t_float x_timegrain; /* time granularity for one pixel */ - t_int *x_sbangs; /* scheduled bangs */ - int x_selected; /* stores selected state */ - int x_loop; /* looping flag */ - int x_save; /* saving contents flag */ - - /* internal processing */ - long long x_plooptime; /* initial time */ - long long x_reltime; /* elapsed time since start */ - long long x_looplength; /* length of a loop */ - t_int x_started; /* start flag */ - t_int x_gindex; /* last scanned index */ -} t_exciter; - -#endif diff --git a/exciter/exciter.tk b/exciter/exciter.tk deleted file mode 100644 index c0280e6..0000000 --- a/exciter/exciter.tk +++ /dev/null @@ -1,123 +0,0 @@ -############ exciter procedures -- ydegoyon@free.fr ######### - -proc exciter_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nbevents [concat graph_nbevents_$vid] - global $var_graph_nbevents - set var_graph_timegrain [concat graph_timegrain_$vid] - global $var_graph_timegrain - set var_graph_loop [concat graph_loop_$vid] - global $var_graph_loop - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set cmd [concat $id dialog \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_nbevents] \ - [eval concat $$var_graph_timegrain] \ - [eval concat $$var_graph_loop] \ - [eval concat $$var_graph_save] \;] - #puts stderr $cmd - pd $cmd -} - -proc exciter_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc exciter_ok {id} { - exciter_apply $id - exciter_cancel $id -} - -proc pdtk_exciter_dialog {id width height nbevents timegrain loop save } { - set vid [string trimleft $id .] - - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nbevents [concat graph_nbevents_$vid] - global $var_graph_nbevents - set var_graph_timegrain [concat graph_timegrain_$vid] - global $var_graph_timegrain - set var_graph_loop [concat graph_loop_$vid] - global $var_graph_loop - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_nbevents $nbevents - set $var_graph_timegrain $timegrain - set $var_graph_loop $loop - set $var_graph_save $save - - toplevel $id - wm title $id {exciter} - wm protocol $id WM_DELETE_WINDOW [concat exciter_cancel $id] - - label $id.label -text {EXCITER PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "exciter_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "exciter_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "exciter_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lwidth -text "Width :" - entry $id.1rangef.width -textvariable $var_graph_width -width 7 - pack $id.1rangef.lwidth $id.1rangef.width -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lheight -text "Height :" - entry $id.2rangef.height -textvariable $var_graph_height -width 7 - pack $id.2rangef.lheight $id.2rangef.height -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lnbevents -text "Nb Events :" - entry $id.3rangef.nbevents -textvariable $var_graph_nbevents -width 7 - pack $id.3rangef.lnbevents $id.3rangef.nbevents -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.ltimegrain -text "Time Grain (seconds) :" - entry $id.4rangef.timegrain -textvariable $var_graph_timegrain -width 7 - pack $id.4rangef.ltimegrain $id.4rangef.timegrain -side left - - checkbutton $id.loop -text {Loop} -variable $var_graph_loop \ - -anchor w - pack $id.loop -side top - - checkbutton $id.save -text {Save contents} -variable $var_graph_save \ - -anchor w - pack $id.save -side top - - bind $id.1rangef.width [concat exciter_ok $id] - bind $id.2rangef.height [concat exciter_ok $id] - bind $id.3rangef.nbevents [concat exciter_ok $id] - bind $id.4rangef.timegrain [concat exciter_ok $id] - focus $id.1rangef.width -} - -############ exciter procedures END -- ydegoyon@free.fr ######### diff --git a/exciter/exciter.tk2c b/exciter/exciter.tk2c deleted file mode 100755 index e201737..0000000 --- a/exciter/exciter.tk2c +++ /dev/null @@ -1,94 +0,0 @@ -// ########### exciter procedures -- ydegoyon@free.fr ######### -sys_gui("proc exciter_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nbevents [concat graph_nbevents_$vid]\n"); -sys_gui("global $var_graph_nbevents\n"); -sys_gui("set var_graph_timegrain [concat graph_timegrain_$vid]\n"); -sys_gui("global $var_graph_timegrain\n"); -sys_gui("set var_graph_loop [concat graph_loop_$vid]\n"); -sys_gui("global $var_graph_loop\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_nbevents] [eval concat $$var_graph_timegrain] [eval concat $$var_graph_loop] [eval concat $$var_graph_save] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc exciter_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc exciter_ok {id} {\n"); -sys_gui("exciter_apply $id\n"); -sys_gui("exciter_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_exciter_dialog {id width height nbevents timegrain loop save } {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nbevents [concat graph_nbevents_$vid]\n"); -sys_gui("global $var_graph_nbevents\n"); -sys_gui("set var_graph_timegrain [concat graph_timegrain_$vid]\n"); -sys_gui("global $var_graph_timegrain\n"); -sys_gui("set var_graph_loop [concat graph_loop_$vid]\n"); -sys_gui("global $var_graph_loop\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_nbevents $nbevents\n"); -sys_gui("set $var_graph_timegrain $timegrain\n"); -sys_gui("set $var_graph_loop $loop\n"); -sys_gui("set $var_graph_save $save\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {exciter}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat exciter_cancel $id]\n"); -sys_gui("label $id.label -text {EXCITER PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"exciter_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"exciter_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"exciter_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.1rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.1rangef.lwidth $id.1rangef.width -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.2rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.2rangef.lheight $id.2rangef.height -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lnbevents -text \"Nb Events :\"\n"); -sys_gui("entry $id.3rangef.nbevents -textvariable $var_graph_nbevents -width 7\n"); -sys_gui("pack $id.3rangef.lnbevents $id.3rangef.nbevents -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.ltimegrain -text \"Time Grain (seconds) :\"\n"); -sys_gui("entry $id.4rangef.timegrain -textvariable $var_graph_timegrain -width 7\n"); -sys_gui("pack $id.4rangef.ltimegrain $id.4rangef.timegrain -side left\n"); -sys_gui("checkbutton $id.loop -text {Loop} -variable $var_graph_loop -anchor w\n"); -sys_gui("pack $id.loop -side top\n"); -sys_gui("checkbutton $id.save -text {Save contents} -variable $var_graph_save -anchor w\n"); -sys_gui("pack $id.save -side top\n"); -sys_gui("bind $id.1rangef.width [concat exciter_ok $id]\n"); -sys_gui("bind $id.2rangef.height [concat exciter_ok $id]\n"); -sys_gui("bind $id.3rangef.nbevents [concat exciter_ok $id]\n"); -sys_gui("bind $id.4rangef.timegrain [concat exciter_ok $id]\n"); -sys_gui("focus $id.1rangef.width\n"); -sys_gui("}\n"); -// ########### exciter procedures END -- ydegoyon@free.fr ######### diff --git a/exciter/timeval.h b/exciter/timeval.h deleted file mode 100644 index ff04962..0000000 --- a/exciter/timeval.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * timeval.h 1.0 01/12/19 - * - * Defines gettimeofday, timeval, etc. for Win32 - * - * By Wu Yongwei - * - */ - -#ifndef _TIMEVAL_H -#define _TIMEVAL_H - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#ifndef __GNUC__ -#define EPOCHFILETIME (116444736000000000i64) -#else -#define EPOCHFILETIME (116444736000000000LL) -#endif /* not __GNUC__ */ - -#if 0 -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* microseconds */ -}; -#endif /* 0 */ - -struct timezone { - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -__inline int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - LARGE_INTEGER li; - __int64 t; - static int tzflag; - - if (tv) - { - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - } - - if (tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} - -#else /* _WIN32 */ - -#include - -#endif /* _WIN32 */ - -#endif /* _TIMEVAL_H */ diff --git a/exciter/tk2c.bash b/exciter/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/exciter/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/filterbank~-help.pd b/filterbank~-help.pd new file mode 100644 index 0000000..855e833 --- /dev/null +++ b/filterbank~-help.pd @@ -0,0 +1,199 @@ +#N canvas 122 3 868 640 10; +#X text 387 606 bugs and comments @ ydegoyon@free.fr [-_-]; +#X text 256 524 (invoke with Properties ); +#X text 256 506 You can set the following properties :; +#X text 321 108 Constructor : filterbank~ + | filterbank~; +#X text 264 543 * Lower Frequency : lower frequency of all filters +; +#X text 264 556 * Higher Frequency : higher frequency of all filters +; +#X text 321 77 filterbank~ outputs the frequency response against a +set of band-pass filters; +#X obj 127 279 filterbank~ 0 2000 30; +#X text 387 588 part of unauthorized PD ( http://ydegoyon.free.fr ) +; +#X msg 31 20 bang; +#X obj 31 41 openpanel; +#X obj 31 62 t s b; +#X obj 77 62 float \$0; +#X text 31 1 Step 1 : Load a sound file; +#X obj 31 83 route float; +#X msg 336 250 bang; +#X obj 32 179 soundfiler; +#X obj 125 250 tabplay~ \$0-filterbank-sample; +#X obj 31 104 makefilename %d-filterbank-sample; +#X obj 32 137 pack s s; +#X msg 32 158 read -resize \$1 \$2; +#X obj 72 599 table \$0-filterbank-sample; +#X text 321 139 Example : filterbank~ 0 3000 30; +#X obj 86 330 env~; +#X obj 122 307 env~; +#X obj 121 329 env~; +#X obj 87 306 env~; +#X obj 101 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 113 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 125 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 138 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 91 250 dac~; +#X obj 156 331 env~; +#X obj 191 307 env~; +#X obj 191 330 env~; +#X obj 158 307 env~; +#X obj 171 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 183 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 195 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 208 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 227 331 env~; +#X obj 262 307 env~; +#X obj 262 330 env~; +#X obj 228 307 env~; +#X obj 242 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 254 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 266 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 279 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 297 331 env~; +#X obj 332 307 env~; +#X obj 332 330 env~; +#X obj 298 307 env~; +#X obj 312 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 324 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 336 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 349 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 367 331 env~; +#X obj 403 308 env~; +#X obj 402 330 env~; +#X obj 368 307 env~; +#X obj 382 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 394 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 406 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 419 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 438 330 env~; +#X obj 473 306 env~; +#X obj 473 329 env~; +#X obj 439 306 env~; +#X obj 453 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 465 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 477 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 490 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 513 328 env~; +#X obj 548 304 env~; +#X obj 548 327 env~; +#X obj 514 304 env~; +#X obj 528 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 540 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 552 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 565 358 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 580 328 env~; +#X obj 581 304 env~; +#X obj 595 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 607 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 203 228 Step 2 : See the filterbank~ output; +#X text 451 252 Step 3 : shift all the outputs randomly; +#X msg 458 274 randomize 1; +#X msg 547 274 randomize 0; +#X connect 7 0 26 0; +#X connect 7 1 23 0; +#X connect 7 2 24 0; +#X connect 7 3 25 0; +#X connect 7 4 35 0; +#X connect 7 5 32 0; +#X connect 7 6 33 0; +#X connect 7 7 34 0; +#X connect 7 8 43 0; +#X connect 7 9 40 0; +#X connect 7 10 41 0; +#X connect 7 11 42 0; +#X connect 7 12 51 0; +#X connect 7 13 48 0; +#X connect 7 14 49 0; +#X connect 7 15 50 0; +#X connect 7 16 59 0; +#X connect 7 17 56 0; +#X connect 7 18 57 0; +#X connect 7 18 58 0; +#X connect 7 20 67 0; +#X connect 7 21 64 0; +#X connect 7 22 65 0; +#X connect 7 23 66 0; +#X connect 7 24 75 0; +#X connect 7 25 72 0; +#X connect 7 26 73 0; +#X connect 7 27 74 0; +#X connect 7 28 81 0; +#X connect 7 29 80 0; +#X connect 9 0 10 0; +#X connect 10 0 11 0; +#X connect 11 0 19 0; +#X connect 11 1 12 0; +#X connect 12 0 14 0; +#X connect 14 0 18 0; +#X connect 15 0 17 0; +#X connect 17 0 31 0; +#X connect 17 0 7 0; +#X connect 17 0 31 1; +#X connect 18 0 19 1; +#X connect 19 0 20 0; +#X connect 20 0 16 0; +#X connect 23 0 28 0; +#X connect 24 0 29 0; +#X connect 25 0 30 0; +#X connect 26 0 27 0; +#X connect 32 0 37 0; +#X connect 33 0 38 0; +#X connect 34 0 39 0; +#X connect 35 0 36 0; +#X connect 40 0 45 0; +#X connect 41 0 46 0; +#X connect 42 0 47 0; +#X connect 43 0 44 0; +#X connect 48 0 53 0; +#X connect 49 0 54 0; +#X connect 50 0 55 0; +#X connect 51 0 52 0; +#X connect 56 0 61 0; +#X connect 57 0 62 0; +#X connect 58 0 63 0; +#X connect 59 0 60 0; +#X connect 64 0 69 0; +#X connect 65 0 70 0; +#X connect 66 0 71 0; +#X connect 67 0 68 0; +#X connect 72 0 77 0; +#X connect 73 0 78 0; +#X connect 74 0 79 0; +#X connect 75 0 76 0; +#X connect 80 0 83 0; +#X connect 81 0 82 0; +#X connect 86 0 7 0; +#X connect 87 0 7 0; diff --git a/filterbank~.c b/filterbank~.c new file mode 100644 index 0000000..626db7d --- /dev/null +++ b/filterbank~.c @@ -0,0 +1,670 @@ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* filterbank.c written by Yves Degoyon 2002 */ +/* outputs frequency responses against a bank of filters */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* The Three Johns -- Teenage Nightingales In Wax */ +/* Kk Null & Jim O Rourke - Neuro Politics */ +/* ---------------------------------------------------------------------------- */ + + +#include "filterbank~.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define DEFAULT_FILTERBANK_LOWFREQ 0 +#define DEFAULT_FILTERBANK_HIGHFREQ 1600 +#define DEFAULT_FILTERBANK_NBFILTERS 10 +#define FILTERBANK_OUTLET_WIDTH 5 +#define FILTERBANK_HEIGHT 16 + +static char *filterbank_version = "filterbank : responses from a set of band-pass filters, version 0.4 (ydegoyon@free.fr)"; + +t_widgetbehavior filterbank_widgetbehavior; +static t_class *filterbank_class_tilde; + +static int guidebug=0; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i);\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j);\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k);\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +/* this code is borrowed from pd's internal object : bp~ */ + +static float miller_sigbp_qcos(float f) +{ + if (f >= -(0.5f*M_PI) && f <= 0.5f*M_PI) + { + float g = f*f; + return (((g*g*g * (-1.0f/720.0f) + g*g*(1.0f/24.0f)) - g*0.5) + 1); + } + else return (0); +} + +static void miller_sigbp_docoef(t_filterbank_tilde *x, t_int index, t_floatarg f, t_floatarg q) +{ + float r, oneminusr, omega; + if (f < 0.001) f = 10; + if (q < 0) q = 0; + x->x_freq[index] = f; + x->x_q[index] = q; + omega = f * (2.0f * 3.14159f) / x->x_sr; + if (q < 0.001) oneminusr = 1.0f; + else oneminusr = omega/q; + if (oneminusr > 1.0f) oneminusr = 1.0f; + r = 1.0f - oneminusr; + x->x_ctl[index]->c_coef1 = 2.0f * miller_sigbp_qcos(omega) * r; + x->x_ctl[index]->c_coef2 = - r * r; + x->x_ctl[index]->c_gain = 2 * oneminusr * (oneminusr + r * omega); +} + +static void filterbank_draw_new(t_filterbank_tilde *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int fi; + + // draw the square + { + + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xFILTERBANK\n", + canvas, + text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height, + x); + + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #000000 -tags %xSIN\n", + canvas, + text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist)+7, + text_ypix(&x->x_obj, glist), + x); + + for ( fi=0; fix_nbfilters; fi++ ) + { + char color[8]; + + sprintf( color, "#%.2x%.2x%.2x", (int)random() % 256, (int)random() % 256, (int)random() % 256 ); + + SYS_VGUI11(".x%x.c create polygon %d %d %d %d %d %d -outline #000000 -fill %s -tags %xFILTER%d\n", + canvas, + text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters, + text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters + x->x_width/(2*x->x_nbfilters), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + (fi+1)*x->x_width/x->x_nbfilters, + text_ypix(&x->x_obj, glist), + color, x, fi); + } + } + + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void filterbank_draw_move(t_filterbank_tilde *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int fi; + + SYS_VGUI7(".x%x.c coords %xFILTERBANK %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height + ); + + SYS_VGUI7(".x%x.c coords %xSIN %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist)+7, + text_ypix(&x->x_obj, glist) + ); + + for ( fi=0; fix_nbfilters; fi++ ) + { + SYS_VGUI10(".x%x.c coords %xFILTER%d %d %d %d %d %d %d\n", + canvas, x, fi, + text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters, + text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters + x->x_width/(2*x->x_nbfilters), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + (fi+1)*x->x_width/x->x_nbfilters, + text_ypix(&x->x_obj, glist) + ); + } + + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void filterbank_draw_erase(t_filterbank_tilde* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int fi; + + SYS_VGUI3(".x%x.c delete %xFILTERBANK\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xSIN\n", canvas, x ); + for ( fi=0; fix_nbfilters; fi++ ) + { + SYS_VGUI4(".x%x.c delete %xFILTER%d\n", canvas, x, fi ); + } + +} + +static void filterbank_draw_select(t_filterbank_tilde* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xFILTERBANK -outline #0000FF\n", canvas, x); + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xFILTERBANK -outline #000000\n", canvas, x); + } +} + +/* ------------------------ filterbank widgetbehaviour----------------------------- */ + + +static void filterbank_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_filterbank_tilde* x = (t_filterbank_tilde*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void filterbank_save(t_gobj *z, t_binbuf *b) +{ + t_filterbank_tilde *x = (t_filterbank_tilde *)z; + t_int ii; + + binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_lowfreq, x->x_highfreq, + x->x_nbfilters ); + binbuf_addv(b, ";"); +} + +static void filterbank_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_filterbank_tilde *x=(t_filterbank_tilde *)z; + + sprintf(buf, "pdtk_filterbank_dialog %%s %d %d\n", + x->x_lowfreq, x->x_highfreq ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void filterbank_select(t_gobj *z, t_glist *glist, int selected) +{ + t_filterbank_tilde *x = (t_filterbank_tilde *)z; + + x->x_selected = selected; + filterbank_draw_select( x, glist ); +} + +static void filterbank_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_filterbank_tilde *x = (t_filterbank_tilde *)z; + + // post( "filterbank~ : vis : %d", vis ); + if (vis) + { + filterbank_draw_new( x, glist ); + } + else + { + filterbank_draw_erase( x, glist ); + } +} + +static void filterbank_dialog(t_filterbank_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + t_int olowfreq = x->x_lowfreq; + t_int ohighfreq = x->x_highfreq; + t_int fi, ei; + t_int dspstate; + t_float Q; + t_float afreq, abandwidth; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + // !!paranoid + if ( !x ) { + post( "filterbank~ : error :tried to set properties on an unexisting object" ); + } + if ( argc != 2 ) + { + post( "filterbank : error in the number of arguments ( %d instead of 2 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT ) { + post( "filterbank~ : wrong arguments" ); + return; + } + + x->x_allocate = 1; + x->x_lowfreq = (int)argv[0].a_w.w_float; + if ( x->x_lowfreq < 0 ) x->x_lowfreq = 0; + x->x_highfreq = (int)argv[1].a_w.w_float; + if ( x->x_highfreq < x->x_lowfreq ) x->x_highfreq = x->x_lowfreq + 100; + + // recalculate filters if needed + if ( ( olowfreq != x->x_lowfreq ) || ( ohighfreq != x->x_highfreq ) ) + { + // free filters + if ( x->x_freq ) + { + freebytes( x->x_freq, x->x_nbfilters*sizeof(t_float) ); + } + if ( x->x_q ) + { + freebytes( x->x_q, x->x_nbfilters*sizeof(t_float) ); + } + if ( x->x_cspace ) + { + freebytes( x->x_cspace, x->x_nbfilters*sizeof(t_bpctl) ); + } + if ( x->x_ctl ) + { + freebytes( x->x_ctl, x->x_nbfilters*sizeof(t_bpctl*) ); + } + // create filters + x->x_freq = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); + x->x_q = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); + x->x_cspace = (t_bpctl *) getbytes( x->x_nbfilters*sizeof(t_bpctl) ); + x->x_ctl = (t_bpctl **) getbytes( x->x_nbfilters*sizeof(t_bpctl*) ); + if ( !x->x_freq || !x->x_q || !x->x_cspace || !x->x_ctl ) + { + post( "filterbank~ : could not allocate filters" ); + return; + } + abandwidth = ( x->x_highfreq - x->x_lowfreq ) / x->x_nbfilters; + afreq = x->x_lowfreq + ( abandwidth / 2 ); + for ( fi=0; fix_nbfilters; fi++ ) + { + x->x_ctl[fi] = &x->x_cspace[fi]; + x->x_cspace[fi].c_x1 = 0; + x->x_cspace[fi].c_x2 = 0; + Q = ( (t_float) afreq )/ ( (t_float) abandwidth ); + miller_sigbp_docoef( x, fi, afreq, Q ); + afreq += abandwidth; + } + } + + x->x_allocate = 0; +} + +static void filterbank_delete(t_gobj *z, t_glist *glist) +{ + t_filterbank_tilde *x = (t_filterbank_tilde *)z; + + // post( "filterbank~ : delete" ); + filterbank_draw_erase( x, glist ); + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void filterbank_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_filterbank_tilde *x = (t_filterbank_tilde *)z; + int xold = text_xpix(&x->x_obj, glist); + int yold = text_ypix(&x->x_obj, glist); + + // post( "filterbank_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist) ) + { + filterbank_draw_move(x, x->x_glist); + } +} + + +static void filterbank_randomize(t_filterbank_tilde *x, t_floatarg fflag ) +{ + t_int shind, tmpi, fi; + + if ( fflag != 0.0 && fflag != 1.0 ) { + post( "filterbank~ : wrong argument in randomize message : should be 0 or 1" ); + return; + } else if ( fflag == 1 ) { + for ( fi=0; fix_nbfilters; fi++ ) + { + shind = rand() % x->x_nbfilters; + tmpi = x->x_outmapping[ shind ]; + x->x_outmapping[ shind ] = x->x_outmapping[ fi ]; + x->x_outmapping[ fi ] = tmpi; + } + } else { + for ( fi=0; fix_nbfilters; fi++ ) + { + x->x_outmapping[ fi ] = fi; + } + } +} + +static t_filterbank_tilde *filterbank_new(t_symbol *s, int argc, t_atom *argv) +{ + t_int fi, ei; + t_filterbank_tilde *x; + char *str; + t_float Q; + t_float afreq, abandwidth; + + x = (t_filterbank_tilde *)pd_new(filterbank_class_tilde); + + x->x_samplerate = (int)sys_getsr(); + x->x_sr = 44100; + + // new filterbank created from the gui + if ( argc != 0 ) + { + if ( argc != 3 ) + { + post( "filterbank~ : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT ) { + post( "filterbank~ : wrong arguments" ); + return NULL; + } + + x->x_lowfreq = (int)argv[0].a_w.w_float; + if ( x->x_lowfreq < 0 ) x->x_lowfreq = 0; + x->x_highfreq = (int)argv[1].a_w.w_float; + if ( x->x_highfreq < x->x_lowfreq ) x->x_highfreq = x->x_lowfreq + 100; + x->x_nbfilters = (int)argv[2].a_w.w_float; + if ( x->x_nbfilters < 1 ) x->x_nbfilters = 1; + } + else + { + x->x_lowfreq = DEFAULT_FILTERBANK_LOWFREQ; + x->x_highfreq = DEFAULT_FILTERBANK_HIGHFREQ; + x->x_nbfilters = DEFAULT_FILTERBANK_NBFILTERS; + } + + // post( "filterbank~ : new [ %d,%d ] with %d filters", x->x_lowfreq, x->x_highfreq, x->x_nbfilters ); + + // create outlets + x->x_outputs = (t_outlet **) getbytes( x->x_nbfilters*sizeof(t_outlet *) ); + if ( !x->x_outputs ) + { + post( "filterbank~ : could not allocate outputs" ); + return NULL; + } + for ( fi=0; fix_nbfilters; fi++ ) + { + x->x_outputs[fi] = outlet_new( &x->x_obj, &s_signal ); + } + + // create filters + x->x_freq = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); + x->x_q = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); + x->x_cspace = (t_bpctl *) getbytes( x->x_nbfilters*sizeof(t_bpctl) ); + x->x_ctl = (t_bpctl **) getbytes( x->x_nbfilters*sizeof(t_bpctl*) ); + if ( !x->x_freq || !x->x_q || !x->x_cspace || !x->x_ctl ) + { + post( "filterbank~ : could not allocate filters" ); + return NULL; + } + abandwidth = ( x->x_highfreq - x->x_lowfreq ) / x->x_nbfilters; + afreq = x->x_lowfreq + ( abandwidth / 2 ); + for ( fi=0; fix_nbfilters; fi++ ) + { + x->x_ctl[fi] = &x->x_cspace[fi]; + x->x_cspace[fi].c_x1 = 0; + x->x_cspace[fi].c_x2 = 0; + Q = ( (t_float) afreq ) / ( (t_float) abandwidth ); + miller_sigbp_docoef( x, fi, afreq, Q ); + afreq += abandwidth; + } + + x->x_width = x->x_nbfilters*FILTERBANK_OUTLET_WIDTH*2; + x->x_height = FILTERBANK_HEIGHT; + + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_f = 0; + + x->x_outmapping = (t_int*) getbytes( x->x_nbfilters*sizeof( t_int ) ); + if ( !x->x_outmapping ) + { + post( "filterbank~ : cannot allocate mapping array" ); + return NULL; // otherwise, pd schrieks + } + for ( fi=0; fix_nbfilters; fi++ ) + { + x->x_outmapping[fi] = fi; + } + return (x); +} + +static void filterbank_free(t_filterbank_tilde *x) +{ + t_int ei, fi; + + if ( x->x_outputs ) + { + for ( ei=0; eix_nbfilters; ei++ ) + { + outlet_free( x->x_outputs[ei] ); + } + freebytes( x->x_outputs, x->x_nbfilters*sizeof(t_outlet*) ); + } + if ( x->x_freq ) + { + freebytes( x->x_freq, x->x_nbfilters*sizeof(t_float) ); + } + if ( x->x_q ) + { + freebytes( x->x_q, x->x_nbfilters*sizeof(t_float) ); + } + if ( x->x_cspace ) + { + freebytes( x->x_cspace, x->x_nbfilters*sizeof(t_bpctl) ); + } + if ( x->x_ctl ) + { + freebytes( x->x_ctl, x->x_nbfilters*sizeof(t_bpctl*) ); + } + if ( x->x_outmapping ) + { + freebytes( x->x_outmapping, x->x_nbfilters*sizeof(t_int) ); + } +} + +static t_int *filterbank_perform(t_int *w) +{ + t_int fi, si; + t_filterbank_tilde *x = (t_filterbank_tilde*)(w[1]); + t_int n = w[2]; + t_float *in, *out; + int i; + t_float last, prev, coef1, coef2, gain; + t_float *acopy; + t_int noneedtofilter = 1; + + in = (t_float*)w[3]; + + // copy input audio block + acopy = (t_float*) getbytes( n*sizeof( t_float ) ); + if ( !acopy ) + { + post( "filterbank~ : cannot allocate audio copy block" ); + return 0; // otherwise, pd schrieks + } + memcpy( acopy, in, n*sizeof(t_float) ); + + for ( i=0; ix_nbfilters; fi++ ) + { + out = (t_float *)(w[x->x_outmapping[fi]+4]); + + last = x->x_ctl[fi]->c_x1; + prev = x->x_ctl[fi]->c_x2; + coef1 = x->x_ctl[fi]->c_coef1; + coef2 = x->x_ctl[fi]->c_coef2; + gain = x->x_ctl[fi]->c_gain; + for (i=0; i < n; i++) + { + float output = *(acopy+i) + coef1 * last + coef2 * prev; + *out++ = gain * output; + prev = last; + last = output; + } + /* NAN protect */ + if (!((last <= 0) || (last >= 0))) + last = 0; + if (!((prev <= 0) || (prev >= 0))) + prev = 0; + x->x_ctl[fi]->c_x1 = last; + x->x_ctl[fi]->c_x2 = prev; + } + } else { + for ( fi=0; fix_nbfilters; fi++ ) + { + out = (t_float *)(w[x->x_outmapping[fi]+4]); + for (i=0; i < n; i++) + { + *out++ = 0.0; + } + } + } + + if ( acopy ) freebytes( acopy, n*sizeof(t_float) ); + + return (w+x->x_nbfilters+4); +} + +static void filterbank_dsp(t_filterbank_tilde *x, t_signal **sp) +{ + t_int *dspargs, fi, nbargs; + + dspargs = (t_int*) getbytes( (x->x_nbfilters+3)*sizeof(t_int) ); + + dspargs[0] = (t_int)x; + dspargs[1] = (t_int)sp[0]->s_n; + dspargs[2] = (t_int)sp[0]->s_vec; + + nbargs = 3; + for ( fi=0; fix_nbfilters; fi++ ) + { + dspargs[3+fi] = (t_int)sp[fi+1]->s_vec; + nbargs++; + } + + dsp_addv(filterbank_perform, nbargs, dspargs ); + + if ( dspargs ) freebytes( dspargs, (x->x_nbfilters+3)*sizeof(t_int) ); +} + +void filterbank_tilde_setup(void) +{ + post( filterbank_version ); + filterbank_class_tilde = class_new(gensym("filterbank~"), (t_newmethod)filterbank_new, + (t_method)filterbank_free, sizeof(t_filterbank_tilde), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN( filterbank_class_tilde, t_filterbank_tilde, x_f ); + class_addmethod(filterbank_class_tilde, (t_method)filterbank_dsp, gensym("dsp"), 0); + class_addmethod(filterbank_class_tilde, (t_method)filterbank_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(filterbank_class_tilde, (t_method)filterbank_randomize, gensym("randomize"), A_DEFFLOAT, 0); + filterbank_widgetbehavior.w_getrectfn = filterbank_getrect; + filterbank_widgetbehavior.w_displacefn = filterbank_displace; + filterbank_widgetbehavior.w_selectfn = filterbank_select; + filterbank_widgetbehavior.w_activatefn = NULL; + filterbank_widgetbehavior.w_deletefn = filterbank_delete; + filterbank_widgetbehavior.w_visfn = filterbank_vis; + filterbank_widgetbehavior.w_clickfn = NULL; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(filterbank_class_tilde, filterbank_properties); + class_setsavefn(filterbank_class_tilde, filterbank_save); +#else + filterbank_widgetbehavior.w_propertiesfn = filterbank_properties; + filterbank_widgetbehavior.w_savefn = filterbank_save; +#endif + class_setwidget(filterbank_class_tilde, &filterbank_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + filterbank_class_tilde->c_externdir->s_name, + filterbank_class_tilde->c_name->s_name); +} diff --git a/filterbank~.h b/filterbank~.h new file mode 100644 index 0000000..34821c8 --- /dev/null +++ b/filterbank~.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* a header for filterbank~ which outputs frequency response */ +/* for a range of filters */ +/* */ +/* The filter code is taken from Speech Filing System */ +/* from Mark Huckvale, University College London */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* Twine -- Instrumentals */ +/* Andy T -- Poetry */ +/* ---------------------------------------------------------------------------- */ + +#ifndef __FILTERBANK_H +#define __FILTERBANK_H + +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + + +/* this code is borrowed from pd's object : bp~ */ + +typedef struct bpctl +{ + float c_x1; + float c_x2; + float c_coef1; + float c_coef2; + float c_gain; +} t_bpctl; + +typedef struct _filterbank_tilde +{ + t_object x_obj; + t_glist *x_glist; + t_int x_samplerate; /* system sample rate */ + t_int x_lowfreq; /* lower frequency of all filters */ + t_int x_highfreq; /* higher frequency of all filters */ + t_int x_nbfilters; /* number of filters */ + t_outlet **x_outputs; /* outputs for frequency responses */ + t_int x_nselected; /* index of item selected */ + t_int x_width; /* graphical x size ( not setable ) */ + t_int x_height; /* graphical y size ( not setable ) */ + t_int x_selected; /* selection flag */ + t_int x_allocate; /* allocation flag */ + t_int *x_outmapping; /* output mapping array */ + + // bp~ section : borrowed from pd's d_filter.c + float x_sr; + float *x_freq; + float *x_q; + t_bpctl *x_cspace; + t_bpctl **x_ctl; + + t_float x_f; /* classical float for signal input */ +} t_filterbank_tilde; + +#endif diff --git a/filterbank~.tcl b/filterbank~.tcl new file mode 100644 index 0000000..4143802 --- /dev/null +++ b/filterbank~.tcl @@ -0,0 +1,77 @@ +############ filterbank procedures -- ydegoyon@free.fr ######### + +proc filterbank_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_lowfreq [concat graph_lowfreq_$vid] + global $var_graph_lowfreq + set var_graph_highfreq [concat graph_highfreq_$vid] + global $var_graph_highfreq + + set cmd [concat $id dialog \ + [eval concat $$var_graph_lowfreq] \ + [eval concat $$var_graph_highfreq] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc filterbank_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc filterbank_ok {id} { + filterbank_apply $id + filterbank_cancel $id +} + +proc pdtk_filterbank_dialog {id lowfreq highfreq} { + set vid [string trimleft $id .] + set var_graph_lowfreq [concat graph_lowfreq_$vid] + global $var_graph_lowfreq + set var_graph_highfreq [concat graph_highfreq_$vid] + global $var_graph_highfreq + + set $var_graph_lowfreq $lowfreq + set $var_graph_highfreq $highfreq + + toplevel $id + wm title $id {filterbank} + wm protocol $id WM_DELETE_WINDOW [concat filterbank_cancel $id] + + label $id.label -text {FILTERBANK PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "filterbank_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "filterbank_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "filterbank_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.llowfreq -text "Lower Frequency :" + entry $id.1rangef.lowfreq -textvariable $var_graph_lowfreq -width 7 + pack $id.1rangef.llowfreq $id.1rangef.lowfreq -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lhighfreq -text "Higher Frequency :" + entry $id.2rangef.highfreq -textvariable $var_graph_highfreq -width 7 + pack $id.2rangef.lhighfreq $id.2rangef.highfreq -side left + + bind $id.1rangef.lowfreq [concat filterbank_ok $id] + bind $id.2rangef.highfreq [concat filterbank_ok $id] + focus $id.1rangef.lowfreq +} + +############ filterbank procedures END -- ydegoyon@free.fr ######### diff --git a/filterbank~/INSTALL b/filterbank~/INSTALL deleted file mode 100644 index a8b614e..0000000 --- a/filterbank~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/filterbank~ - -make clean - -make - -make install - -open help-filterbank~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/filterbank~/analyze-100.pd b/filterbank~/analyze-100.pd deleted file mode 100644 index 132876b..0000000 --- a/filterbank~/analyze-100.pd +++ /dev/null @@ -1,41 +0,0 @@ -#N canvas 112 -6 970 685 10; -#X obj 236 283 filterbank~ 0 2000 100; -#X obj 31 62 t s b; -#X obj 80 68 float \$0; -#X text 31 1 Step 1 : Load a sound file; -#X obj 31 83 route float; -#X msg 336 250 bang; -#X obj 125 250 tabplay~ \$0-filterbank-sample; -#X obj 31 104 makefilename %d-filterbank-sample; -#X obj 32 137 pack s s; -#X msg 32 158 read -resize \$1 \$2; -#X msg 239 220 bang; -#X obj 28 220 tabplay~ \$0-filterbank-sample; -#X obj 365 149 table \$0-filterbank-sample; -#X msg 440 223 randomize 1; -#X msg 442 246 randomize 0; -#X obj 32 180 soundfiler; -#X obj 719 55 playlist all 200 200; -#X msg 484 52 location /Samples; -#X obj 484 25 loadbang; -#X obj 391 369 dac~; -#X connect 0 8 19 0; -#X connect 0 15 19 1; -#X connect 0 28 19 1; -#X connect 1 0 8 0; -#X connect 1 1 2 0; -#X connect 2 0 4 0; -#X connect 4 0 7 0; -#X connect 5 0 6 0; -#X connect 6 0 0 0; -#X connect 7 0 8 1; -#X connect 8 0 9 0; -#X connect 9 0 15 0; -#X connect 10 0 11 0; -#X connect 11 0 19 1; -#X connect 11 0 19 0; -#X connect 13 0 0 0; -#X connect 14 0 0 0; -#X connect 16 0 1 0; -#X connect 17 0 16 0; -#X connect 18 0 17 0; diff --git a/filterbank~/filterbank~-help.pd b/filterbank~/filterbank~-help.pd deleted file mode 100644 index 855e833..0000000 --- a/filterbank~/filterbank~-help.pd +++ /dev/null @@ -1,199 +0,0 @@ -#N canvas 122 3 868 640 10; -#X text 387 606 bugs and comments @ ydegoyon@free.fr [-_-]; -#X text 256 524 (invoke with Properties ); -#X text 256 506 You can set the following properties :; -#X text 321 108 Constructor : filterbank~ - | filterbank~; -#X text 264 543 * Lower Frequency : lower frequency of all filters -; -#X text 264 556 * Higher Frequency : higher frequency of all filters -; -#X text 321 77 filterbank~ outputs the frequency response against a -set of band-pass filters; -#X obj 127 279 filterbank~ 0 2000 30; -#X text 387 588 part of unauthorized PD ( http://ydegoyon.free.fr ) -; -#X msg 31 20 bang; -#X obj 31 41 openpanel; -#X obj 31 62 t s b; -#X obj 77 62 float \$0; -#X text 31 1 Step 1 : Load a sound file; -#X obj 31 83 route float; -#X msg 336 250 bang; -#X obj 32 179 soundfiler; -#X obj 125 250 tabplay~ \$0-filterbank-sample; -#X obj 31 104 makefilename %d-filterbank-sample; -#X obj 32 137 pack s s; -#X msg 32 158 read -resize \$1 \$2; -#X obj 72 599 table \$0-filterbank-sample; -#X text 321 139 Example : filterbank~ 0 3000 30; -#X obj 86 330 env~; -#X obj 122 307 env~; -#X obj 121 329 env~; -#X obj 87 306 env~; -#X obj 101 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 113 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 125 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 138 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 91 250 dac~; -#X obj 156 331 env~; -#X obj 191 307 env~; -#X obj 191 330 env~; -#X obj 158 307 env~; -#X obj 171 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 183 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 195 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 208 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 227 331 env~; -#X obj 262 307 env~; -#X obj 262 330 env~; -#X obj 228 307 env~; -#X obj 242 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 254 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 266 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 279 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 297 331 env~; -#X obj 332 307 env~; -#X obj 332 330 env~; -#X obj 298 307 env~; -#X obj 312 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 324 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 336 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 349 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 367 331 env~; -#X obj 403 308 env~; -#X obj 402 330 env~; -#X obj 368 307 env~; -#X obj 382 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 394 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 406 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 419 361 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 438 330 env~; -#X obj 473 306 env~; -#X obj 473 329 env~; -#X obj 439 306 env~; -#X obj 453 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 465 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 477 359 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 490 360 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 513 328 env~; -#X obj 548 304 env~; -#X obj 548 327 env~; -#X obj 514 304 env~; -#X obj 528 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 540 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 552 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 565 358 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 580 328 env~; -#X obj 581 304 env~; -#X obj 595 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 607 357 vsl 8 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 203 228 Step 2 : See the filterbank~ output; -#X text 451 252 Step 3 : shift all the outputs randomly; -#X msg 458 274 randomize 1; -#X msg 547 274 randomize 0; -#X connect 7 0 26 0; -#X connect 7 1 23 0; -#X connect 7 2 24 0; -#X connect 7 3 25 0; -#X connect 7 4 35 0; -#X connect 7 5 32 0; -#X connect 7 6 33 0; -#X connect 7 7 34 0; -#X connect 7 8 43 0; -#X connect 7 9 40 0; -#X connect 7 10 41 0; -#X connect 7 11 42 0; -#X connect 7 12 51 0; -#X connect 7 13 48 0; -#X connect 7 14 49 0; -#X connect 7 15 50 0; -#X connect 7 16 59 0; -#X connect 7 17 56 0; -#X connect 7 18 57 0; -#X connect 7 18 58 0; -#X connect 7 20 67 0; -#X connect 7 21 64 0; -#X connect 7 22 65 0; -#X connect 7 23 66 0; -#X connect 7 24 75 0; -#X connect 7 25 72 0; -#X connect 7 26 73 0; -#X connect 7 27 74 0; -#X connect 7 28 81 0; -#X connect 7 29 80 0; -#X connect 9 0 10 0; -#X connect 10 0 11 0; -#X connect 11 0 19 0; -#X connect 11 1 12 0; -#X connect 12 0 14 0; -#X connect 14 0 18 0; -#X connect 15 0 17 0; -#X connect 17 0 31 0; -#X connect 17 0 7 0; -#X connect 17 0 31 1; -#X connect 18 0 19 1; -#X connect 19 0 20 0; -#X connect 20 0 16 0; -#X connect 23 0 28 0; -#X connect 24 0 29 0; -#X connect 25 0 30 0; -#X connect 26 0 27 0; -#X connect 32 0 37 0; -#X connect 33 0 38 0; -#X connect 34 0 39 0; -#X connect 35 0 36 0; -#X connect 40 0 45 0; -#X connect 41 0 46 0; -#X connect 42 0 47 0; -#X connect 43 0 44 0; -#X connect 48 0 53 0; -#X connect 49 0 54 0; -#X connect 50 0 55 0; -#X connect 51 0 52 0; -#X connect 56 0 61 0; -#X connect 57 0 62 0; -#X connect 58 0 63 0; -#X connect 59 0 60 0; -#X connect 64 0 69 0; -#X connect 65 0 70 0; -#X connect 66 0 71 0; -#X connect 67 0 68 0; -#X connect 72 0 77 0; -#X connect 73 0 78 0; -#X connect 74 0 79 0; -#X connect 75 0 76 0; -#X connect 80 0 83 0; -#X connect 81 0 82 0; -#X connect 86 0 7 0; -#X connect 87 0 7 0; diff --git a/filterbank~/filterbank~.c b/filterbank~/filterbank~.c deleted file mode 100644 index 4e44c2a..0000000 --- a/filterbank~/filterbank~.c +++ /dev/null @@ -1,668 +0,0 @@ -/* ---------------------------------------------------------------------------- */ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* filterbank.c written by Yves Degoyon 2002 */ -/* outputs frequency responses against a bank of filters */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* The Three Johns -- Teenage Nightingales In Wax */ -/* Kk Null & Jim O Rourke - Neuro Politics */ -/* ---------------------------------------------------------------------------- */ - - -#include "filterbank~.h" - -#ifdef NT -#include -#else -#include -#endif - -#define DEFAULT_FILTERBANK_LOWFREQ 0 -#define DEFAULT_FILTERBANK_HIGHFREQ 1600 -#define DEFAULT_FILTERBANK_NBFILTERS 10 -#define FILTERBANK_OUTLET_WIDTH 5 -#define FILTERBANK_HEIGHT 16 - -static char *filterbank_version = "filterbank : responses from a set of band-pass filters, version 0.4 (ydegoyon@free.fr)"; - -t_widgetbehavior filterbank_widgetbehavior; -static t_class *filterbank_class_tilde; - -static int guidebug=0; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i);\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j);\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k);\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -/* this code is borrowed from pd's internal object : bp~ */ - -static float miller_sigbp_qcos(float f) -{ - if (f >= -(0.5f*M_PI) && f <= 0.5f*M_PI) - { - float g = f*f; - return (((g*g*g * (-1.0f/720.0f) + g*g*(1.0f/24.0f)) - g*0.5) + 1); - } - else return (0); -} - -static void miller_sigbp_docoef(t_filterbank_tilde *x, t_int index, t_floatarg f, t_floatarg q) -{ - float r, oneminusr, omega; - if (f < 0.001) f = 10; - if (q < 0) q = 0; - x->x_freq[index] = f; - x->x_q[index] = q; - omega = f * (2.0f * 3.14159f) / x->x_sr; - if (q < 0.001) oneminusr = 1.0f; - else oneminusr = omega/q; - if (oneminusr > 1.0f) oneminusr = 1.0f; - r = 1.0f - oneminusr; - x->x_ctl[index]->c_coef1 = 2.0f * miller_sigbp_qcos(omega) * r; - x->x_ctl[index]->c_coef2 = - r * r; - x->x_ctl[index]->c_gain = 2 * oneminusr * (oneminusr + r * omega); -} - -static void filterbank_draw_new(t_filterbank_tilde *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int fi; - - // draw the square - { - - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xFILTERBANK\n", - canvas, - text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height, - x); - - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #000000 -tags %xSIN\n", - canvas, - text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist)-1, - text_xpix(&x->x_obj, glist)+7, - text_ypix(&x->x_obj, glist), - x); - - for ( fi=0; fix_nbfilters; fi++ ) - { - char color[8]; - - sprintf( color, "#%.2x%.2x%.2x", (int)random() % 256, (int)random() % 256, (int)random() % 256 ); - - SYS_VGUI11(".x%x.c create polygon %d %d %d %d %d %d -outline #000000 -fill %s -tags %xFILTER%d\n", - canvas, - text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters, - text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters + x->x_width/(2*x->x_nbfilters), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + (fi+1)*x->x_width/x->x_nbfilters, - text_ypix(&x->x_obj, glist), - color, x, fi); - } - } - - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void filterbank_draw_move(t_filterbank_tilde *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int fi; - - SYS_VGUI7(".x%x.c coords %xFILTERBANK %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height - ); - - SYS_VGUI7(".x%x.c coords %xSIN %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist)-1, - text_xpix(&x->x_obj, glist)+7, - text_ypix(&x->x_obj, glist) - ); - - for ( fi=0; fix_nbfilters; fi++ ) - { - SYS_VGUI10(".x%x.c coords %xFILTER%d %d %d %d %d %d %d\n", - canvas, x, fi, - text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters, - text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + fi*x->x_width/x->x_nbfilters + x->x_width/(2*x->x_nbfilters), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + (fi+1)*x->x_width/x->x_nbfilters, - text_ypix(&x->x_obj, glist) - ); - } - - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void filterbank_draw_erase(t_filterbank_tilde* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int fi; - - SYS_VGUI3(".x%x.c delete %xFILTERBANK\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xSIN\n", canvas, x ); - for ( fi=0; fix_nbfilters; fi++ ) - { - SYS_VGUI4(".x%x.c delete %xFILTER%d\n", canvas, x, fi ); - } - -} - -static void filterbank_draw_select(t_filterbank_tilde* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xFILTERBANK -outline #0000FF\n", canvas, x); - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xFILTERBANK -outline #000000\n", canvas, x); - } -} - -/* ------------------------ filterbank widgetbehaviour----------------------------- */ - - -static void filterbank_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_filterbank_tilde* x = (t_filterbank_tilde*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void filterbank_save(t_gobj *z, t_binbuf *b) -{ - t_filterbank_tilde *x = (t_filterbank_tilde *)z; - t_int ii; - - binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_lowfreq, x->x_highfreq, - x->x_nbfilters ); - binbuf_addv(b, ";"); -} - -static void filterbank_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_filterbank_tilde *x=(t_filterbank_tilde *)z; - - sprintf(buf, "pdtk_filterbank_dialog %%s %d %d\n", - x->x_lowfreq, x->x_highfreq ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void filterbank_select(t_gobj *z, t_glist *glist, int selected) -{ - t_filterbank_tilde *x = (t_filterbank_tilde *)z; - - x->x_selected = selected; - filterbank_draw_select( x, glist ); -} - -static void filterbank_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_filterbank_tilde *x = (t_filterbank_tilde *)z; - - // post( "filterbank~ : vis : %d", vis ); - if (vis) - { - filterbank_draw_new( x, glist ); - } - else - { - filterbank_draw_erase( x, glist ); - } -} - -static void filterbank_dialog(t_filterbank_tilde *x, t_symbol *s, int argc, t_atom *argv) -{ - t_int olowfreq = x->x_lowfreq; - t_int ohighfreq = x->x_highfreq; - t_int fi, ei; - t_int dspstate; - t_float Q; - t_float afreq, abandwidth; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - // !!paranoid - if ( !x ) { - post( "filterbank~ : error :tried to set properties on an unexisting object" ); - } - if ( argc != 2 ) - { - post( "filterbank : error in the number of arguments ( %d instead of 2 )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT ) { - post( "filterbank~ : wrong arguments" ); - return; - } - - x->x_allocate = 1; - x->x_lowfreq = (int)argv[0].a_w.w_float; - if ( x->x_lowfreq < 0 ) x->x_lowfreq = 0; - x->x_highfreq = (int)argv[1].a_w.w_float; - if ( x->x_highfreq < x->x_lowfreq ) x->x_highfreq = x->x_lowfreq + 100; - - // recalculate filters if needed - if ( ( olowfreq != x->x_lowfreq ) || ( ohighfreq != x->x_highfreq ) ) - { - // free filters - if ( x->x_freq ) - { - freebytes( x->x_freq, x->x_nbfilters*sizeof(t_float) ); - } - if ( x->x_q ) - { - freebytes( x->x_q, x->x_nbfilters*sizeof(t_float) ); - } - if ( x->x_cspace ) - { - freebytes( x->x_cspace, x->x_nbfilters*sizeof(t_bpctl) ); - } - if ( x->x_ctl ) - { - freebytes( x->x_ctl, x->x_nbfilters*sizeof(t_bpctl*) ); - } - // create filters - x->x_freq = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); - x->x_q = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); - x->x_cspace = (t_bpctl *) getbytes( x->x_nbfilters*sizeof(t_bpctl) ); - x->x_ctl = (t_bpctl **) getbytes( x->x_nbfilters*sizeof(t_bpctl*) ); - if ( !x->x_freq || !x->x_q || !x->x_cspace || !x->x_ctl ) - { - post( "filterbank~ : could not allocate filters" ); - return; - } - abandwidth = ( x->x_highfreq - x->x_lowfreq ) / x->x_nbfilters; - afreq = x->x_lowfreq + ( abandwidth / 2 ); - for ( fi=0; fix_nbfilters; fi++ ) - { - x->x_ctl[fi] = &x->x_cspace[fi]; - x->x_cspace[fi].c_x1 = 0; - x->x_cspace[fi].c_x2 = 0; - Q = ( (t_float) afreq )/ ( (t_float) abandwidth ); - miller_sigbp_docoef( x, fi, afreq, Q ); - afreq += abandwidth; - } - } - - x->x_allocate = 0; -} - -static void filterbank_delete(t_gobj *z, t_glist *glist) -{ - t_filterbank_tilde *x = (t_filterbank_tilde *)z; - - // post( "filterbank~ : delete" ); - filterbank_draw_erase( x, glist ); - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void filterbank_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_filterbank_tilde *x = (t_filterbank_tilde *)z; - int xold = text_xpix(&x->x_obj, glist); - int yold = text_ypix(&x->x_obj, glist); - - // post( "filterbank_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist) ) - { - filterbank_draw_move(x, x->x_glist); - } -} - - -static void filterbank_randomize(t_filterbank_tilde *x, t_floatarg fflag ) -{ - t_int shind, tmpi, fi; - - if ( fflag != 0.0 && fflag != 1.0 ) { - post( "filterbank~ : wrong argument in randomize message : should be 0 or 1" ); - return; - } else if ( fflag == 1 ) { - for ( fi=0; fix_nbfilters; fi++ ) - { - shind = rand() % x->x_nbfilters; - tmpi = x->x_outmapping[ shind ]; - x->x_outmapping[ shind ] = x->x_outmapping[ fi ]; - x->x_outmapping[ fi ] = tmpi; - } - } else { - for ( fi=0; fix_nbfilters; fi++ ) - { - x->x_outmapping[ fi ] = fi; - } - } -} - -static t_filterbank_tilde *filterbank_new(t_symbol *s, int argc, t_atom *argv) -{ - t_int fi, ei; - t_filterbank_tilde *x; - char *str; - t_float Q; - t_float afreq, abandwidth; - - x = (t_filterbank_tilde *)pd_new(filterbank_class_tilde); - - x->x_samplerate = (int)sys_getsr(); - x->x_sr = 44100; - - // new filterbank created from the gui - if ( argc != 0 ) - { - if ( argc != 3 ) - { - post( "filterbank~ : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT ) { - post( "filterbank~ : wrong arguments" ); - return NULL; - } - - x->x_lowfreq = (int)argv[0].a_w.w_float; - if ( x->x_lowfreq < 0 ) x->x_lowfreq = 0; - x->x_highfreq = (int)argv[1].a_w.w_float; - if ( x->x_highfreq < x->x_lowfreq ) x->x_highfreq = x->x_lowfreq + 100; - x->x_nbfilters = (int)argv[2].a_w.w_float; - if ( x->x_nbfilters < 1 ) x->x_nbfilters = 1; - } - else - { - x->x_lowfreq = DEFAULT_FILTERBANK_LOWFREQ; - x->x_highfreq = DEFAULT_FILTERBANK_HIGHFREQ; - x->x_nbfilters = DEFAULT_FILTERBANK_NBFILTERS; - } - - // post( "filterbank~ : new [ %d,%d ] with %d filters", x->x_lowfreq, x->x_highfreq, x->x_nbfilters ); - - // create outlets - x->x_outputs = (t_outlet **) getbytes( x->x_nbfilters*sizeof(t_outlet *) ); - if ( !x->x_outputs ) - { - post( "filterbank~ : could not allocate outputs" ); - return NULL; - } - for ( fi=0; fix_nbfilters; fi++ ) - { - x->x_outputs[fi] = outlet_new( &x->x_obj, &s_signal ); - } - - // create filters - x->x_freq = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); - x->x_q = (t_float *) getbytes( x->x_nbfilters*sizeof(t_float) ); - x->x_cspace = (t_bpctl *) getbytes( x->x_nbfilters*sizeof(t_bpctl) ); - x->x_ctl = (t_bpctl **) getbytes( x->x_nbfilters*sizeof(t_bpctl*) ); - if ( !x->x_freq || !x->x_q || !x->x_cspace || !x->x_ctl ) - { - post( "filterbank~ : could not allocate filters" ); - return NULL; - } - abandwidth = ( x->x_highfreq - x->x_lowfreq ) / x->x_nbfilters; - afreq = x->x_lowfreq + ( abandwidth / 2 ); - for ( fi=0; fix_nbfilters; fi++ ) - { - x->x_ctl[fi] = &x->x_cspace[fi]; - x->x_cspace[fi].c_x1 = 0; - x->x_cspace[fi].c_x2 = 0; - Q = ( (t_float) afreq ) / ( (t_float) abandwidth ); - miller_sigbp_docoef( x, fi, afreq, Q ); - afreq += abandwidth; - } - - x->x_width = x->x_nbfilters*FILTERBANK_OUTLET_WIDTH*2; - x->x_height = FILTERBANK_HEIGHT; - - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_f = 0; - - x->x_outmapping = (t_int*) getbytes( x->x_nbfilters*sizeof( t_int ) ); - if ( !x->x_outmapping ) - { - post( "filterbank~ : cannot allocate mapping array" ); - return NULL; // otherwise, pd schrieks - } - for ( fi=0; fix_nbfilters; fi++ ) - { - x->x_outmapping[fi] = fi; - } - return (x); -} - -static void filterbank_free(t_filterbank_tilde *x) -{ - t_int ei, fi; - - if ( x->x_outputs ) - { - for ( ei=0; eix_nbfilters; ei++ ) - { - outlet_free( x->x_outputs[ei] ); - } - freebytes( x->x_outputs, x->x_nbfilters*sizeof(t_outlet*) ); - } - if ( x->x_freq ) - { - freebytes( x->x_freq, x->x_nbfilters*sizeof(t_float) ); - } - if ( x->x_q ) - { - freebytes( x->x_q, x->x_nbfilters*sizeof(t_float) ); - } - if ( x->x_cspace ) - { - freebytes( x->x_cspace, x->x_nbfilters*sizeof(t_bpctl) ); - } - if ( x->x_ctl ) - { - freebytes( x->x_ctl, x->x_nbfilters*sizeof(t_bpctl*) ); - } - if ( x->x_outmapping ) - { - freebytes( x->x_outmapping, x->x_nbfilters*sizeof(t_int) ); - } -} - -static t_int *filterbank_perform(t_int *w) -{ - t_int fi, si; - t_filterbank_tilde *x = (t_filterbank_tilde*)(w[1]); - t_int n = w[2]; - t_float *in, *out; - int i; - t_float last, prev, coef1, coef2, gain; - t_float *acopy; - t_int noneedtofilter = 1; - - in = (t_float*)w[3]; - - // copy input audio block - acopy = (t_float*) getbytes( n*sizeof( t_float ) ); - if ( !acopy ) - { - post( "filterbank~ : cannot allocate audio copy block" ); - return 0; // otherwise, pd schrieks - } - memcpy( acopy, in, n*sizeof(t_float) ); - - for ( i=0; ix_nbfilters; fi++ ) - { - out = (t_float *)(w[x->x_outmapping[fi]+4]); - - last = x->x_ctl[fi]->c_x1; - prev = x->x_ctl[fi]->c_x2; - coef1 = x->x_ctl[fi]->c_coef1; - coef2 = x->x_ctl[fi]->c_coef2; - gain = x->x_ctl[fi]->c_gain; - for (i=0; i < n; i++) - { - float output = *(acopy+i) + coef1 * last + coef2 * prev; - *out++ = gain * output; - prev = last; - last = output; - } - /* NAN protect */ - if (!((last <= 0) || (last >= 0))) - last = 0; - if (!((prev <= 0) || (prev >= 0))) - prev = 0; - x->x_ctl[fi]->c_x1 = last; - x->x_ctl[fi]->c_x2 = prev; - } - } else { - for ( fi=0; fix_nbfilters; fi++ ) - { - out = (t_float *)(w[x->x_outmapping[fi]+4]); - for (i=0; i < n; i++) - { - *out++ = 0.0; - } - } - } - - if ( acopy ) freebytes( acopy, n*sizeof(t_float) ); - - return (w+x->x_nbfilters+4); -} - -static void filterbank_dsp(t_filterbank_tilde *x, t_signal **sp) -{ - t_int *dspargs, fi, nbargs; - - dspargs = (t_int*) getbytes( (x->x_nbfilters+3)*sizeof(t_int) ); - - dspargs[0] = (t_int)x; - dspargs[1] = (t_int)sp[0]->s_n; - dspargs[2] = (t_int)sp[0]->s_vec; - - nbargs = 3; - for ( fi=0; fix_nbfilters; fi++ ) - { - dspargs[3+fi] = (t_int)sp[fi+1]->s_vec; - nbargs++; - } - - dsp_addv(filterbank_perform, nbargs, dspargs ); - - if ( dspargs ) freebytes( dspargs, (x->x_nbfilters+3)*sizeof(t_int) ); -} - -void filterbank_tilde_setup(void) -{ - post( filterbank_version ); -#include "filterbank~.tk2c" - filterbank_class_tilde = class_new(gensym("filterbank~"), (t_newmethod)filterbank_new, - (t_method)filterbank_free, sizeof(t_filterbank_tilde), 0, A_GIMME, 0); - CLASS_MAINSIGNALIN( filterbank_class_tilde, t_filterbank_tilde, x_f ); - class_addmethod(filterbank_class_tilde, (t_method)filterbank_dsp, gensym("dsp"), 0); - class_addmethod(filterbank_class_tilde, (t_method)filterbank_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(filterbank_class_tilde, (t_method)filterbank_randomize, gensym("randomize"), A_DEFFLOAT, 0); - filterbank_widgetbehavior.w_getrectfn = filterbank_getrect; - filterbank_widgetbehavior.w_displacefn = filterbank_displace; - filterbank_widgetbehavior.w_selectfn = filterbank_select; - filterbank_widgetbehavior.w_activatefn = NULL; - filterbank_widgetbehavior.w_deletefn = filterbank_delete; - filterbank_widgetbehavior.w_visfn = filterbank_vis; - filterbank_widgetbehavior.w_clickfn = NULL; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(filterbank_class_tilde, filterbank_properties); - class_setsavefn(filterbank_class_tilde, filterbank_save); -#else - filterbank_widgetbehavior.w_propertiesfn = filterbank_properties; - filterbank_widgetbehavior.w_savefn = filterbank_save; -#endif - class_setwidget(filterbank_class_tilde, &filterbank_widgetbehavior); - -} diff --git a/filterbank~/filterbank~.h b/filterbank~/filterbank~.h deleted file mode 100644 index 34821c8..0000000 --- a/filterbank~/filterbank~.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* a header for filterbank~ which outputs frequency response */ -/* for a range of filters */ -/* */ -/* The filter code is taken from Speech Filing System */ -/* from Mark Huckvale, University College London */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* Twine -- Instrumentals */ -/* Andy T -- Poetry */ -/* ---------------------------------------------------------------------------- */ - -#ifndef __FILTERBANK_H -#define __FILTERBANK_H - -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - - -/* this code is borrowed from pd's object : bp~ */ - -typedef struct bpctl -{ - float c_x1; - float c_x2; - float c_coef1; - float c_coef2; - float c_gain; -} t_bpctl; - -typedef struct _filterbank_tilde -{ - t_object x_obj; - t_glist *x_glist; - t_int x_samplerate; /* system sample rate */ - t_int x_lowfreq; /* lower frequency of all filters */ - t_int x_highfreq; /* higher frequency of all filters */ - t_int x_nbfilters; /* number of filters */ - t_outlet **x_outputs; /* outputs for frequency responses */ - t_int x_nselected; /* index of item selected */ - t_int x_width; /* graphical x size ( not setable ) */ - t_int x_height; /* graphical y size ( not setable ) */ - t_int x_selected; /* selection flag */ - t_int x_allocate; /* allocation flag */ - t_int *x_outmapping; /* output mapping array */ - - // bp~ section : borrowed from pd's d_filter.c - float x_sr; - float *x_freq; - float *x_q; - t_bpctl *x_cspace; - t_bpctl **x_ctl; - - t_float x_f; /* classical float for signal input */ -} t_filterbank_tilde; - -#endif diff --git a/filterbank~/filterbank~.tk b/filterbank~/filterbank~.tk deleted file mode 100644 index 4143802..0000000 --- a/filterbank~/filterbank~.tk +++ /dev/null @@ -1,77 +0,0 @@ -############ filterbank procedures -- ydegoyon@free.fr ######### - -proc filterbank_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_lowfreq [concat graph_lowfreq_$vid] - global $var_graph_lowfreq - set var_graph_highfreq [concat graph_highfreq_$vid] - global $var_graph_highfreq - - set cmd [concat $id dialog \ - [eval concat $$var_graph_lowfreq] \ - [eval concat $$var_graph_highfreq] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc filterbank_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc filterbank_ok {id} { - filterbank_apply $id - filterbank_cancel $id -} - -proc pdtk_filterbank_dialog {id lowfreq highfreq} { - set vid [string trimleft $id .] - set var_graph_lowfreq [concat graph_lowfreq_$vid] - global $var_graph_lowfreq - set var_graph_highfreq [concat graph_highfreq_$vid] - global $var_graph_highfreq - - set $var_graph_lowfreq $lowfreq - set $var_graph_highfreq $highfreq - - toplevel $id - wm title $id {filterbank} - wm protocol $id WM_DELETE_WINDOW [concat filterbank_cancel $id] - - label $id.label -text {FILTERBANK PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "filterbank_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "filterbank_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "filterbank_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.llowfreq -text "Lower Frequency :" - entry $id.1rangef.lowfreq -textvariable $var_graph_lowfreq -width 7 - pack $id.1rangef.llowfreq $id.1rangef.lowfreq -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lhighfreq -text "Higher Frequency :" - entry $id.2rangef.highfreq -textvariable $var_graph_highfreq -width 7 - pack $id.2rangef.lhighfreq $id.2rangef.highfreq -side left - - bind $id.1rangef.lowfreq [concat filterbank_ok $id] - bind $id.2rangef.highfreq [concat filterbank_ok $id] - focus $id.1rangef.lowfreq -} - -############ filterbank procedures END -- ydegoyon@free.fr ######### diff --git a/filterbank~/filterbank~.tk2c b/filterbank~/filterbank~.tk2c deleted file mode 100755 index 13d8482..0000000 --- a/filterbank~/filterbank~.tk2c +++ /dev/null @@ -1,58 +0,0 @@ -// ########### filterbank procedures -- ydegoyon@free.fr ######### -sys_gui("proc filterbank_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_lowfreq [concat graph_lowfreq_$vid]\n"); -sys_gui("global $var_graph_lowfreq\n"); -sys_gui("set var_graph_highfreq [concat graph_highfreq_$vid]\n"); -sys_gui("global $var_graph_highfreq\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_lowfreq] [eval concat $$var_graph_highfreq] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc filterbank_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc filterbank_ok {id} {\n"); -sys_gui("filterbank_apply $id\n"); -sys_gui("filterbank_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_filterbank_dialog {id lowfreq highfreq} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_lowfreq [concat graph_lowfreq_$vid]\n"); -sys_gui("global $var_graph_lowfreq\n"); -sys_gui("set var_graph_highfreq [concat graph_highfreq_$vid]\n"); -sys_gui("global $var_graph_highfreq\n"); -sys_gui("set $var_graph_lowfreq $lowfreq\n"); -sys_gui("set $var_graph_highfreq $highfreq\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {filterbank}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat filterbank_cancel $id]\n"); -sys_gui("label $id.label -text {FILTERBANK PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"filterbank_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"filterbank_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"filterbank_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.llowfreq -text \"Lower Frequency :\"\n"); -sys_gui("entry $id.1rangef.lowfreq -textvariable $var_graph_lowfreq -width 7\n"); -sys_gui("pack $id.1rangef.llowfreq $id.1rangef.lowfreq -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lhighfreq -text \"Higher Frequency :\"\n"); -sys_gui("entry $id.2rangef.highfreq -textvariable $var_graph_highfreq -width 7\n"); -sys_gui("pack $id.2rangef.lhighfreq $id.2rangef.highfreq -side left\n"); -sys_gui("bind $id.1rangef.lowfreq [concat filterbank_ok $id]\n"); -sys_gui("bind $id.2rangef.highfreq [concat filterbank_ok $id]\n"); -sys_gui("focus $id.1rangef.lowfreq\n"); -sys_gui("}\n"); -// ########### filterbank procedures END -- ydegoyon@free.fr ######### diff --git a/filterbank~/resynth-64.pd b/filterbank~/resynth-64.pd deleted file mode 100644 index bb5a93d..0000000 --- a/filterbank~/resynth-64.pd +++ /dev/null @@ -1,285 +0,0 @@ -#N canvas 36 14 971 657 10; -#X obj 56 522 *~ 1; -#X obj 103 522 / 100; -#X floatatom 147 522 5 0 0; -#X obj 272 280 filterbank~ 0 1920 64; -#X obj 31 62 t s b; -#X obj 80 68 float \$0; -#X obj 31 85 route float; -#X msg 336 250 bang; -#X obj 31 177 soundfiler; -#X obj 125 250 tabplay~ \$0-filterbank-sample; -#X obj 31 108 makefilename %d-filterbank-sample; -#X obj 31 131 pack s s; -#X msg 31 154 read -resize \$1 \$2; -#X msg 239 220 bang; -#X obj 28 220 tabplay~ \$0-filterbank-sample; -#X obj 72 599 table \$0-filterbank-sample; -#X msg 430 250 randomize 1; -#X obj 486 42 playlist all 200 200; -#X msg 359 35 location /Samples; -#X obj 359 12 loadbang; -#X obj 374 569 volpan; -#X msg 518 250 randomize 0; -#X obj 354 123 s fbstep; -#X floatatom 354 100 5 0 0; -#X msg 306 91 30; -#X obj 306 68 loadbang; -#X floatatom 229 42 5 0 0; -#X obj 210 68 s firstfreq; -#X msg 181 35 15; -#X obj 181 12 loadbang; -#X obj 107 314 setosc 0; -#X obj 107 337 setosc 1; -#X obj 107 360 setosc 2; -#X obj 107 383 setosc 3; -#X obj 107 406 setosc 4; -#X obj 107 429 setosc 5; -#X obj 107 452 setosc 6; -#X obj 108 476 setosc 7; -#X obj 199 521 *~ 1; -#X obj 246 521 / 100; -#X floatatom 290 521 5 0 0; -#X obj 250 313 setosc 8; -#X obj 250 336 setosc 9; -#X obj 250 359 setosc 10; -#X obj 250 382 setosc 11; -#X obj 250 405 setosc 12; -#X obj 250 428 setosc 13; -#X obj 250 451 setosc 14; -#X obj 251 475 setosc 15; -#X obj 339 519 *~ 1; -#X obj 386 519 / 100; -#X floatatom 430 519 5 0 0; -#X obj 390 311 setosc 16; -#X obj 390 334 setosc 17; -#X obj 390 357 setosc 18; -#X obj 390 380 setosc 19; -#X obj 390 403 setosc 20; -#X obj 390 426 setosc 21; -#X obj 390 449 setosc 22; -#X obj 391 473 setosc 23; -#X obj 479 519 *~ 1; -#X obj 526 519 / 100; -#X floatatom 570 519 5 0 0; -#X obj 530 311 setosc 24; -#X obj 530 334 setosc 25; -#X obj 530 357 setosc 26; -#X obj 530 380 setosc 27; -#X obj 530 403 setosc 28; -#X obj 530 426 setosc 29; -#X obj 530 449 setosc 30; -#X obj 531 473 setosc 31; -#X obj 621 518 *~ 1; -#X obj 668 518 / 100; -#X floatatom 712 518 5 0 0; -#X obj 672 310 setosc 32; -#X obj 672 333 setosc 33; -#X obj 672 356 setosc 34; -#X obj 672 379 setosc 35; -#X obj 672 402 setosc 36; -#X obj 672 425 setosc 37; -#X obj 672 448 setosc 38; -#X obj 673 472 setosc 39; -#X obj 762 519 *~ 1; -#X obj 809 519 / 100; -#X floatatom 853 519 5 0 0; -#X obj 813 311 setosc 40; -#X obj 813 334 setosc 41; -#X obj 813 357 setosc 42; -#X obj 813 380 setosc 43; -#X obj 813 403 setosc 44; -#X obj 813 426 setosc 45; -#X obj 813 449 setosc 46; -#X obj 814 473 setosc 47; -#X obj 903 519 *~ 1; -#X obj 950 519 / 100; -#X floatatom 994 519 5 0 0; -#X obj 954 311 setosc 48; -#X obj 954 334 setosc 49; -#X obj 954 357 setosc 50; -#X obj 954 380 setosc 51; -#X obj 954 403 setosc 52; -#X obj 954 426 setosc 53; -#X obj 954 449 setosc 54; -#X obj 955 473 setosc 55; -#X obj 1041 518 *~ 1; -#X obj 1088 518 / 100; -#X floatatom 1132 518 5 0 0; -#X obj 1092 310 setosc 56; -#X obj 1092 333 setosc 57; -#X obj 1092 356 setosc 58; -#X obj 1092 379 setosc 59; -#X obj 1092 402 setosc 60; -#X obj 1092 425 setosc 61; -#X obj 1092 448 setosc 62; -#X obj 1093 472 setosc 63; -#X connect 0 0 20 0; -#X connect 1 0 0 1; -#X connect 2 0 1 0; -#X connect 3 0 30 0; -#X connect 3 1 31 0; -#X connect 3 2 32 0; -#X connect 3 3 33 0; -#X connect 3 4 34 0; -#X connect 3 5 35 0; -#X connect 3 6 36 0; -#X connect 3 7 37 0; -#X connect 3 8 41 0; -#X connect 3 9 42 0; -#X connect 3 10 43 0; -#X connect 3 11 44 0; -#X connect 3 12 45 0; -#X connect 3 13 46 0; -#X connect 3 14 47 0; -#X connect 3 15 48 0; -#X connect 3 16 52 0; -#X connect 3 17 53 0; -#X connect 3 18 54 0; -#X connect 3 19 55 0; -#X connect 3 20 56 0; -#X connect 3 21 57 0; -#X connect 3 22 58 0; -#X connect 3 23 59 0; -#X connect 3 24 63 0; -#X connect 3 25 64 0; -#X connect 3 26 65 0; -#X connect 3 27 66 0; -#X connect 3 28 67 0; -#X connect 3 29 68 0; -#X connect 3 30 69 0; -#X connect 3 31 70 0; -#X connect 3 32 74 0; -#X connect 3 33 75 0; -#X connect 3 34 76 0; -#X connect 3 35 77 0; -#X connect 3 36 78 0; -#X connect 3 37 79 0; -#X connect 3 38 80 0; -#X connect 3 39 81 0; -#X connect 3 40 85 0; -#X connect 3 41 86 0; -#X connect 3 42 87 0; -#X connect 3 43 88 0; -#X connect 3 44 89 0; -#X connect 3 45 90 0; -#X connect 3 46 91 0; -#X connect 3 47 92 0; -#X connect 3 48 96 0; -#X connect 3 49 97 0; -#X connect 3 50 98 0; -#X connect 3 51 99 0; -#X connect 3 52 100 0; -#X connect 3 53 101 0; -#X connect 3 54 102 0; -#X connect 3 55 103 0; -#X connect 3 56 107 0; -#X connect 3 57 108 0; -#X connect 3 58 109 0; -#X connect 3 59 110 0; -#X connect 3 60 111 0; -#X connect 3 61 112 0; -#X connect 3 62 113 0; -#X connect 3 63 114 0; -#X connect 4 0 11 0; -#X connect 4 1 5 0; -#X connect 5 0 6 0; -#X connect 6 0 10 0; -#X connect 7 0 9 0; -#X connect 9 0 3 0; -#X connect 10 0 11 1; -#X connect 11 0 12 0; -#X connect 12 0 8 0; -#X connect 13 0 14 0; -#X connect 14 0 0 0; -#X connect 16 0 3 0; -#X connect 17 0 4 0; -#X connect 18 0 17 0; -#X connect 19 0 18 0; -#X connect 21 0 3 0; -#X connect 23 0 22 0; -#X connect 24 0 22 0; -#X connect 25 0 24 0; -#X connect 26 0 27 0; -#X connect 28 0 27 0; -#X connect 29 0 28 0; -#X connect 30 0 0 0; -#X connect 31 0 0 0; -#X connect 32 0 0 0; -#X connect 33 0 0 0; -#X connect 34 0 0 0; -#X connect 35 0 0 0; -#X connect 36 0 0 0; -#X connect 37 0 0 0; -#X connect 38 0 20 0; -#X connect 39 0 38 1; -#X connect 40 0 39 0; -#X connect 41 0 38 0; -#X connect 42 0 38 0; -#X connect 43 0 38 0; -#X connect 44 0 38 0; -#X connect 45 0 38 0; -#X connect 46 0 38 0; -#X connect 47 0 38 0; -#X connect 48 0 38 0; -#X connect 49 0 20 0; -#X connect 50 0 49 1; -#X connect 51 0 50 0; -#X connect 52 0 49 0; -#X connect 53 0 49 0; -#X connect 54 0 49 0; -#X connect 55 0 49 0; -#X connect 56 0 49 0; -#X connect 57 0 49 0; -#X connect 58 0 49 0; -#X connect 59 0 49 0; -#X connect 61 0 60 1; -#X connect 62 0 61 0; -#X connect 63 0 60 0; -#X connect 64 0 60 0; -#X connect 65 0 60 0; -#X connect 66 0 60 0; -#X connect 67 0 60 0; -#X connect 68 0 60 0; -#X connect 69 0 60 0; -#X connect 70 0 60 0; -#X connect 72 0 71 1; -#X connect 73 0 72 0; -#X connect 74 0 71 0; -#X connect 75 0 71 0; -#X connect 76 0 71 0; -#X connect 77 0 71 0; -#X connect 78 0 71 0; -#X connect 79 0 71 0; -#X connect 80 0 71 0; -#X connect 81 0 71 0; -#X connect 83 0 82 1; -#X connect 84 0 83 0; -#X connect 85 0 82 0; -#X connect 86 0 82 0; -#X connect 87 0 82 0; -#X connect 88 0 82 0; -#X connect 89 0 82 0; -#X connect 90 0 82 0; -#X connect 91 0 82 0; -#X connect 92 0 82 0; -#X connect 94 0 93 1; -#X connect 95 0 94 0; -#X connect 96 0 93 0; -#X connect 97 0 93 0; -#X connect 98 0 93 0; -#X connect 99 0 93 0; -#X connect 100 0 93 0; -#X connect 101 0 93 0; -#X connect 102 0 93 0; -#X connect 103 0 93 0; -#X connect 105 0 104 1; -#X connect 106 0 105 0; -#X connect 107 0 104 0; -#X connect 108 0 104 0; -#X connect 109 0 104 0; -#X connect 110 0 104 0; -#X connect 111 0 104 0; -#X connect 112 0 104 0; -#X connect 113 0 104 0; -#X connect 114 0 104 0; diff --git a/filterbank~/setosc.pd b/filterbank~/setosc.pd deleted file mode 100644 index 6cb4ff0..0000000 --- a/filterbank~/setosc.pd +++ /dev/null @@ -1,21 +0,0 @@ -#N canvas 242 244 450 300 10; -#X obj 191 209 osc~; -#X obj 140 247 *~; -#X obj 140 277 outlet~; -#X obj 83 112 inlet~; -#X floatatom 236 186 5 0 0; -#X msg 274 87 bang; -#X obj 335 64 r fbstep; -#X obj 145 55 r firstfreq; -#X obj 217 138 expr $f1 + $f2 * \$1; -#X obj 341 100 t b f; -#X connect 0 0 1 0; -#X connect 1 0 2 0; -#X connect 3 0 1 1; -#X connect 5 0 8 0; -#X connect 6 0 9 0; -#X connect 7 0 8 0; -#X connect 8 0 4 0; -#X connect 8 0 0 0; -#X connect 9 0 8 0; -#X connect 9 1 8 1; diff --git a/filterbank~/tk2c.bash b/filterbank~/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/filterbank~/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/filters.c b/filters.c new file mode 100644 index 0000000..2bf9253 --- /dev/null +++ b/filters.c @@ -0,0 +1,49 @@ +/* +vox - a musical real-time vocoder. version 1.0 +Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + + +void lpc_filter(double *buf_ppf, double *lpc_coef, double *buf_sy, int n) +{ + int i,j; + double acc; + + for(i=0;i +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#ifdef UNIX +#include +#endif +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif +#include + +#include /* standard pd stuff */ + +static char *formant_version = "formant~: formant synthesis version 0.1, written by Yves Degoyon"; + + +static t_class *formant_class; + +typedef struct _formant +{ + t_object x_obj; + + t_int x_size; /* size of the sample */ + t_float x_central_freq; /* central frequency of the filter */ + t_float x_filter_width; /* width of the filter */ + t_float x_skirt_width; /* width of the skirt */ + t_float x_samplerate; /* sample rate */ + t_float x_time_stretch; /* time stretch */ + t_int x_readpos; /* data's reading position */ + t_int x_play; /* playing on/off flag */ + t_outlet *x_end; /* outlet for outputing a bang at the end */ + t_float x_gendata; /* flag to avoid reading data during generation ( might be null )*/ + t_float* x_data; /* sample containing formant synthesis*/ + +} t_formant; + + /* clean up */ +static void formant_free(t_formant *x) +{ + if ( x->x_data != NULL ) { + freebytes(x->x_data, x->x_size*sizeof(float) ); + x->x_data = NULL; + } +} + + /* generate sample data */ +static t_int formant_gendata(t_formant *x) +{ + t_float t, b, fs; + + if ( x->x_size <= 0 || x->x_central_freq <= 0 || x->x_filter_width <= 0 || x->x_skirt_width <= 0 ) { + error( "formant~ : error generating data : negative or null parameter(s)" ); + return -1; + } + + x->x_gendata = 1; + + /* freeing data */ + formant_free( x ); + if ( !( x->x_data = (float*) getbytes( x->x_size*sizeof(float) ) ) ) { + post( "formant~ : error generating data : cannot allocate table" ); + return -1; + } + + fs = 0; + while( fs < x->x_size-1 ) { + t = (fs/x->x_samplerate) * x->x_time_stretch; /* time taken from zero */ + b = M_PI / x->x_skirt_width ; + if ( t < b ) { + *(x->x_data+(int)fs) = 0.5*(1-cos(x->x_skirt_width*t))*exp(- x->x_filter_width*t )*sin( x->x_central_freq*t); + } else { + *(x->x_data+(int)fs) = exp(- x->x_filter_width*t )*sin( x->x_central_freq*t); + } + fs++; + } + + /* everything went fine */ + x->x_gendata = 0; + return 0; +} + + /* generates a formant */ +static t_int *formant_perform(t_int *w) +{ + t_formant *x = (t_formant *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); /* number of samples */ + + while (n--) { + if ( !x->x_gendata && x->x_play) { + *out=*(x->x_data+x->x_readpos); + x->x_readpos = (x->x_readpos+1)%x->x_size; + if ( x->x_readpos == 0 ) { + x->x_play=0; + outlet_bang(x->x_end); + } + } else { + *out=0.0; + } + out++; + } + return (w+4); +} + +static void formant_dsp(t_formant *x, t_signal **sp) +{ + dsp_add(formant_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + + /* replay the sample */ +static void formant_bang(t_formant *x, t_floatarg fsize) +{ + x->x_play=1; + x->x_readpos=0; +} + + /* set size of the sample */ +static void formant_size(t_formant *x, t_floatarg fsize) +{ + if ( fsize <= 0 ) { + post( "formant~ : error : sample size should be >0" ); + return; + } + x->x_size = fsize; + formant_gendata( x ); +} + + /* set central frequency of the formant */ +static void formant_central_freq(t_formant *x, t_floatarg ffreq) +{ + if ( ffreq <= 0 ) { + post( "formant~ : error : filter central frequency should be >0" ); + return; + } + x->x_central_freq = ffreq; + formant_gendata( x ); +} + + /* set filter width of the formant */ +static void formant_filter_width(t_formant *x, t_floatarg fwidth) +{ + if ( fwidth <= 0 ) { + post( "formant~ : error : filter width should be >0" ); + return; + } + x->x_filter_width = fwidth; + formant_gendata( x ); +} + + /* set skirt width of the formant */ +static void formant_skirt_width(t_formant *x, t_floatarg swidth) +{ + if ( swidth <= 0 ) { + post( "formant~ : error : skirt width should be >0" ); + return; + } + x->x_skirt_width = swidth; + formant_gendata( x ); +} + + /* set time stretch factor */ +static void formant_time_stretch(t_formant *x, t_floatarg fstretch) +{ + if ( fstretch <= 0 ) { + post( "formant~ : error : time stretch should be >0" ); + return; + } + x->x_time_stretch = fstretch; + formant_gendata( x ); +} + +static void *formant_new(t_floatarg fsize, t_floatarg ffreq, t_floatarg ffwidth, t_floatarg fswidth) +{ + t_formant *x = (t_formant *)pd_new(formant_class); + outlet_new(&x->x_obj, &s_signal); + + if ( fsize <= 0 || ffreq <= 0 || ffwidth <= 0 || fswidth <= 0 ) { + error( "formant~ : missing or negative creation arguments" ); + return NULL; + } + + x->x_size = fsize; + x->x_central_freq = ffreq; + x->x_filter_width = ffwidth; + x->x_skirt_width = fswidth; + x->x_readpos = 0; + x->x_data = NULL; + x->x_time_stretch = 1.0; + x->x_samplerate = sys_getsr(); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("size")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("freq")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("fwidth")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("swidth")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("stretch")); + x->x_end = outlet_new( &x->x_obj, &s_bang ); + if ( formant_gendata( x ) ) { + post( "formant~ : error generating data" ); + return NULL; + } else { + return(x); + } +} + +void formant_tilde_setup(void) +{ + post(formant_version); + formant_class = class_new(gensym("formant~"), (t_newmethod)formant_new, (t_method)formant_free, + sizeof(t_formant), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(formant_class, (t_method)formant_dsp, gensym("dsp"), 0); + class_addmethod(formant_class, (t_method)formant_size, gensym("size"), A_FLOAT, 0); + class_addmethod(formant_class, (t_method)formant_bang, gensym("bang"), 0); + class_addmethod(formant_class, (t_method)formant_central_freq, gensym("freq"), A_FLOAT, 0); + class_addmethod(formant_class, (t_method)formant_filter_width, gensym("fwidth"), A_FLOAT, 0); + class_addmethod(formant_class, (t_method)formant_skirt_width, gensym("swidth"), A_FLOAT, 0); + class_addmethod(formant_class, (t_method)formant_time_stretch, gensym("stretch"), A_FLOAT, 0); +} diff --git a/formant~/INSTALL b/formant~/INSTALL deleted file mode 100644 index bcbc08b..0000000 --- a/formant~/INSTALL +++ /dev/null @@ -1,9 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/formant~ - -make - -make install - -you're set !! diff --git a/formant~/formant~-help.pd b/formant~/formant~-help.pd deleted file mode 100644 index c8102b4..0000000 --- a/formant~/formant~-help.pd +++ /dev/null @@ -1,56 +0,0 @@ -#N canvas 190 63 711 524 10; -#X msg 172 385 \; pd dsp 1; -#X msg 238 385 \; pd dsp 0; -#X floatatom 150 58 10 0 0; -#X floatatom 232 121 5 0 0; -#X floatatom 190 93 5 0 0; -#X floatatom 295 140 5 0 0; -#X text 149 42 Size of the synthetized sound; -#X text 189 78 Central frequency; -#X text 232 104 Filter width; -#X text 294 125 Skirt width ( "largeur de jupe" in french ); -#X msg 114 136 bang; -#X text 99 13 Formant synthesis as described by JP Smets; -#X floatatom 340 159 5 0 0; -#X text 382 158 Time Stretch; -#X obj 333 390 dac~; -#X obj 303 244 delay 200; -#X floatatom 364 244 5 0 0; -#X obj 368 298 f; -#X floatatom 367 343 5 0 0; -#X obj 446 297 loadbang; -#X text 323 217 Theoretically \, a singing voice is a combination of -formants but you have to set right frequencies; -#X msg 406 298 2500; -#X obj 367 320 + 100; -#X obj 121 263 formant~ 10000 2600 50 25; -#X obj 303 263 formant~ 10000 1750 70 25; -#X obj 199 319 formant~ 20000 4500 60 25; -#X obj 466 263 formant~ 10000 1200 30 45; -#X connect 2 0 23 1; -#X connect 3 0 23 3; -#X connect 4 0 23 2; -#X connect 5 0 23 4; -#X connect 10 0 15 0; -#X connect 10 0 23 0; -#X connect 10 0 26 0; -#X connect 12 0 23 5; -#X connect 15 0 24 0; -#X connect 16 0 15 1; -#X connect 17 0 22 0; -#X connect 17 0 25 2; -#X connect 19 0 21 0; -#X connect 21 0 17 1; -#X connect 22 0 17 1; -#X connect 22 0 18 0; -#X connect 23 0 14 0; -#X connect 23 0 14 1; -#X connect 23 1 17 0; -#X connect 23 1 25 0; -#X connect 24 0 14 1; -#X connect 24 0 14 0; -#X connect 25 0 14 1; -#X connect 25 0 14 0; -#X connect 25 1 10 0; -#X connect 26 0 14 1; -#X connect 26 0 14 0; diff --git a/formant~/formant~.c b/formant~/formant~.c deleted file mode 100644 index 686974b..0000000 --- a/formant~/formant~.c +++ /dev/null @@ -1,253 +0,0 @@ -/* ------------------------ formant~ ------------------------------------------ */ -/* */ -/* Tilde object to produce formant synthesis. */ -/* By using several ones, you should be able to generate voice sounds. */ -/* Written by Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Also inspired by an article by Jean-Paul Smets - Solanes */ -/* */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef UNIX -#include -#endif -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif -#include - -#include /* standard pd stuff */ - -static char *formant_version = "formant~: formant synthesis version 0.1, written by Yves Degoyon"; - - -static t_class *formant_class; - -typedef struct _formant -{ - t_object x_obj; - - t_int x_size; /* size of the sample */ - t_float x_central_freq; /* central frequency of the filter */ - t_float x_filter_width; /* width of the filter */ - t_float x_skirt_width; /* width of the skirt */ - t_float x_samplerate; /* sample rate */ - t_float x_time_stretch; /* time stretch */ - t_int x_readpos; /* data's reading position */ - t_int x_play; /* playing on/off flag */ - t_outlet *x_end; /* outlet for outputing a bang at the end */ - t_float x_gendata; /* flag to avoid reading data during generation ( might be null )*/ - t_float* x_data; /* sample containing formant synthesis*/ - -} t_formant; - - /* clean up */ -static void formant_free(t_formant *x) -{ - if ( x->x_data != NULL ) { - freebytes(x->x_data, x->x_size*sizeof(float) ); - x->x_data = NULL; - } -} - - /* generate sample data */ -static t_int formant_gendata(t_formant *x) -{ - t_float t, b, fs; - - if ( x->x_size <= 0 || x->x_central_freq <= 0 || x->x_filter_width <= 0 || x->x_skirt_width <= 0 ) { - error( "formant~ : error generating data : negative or null parameter(s)" ); - return -1; - } - - x->x_gendata = 1; - - /* freeing data */ - formant_free( x ); - if ( !( x->x_data = (float*) getbytes( x->x_size*sizeof(float) ) ) ) { - post( "formant~ : error generating data : cannot allocate table" ); - return -1; - } - - fs = 0; - while( fs < x->x_size-1 ) { - t = (fs/x->x_samplerate) * x->x_time_stretch; /* time taken from zero */ - b = M_PI / x->x_skirt_width ; - if ( t < b ) { - *(x->x_data+(int)fs) = 0.5*(1-cos(x->x_skirt_width*t))*exp(- x->x_filter_width*t )*sin( x->x_central_freq*t); - } else { - *(x->x_data+(int)fs) = exp(- x->x_filter_width*t )*sin( x->x_central_freq*t); - } - fs++; - } - - /* everything went fine */ - x->x_gendata = 0; - return 0; -} - - /* generates a formant */ -static t_int *formant_perform(t_int *w) -{ - t_formant *x = (t_formant *)(w[1]); - t_float *out = (t_float *)(w[2]); - int n = (int)(w[3]); /* number of samples */ - - while (n--) { - if ( !x->x_gendata && x->x_play) { - *out=*(x->x_data+x->x_readpos); - x->x_readpos = (x->x_readpos+1)%x->x_size; - if ( x->x_readpos == 0 ) { - x->x_play=0; - outlet_bang(x->x_end); - } - } else { - *out=0.0; - } - out++; - } - return (w+4); -} - -static void formant_dsp(t_formant *x, t_signal **sp) -{ - dsp_add(formant_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); -} - - /* replay the sample */ -static void formant_bang(t_formant *x, t_floatarg fsize) -{ - x->x_play=1; - x->x_readpos=0; -} - - /* set size of the sample */ -static void formant_size(t_formant *x, t_floatarg fsize) -{ - if ( fsize <= 0 ) { - post( "formant~ : error : sample size should be >0" ); - return; - } - x->x_size = fsize; - formant_gendata( x ); -} - - /* set central frequency of the formant */ -static void formant_central_freq(t_formant *x, t_floatarg ffreq) -{ - if ( ffreq <= 0 ) { - post( "formant~ : error : filter central frequency should be >0" ); - return; - } - x->x_central_freq = ffreq; - formant_gendata( x ); -} - - /* set filter width of the formant */ -static void formant_filter_width(t_formant *x, t_floatarg fwidth) -{ - if ( fwidth <= 0 ) { - post( "formant~ : error : filter width should be >0" ); - return; - } - x->x_filter_width = fwidth; - formant_gendata( x ); -} - - /* set skirt width of the formant */ -static void formant_skirt_width(t_formant *x, t_floatarg swidth) -{ - if ( swidth <= 0 ) { - post( "formant~ : error : skirt width should be >0" ); - return; - } - x->x_skirt_width = swidth; - formant_gendata( x ); -} - - /* set time stretch factor */ -static void formant_time_stretch(t_formant *x, t_floatarg fstretch) -{ - if ( fstretch <= 0 ) { - post( "formant~ : error : time stretch should be >0" ); - return; - } - x->x_time_stretch = fstretch; - formant_gendata( x ); -} - -static void *formant_new(t_floatarg fsize, t_floatarg ffreq, t_floatarg ffwidth, t_floatarg fswidth) -{ - t_formant *x = (t_formant *)pd_new(formant_class); - outlet_new(&x->x_obj, &s_signal); - - if ( fsize <= 0 || ffreq <= 0 || ffwidth <= 0 || fswidth <= 0 ) { - error( "formant~ : missing or negative creation arguments" ); - return NULL; - } - - x->x_size = fsize; - x->x_central_freq = ffreq; - x->x_filter_width = ffwidth; - x->x_skirt_width = fswidth; - x->x_readpos = 0; - x->x_data = NULL; - x->x_time_stretch = 1.0; - x->x_samplerate = sys_getsr(); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("size")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("freq")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("fwidth")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("swidth")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("stretch")); - x->x_end = outlet_new( &x->x_obj, &s_bang ); - if ( formant_gendata( x ) ) { - post( "formant~ : error generating data" ); - return NULL; - } else { - return(x); - } -} - -void formant_tilde_setup(void) -{ - post(formant_version); - formant_class = class_new(gensym("formant~"), (t_newmethod)formant_new, (t_method)formant_free, - sizeof(t_formant), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - class_addmethod(formant_class, (t_method)formant_dsp, gensym("dsp"), 0); - class_addmethod(formant_class, (t_method)formant_size, gensym("size"), A_FLOAT, 0); - class_addmethod(formant_class, (t_method)formant_bang, gensym("bang"), 0); - class_addmethod(formant_class, (t_method)formant_central_freq, gensym("freq"), A_FLOAT, 0); - class_addmethod(formant_class, (t_method)formant_filter_width, gensym("fwidth"), A_FLOAT, 0); - class_addmethod(formant_class, (t_method)formant_skirt_width, gensym("swidth"), A_FLOAT, 0); - class_addmethod(formant_class, (t_method)formant_time_stretch, gensym("stretch"), A_FLOAT, 0); -} diff --git a/g_grid.h b/g_grid.h new file mode 100644 index 0000000..9c89228 --- /dev/null +++ b/g_grid.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2002 Yves Degoyon +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* a header for grid which enables to control +* 2 parameters with the mouse cursor +*/ + +#ifndef __G_GRID_H +#define __G_GRID_H + +typedef struct _grid +{ + t_object x_obj; + t_glist *x_glist; + t_symbol *x_name; + t_outlet *x_xoutlet; + t_outlet *x_youtlet; + int x_height; /* height of the grid */ + t_float x_min; /* minimum value of x */ + t_float x_max; /* max value of x */ + int x_width; /* width of the grid */ + t_float y_min; /* minimum value of y */ + t_float y_max; /* max value of y */ + t_float x_current; /* x coordinate of current position */ + t_float y_current; /* y coordinate of current position */ + int x_selected; /* stores selected state */ + int x_point; /* indicates if a point is plotted */ + int x_grid; /* indicates if a grid is requested */ + t_float x_xstep; /* sets the step ( grain ) for x */ + t_float x_ystep; /* sets the step ( grain ) for y */ + int x_xlines; /* number of vertical lines */ + int x_ylines; /* number of horizontal lines */ + char *x_bgcolor; /* background color */ +} t_grid; + +#endif diff --git a/graphic-mp3amp~-help.pd b/graphic-mp3amp~-help.pd new file mode 100644 index 0000000..241a607 --- /dev/null +++ b/graphic-mp3amp~-help.pd @@ -0,0 +1,52 @@ +#N canvas 171 33 789 555 10; +#X obj 115 265 dac~; +#X floatatom 164 265 5 0 0; +#X msg 29 150 disconnect; +#X text 208 267 connection status; +#X obj 458 48 loadbang; +#X msg 458 71 \; pd dsp 1; +#X msg 99 76 connect yves puredata 8000; +#X text 96 55 connect ; +#X text 38 18 constructor : mp3amp~ ; +#X text 151 127 connect to SHOUTcast server; +#X msg 157 145 connect localhost listen.pls 8000; +#X msg 176 165 connect localhost content/scpromo.mp3 8000; +#X text 399 141 <-- play livestream; +#X text 479 165 <-- play file; +#X msg 121 99 connect localhost kas 8000; +#X text 97 44 connect to ICEcast server; +#X text 38 7 mp3amp~ : an icecast/shoucast client for PD; +#X text 226 186 Another way of connecting; +#X msg 226 205 connecturl http://localhost:8000/kas; +#X msg 31 374 standby 0; +#X text 114 380 for CPU load reasons \,; +#X text 115 392 ability to freeze decoding; +#X text 114 405 ( packets are read and ignored ); +#X msg 31 399 standby 1; +#X obj 115 196 mp3amp~ 1; +#X msg 353 230 connecturl http://216.235.81.7:20690/play?session=panjabiradio:0&\;lid=-1-fra&\;SaneID=212.198.0.97-1030988754258 +; +#X msg 352 280 connecturl http://213.197.144.44:8000/; +#X msg 352 334 connecturl http://24.207.26.60:8000/; +#X msg 354 307 connecturl http://64.113.197.158:8000/; +#X msg 352 361 connecturl http://liveice.agria.hu:8000/radioeger-hq +; +#X text 406 511 Authors : Yves Degoyon ( ydegoyon@free.fr ); +#X connect 2 0 24 0; +#X connect 4 0 5 0; +#X connect 6 0 24 0; +#X connect 10 0 24 0; +#X connect 11 0 24 0; +#X connect 14 0 24 0; +#X connect 18 0 24 0; +#X connect 19 0 24 0; +#X connect 23 0 24 0; +#X connect 24 0 0 0; +#X connect 24 0 0 1; +#X connect 24 1 0 1; +#X connect 24 2 1 0; +#X connect 25 0 24 0; +#X connect 26 0 24 0; +#X connect 27 0 24 0; +#X connect 28 0 24 0; +#X connect 29 0 24 0; diff --git a/grid-help.pd b/grid-help.pd new file mode 100644 index 0000000..23d6cc5 --- /dev/null +++ b/grid-help.pd @@ -0,0 +1,201 @@ +#N canvas 26 1 763 647 10; +#X obj 72 77 grid grid1 200 0 199 200 0 199 1 1 1 10 10 72 77; +#X floatatom 72 293 5 0 0 0 - - -; +#X floatatom 257 282 5 0 0 0 - - -; +#X text 41 21 Grid is a 2-dimensional control object; +#X text 319 449 (invoke with Properties ); +#X text 322 439 You can set the following properties :; +#X text 347 468 * Name; +#X text 346 480 * Width : graphical x size; +#X text 346 491 * X min : minimum value delivered by left outlet ( +X ); +#X text 346 503 * X max : maximum value delivered by left outlet ( +X ); +#X text 347 513 * X step : X delta for an X update; +#X text 346 524 * X sections : number of vertical lines of the inner +grid; +#X text 347 534 * Height : graphical y size; +#X text 346 546 * Y min : minimum value delivered by right outlet ( +Y ); +#X text 347 558 * Y max : maximum value delivered by right outlet ( +Y ); +#X text 346 579 * Y sections : number of horizontal lines of the inner +grid; +#X text 347 591 * Show Grid : option to draw an inner grid; +#X text 328 609 bugs and comments @ ydegoyon@free.fr; +#X text 120 292 X value; +#X text 303 281 Y value; +#X msg 587 271 \; pd dsp 0; +#X msg 653 271 \; pd dsp 1; +#X obj 276 417 *~; +#X floatatom 276 360 0 0 0 0 - - -; +#X obj 357 397 line~; +#X floatatom 188 380 0 0 0 0 - - -; +#X obj 188 494 cos~; +#X obj 188 450 +~; +#X floatatom 228 506 0 0 100 0 - - -; +#N canvas 159 26 495 270 output 0; +#X obj 338 160 t b; +#X obj 338 110 f; +#X obj 338 60 inlet; +#X text 344 29 mute; +#X obj 338 185 f; +#X msg 425 178 0; +#X msg 338 85 bang; +#X obj 338 135 moses 1; +#X obj 425 153 t b f; +#X obj 397 117 moses 1; +#X obj 83 148 dbtorms; +#X obj 397 92 r master-lvl; +#X obj 83 42 r master-lvl; +#X obj 338 210 s master-lvl; +#X obj 22 182 inlet~; +#X obj 199 41 inlet; +#X text 199 18 level; +#X obj 199 100 s master-lvl; +#X msg 96 65 set \$1; +#X obj 96 89 outlet; +#X msg 214 64 \; pd dsp 1; +#X obj 83 194 line~; +#X obj 22 212 *~; +#X obj 22 241 dac~; +#X obj 83 171 pack 0 50; +#X text 20 159 audio; +#X text 93 110 show level; +#X connect 0 0 4 0; +#X connect 1 0 7 0; +#X connect 2 0 6 0; +#X connect 4 0 13 0; +#X connect 5 0 13 0; +#X connect 6 0 1 0; +#X connect 7 0 0 0; +#X connect 7 1 8 0; +#X connect 8 0 5 0; +#X connect 9 1 4 1; +#X connect 10 0 24 0; +#X connect 11 0 1 1; +#X connect 11 0 9 0; +#X connect 12 0 10 0; +#X connect 12 0 18 0; +#X connect 14 0 22 0; +#X connect 15 0 17 0; +#X connect 15 0 20 0; +#X connect 18 0 19 0; +#X connect 21 0 22 1; +#X connect 22 0 23 0; +#X connect 22 0 23 1; +#X connect 24 0 21 0; +#X restore 190 533 pd output; +#X msg 266 506 MUTE; +#X obj 276 385 osc~ 0; +#X obj 357 371 pack 0 50; +#X floatatom 357 318 0 0 0 0 - - -; +#X obj 357 345 / 100; +#X text 188 345 carrier; +#X text 184 355 frequency; +#X text 261 336 frequency; +#X text 262 319 modulation; +#X obj 188 407 phasor~; +#X msg 39 350 250; +#X obj 39 328 loadbang; +#X text 17 377 3-dimensional control; +#X text 16 389 would be nice :-); +#X text 393 310 modulation index; +#X text 393 325 in hundredths; +#X text 40 32 It was inspired by the chaospad device; +#X text 346 568 * Y step : Y delta for an Y update; +#X floatatom 474 85 5 0 0 0 - - -; +#X floatatom 586 84 5 0 0 0 - - -; +#X obj 411 82 pack f f; +#X msg 332 81 goto \$1 \$2; +#X msg 546 83 bang; +#X text 524 84 X; +#X text 333 63 Set position :; +#X text 631 85 Y; +#X floatatom 486 120 5 0 0 0 - - -; +#X floatatom 586 121 5 0 0 0 - - -; +#X obj 423 119 pack f f; +#X msg 546 120 bang; +#X text 530 120 X; +#X text 634 121 Y; +#X floatatom 528 156 5 0 0 0 - - -; +#X floatatom 633 156 5 0 0 0 - - -; +#X obj 465 153 pack f f; +#X msg 593 154 bang; +#X text 578 155 X; +#X text 679 156 Y; +#X floatatom 503 191 5 0 0 0 - - -; +#X floatatom 607 190 5 0 0 0 - - -; +#X obj 440 188 pack f f; +#X msg 568 189 bang; +#X text 553 190 X; +#X text 656 191 Y; +#X floatatom 539 224 5 0 0 0 - - -; +#X floatatom 638 226 5 0 0 0 - - -; +#X obj 472 223 pack f f; +#X msg 600 224 bang; +#X text 585 225 X; +#X text 685 225 Y; +#X msg 109 49 bang; +#X msg 332 118 values \$1 \$2; +#X text 333 100 Set values :; +#X text 331 135 Set deltas for values :; +#X msg 333 152 valuemotion \$1 \$2; +#X msg 333 187 xvalues \$1 \$2; +#X text 334 170 Set values without changing output :; +#X text 332 205 Set deltas for values without changing output:; +#X msg 334 223 xvaluemotion \$1 \$2; +#X msg 334 250 color 123 45 185; +#X text 461 250 change bg color ( from alberto zin ); +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 1 0 23 0; +#X connect 2 0 33 0; +#X connect 22 0 27 1; +#X connect 23 0 31 0; +#X connect 24 0 22 1; +#X connect 25 0 39 0; +#X connect 26 0 29 0; +#X connect 27 0 26 0; +#X connect 28 0 29 1; +#X connect 29 0 28 0; +#X connect 30 0 29 2; +#X connect 31 0 22 0; +#X connect 32 0 24 0; +#X connect 33 0 34 0; +#X connect 34 0 32 0; +#X connect 39 0 27 0; +#X connect 40 0 25 0; +#X connect 41 0 40 0; +#X connect 48 0 50 0; +#X connect 49 0 50 1; +#X connect 49 0 52 0; +#X connect 50 0 51 0; +#X connect 51 0 0 0; +#X connect 52 0 48 0; +#X connect 56 0 58 0; +#X connect 57 0 58 1; +#X connect 57 0 59 0; +#X connect 58 0 81 0; +#X connect 59 0 56 0; +#X connect 62 0 64 0; +#X connect 63 0 64 1; +#X connect 63 0 65 0; +#X connect 64 0 84 0; +#X connect 65 0 62 0; +#X connect 68 0 70 0; +#X connect 69 0 70 1; +#X connect 69 0 71 0; +#X connect 70 0 85 0; +#X connect 71 0 68 0; +#X connect 74 0 76 0; +#X connect 75 0 76 1; +#X connect 75 0 77 0; +#X connect 76 0 88 0; +#X connect 77 0 74 0; +#X connect 80 0 0 0; +#X connect 81 0 0 0; +#X connect 84 0 0 0; +#X connect 85 0 0 0; +#X connect 88 0 0 0; +#X connect 89 0 0 0; diff --git a/grid.c b/grid.c new file mode 100644 index 0000000..84c0d7c --- /dev/null +++ b/grid.c @@ -0,0 +1,717 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_grid.c written by Yves Degoyon 2002 */ +/* grid control object : two dimensionnal grid */ +/* thanks to Thomas Musil, Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + +#include "g_grid.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define DEFAULT_GRID_WIDTH 200 +#define DEFAULT_GRID_HEIGHT 200 +#define DEFAULT_GRID_NBLINES 10 + +t_widgetbehavior grid_widgetbehavior; +static t_class *grid_class; +static int gridcount=0; + +static int guidebug=0; +static int pointsize = 5; + +static char *grid_version = "grid: version 0.8, written by Yves Degoyon (ydegoyon@free.fr)"; + +#define GRID_SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define GRID_SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define GRID_SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define GRID_SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define GRID_SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define GRID_SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +/* drawing functions */ +static void grid_draw_update(t_grid *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int xpoint=x->x_current, ypoint=x->y_current; + + // later : try to figure out what's this test for ?? + // if (glist_isvisible(glist)) + // { + // delete previous point if existing + if (x->x_point) + { + GRID_SYS_VGUI3(".x%lx.c delete %lxPOINT\n", canvas, x); + } + + if ( x->x_current < text_xpix(&x->x_obj, glist) ) xpoint = text_xpix(&x->x_obj, glist); + if ( x->x_current > text_xpix(&x->x_obj, glist) + x->x_width - pointsize ) + xpoint = text_xpix(&x->x_obj, glist) + x->x_width - pointsize; + if ( x->y_current < text_ypix(&x->x_obj, glist) ) ypoint = text_ypix(&x->x_obj, glist); + if ( x->y_current > text_ypix(&x->x_obj, glist) + x->x_height - pointsize ) + ypoint = text_ypix(&x->x_obj, glist) + x->x_height - pointsize; + // draw the selected point + GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -fill #FF0000 -tags %lxPOINT\n", + canvas, xpoint, ypoint, xpoint+pointsize, ypoint+pointsize, x); + x->x_point = 1; + // } + // else + // { + // post( "grid : position updated in an invisible grid" ); + // } +} + +static void grid_draw_new(t_grid *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + GRID_SYS_VGUI8(".x%lx.c create rectangle %d %d %d %d -fill %s -tags %lxGRID\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x->x_bgcolor, x); + GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -tags %lxo0\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2, + x); + GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -tags %lxo1\n", + canvas, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2, + x); + + if ( x->x_grid ) + { + int xlpos = text_xpix(&x->x_obj, glist)+x->x_width/x->x_xlines; + int ylpos = text_ypix(&x->x_obj, glist)+x->x_height/x->x_ylines; + int xcount = 1; + int ycount = 1; + while ( xlpos < text_xpix(&x->x_obj, glist)+x->x_width ) + { + GRID_SYS_VGUI9(".x%lx.c create line %d %d %d %d -fill #FFFFFF -tags %lxLINE%d%d\n", + canvas, xlpos, text_ypix(&x->x_obj, glist), + xlpos, text_ypix(&x->x_obj, glist)+x->x_height, + x, xcount, 0 ); + xlpos+=x->x_width/x->x_xlines; + xcount++; + } + while ( ylpos < text_ypix(&x->x_obj, glist)+x->x_height ) + { + GRID_SYS_VGUI9(".x%lx.c create line %d %d %d %d -fill #FFFFFF -tags %lxLINE%d%d\n", + canvas, text_xpix(&x->x_obj, glist), ylpos, + text_xpix(&x->x_obj, glist)+x->x_width, ylpos, + x, 0, ycount); + ylpos+=x->x_height/x->x_ylines; + ycount++; + } + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void grid_draw_move(t_grid *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + GRID_SYS_VGUI7(".x%lx.c coords %lxGRID %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height); + GRID_SYS_VGUI7(".x%lx.c coords %lxo0 %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2 ); + GRID_SYS_VGUI7(".x%lx.c coords %lxo1 %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2 ); + if ( x->x_point ) + { + grid_draw_update(x, glist); + } + if ( x->x_grid ) + { + int xlpos = text_xpix(&x->x_obj, glist)+x->x_width/x->x_xlines; + int ylpos = text_ypix(&x->x_obj, glist)+x->x_height/x->x_ylines; + int xcount = 1; + int ycount = 1; + while ( xlpos < text_xpix(&x->x_obj, glist)+x->x_width ) + { + GRID_SYS_VGUI9(".x%lx.c coords %lxLINE%d%d %d %d %d %d\n", + canvas, x, xcount, 0, xlpos, text_ypix(&x->x_obj, glist), + xlpos, text_ypix(&x->x_obj, glist) + x->x_height); + xlpos+=x->x_width/x->x_xlines; + xcount++; + } + while ( ylpos < text_ypix(&x->x_obj, glist)+x->x_height ) + { + GRID_SYS_VGUI9(".x%lx.c coords %lxLINE%d%d %d %d %d %d\n", + canvas, x, 0, ycount, text_xpix(&x->x_obj, glist), ylpos, + text_xpix(&x->x_obj, glist) + x->x_width, ylpos); + ylpos+=x->x_height/x->x_ylines; + ycount++; + } + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void grid_draw_erase(t_grid* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int i; + + GRID_SYS_VGUI3(".x%lx.c delete %lxGRID\n", canvas, x); + GRID_SYS_VGUI3(".x%lx.c delete %lxo0\n", canvas, x); + GRID_SYS_VGUI3(".x%lx.c delete %lxo1\n", canvas, x); + if (x->x_grid) + { + for (i=1; ix_xlines; i++ ) + { + GRID_SYS_VGUI4(".x%lx.c delete %lxLINE%d0\n", canvas, x, i); + } + for (i=1; ix_ylines; i++ ) + { + GRID_SYS_VGUI4(".x%lx.c delete %lxLINE0%d\n", canvas, x, i); + } + } + if (x->x_point) + { + GRID_SYS_VGUI3(".x%lx.c delete %lxPOINT\n", canvas, x); + x->x_point = 0; + } +} + +static void grid_draw_select(t_grid* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + pd_bind(&x->x_obj.ob_pd, x->x_name); + /* sets the item in blue */ + GRID_SYS_VGUI3(".x%lx.c itemconfigure %lxGRID -outline #0000FF\n", canvas, x); + } + else + { + pd_unbind(&x->x_obj.ob_pd, x->x_name); + GRID_SYS_VGUI3(".x%lx.c itemconfigure %lxGRID -outline #000000\n", canvas, x); + } +} + +static void grid_output_current(t_grid* x) +{ + t_float xvalue, yvalue; + t_float xmodstep, ymodstep; + + xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + xmodstep = ((float)((int)(xvalue*10000) % (int)(x->x_xstep*10000))/10000.); + xvalue = xvalue - xmodstep; + outlet_float( x->x_xoutlet, xvalue ); + + yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + ymodstep = ((float)((int)(yvalue*10000) % (int)(x->x_ystep*10000))/10000.); + yvalue = yvalue - ymodstep; + outlet_float( x->x_youtlet, yvalue ); +} + +/* ------------------------ grid widgetbehaviour----------------------------- */ + + +static void grid_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_grid* x = (t_grid*)z; + + *xp1 = text_xpix(&x->x_obj, x->x_glist); + *yp1 = text_ypix(&x->x_obj, x->x_glist); + *xp2 = text_xpix(&x->x_obj, x->x_glist)+x->x_width; + *yp2 = text_ypix(&x->x_obj, x->x_glist)+x->x_height; +} + +static void grid_save(t_gobj *z, t_binbuf *b) +{ + t_grid *x = (t_grid *)z; + + // post( "saving grid : %s", x->x_name->s_name ); + binbuf_addv(b, "ssiissiffiffiffiiff", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_name, x->x_width, x->x_min, + x->x_max, x->x_height, + x->y_min, x->y_max, + x->x_grid, x->x_xstep, + x->x_ystep, x->x_xlines, x->x_ylines, + x->x_current, x->y_current ); + binbuf_addv(b, ";"); +} + +static void grid_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_grid *x=(t_grid *)z; + + sprintf(buf, "pdtk_grid_dialog %%s %s %d %.2f %.2f %d %.2f %.2f %d %.2f %.2f %d %d\n", + x->x_name->s_name, x->x_width, x->x_min, x->x_max, x->x_height, + x->y_min, x->y_max, x->x_grid, x->x_xstep, x->x_ystep, + x->x_xlines, x->x_ylines ); + // post("grid_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void grid_select(t_gobj *z, t_glist *glist, int selected) +{ + t_grid *x = (t_grid *)z; + + x->x_selected = selected; + grid_draw_select( x, glist ); +} + +static void grid_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_grid *x = (t_grid *)z; + + if (vis) + { + grid_draw_new( x, glist ); + grid_draw_update( x, glist ); + grid_output_current(x); + } + else + { + grid_draw_erase( x, glist ); + } +} + +static void grid_dialog(t_grid *x, t_symbol *s, int argc, t_atom *argv) +{ + if ( !x ) { + post( "grid : error :tried to set properties on an unexisting object" ); + } + if ( argc != 12 ) + { + post( "grid : error in the number of arguments ( %d instead of 12 )", argc ); + return; + } + if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || + argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || + argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT || + argv[10].a_type != A_FLOAT || argv[11].a_type != A_FLOAT ) { + post( "grid : wrong arguments" ); + return; + } + x->x_name = argv[0].a_w.w_symbol; + x->x_width = (int)argv[1].a_w.w_float; + x->x_min = argv[2].a_w.w_float; + x->x_max = argv[3].a_w.w_float; + x->x_height = (int)argv[4].a_w.w_float; + x->y_min = argv[5].a_w.w_float; + x->y_max = argv[6].a_w.w_float; + x->x_grid = argv[7].a_w.w_float; + x->x_xstep = argv[8].a_w.w_float; + x->x_ystep = argv[9].a_w.w_float; + x->x_xlines = argv[10].a_w.w_float; + x->x_ylines = argv[11].a_w.w_float; + grid_draw_erase(x, x->x_glist); + grid_draw_new(x, x->x_glist); +} + +static void grid_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void grid_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_grid *x = (t_grid *)z; + int xold = text_xpix(&x->x_obj, glist); + int yold = text_ypix(&x->x_obj, glist); + + // post( "grid_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_current += dx; + x->x_obj.te_ypix += dy; + x->y_current += dy; + if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) + { + grid_draw_move(x, x->x_glist); + } +} + +static void grid_motion(t_grid *x, t_floatarg dx, t_floatarg dy) +{ + int xold = x->x_current; + int yold = x->y_current; + + // post( "grid_motion dx=%f dy=%f", dx, dy ); + + x->x_current += dx; + x->y_current += dy; + if(xold != x->x_current || yold != x->y_current) + { + grid_output_current(x); + grid_draw_update(x, x->x_glist); + } +} + +static int grid_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_grid* x = (t_grid *)z; + + // post( "grid_click doit=%d x=%d y=%d", doit, xpix, ypix ); + if ( doit) + { + x->x_current = xpix; + x->y_current = ypix; + grid_output_current(x); + grid_draw_update(x, glist); + glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)grid_motion, + 0, xpix, ypix); + } + return (1); +} + +static void grid_goto(t_grid *x, t_floatarg newx, t_floatarg newy) +{ + int xold = x->x_current; + int yold = x->y_current; + + if ( newx > x->x_width-1 ) newx = x->x_width-1; + if ( newx < 0 ) newx = 0; + if ( newy > x->x_height-1 ) newy = x->x_height-1; + if ( newy < 0 ) newy = 0; + + // post( "grid_set x=%f y=%f", newx, newy ); + + x->x_current = newx + text_xpix(&x->x_obj, x->x_glist); + x->y_current = newy + text_ypix(&x->x_obj, x->x_glist); + if(xold != x->x_current || yold != x->y_current) + { + grid_output_current(x); + grid_draw_update(x, x->x_glist); + } +} + + +static void grid_new_color(t_grid *x, t_floatarg color1, t_floatarg color2, t_floatarg color3) +{ + char col1[10], col2[10], col3[10]; + + if ( ( color1 < 0 ) || ( color1 > 255 ) ) + { + post( "wrong color component : %d", (int) color1 ); + } + if ( ( color2 < 0 ) || ( color2 > 255 ) ) + { + post( "wrong color component : %d", (int) color2 ); + } + if ( ( color3 < 0 ) || ( color3 > 255 ) ) + { + post( "wrong color component : %d", (int) color3 ); + } + + if (color1 < 17) + sprintf(col1,"0%X",(int) color1); + else + sprintf(col1,"%X",(int) color1); + + if (color2 < 17) + sprintf(col2,"0%X",(int) color2); + else + sprintf(col2,"%X",(int) color2); + + if (color3 < 17) + sprintf(col3,"0%X",(int) color3); + else + sprintf(col3,"%X",(int) color3); + sprintf( x->x_bgcolor, "#%s%s%s", col1, col2, col3); + + grid_draw_erase( x, x->x_glist); + grid_draw_new( x, x->x_glist ); +} + +static void grid_values(t_grid* x, t_floatarg xvalue, t_floatarg yvalue) +{ + int xold = x->x_current; + int yold = x->y_current; + + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; + + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; + + if(xold != x->x_current || yold != x->y_current) { + grid_output_current(x); + grid_draw_update(x, x->x_glist); + } +} + +static void grid_xvalues(t_grid* x, t_floatarg xvalue, t_floatarg yvalue) +{ + int xold = x->x_current; + int yold = x->y_current; + + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; + + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; + + if(xold != x->x_current || yold != x->y_current) { + grid_draw_update(x, x->x_glist); + } +} + +static void grid_valuemotion(t_grid* x, t_floatarg dx, t_floatarg dy) +{ + int xold = x->x_current; + int yold = x->y_current; + t_float xvalue, yvalue; + + xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + xvalue += dx; + yvalue += dy; + + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; + + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; + + if(xold != x->x_current || yold != x->y_current) { + grid_output_current(x); + grid_draw_update(x, x->x_glist); + } +} + +static void grid_xvaluemotion(t_grid* x, t_floatarg dx, t_floatarg dy) +{ + int xold = x->x_current; + int yold = x->y_current; + t_float xvalue, yvalue; + + xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + xvalue += dx; + yvalue += dy; + + if (xvalue < x->x_min ) xvalue = x->x_min; + if (xvalue > x->x_max ) xvalue = x->x_max; + + x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; + + if (yvalue < x->y_min ) yvalue = x->y_min; + if (yvalue > x->y_max ) yvalue = x->y_max; + + x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; + + if(xold != x->x_current || yold != x->y_current) { + grid_draw_update(x, x->x_glist); + } +} + +static void grid_bang(t_grid *x) { + grid_output_current(x); +} + +static t_grid *grid_new(t_symbol *s, int argc, t_atom *argv) +{ + int zz; + t_grid *x; + char *str; + + // post( "grid_new : create : %s argc =%d", s->s_name, argc ); + + x = (t_grid *)pd_new(grid_class); + // new grid created from the gui + if ( argc != 0 ) + { + if ( argc != 14 ) + { + post( "grid : error in the number of arguments ( %d instead of 14 )", argc ); + return NULL; + } + if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || + argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || + argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT || + argv[10].a_type != A_FLOAT || argv[11].a_type != A_FLOAT || + argv[12].a_type != A_FLOAT || argv[13].a_type != A_FLOAT ) { + post( "grid : wrong arguments" ); + return NULL; + } + + // update grid count + if (!strncmp((str = argv[0].a_w.w_symbol->s_name), "grid", 5) + && (zz = atoi(str + 5)) > gridcount) + { + gridcount = zz; + } + x->x_name = argv[0].a_w.w_symbol; + pd_bind(&x->x_obj.ob_pd, x->x_name); + x->x_width = argv[1].a_w.w_float; + x->x_min = argv[2].a_w.w_float; + x->x_max = argv[3].a_w.w_float; + x->x_height = argv[4].a_w.w_float; + x->y_min = argv[5].a_w.w_float; + x->y_max = argv[6].a_w.w_float; + x->x_grid = argv[7].a_w.w_float; + x->x_xstep = argv[8].a_w.w_float; + x->x_ystep = argv[9].a_w.w_float; + x->x_xlines = argv[10].a_w.w_float; + x->x_ylines = argv[11].a_w.w_float; + x->x_current = argv[12].a_w.w_float; + x->y_current = argv[13].a_w.w_float; + x->x_point = 1; + } + else + { + char buf[40]; + + sprintf(buf, "grid%d", ++gridcount); + s = gensym(buf); + + x->x_name = s; + pd_bind(&x->x_obj.ob_pd, x->x_name); + + x->x_width = DEFAULT_GRID_WIDTH; + x->x_min = 0; + x->x_max = DEFAULT_GRID_WIDTH - 1; + x->x_height = DEFAULT_GRID_HEIGHT; + x->y_min = 0; + x->y_max = DEFAULT_GRID_HEIGHT - 1; + x->x_grid = 1; + x->x_xstep = 1.0; + x->x_ystep = 1.0; + x->x_xlines = DEFAULT_GRID_NBLINES; + x->x_ylines = DEFAULT_GRID_NBLINES; + x->x_current = 0; + x->y_current = 0; + + } + + // common fields for new and restored grids + x->x_point = 0; + x->x_selected = 0; + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_xoutlet = outlet_new(&x->x_obj, &s_float ); + x->x_youtlet = outlet_new(&x->x_obj, &s_float ); + + x->x_bgcolor = (char*)getbytes(12); + strcpy( x->x_bgcolor, "#123589" ); + + // post( "grid_new name : %s width: %d height : %d", x->x_name->s_name, x->x_width, x->x_height ); + + return (x); +} + +static void grid_free(t_grid *x) +{ + post( "grid~: freeing ressources [NULL]" ); +} + +void grid_setup(void) +{ + post ( grid_version ); + grid_class = class_new(gensym("grid"), (t_newmethod)grid_new, + (t_method)grid_free, sizeof(t_grid), 0, A_GIMME, 0); + class_addmethod(grid_class, (t_method)grid_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_motion, gensym("motion"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_bang, gensym("bang"), 0); + class_addmethod(grid_class, (t_method)grid_values, gensym("values"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_valuemotion, gensym("valuemotion"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_xvalues, gensym("xvalues"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_xvaluemotion, gensym("xvaluemotion"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_goto, gensym("goto"), A_FLOAT, A_FLOAT, 0); + class_addmethod(grid_class, (t_method)grid_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(grid_class, (t_method)grid_new_color, gensym("color"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + grid_widgetbehavior.w_getrectfn = grid_getrect; + grid_widgetbehavior.w_displacefn = grid_displace; + grid_widgetbehavior.w_selectfn = grid_select; + grid_widgetbehavior.w_activatefn = NULL; + grid_widgetbehavior.w_deletefn = grid_delete; + grid_widgetbehavior.w_visfn = grid_vis; + grid_widgetbehavior.w_clickfn = grid_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(grid_class, grid_properties); + class_setsavefn(grid_class, grid_save); +#else + grid_widgetbehavior.w_propertiesfn = grid_properties; + grid_widgetbehavior.w_savefn = grid_save; +#endif + + class_setwidget(grid_class, &grid_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + grid_class->c_externdir->s_name, grid_class->c_name->s_name); +} diff --git a/grid.tcl b/grid.tcl new file mode 100644 index 0000000..fb8d403 --- /dev/null +++ b/grid.tcl @@ -0,0 +1,204 @@ +############ grid procedures -- ydegoyon@free.fr ######### + +proc grid_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_name [concat graph_name_$vid] + global $var_graph_name + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_xmin [concat graph_xmin_$vid] + global $var_graph_xmin + set var_graph_xmax [concat graph_xmax_$vid] + global $var_graph_xmax + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_ymin [concat graph_ymin_$vid] + global $var_graph_ymin + set var_graph_ymax [concat graph_ymax_$vid] + global $var_graph_ymax + set var_graph_grid [concat graph_grid_$vid] + global $var_graph_grid + set var_graph_xstep [concat graph_xstep_$vid] + global $var_graph_xstep + set var_graph_ystep [concat graph_ystep_$vid] + global $var_graph_ystep + set var_graph_xlines [concat graph_xlines_$vid] + global $var_graph_xlines + set var_graph_ylines [concat graph_ylines_$vid] + global $var_graph_ylines + + set cmd [concat $id dialog \ + [eval concat $$var_graph_name] \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_xmin] \ + [eval concat $$var_graph_xmax] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_ymin] \ + [eval concat $$var_graph_ymax] \ + [eval concat $$var_graph_grid] \ + [eval concat $$var_graph_xstep] \ + [eval concat $$var_graph_ystep] \ + [eval concat $$var_graph_xlines] \ + [eval concat $$var_graph_ylines] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc grid_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc grid_ok {id} { + grid_apply $id + grid_cancel $id +} + +proc pdtk_grid_dialog {id name width xmin xmax height ymin ymax grid xstep ystep xlines ylines} { + set vid [string trimleft $id .] + set var_graph_name [concat graph_name_$vid] + global $var_graph_name + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_xmin [concat graph_xmin_$vid] + global $var_graph_xmin + set var_graph_xmax [concat graph_xmax_$vid] + global $var_graph_xmax + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_ymin [concat graph_ymin_$vid] + global $var_graph_ymin + set var_graph_ymax [concat graph_ymax_$vid] + global $var_graph_ymax + set var_graph_grid [concat graph_grid_$vid] + global $var_graph_grid + set var_graph_xstep [concat graph_xstep_$vid] + global $var_graph_xstep + set var_graph_ystep [concat graph_ystep_$vid] + global $var_graph_ystep + set var_graph_xlines [concat graph_xlines_$vid] + global $var_graph_xlines + set var_graph_ylines [concat graph_ylines_$vid] + global $var_graph_ylines + + set $var_graph_name $name + set $var_graph_width $width + set $var_graph_xmin $xmin + set $var_graph_xmax $xmax + set $var_graph_height $height + set $var_graph_ymin $ymin + set $var_graph_ymax $ymax + set $var_graph_grid $grid + set $var_graph_xstep $xstep + set $var_graph_ystep $ystep + set $var_graph_xlines $xlines + set $var_graph_ylines $ylines + + toplevel $id + wm title $id {grid} + wm protocol $id WM_DELETE_WINDOW [concat grid_cancel $id] + + label $id.label -text {GRID PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "grid_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "grid_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "grid_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lname -text "Name :" + entry $id.1rangef.name -textvariable $var_graph_name -width 7 + pack $id.1rangef.lname $id.1rangef.name -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lwidth -text "Width :" + entry $id.2rangef.width -textvariable $var_graph_width -width 7 + pack $id.2rangef.lwidth $id.2rangef.width -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lxmin -text "X min :" + entry $id.3rangef.xmin -textvariable $var_graph_xmin -width 7 + pack $id.3rangef.lxmin $id.3rangef.xmin -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.lxmax -text "X max :" + entry $id.4rangef.xmax -textvariable $var_graph_xmax -width 7 + pack $id.4rangef.lxmax $id.4rangef.xmax -side left + + frame $id.41rangef + pack $id.41rangef -side top + label $id.41rangef.lxstep -text "X step :" + entry $id.41rangef.xstep -textvariable $var_graph_xstep -width 7 + pack $id.41rangef.lxstep $id.41rangef.xstep -side left + + frame $id.42rangef + pack $id.42rangef -side top + label $id.42rangef.lxlines -text "X sections :" + entry $id.42rangef.xlines -textvariable $var_graph_xlines -width 7 + pack $id.42rangef.lxlines $id.42rangef.xlines -side left + + frame $id.5rangef + pack $id.5rangef -side top + label $id.5rangef.lheight -text "Height :" + entry $id.5rangef.height -textvariable $var_graph_height -width 7 + pack $id.5rangef.lheight $id.5rangef.height -side left + + frame $id.6rangef + pack $id.6rangef -side top + label $id.6rangef.lymin -text "Y min :" + entry $id.6rangef.ymin -textvariable $var_graph_ymin -width 7 + pack $id.6rangef.lymin $id.6rangef.ymin -side left + + frame $id.7rangef + pack $id.7rangef -side top + label $id.7rangef.lymax -text "Y max :" + entry $id.7rangef.ymax -textvariable $var_graph_ymax -width 7 + pack $id.7rangef.lymax $id.7rangef.ymax -side left + + frame $id.71rangef + pack $id.71rangef -side top + label $id.71rangef.lystep -text "Y step :" + entry $id.71rangef.ystep -textvariable $var_graph_ystep -width 7 + pack $id.71rangef.lystep $id.71rangef.ystep -side left + + frame $id.72rangef + pack $id.72rangef -side top + label $id.72rangef.lylines -text "Y sections :" + entry $id.72rangef.ylines -textvariable $var_graph_ylines -width 7 + pack $id.72rangef.lylines $id.72rangef.ylines -side left + + checkbutton $id.showgrid -text {Show Grid} -variable $var_graph_grid \ + -anchor w + pack $id.showgrid -side top + + bind $id.1rangef.name [concat grid_ok $id] + bind $id.2rangef.width [concat grid_ok $id] + bind $id.3rangef.xmin [concat grid_ok $id] + bind $id.4rangef.xmax [concat grid_ok $id] + bind $id.41rangef.xstep [concat grid_ok $id] + bind $id.42rangef.xlines [concat grid_ok $id] + bind $id.5rangef.height [concat grid_ok $id] + bind $id.6rangef.ymin [concat grid_ok $id] + bind $id.7rangef.ymax [concat grid_ok $id] + bind $id.71rangef.ystep [concat grid_ok $id] + bind $id.72rangef.ylines [concat grid_ok $id] + focus $id.1rangef.name +} + +############ grid procedures END -- ydegoyon@free.fr ######### diff --git a/grid/INSTALL b/grid/INSTALL deleted file mode 100644 index 22c4df6..0000000 --- a/grid/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/grid - -make clean - -make - -make install - -open help-grid.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/grid/g_grid.h b/grid/g_grid.h deleted file mode 100644 index 9c89228..0000000 --- a/grid/g_grid.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* a header for grid which enables to control -* 2 parameters with the mouse cursor -*/ - -#ifndef __G_GRID_H -#define __G_GRID_H - -typedef struct _grid -{ - t_object x_obj; - t_glist *x_glist; - t_symbol *x_name; - t_outlet *x_xoutlet; - t_outlet *x_youtlet; - int x_height; /* height of the grid */ - t_float x_min; /* minimum value of x */ - t_float x_max; /* max value of x */ - int x_width; /* width of the grid */ - t_float y_min; /* minimum value of y */ - t_float y_max; /* max value of y */ - t_float x_current; /* x coordinate of current position */ - t_float y_current; /* y coordinate of current position */ - int x_selected; /* stores selected state */ - int x_point; /* indicates if a point is plotted */ - int x_grid; /* indicates if a grid is requested */ - t_float x_xstep; /* sets the step ( grain ) for x */ - t_float x_ystep; /* sets the step ( grain ) for y */ - int x_xlines; /* number of vertical lines */ - int x_ylines; /* number of horizontal lines */ - char *x_bgcolor; /* background color */ -} t_grid; - -#endif diff --git a/grid/grid-help.pd b/grid/grid-help.pd deleted file mode 100644 index 23d6cc5..0000000 --- a/grid/grid-help.pd +++ /dev/null @@ -1,201 +0,0 @@ -#N canvas 26 1 763 647 10; -#X obj 72 77 grid grid1 200 0 199 200 0 199 1 1 1 10 10 72 77; -#X floatatom 72 293 5 0 0 0 - - -; -#X floatatom 257 282 5 0 0 0 - - -; -#X text 41 21 Grid is a 2-dimensional control object; -#X text 319 449 (invoke with Properties ); -#X text 322 439 You can set the following properties :; -#X text 347 468 * Name; -#X text 346 480 * Width : graphical x size; -#X text 346 491 * X min : minimum value delivered by left outlet ( -X ); -#X text 346 503 * X max : maximum value delivered by left outlet ( -X ); -#X text 347 513 * X step : X delta for an X update; -#X text 346 524 * X sections : number of vertical lines of the inner -grid; -#X text 347 534 * Height : graphical y size; -#X text 346 546 * Y min : minimum value delivered by right outlet ( -Y ); -#X text 347 558 * Y max : maximum value delivered by right outlet ( -Y ); -#X text 346 579 * Y sections : number of horizontal lines of the inner -grid; -#X text 347 591 * Show Grid : option to draw an inner grid; -#X text 328 609 bugs and comments @ ydegoyon@free.fr; -#X text 120 292 X value; -#X text 303 281 Y value; -#X msg 587 271 \; pd dsp 0; -#X msg 653 271 \; pd dsp 1; -#X obj 276 417 *~; -#X floatatom 276 360 0 0 0 0 - - -; -#X obj 357 397 line~; -#X floatatom 188 380 0 0 0 0 - - -; -#X obj 188 494 cos~; -#X obj 188 450 +~; -#X floatatom 228 506 0 0 100 0 - - -; -#N canvas 159 26 495 270 output 0; -#X obj 338 160 t b; -#X obj 338 110 f; -#X obj 338 60 inlet; -#X text 344 29 mute; -#X obj 338 185 f; -#X msg 425 178 0; -#X msg 338 85 bang; -#X obj 338 135 moses 1; -#X obj 425 153 t b f; -#X obj 397 117 moses 1; -#X obj 83 148 dbtorms; -#X obj 397 92 r master-lvl; -#X obj 83 42 r master-lvl; -#X obj 338 210 s master-lvl; -#X obj 22 182 inlet~; -#X obj 199 41 inlet; -#X text 199 18 level; -#X obj 199 100 s master-lvl; -#X msg 96 65 set \$1; -#X obj 96 89 outlet; -#X msg 214 64 \; pd dsp 1; -#X obj 83 194 line~; -#X obj 22 212 *~; -#X obj 22 241 dac~; -#X obj 83 171 pack 0 50; -#X text 20 159 audio; -#X text 93 110 show level; -#X connect 0 0 4 0; -#X connect 1 0 7 0; -#X connect 2 0 6 0; -#X connect 4 0 13 0; -#X connect 5 0 13 0; -#X connect 6 0 1 0; -#X connect 7 0 0 0; -#X connect 7 1 8 0; -#X connect 8 0 5 0; -#X connect 9 1 4 1; -#X connect 10 0 24 0; -#X connect 11 0 1 1; -#X connect 11 0 9 0; -#X connect 12 0 10 0; -#X connect 12 0 18 0; -#X connect 14 0 22 0; -#X connect 15 0 17 0; -#X connect 15 0 20 0; -#X connect 18 0 19 0; -#X connect 21 0 22 1; -#X connect 22 0 23 0; -#X connect 22 0 23 1; -#X connect 24 0 21 0; -#X restore 190 533 pd output; -#X msg 266 506 MUTE; -#X obj 276 385 osc~ 0; -#X obj 357 371 pack 0 50; -#X floatatom 357 318 0 0 0 0 - - -; -#X obj 357 345 / 100; -#X text 188 345 carrier; -#X text 184 355 frequency; -#X text 261 336 frequency; -#X text 262 319 modulation; -#X obj 188 407 phasor~; -#X msg 39 350 250; -#X obj 39 328 loadbang; -#X text 17 377 3-dimensional control; -#X text 16 389 would be nice :-); -#X text 393 310 modulation index; -#X text 393 325 in hundredths; -#X text 40 32 It was inspired by the chaospad device; -#X text 346 568 * Y step : Y delta for an Y update; -#X floatatom 474 85 5 0 0 0 - - -; -#X floatatom 586 84 5 0 0 0 - - -; -#X obj 411 82 pack f f; -#X msg 332 81 goto \$1 \$2; -#X msg 546 83 bang; -#X text 524 84 X; -#X text 333 63 Set position :; -#X text 631 85 Y; -#X floatatom 486 120 5 0 0 0 - - -; -#X floatatom 586 121 5 0 0 0 - - -; -#X obj 423 119 pack f f; -#X msg 546 120 bang; -#X text 530 120 X; -#X text 634 121 Y; -#X floatatom 528 156 5 0 0 0 - - -; -#X floatatom 633 156 5 0 0 0 - - -; -#X obj 465 153 pack f f; -#X msg 593 154 bang; -#X text 578 155 X; -#X text 679 156 Y; -#X floatatom 503 191 5 0 0 0 - - -; -#X floatatom 607 190 5 0 0 0 - - -; -#X obj 440 188 pack f f; -#X msg 568 189 bang; -#X text 553 190 X; -#X text 656 191 Y; -#X floatatom 539 224 5 0 0 0 - - -; -#X floatatom 638 226 5 0 0 0 - - -; -#X obj 472 223 pack f f; -#X msg 600 224 bang; -#X text 585 225 X; -#X text 685 225 Y; -#X msg 109 49 bang; -#X msg 332 118 values \$1 \$2; -#X text 333 100 Set values :; -#X text 331 135 Set deltas for values :; -#X msg 333 152 valuemotion \$1 \$2; -#X msg 333 187 xvalues \$1 \$2; -#X text 334 170 Set values without changing output :; -#X text 332 205 Set deltas for values without changing output:; -#X msg 334 223 xvaluemotion \$1 \$2; -#X msg 334 250 color 123 45 185; -#X text 461 250 change bg color ( from alberto zin ); -#X connect 0 0 1 0; -#X connect 0 1 2 0; -#X connect 1 0 23 0; -#X connect 2 0 33 0; -#X connect 22 0 27 1; -#X connect 23 0 31 0; -#X connect 24 0 22 1; -#X connect 25 0 39 0; -#X connect 26 0 29 0; -#X connect 27 0 26 0; -#X connect 28 0 29 1; -#X connect 29 0 28 0; -#X connect 30 0 29 2; -#X connect 31 0 22 0; -#X connect 32 0 24 0; -#X connect 33 0 34 0; -#X connect 34 0 32 0; -#X connect 39 0 27 0; -#X connect 40 0 25 0; -#X connect 41 0 40 0; -#X connect 48 0 50 0; -#X connect 49 0 50 1; -#X connect 49 0 52 0; -#X connect 50 0 51 0; -#X connect 51 0 0 0; -#X connect 52 0 48 0; -#X connect 56 0 58 0; -#X connect 57 0 58 1; -#X connect 57 0 59 0; -#X connect 58 0 81 0; -#X connect 59 0 56 0; -#X connect 62 0 64 0; -#X connect 63 0 64 1; -#X connect 63 0 65 0; -#X connect 64 0 84 0; -#X connect 65 0 62 0; -#X connect 68 0 70 0; -#X connect 69 0 70 1; -#X connect 69 0 71 0; -#X connect 70 0 85 0; -#X connect 71 0 68 0; -#X connect 74 0 76 0; -#X connect 75 0 76 1; -#X connect 75 0 77 0; -#X connect 76 0 88 0; -#X connect 77 0 74 0; -#X connect 80 0 0 0; -#X connect 81 0 0 0; -#X connect 84 0 0 0; -#X connect 85 0 0 0; -#X connect 88 0 0 0; -#X connect 89 0 0 0; diff --git a/grid/grid.c b/grid/grid.c deleted file mode 100644 index d32fcf7..0000000 --- a/grid/grid.c +++ /dev/null @@ -1,715 +0,0 @@ -/* Copyright (c) 1997-1999 Miller Puckette. - * For information on usage and redistribution, and for a DISCLAIMER OF ALL - * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* g_grid.c written by Yves Degoyon 2002 */ -/* grid control object : two dimensionnal grid */ -/* thanks to Thomas Musil, Miller Puckette, Guenther Geiger and Krzystof Czaja */ - - -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "g_canvas.h" - -#include "g_grid.h" - -#ifdef _WIN32 -#include -#else -#include -#endif - -#define DEFAULT_GRID_WIDTH 200 -#define DEFAULT_GRID_HEIGHT 200 -#define DEFAULT_GRID_NBLINES 10 - -t_widgetbehavior grid_widgetbehavior; -static t_class *grid_class; -static int gridcount=0; - -static int guidebug=0; -static int pointsize = 5; - -static char *grid_version = "grid: version 0.8, written by Yves Degoyon (ydegoyon@free.fr)"; - -#define GRID_SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define GRID_SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define GRID_SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define GRID_SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define GRID_SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define GRID_SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -/* drawing functions */ -static void grid_draw_update(t_grid *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int xpoint=x->x_current, ypoint=x->y_current; - - // later : try to figure out what's this test for ?? - // if (glist_isvisible(glist)) - // { - // delete previous point if existing - if (x->x_point) - { - GRID_SYS_VGUI3(".x%lx.c delete %lxPOINT\n", canvas, x); - } - - if ( x->x_current < text_xpix(&x->x_obj, glist) ) xpoint = text_xpix(&x->x_obj, glist); - if ( x->x_current > text_xpix(&x->x_obj, glist) + x->x_width - pointsize ) - xpoint = text_xpix(&x->x_obj, glist) + x->x_width - pointsize; - if ( x->y_current < text_ypix(&x->x_obj, glist) ) ypoint = text_ypix(&x->x_obj, glist); - if ( x->y_current > text_ypix(&x->x_obj, glist) + x->x_height - pointsize ) - ypoint = text_ypix(&x->x_obj, glist) + x->x_height - pointsize; - // draw the selected point - GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -fill #FF0000 -tags %lxPOINT\n", - canvas, xpoint, ypoint, xpoint+pointsize, ypoint+pointsize, x); - x->x_point = 1; - // } - // else - // { - // post( "grid : position updated in an invisible grid" ); - // } -} - -static void grid_draw_new(t_grid *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - GRID_SYS_VGUI8(".x%lx.c create rectangle %d %d %d %d -fill %s -tags %lxGRID\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, - x->x_bgcolor, x); - GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -tags %lxo0\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2, - x); - GRID_SYS_VGUI7(".x%lx.c create rectangle %d %d %d %d -tags %lxo1\n", - canvas, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2, - x); - - if ( x->x_grid ) - { - int xlpos = text_xpix(&x->x_obj, glist)+x->x_width/x->x_xlines; - int ylpos = text_ypix(&x->x_obj, glist)+x->x_height/x->x_ylines; - int xcount = 1; - int ycount = 1; - while ( xlpos < text_xpix(&x->x_obj, glist)+x->x_width ) - { - GRID_SYS_VGUI9(".x%lx.c create line %d %d %d %d -fill #FFFFFF -tags %lxLINE%d%d\n", - canvas, xlpos, text_ypix(&x->x_obj, glist), - xlpos, text_ypix(&x->x_obj, glist)+x->x_height, - x, xcount, 0 ); - xlpos+=x->x_width/x->x_xlines; - xcount++; - } - while ( ylpos < text_ypix(&x->x_obj, glist)+x->x_height ) - { - GRID_SYS_VGUI9(".x%lx.c create line %d %d %d %d -fill #FFFFFF -tags %lxLINE%d%d\n", - canvas, text_xpix(&x->x_obj, glist), ylpos, - text_xpix(&x->x_obj, glist)+x->x_width, ylpos, - x, 0, ycount); - ylpos+=x->x_height/x->x_ylines; - ycount++; - } - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void grid_draw_move(t_grid *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - GRID_SYS_VGUI7(".x%lx.c coords %lxGRID %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height); - GRID_SYS_VGUI7(".x%lx.c coords %lxo0 %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2 ); - GRID_SYS_VGUI7(".x%lx.c coords %lxo1 %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2 ); - if ( x->x_point ) - { - grid_draw_update(x, glist); - } - if ( x->x_grid ) - { - int xlpos = text_xpix(&x->x_obj, glist)+x->x_width/x->x_xlines; - int ylpos = text_ypix(&x->x_obj, glist)+x->x_height/x->x_ylines; - int xcount = 1; - int ycount = 1; - while ( xlpos < text_xpix(&x->x_obj, glist)+x->x_width ) - { - GRID_SYS_VGUI9(".x%lx.c coords %lxLINE%d%d %d %d %d %d\n", - canvas, x, xcount, 0, xlpos, text_ypix(&x->x_obj, glist), - xlpos, text_ypix(&x->x_obj, glist) + x->x_height); - xlpos+=x->x_width/x->x_xlines; - xcount++; - } - while ( ylpos < text_ypix(&x->x_obj, glist)+x->x_height ) - { - GRID_SYS_VGUI9(".x%lx.c coords %lxLINE%d%d %d %d %d %d\n", - canvas, x, 0, ycount, text_xpix(&x->x_obj, glist), ylpos, - text_xpix(&x->x_obj, glist) + x->x_width, ylpos); - ylpos+=x->x_height/x->x_ylines; - ycount++; - } - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void grid_draw_erase(t_grid* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int i; - - GRID_SYS_VGUI3(".x%lx.c delete %lxGRID\n", canvas, x); - GRID_SYS_VGUI3(".x%lx.c delete %lxo0\n", canvas, x); - GRID_SYS_VGUI3(".x%lx.c delete %lxo1\n", canvas, x); - if (x->x_grid) - { - for (i=1; ix_xlines; i++ ) - { - GRID_SYS_VGUI4(".x%lx.c delete %lxLINE%d0\n", canvas, x, i); - } - for (i=1; ix_ylines; i++ ) - { - GRID_SYS_VGUI4(".x%lx.c delete %lxLINE0%d\n", canvas, x, i); - } - } - if (x->x_point) - { - GRID_SYS_VGUI3(".x%lx.c delete %lxPOINT\n", canvas, x); - x->x_point = 0; - } -} - -static void grid_draw_select(t_grid* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - pd_bind(&x->x_obj.ob_pd, x->x_name); - /* sets the item in blue */ - GRID_SYS_VGUI3(".x%lx.c itemconfigure %lxGRID -outline #0000FF\n", canvas, x); - } - else - { - pd_unbind(&x->x_obj.ob_pd, x->x_name); - GRID_SYS_VGUI3(".x%lx.c itemconfigure %lxGRID -outline #000000\n", canvas, x); - } -} - -static void grid_output_current(t_grid* x) -{ - t_float xvalue, yvalue; - t_float xmodstep, ymodstep; - - xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - xmodstep = ((float)((int)(xvalue*10000) % (int)(x->x_xstep*10000))/10000.); - xvalue = xvalue - xmodstep; - outlet_float( x->x_xoutlet, xvalue ); - - yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - ymodstep = ((float)((int)(yvalue*10000) % (int)(x->x_ystep*10000))/10000.); - yvalue = yvalue - ymodstep; - outlet_float( x->x_youtlet, yvalue ); -} - -/* ------------------------ grid widgetbehaviour----------------------------- */ - - -static void grid_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_grid* x = (t_grid*)z; - - *xp1 = text_xpix(&x->x_obj, x->x_glist); - *yp1 = text_ypix(&x->x_obj, x->x_glist); - *xp2 = text_xpix(&x->x_obj, x->x_glist)+x->x_width; - *yp2 = text_ypix(&x->x_obj, x->x_glist)+x->x_height; -} - -static void grid_save(t_gobj *z, t_binbuf *b) -{ - t_grid *x = (t_grid *)z; - - // post( "saving grid : %s", x->x_name->s_name ); - binbuf_addv(b, "ssiissiffiffiffiiff", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_name, x->x_width, x->x_min, - x->x_max, x->x_height, - x->y_min, x->y_max, - x->x_grid, x->x_xstep, - x->x_ystep, x->x_xlines, x->x_ylines, - x->x_current, x->y_current ); - binbuf_addv(b, ";"); -} - -static void grid_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_grid *x=(t_grid *)z; - - sprintf(buf, "pdtk_grid_dialog %%s %s %d %.2f %.2f %d %.2f %.2f %d %.2f %.2f %d %d\n", - x->x_name->s_name, x->x_width, x->x_min, x->x_max, x->x_height, - x->y_min, x->y_max, x->x_grid, x->x_xstep, x->x_ystep, - x->x_xlines, x->x_ylines ); - // post("grid_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void grid_select(t_gobj *z, t_glist *glist, int selected) -{ - t_grid *x = (t_grid *)z; - - x->x_selected = selected; - grid_draw_select( x, glist ); -} - -static void grid_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_grid *x = (t_grid *)z; - - if (vis) - { - grid_draw_new( x, glist ); - grid_draw_update( x, glist ); - grid_output_current(x); - } - else - { - grid_draw_erase( x, glist ); - } -} - -static void grid_dialog(t_grid *x, t_symbol *s, int argc, t_atom *argv) -{ - if ( !x ) { - post( "grid : error :tried to set properties on an unexisting object" ); - } - if ( argc != 12 ) - { - post( "grid : error in the number of arguments ( %d instead of 12 )", argc ); - return; - } - if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || - argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || - argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT || - argv[10].a_type != A_FLOAT || argv[11].a_type != A_FLOAT ) { - post( "grid : wrong arguments" ); - return; - } - x->x_name = argv[0].a_w.w_symbol; - x->x_width = (int)argv[1].a_w.w_float; - x->x_min = argv[2].a_w.w_float; - x->x_max = argv[3].a_w.w_float; - x->x_height = (int)argv[4].a_w.w_float; - x->y_min = argv[5].a_w.w_float; - x->y_max = argv[6].a_w.w_float; - x->x_grid = argv[7].a_w.w_float; - x->x_xstep = argv[8].a_w.w_float; - x->x_ystep = argv[9].a_w.w_float; - x->x_xlines = argv[10].a_w.w_float; - x->x_ylines = argv[11].a_w.w_float; - grid_draw_erase(x, x->x_glist); - grid_draw_new(x, x->x_glist); -} - -static void grid_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void grid_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_grid *x = (t_grid *)z; - int xold = text_xpix(&x->x_obj, glist); - int yold = text_ypix(&x->x_obj, glist); - - // post( "grid_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_current += dx; - x->x_obj.te_ypix += dy; - x->y_current += dy; - if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) - { - grid_draw_move(x, x->x_glist); - } -} - -static void grid_motion(t_grid *x, t_floatarg dx, t_floatarg dy) -{ - int xold = x->x_current; - int yold = x->y_current; - - // post( "grid_motion dx=%f dy=%f", dx, dy ); - - x->x_current += dx; - x->y_current += dy; - if(xold != x->x_current || yold != x->y_current) - { - grid_output_current(x); - grid_draw_update(x, x->x_glist); - } -} - -static int grid_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_grid* x = (t_grid *)z; - - // post( "grid_click doit=%d x=%d y=%d", doit, xpix, ypix ); - if ( doit) - { - x->x_current = xpix; - x->y_current = ypix; - grid_output_current(x); - grid_draw_update(x, glist); - glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)grid_motion, - 0, xpix, ypix); - } - return (1); -} - -static void grid_goto(t_grid *x, t_floatarg newx, t_floatarg newy) -{ - int xold = x->x_current; - int yold = x->y_current; - - if ( newx > x->x_width-1 ) newx = x->x_width-1; - if ( newx < 0 ) newx = 0; - if ( newy > x->x_height-1 ) newy = x->x_height-1; - if ( newy < 0 ) newy = 0; - - // post( "grid_set x=%f y=%f", newx, newy ); - - x->x_current = newx + text_xpix(&x->x_obj, x->x_glist); - x->y_current = newy + text_ypix(&x->x_obj, x->x_glist); - if(xold != x->x_current || yold != x->y_current) - { - grid_output_current(x); - grid_draw_update(x, x->x_glist); - } -} - - -static void grid_new_color(t_grid *x, t_floatarg color1, t_floatarg color2, t_floatarg color3) -{ - char col1[10], col2[10], col3[10]; - - if ( ( color1 < 0 ) || ( color1 > 255 ) ) - { - post( "wrong color component : %d", (int) color1 ); - } - if ( ( color2 < 0 ) || ( color2 > 255 ) ) - { - post( "wrong color component : %d", (int) color2 ); - } - if ( ( color3 < 0 ) || ( color3 > 255 ) ) - { - post( "wrong color component : %d", (int) color3 ); - } - - if (color1 < 17) - sprintf(col1,"0%X",(int) color1); - else - sprintf(col1,"%X",(int) color1); - - if (color2 < 17) - sprintf(col2,"0%X",(int) color2); - else - sprintf(col2,"%X",(int) color2); - - if (color3 < 17) - sprintf(col3,"0%X",(int) color3); - else - sprintf(col3,"%X",(int) color3); - sprintf( x->x_bgcolor, "#%s%s%s", col1, col2, col3); - - grid_draw_erase( x, x->x_glist); - grid_draw_new( x, x->x_glist ); -} - -static void grid_values(t_grid* x, t_floatarg xvalue, t_floatarg yvalue) -{ - int xold = x->x_current; - int yold = x->y_current; - - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; - - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; - - if(xold != x->x_current || yold != x->y_current) { - grid_output_current(x); - grid_draw_update(x, x->x_glist); - } -} - -static void grid_xvalues(t_grid* x, t_floatarg xvalue, t_floatarg yvalue) -{ - int xold = x->x_current; - int yold = x->y_current; - - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; - - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; - - if(xold != x->x_current || yold != x->y_current) { - grid_draw_update(x, x->x_glist); - } -} - -static void grid_valuemotion(t_grid* x, t_floatarg dx, t_floatarg dy) -{ - int xold = x->x_current; - int yold = x->y_current; - t_float xvalue, yvalue; - - xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - xvalue += dx; - yvalue += dy; - - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; - - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; - - if(xold != x->x_current || yold != x->y_current) { - grid_output_current(x); - grid_draw_update(x, x->x_glist); - } -} - -static void grid_xvaluemotion(t_grid* x, t_floatarg dx, t_floatarg dy) -{ - int xold = x->x_current; - int yold = x->y_current; - t_float xvalue, yvalue; - - xvalue = x->x_min + (x->x_current - text_xpix(&x->x_obj, x->x_glist)) * (x->x_max-x->x_min) / x->x_width ; - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - yvalue = x->y_max - (x->y_current - text_ypix(&x->x_obj, x->x_glist) ) * (x->y_max-x->y_min) / x->x_height ; - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - xvalue += dx; - yvalue += dy; - - if (xvalue < x->x_min ) xvalue = x->x_min; - if (xvalue > x->x_max ) xvalue = x->x_max; - - x->x_current = text_xpix(&x->x_obj, x->x_glist) + ((xvalue - x->x_min) / x->x_max) * x->x_width; - - if (yvalue < x->y_min ) yvalue = x->y_min; - if (yvalue > x->y_max ) yvalue = x->y_max; - - x->y_current = text_ypix(&x->x_obj, x->x_glist) + (1 - ((yvalue - x->y_min) / x->y_max)) * x->x_height; - - if(xold != x->x_current || yold != x->y_current) { - grid_draw_update(x, x->x_glist); - } -} - -static void grid_bang(t_grid *x) { - grid_output_current(x); -} - -static t_grid *grid_new(t_symbol *s, int argc, t_atom *argv) -{ - int zz; - t_grid *x; - char *str; - - // post( "grid_new : create : %s argc =%d", s->s_name, argc ); - - x = (t_grid *)pd_new(grid_class); - // new grid created from the gui - if ( argc != 0 ) - { - if ( argc != 14 ) - { - post( "grid : error in the number of arguments ( %d instead of 14 )", argc ); - return NULL; - } - if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || - argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || - argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT || - argv[10].a_type != A_FLOAT || argv[11].a_type != A_FLOAT || - argv[12].a_type != A_FLOAT || argv[13].a_type != A_FLOAT ) { - post( "grid : wrong arguments" ); - return NULL; - } - - // update grid count - if (!strncmp((str = argv[0].a_w.w_symbol->s_name), "grid", 5) - && (zz = atoi(str + 5)) > gridcount) - { - gridcount = zz; - } - x->x_name = argv[0].a_w.w_symbol; - pd_bind(&x->x_obj.ob_pd, x->x_name); - x->x_width = argv[1].a_w.w_float; - x->x_min = argv[2].a_w.w_float; - x->x_max = argv[3].a_w.w_float; - x->x_height = argv[4].a_w.w_float; - x->y_min = argv[5].a_w.w_float; - x->y_max = argv[6].a_w.w_float; - x->x_grid = argv[7].a_w.w_float; - x->x_xstep = argv[8].a_w.w_float; - x->x_ystep = argv[9].a_w.w_float; - x->x_xlines = argv[10].a_w.w_float; - x->x_ylines = argv[11].a_w.w_float; - x->x_current = argv[12].a_w.w_float; - x->y_current = argv[13].a_w.w_float; - x->x_point = 1; - } - else - { - char buf[40]; - - sprintf(buf, "grid%d", ++gridcount); - s = gensym(buf); - - x->x_name = s; - pd_bind(&x->x_obj.ob_pd, x->x_name); - - x->x_width = DEFAULT_GRID_WIDTH; - x->x_min = 0; - x->x_max = DEFAULT_GRID_WIDTH - 1; - x->x_height = DEFAULT_GRID_HEIGHT; - x->y_min = 0; - x->y_max = DEFAULT_GRID_HEIGHT - 1; - x->x_grid = 1; - x->x_xstep = 1.0; - x->x_ystep = 1.0; - x->x_xlines = DEFAULT_GRID_NBLINES; - x->x_ylines = DEFAULT_GRID_NBLINES; - x->x_current = 0; - x->y_current = 0; - - } - - // common fields for new and restored grids - x->x_point = 0; - x->x_selected = 0; - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_xoutlet = outlet_new(&x->x_obj, &s_float ); - x->x_youtlet = outlet_new(&x->x_obj, &s_float ); - - x->x_bgcolor = (char*)getbytes(12); - strcpy( x->x_bgcolor, "#123589" ); - - // post( "grid_new name : %s width: %d height : %d", x->x_name->s_name, x->x_width, x->x_height ); - - return (x); -} - -static void grid_free(t_grid *x) -{ - post( "grid~: freeing ressources [NULL]" ); -} - -void grid_setup(void) -{ -#include "grid.tk2c" - post ( grid_version ); - grid_class = class_new(gensym("grid"), (t_newmethod)grid_new, - (t_method)grid_free, sizeof(t_grid), 0, A_GIMME, 0); - class_addmethod(grid_class, (t_method)grid_click, gensym("click"), - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_motion, gensym("motion"), - A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_bang, gensym("bang"), 0); - class_addmethod(grid_class, (t_method)grid_values, gensym("values"), - A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_valuemotion, gensym("valuemotion"), - A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_xvalues, gensym("xvalues"), - A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_xvaluemotion, gensym("xvaluemotion"), - A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_goto, gensym("goto"), A_FLOAT, A_FLOAT, 0); - class_addmethod(grid_class, (t_method)grid_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(grid_class, (t_method)grid_new_color, gensym("color"), A_FLOAT, A_FLOAT, A_FLOAT, 0); - grid_widgetbehavior.w_getrectfn = grid_getrect; - grid_widgetbehavior.w_displacefn = grid_displace; - grid_widgetbehavior.w_selectfn = grid_select; - grid_widgetbehavior.w_activatefn = NULL; - grid_widgetbehavior.w_deletefn = grid_delete; - grid_widgetbehavior.w_visfn = grid_vis; - grid_widgetbehavior.w_clickfn = grid_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(grid_class, grid_properties); - class_setsavefn(grid_class, grid_save); -#else - grid_widgetbehavior.w_propertiesfn = grid_properties; - grid_widgetbehavior.w_savefn = grid_save; -#endif - - class_setwidget(grid_class, &grid_widgetbehavior); - -} diff --git a/grid/grid.tk b/grid/grid.tk deleted file mode 100644 index fb8d403..0000000 --- a/grid/grid.tk +++ /dev/null @@ -1,204 +0,0 @@ -############ grid procedures -- ydegoyon@free.fr ######### - -proc grid_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_name [concat graph_name_$vid] - global $var_graph_name - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_xmin [concat graph_xmin_$vid] - global $var_graph_xmin - set var_graph_xmax [concat graph_xmax_$vid] - global $var_graph_xmax - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_ymin [concat graph_ymin_$vid] - global $var_graph_ymin - set var_graph_ymax [concat graph_ymax_$vid] - global $var_graph_ymax - set var_graph_grid [concat graph_grid_$vid] - global $var_graph_grid - set var_graph_xstep [concat graph_xstep_$vid] - global $var_graph_xstep - set var_graph_ystep [concat graph_ystep_$vid] - global $var_graph_ystep - set var_graph_xlines [concat graph_xlines_$vid] - global $var_graph_xlines - set var_graph_ylines [concat graph_ylines_$vid] - global $var_graph_ylines - - set cmd [concat $id dialog \ - [eval concat $$var_graph_name] \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_xmin] \ - [eval concat $$var_graph_xmax] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_ymin] \ - [eval concat $$var_graph_ymax] \ - [eval concat $$var_graph_grid] \ - [eval concat $$var_graph_xstep] \ - [eval concat $$var_graph_ystep] \ - [eval concat $$var_graph_xlines] \ - [eval concat $$var_graph_ylines] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc grid_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc grid_ok {id} { - grid_apply $id - grid_cancel $id -} - -proc pdtk_grid_dialog {id name width xmin xmax height ymin ymax grid xstep ystep xlines ylines} { - set vid [string trimleft $id .] - set var_graph_name [concat graph_name_$vid] - global $var_graph_name - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_xmin [concat graph_xmin_$vid] - global $var_graph_xmin - set var_graph_xmax [concat graph_xmax_$vid] - global $var_graph_xmax - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_ymin [concat graph_ymin_$vid] - global $var_graph_ymin - set var_graph_ymax [concat graph_ymax_$vid] - global $var_graph_ymax - set var_graph_grid [concat graph_grid_$vid] - global $var_graph_grid - set var_graph_xstep [concat graph_xstep_$vid] - global $var_graph_xstep - set var_graph_ystep [concat graph_ystep_$vid] - global $var_graph_ystep - set var_graph_xlines [concat graph_xlines_$vid] - global $var_graph_xlines - set var_graph_ylines [concat graph_ylines_$vid] - global $var_graph_ylines - - set $var_graph_name $name - set $var_graph_width $width - set $var_graph_xmin $xmin - set $var_graph_xmax $xmax - set $var_graph_height $height - set $var_graph_ymin $ymin - set $var_graph_ymax $ymax - set $var_graph_grid $grid - set $var_graph_xstep $xstep - set $var_graph_ystep $ystep - set $var_graph_xlines $xlines - set $var_graph_ylines $ylines - - toplevel $id - wm title $id {grid} - wm protocol $id WM_DELETE_WINDOW [concat grid_cancel $id] - - label $id.label -text {GRID PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "grid_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "grid_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "grid_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lname -text "Name :" - entry $id.1rangef.name -textvariable $var_graph_name -width 7 - pack $id.1rangef.lname $id.1rangef.name -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lwidth -text "Width :" - entry $id.2rangef.width -textvariable $var_graph_width -width 7 - pack $id.2rangef.lwidth $id.2rangef.width -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lxmin -text "X min :" - entry $id.3rangef.xmin -textvariable $var_graph_xmin -width 7 - pack $id.3rangef.lxmin $id.3rangef.xmin -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.lxmax -text "X max :" - entry $id.4rangef.xmax -textvariable $var_graph_xmax -width 7 - pack $id.4rangef.lxmax $id.4rangef.xmax -side left - - frame $id.41rangef - pack $id.41rangef -side top - label $id.41rangef.lxstep -text "X step :" - entry $id.41rangef.xstep -textvariable $var_graph_xstep -width 7 - pack $id.41rangef.lxstep $id.41rangef.xstep -side left - - frame $id.42rangef - pack $id.42rangef -side top - label $id.42rangef.lxlines -text "X sections :" - entry $id.42rangef.xlines -textvariable $var_graph_xlines -width 7 - pack $id.42rangef.lxlines $id.42rangef.xlines -side left - - frame $id.5rangef - pack $id.5rangef -side top - label $id.5rangef.lheight -text "Height :" - entry $id.5rangef.height -textvariable $var_graph_height -width 7 - pack $id.5rangef.lheight $id.5rangef.height -side left - - frame $id.6rangef - pack $id.6rangef -side top - label $id.6rangef.lymin -text "Y min :" - entry $id.6rangef.ymin -textvariable $var_graph_ymin -width 7 - pack $id.6rangef.lymin $id.6rangef.ymin -side left - - frame $id.7rangef - pack $id.7rangef -side top - label $id.7rangef.lymax -text "Y max :" - entry $id.7rangef.ymax -textvariable $var_graph_ymax -width 7 - pack $id.7rangef.lymax $id.7rangef.ymax -side left - - frame $id.71rangef - pack $id.71rangef -side top - label $id.71rangef.lystep -text "Y step :" - entry $id.71rangef.ystep -textvariable $var_graph_ystep -width 7 - pack $id.71rangef.lystep $id.71rangef.ystep -side left - - frame $id.72rangef - pack $id.72rangef -side top - label $id.72rangef.lylines -text "Y sections :" - entry $id.72rangef.ylines -textvariable $var_graph_ylines -width 7 - pack $id.72rangef.lylines $id.72rangef.ylines -side left - - checkbutton $id.showgrid -text {Show Grid} -variable $var_graph_grid \ - -anchor w - pack $id.showgrid -side top - - bind $id.1rangef.name [concat grid_ok $id] - bind $id.2rangef.width [concat grid_ok $id] - bind $id.3rangef.xmin [concat grid_ok $id] - bind $id.4rangef.xmax [concat grid_ok $id] - bind $id.41rangef.xstep [concat grid_ok $id] - bind $id.42rangef.xlines [concat grid_ok $id] - bind $id.5rangef.height [concat grid_ok $id] - bind $id.6rangef.ymin [concat grid_ok $id] - bind $id.7rangef.ymax [concat grid_ok $id] - bind $id.71rangef.ystep [concat grid_ok $id] - bind $id.72rangef.ylines [concat grid_ok $id] - focus $id.1rangef.name -} - -############ grid procedures END -- ydegoyon@free.fr ######### diff --git a/grid/grid.tk2c b/grid/grid.tk2c deleted file mode 100644 index 3e8f18f..0000000 --- a/grid/grid.tk2c +++ /dev/null @@ -1,164 +0,0 @@ -// ########### grid procedures -- ydegoyon@free.fr ######### -sys_gui("proc grid_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_name [concat graph_name_$vid]\n"); -sys_gui("global $var_graph_name\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_xmin [concat graph_xmin_$vid]\n"); -sys_gui("global $var_graph_xmin\n"); -sys_gui("set var_graph_xmax [concat graph_xmax_$vid]\n"); -sys_gui("global $var_graph_xmax\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_ymin [concat graph_ymin_$vid]\n"); -sys_gui("global $var_graph_ymin\n"); -sys_gui("set var_graph_ymax [concat graph_ymax_$vid]\n"); -sys_gui("global $var_graph_ymax\n"); -sys_gui("set var_graph_grid [concat graph_grid_$vid]\n"); -sys_gui("global $var_graph_grid\n"); -sys_gui("set var_graph_xstep [concat graph_xstep_$vid]\n"); -sys_gui("global $var_graph_xstep\n"); -sys_gui("set var_graph_ystep [concat graph_ystep_$vid]\n"); -sys_gui("global $var_graph_ystep\n"); -sys_gui("set var_graph_xlines [concat graph_xlines_$vid]\n"); -sys_gui("global $var_graph_xlines\n"); -sys_gui("set var_graph_ylines [concat graph_ylines_$vid]\n"); -sys_gui("global $var_graph_ylines\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_name] [eval concat $$var_graph_width] [eval concat $$var_graph_xmin] [eval concat $$var_graph_xmax] [eval concat $$var_graph_height] [eval concat $$var_graph_ymin] [eval concat $$var_graph_ymax] [eval concat $$var_graph_grid] [eval concat $$var_graph_xstep] [eval concat $$var_graph_ystep] [eval concat $$var_graph_xlines] [eval concat $$var_graph_ylines] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc grid_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc grid_ok {id} {\n"); -sys_gui("grid_apply $id\n"); -sys_gui("grid_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_grid_dialog {id name width xmin xmax height ymin ymax grid xstep ystep xlines ylines} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_name [concat graph_name_$vid]\n"); -sys_gui("global $var_graph_name\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_xmin [concat graph_xmin_$vid]\n"); -sys_gui("global $var_graph_xmin\n"); -sys_gui("set var_graph_xmax [concat graph_xmax_$vid]\n"); -sys_gui("global $var_graph_xmax\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_ymin [concat graph_ymin_$vid]\n"); -sys_gui("global $var_graph_ymin\n"); -sys_gui("set var_graph_ymax [concat graph_ymax_$vid]\n"); -sys_gui("global $var_graph_ymax\n"); -sys_gui("set var_graph_grid [concat graph_grid_$vid]\n"); -sys_gui("global $var_graph_grid\n"); -sys_gui("set var_graph_xstep [concat graph_xstep_$vid]\n"); -sys_gui("global $var_graph_xstep\n"); -sys_gui("set var_graph_ystep [concat graph_ystep_$vid]\n"); -sys_gui("global $var_graph_ystep\n"); -sys_gui("set var_graph_xlines [concat graph_xlines_$vid]\n"); -sys_gui("global $var_graph_xlines\n"); -sys_gui("set var_graph_ylines [concat graph_ylines_$vid]\n"); -sys_gui("global $var_graph_ylines\n"); -sys_gui("set $var_graph_name $name\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_xmin $xmin\n"); -sys_gui("set $var_graph_xmax $xmax\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_ymin $ymin\n"); -sys_gui("set $var_graph_ymax $ymax\n"); -sys_gui("set $var_graph_grid $grid\n"); -sys_gui("set $var_graph_xstep $xstep\n"); -sys_gui("set $var_graph_ystep $ystep\n"); -sys_gui("set $var_graph_xlines $xlines\n"); -sys_gui("set $var_graph_ylines $ylines\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {grid}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat grid_cancel $id]\n"); -sys_gui("label $id.label -text {GRID PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"grid_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"grid_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"grid_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lname -text \"Name :\"\n"); -sys_gui("entry $id.1rangef.name -textvariable $var_graph_name -width 7\n"); -sys_gui("pack $id.1rangef.lname $id.1rangef.name -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.2rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.2rangef.lwidth $id.2rangef.width -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lxmin -text \"X min :\"\n"); -sys_gui("entry $id.3rangef.xmin -textvariable $var_graph_xmin -width 7\n"); -sys_gui("pack $id.3rangef.lxmin $id.3rangef.xmin -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.lxmax -text \"X max :\"\n"); -sys_gui("entry $id.4rangef.xmax -textvariable $var_graph_xmax -width 7\n"); -sys_gui("pack $id.4rangef.lxmax $id.4rangef.xmax -side left\n"); -sys_gui("frame $id.41rangef\n"); -sys_gui("pack $id.41rangef -side top\n"); -sys_gui("label $id.41rangef.lxstep -text \"X step :\"\n"); -sys_gui("entry $id.41rangef.xstep -textvariable $var_graph_xstep -width 7\n"); -sys_gui("pack $id.41rangef.lxstep $id.41rangef.xstep -side left\n"); -sys_gui("frame $id.42rangef\n"); -sys_gui("pack $id.42rangef -side top\n"); -sys_gui("label $id.42rangef.lxlines -text \"X sections :\"\n"); -sys_gui("entry $id.42rangef.xlines -textvariable $var_graph_xlines -width 7\n"); -sys_gui("pack $id.42rangef.lxlines $id.42rangef.xlines -side left\n"); -sys_gui("frame $id.5rangef\n"); -sys_gui("pack $id.5rangef -side top\n"); -sys_gui("label $id.5rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.5rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.5rangef.lheight $id.5rangef.height -side left\n"); -sys_gui("frame $id.6rangef\n"); -sys_gui("pack $id.6rangef -side top\n"); -sys_gui("label $id.6rangef.lymin -text \"Y min :\"\n"); -sys_gui("entry $id.6rangef.ymin -textvariable $var_graph_ymin -width 7\n"); -sys_gui("pack $id.6rangef.lymin $id.6rangef.ymin -side left\n"); -sys_gui("frame $id.7rangef\n"); -sys_gui("pack $id.7rangef -side top\n"); -sys_gui("label $id.7rangef.lymax -text \"Y max :\"\n"); -sys_gui("entry $id.7rangef.ymax -textvariable $var_graph_ymax -width 7\n"); -sys_gui("pack $id.7rangef.lymax $id.7rangef.ymax -side left\n"); -sys_gui("frame $id.71rangef\n"); -sys_gui("pack $id.71rangef -side top\n"); -sys_gui("label $id.71rangef.lystep -text \"Y step :\"\n"); -sys_gui("entry $id.71rangef.ystep -textvariable $var_graph_ystep -width 7\n"); -sys_gui("pack $id.71rangef.lystep $id.71rangef.ystep -side left\n"); -sys_gui("frame $id.72rangef\n"); -sys_gui("pack $id.72rangef -side top\n"); -sys_gui("label $id.72rangef.lylines -text \"Y sections :\"\n"); -sys_gui("entry $id.72rangef.ylines -textvariable $var_graph_ylines -width 7\n"); -sys_gui("pack $id.72rangef.lylines $id.72rangef.ylines -side left\n"); -sys_gui("checkbutton $id.showgrid -text {Show Grid} -variable $var_graph_grid -anchor w\n"); -sys_gui("pack $id.showgrid -side top\n"); -sys_gui("bind $id.1rangef.name [concat grid_ok $id]\n"); -sys_gui("bind $id.2rangef.width [concat grid_ok $id]\n"); -sys_gui("bind $id.3rangef.xmin [concat grid_ok $id]\n"); -sys_gui("bind $id.4rangef.xmax [concat grid_ok $id]\n"); -sys_gui("bind $id.41rangef.xstep [concat grid_ok $id]\n"); -sys_gui("bind $id.42rangef.xlines [concat grid_ok $id]\n"); -sys_gui("bind $id.5rangef.height [concat grid_ok $id]\n"); -sys_gui("bind $id.6rangef.ymin [concat grid_ok $id]\n"); -sys_gui("bind $id.7rangef.ymax [concat grid_ok $id]\n"); -sys_gui("bind $id.71rangef.ystep [concat grid_ok $id]\n"); -sys_gui("bind $id.72rangef.ylines [concat grid_ok $id]\n"); -sys_gui("focus $id.1rangef.name\n"); -sys_gui("}\n"); -// ########### grid procedures END -- ydegoyon@free.fr ######### diff --git a/grid/tk2c.bash b/grid/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/grid/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/interface.h b/interface.h new file mode 100644 index 0000000..de3136a --- /dev/null +++ b/interface.h @@ -0,0 +1,32 @@ +/* +** Copyright (C) 2000 Albert L. Faber +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef INTERFACE_H_INCLUDED +#define INTERFACE_H_INCLUDED + +// #include "common.h" +#include "interface.h" + +BOOL InitMP3(PMPSTR mp); +int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done); +void ExitMP3(PMPSTR mp); + +/* added remove_buf to support mpglib seeking */ +void remove_buf(PMPSTR mp); + +#endif diff --git a/lpc.c b/lpc.c new file mode 100644 index 0000000..33159d4 --- /dev/null +++ b/lpc.c @@ -0,0 +1,252 @@ +/* +vox - a musical real-time vocoder. version 1.0 +Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "tables.h" +#include "lpc.h" +#define THRES 0.06 +#define Dmin 10.81e-3 + +/* Levinson Durbin algorithm for computing LPC coefficients using +autocorrelation fonction */ +void lev_durb(double *corr,double *lpc_coef) +{ + double k[11],tab[11]; + double err,acc; + int i,j; + double *a=tab; + double *prev_a=lpc_coef; + double *exch; + + + /*init vectors*/ + for (i=0;i<11;i++) + { + prev_a[i]=0; + a[i]=0; + }; + err=corr[0]; + for(i=1;i<11;i++) + { + prev_a[0]=1; + acc=0; + for(j=0;jTHRES) + { + for(i=0;i<3*n;i++) + { + buffer[i]=buf_x[i-n]*HammingWindowTable[i]; + }; + /* autocorrelation computation*/ + for(i=0;i<11;i++) + { + acc=0; + for(j=i;j0;k--) + { + b[k]=2*x*b[k+1]-b[k+2]+fonc[5-k]; + }; + res=x*b[1]-b[2]+fonc[5]/2; + return(res); +} + + + +/* converts LPC vector into LSP frequency vector */ +/* all LSP frenquencies are in [0;PI] but are normalized to be in [0;1] */ +void lpc2lsp(double lpc_coef[],double *f1,double *f2,double lsp_coef[]) +{ + + int i,k=1; + double *fonc,*prev_f,*f_exch; + double prev_sign1,sign,prev_sign2; + double *s, *prev_s,*s_exch; + double lpc_exp[11]; + + /* first computes an additional bandwidth expansion on LPC coeffs*/ + for(i=1;i<11;i++) + { + lpc_exp[i]=lpc_coef[i]*BandExpTable[i]; + }; + /* computes the F1 and F2 coeffs*/ + f1[0]=f2[0]=1; + for(i=0;i<5;i++) + { + f1[i+1]=lpc_exp[i+1]+lpc_exp[10-i]-f1[i]; + f2[i+1]=lpc_exp[i+1]-lpc_exp[10-i]+f2[i]; + }; + + /*find the roots of C(x) alternatively for F1 and F2*/ + fonc=f1; + prev_f=f2; + prev_sign1=evalc(1.0,f1); + prev_sign2=evalc(1.0,f2); + s=&prev_sign1; + prev_s=&prev_sign2; + for(i=1;i<256;i++) + { + sign=evalc(CosineTable[i],fonc); + if ((sign)*(*s)<0) + { + /* interpolate to find root*/ + lsp_coef[k]=((double)i-(*s)/(sign-(*s)))/256.0; + k++; + /* chek if all roots are found */ + if (k==11) i=257; + (*s)=sign; + /* pointers exchange */ + s_exch=s; + s=prev_s; + prev_s=s_exch; + f_exch=fonc; + fonc=prev_f; + prev_f=f_exch; + } + else (*s)=sign; + } + /* if here all roots are not found , use lspDC vector */ + if (k!=11) + { + for(i=1;i<11;i++) + { + lsp_coef[i]=LspDcTable[i]; + }; + }; +} + + +/* converts lsp frequencies to lpc coeffs */ + +void lsp2lpc(double *lsp_coef,double *lpc_coef) +{ + int i,j=0,index,ok=1; + double lspcos[11],delta,tmp,p_avg; + double F1[12],F2[12]; /* begin at indice two*/ + + F1[0]=0;F1[1]=1; + F2[0]=0;F2[1]=1; + /* stability check */ + while(ok && (j<11)) + { + ok=0; + for(i=1;i<10;i++) + { + if( (lsp_coef[i+1]-lsp_coef[i]) < Dmin) + { + ok=1; + p_avg=(lsp_coef[i]+lsp_coef[i+1])/2.0; + lsp_coef[i]=p_avg-Dmin/2.0; + lsp_coef[i+1]=p_avg+Dmin/2.0; + }; + }; + j++; + } + + /* first converts lsp frequencies to lsp coefficients */ + for (i=1;i<11;i++) + { + /* interpolation */ + tmp=lsp_coef[i]*255.0; + index=(int)tmp; + delta=CosineTable[index+1]-CosineTable[index]; + lspcos[i]=CosineTable[index]+delta*(tmp-index); + }; + + for(i=2;i<7;i++) + { + F1[i]=-2*lspcos[2*i-3]*F1[i-1]+2*F1[i-2]; + F2[i]=-2*lspcos[2*i-2]*F2[i-1]+2*F2[i-2]; + for(j=i-1;j>1;j--) + { + F1[j]=F1[j]-2*lspcos[2*i-3]*F1[j-1]+F1[j-2]; + F2[j]=F2[j]-2*lspcos[2*i-2]*F2[j-1]+F2[j-2]; + }; + }; + for(i=6;i>1;i--) + { + F1[i]=F1[i]+F1[i-1]; + F2[i]=F2[i]-F2[i-1]; + }; + for(i=2;i<7;i++) + { + lpc_coef[i-1]=(F1[i]+F2[i])*0.5; + lpc_coef[i+4]=(F1[8-i]-F2[8-i])*0.5; + }; + lpc_coef[0]=1; +} + diff --git a/mp3amp~-help.pd b/mp3amp~-help.pd new file mode 100644 index 0000000..47249b7 --- /dev/null +++ b/mp3amp~-help.pd @@ -0,0 +1,53 @@ +#N canvas 125 102 789 555 10; +#X obj 115 265 dac~; +#X floatatom 164 265 5 0 0; +#X msg 29 150 disconnect; +#X text 208 267 connection status; +#X obj 458 48 loadbang; +#X msg 458 71 \; pd dsp 1; +#X msg 99 76 connect yves puredata 8000; +#X text 96 55 connect ; +#X text 38 18 constructor : mp3amp~ ; +#X text 151 127 connect to SHOUTcast server; +#X msg 157 145 connect localhost listen.pls 8000; +#X msg 176 165 connect localhost content/scpromo.mp3 8000; +#X text 399 141 <-- play livestream; +#X text 479 165 <-- play file; +#X msg 121 99 connect localhost kas 8000; +#X text 97 44 connect to ICEcast server; +#X text 38 7 mp3amp~ : an icecast/shoucast client for PD; +#X text 226 186 Another way of connecting; +#X msg 226 205 connecturl http://localhost:8000/kas; +#X msg 31 374 standby 0; +#X text 114 380 for CPU load reasons \,; +#X text 115 392 ability to freeze decoding; +#X text 114 405 ( packets are read and ignored ); +#X msg 31 399 standby 1; +#X msg 353 230 connecturl http://216.235.81.7:20690/play?session=panjabiradio:0&\;lid=-1-fra&\;SaneID=212.198.0.97-1030988754258 +; +#X msg 352 280 connecturl http://213.197.144.44:8000/; +#X msg 352 334 connecturl http://24.207.26.60:8000/; +#X msg 354 307 connecturl http://64.113.197.158:8000/; +#X msg 352 361 connecturl http://liveice.agria.hu:8000/radioeger-hq +; +#X text 406 511 Authors : Yves Degoyon ( ydegoyon@free.fr ); +#X obj 115 196 mp3amp~; +#X msg 354 384 connecturl http://www.deliciound.net:8000/; +#X connect 2 0 30 0; +#X connect 4 0 5 0; +#X connect 6 0 30 0; +#X connect 10 0 30 0; +#X connect 11 0 30 0; +#X connect 14 0 30 0; +#X connect 18 0 30 0; +#X connect 19 0 30 0; +#X connect 23 0 30 0; +#X connect 24 0 30 0; +#X connect 25 0 30 0; +#X connect 26 0 30 0; +#X connect 27 0 30 0; +#X connect 28 0 30 0; +#X connect 30 0 0 0; +#X connect 30 1 0 1; +#X connect 30 2 1 0; +#X connect 31 0 30 0; diff --git a/mp3amp~.c b/mp3amp~.c new file mode 100644 index 0000000..9dfc54e --- /dev/null +++ b/mp3amp~.c @@ -0,0 +1,1262 @@ +/* ------------------------- mp3amp~ ------------------------------------------ */ +/* */ +/* Tilde object to receive an mp3-stream from a shoutcast/icecast server. */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Get source at http://ydegoyon.free.fr */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later version. */ +/* */ +/* This library is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; if not, write to the */ +/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ +/* Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 encoding library which can be found at */ +/* http://www.mp3dev.org */ +/* */ +/* ---------------------------------------------------------------------------- */ + +#include +#include "m_imp.h" +#include "g_canvas.h" +#include "s_stuff.h" +#include "pthread.h" + +#include +#include +#include +#include +#include +#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ +#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ +#include "interface.h" /* mpglib decoding library from lame 3.92 */ +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif /* _WIN32 */ + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#if defined(__APPLE__) || defined(WIN32) +#define MSG_NOSIGNAL 0 +#endif +#ifdef UNIX +#define STRDUP strdup +#endif +#ifdef WIN32 +#define STRDUP _strdup +#define sys_closesocket closesocket +#endif + + +#define LAME_AUDIO_CHUNK_SIZE 1152 +#define MIN_AUDIO_INPUT 2*LAME_AUDIO_CHUNK_SIZE /* we must have at least n chunks to play a steady sound */ +#define INPUT_BUFFER_SIZE 131072 /* data received on the socket : 128k */ +#define OUTPUT_BUFFER_SIZE 131072 /* audio output buffer : 128k */ +#define DECODE_PACKET_SIZE 131072 /* size of the data returned by mpglib : 128k */ +#define STRBUF_SIZE 4096 /* char received from server on startup */ +#define MAX_DECODERS 50 +#define BARHEIGHT 10 + +static int guidebug=0; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h );\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + + + /* useful debugging functions from mpglib */ +extern int decode_header( struct frame* fr, unsigned long newhead ); +extern void print_header_compact( struct frame* fr ); +extern int head_check( unsigned long head, int check_layer ); + +static char *mp3amp_version = "mp3amp~: mp3 streaming client v0.12, written by Yves Degoyon"; + +/* ------------------------ mp3amp~ ----------------------------- */ + +static t_class *mp3amp_class; + +/* too bad, this needs to be static, + handling an array to enable several decoders in pd */ +static MPSTR mps[MAX_DECODERS]; /* decoder buffer */ +static int nbinstances = 0; + +extern const long freqs[9]; + +/* time-out used for select() call */ +static struct timeval ztout; + +typedef struct _mp3amp +{ + t_object x_obj; + t_int x_instance; /* instance of the object */ + t_outlet *x_connection; + t_int x_fd; /* the socket number */ + t_int x_inframes; /* number of waiting frames */ + t_int x_dframes; /* displayed frames in status bar */ + t_int x_packetsize; /* size of the packets */ + t_int x_pblocks; /* processed blocks */ + t_int x_graphic; /* indicates if we show a graphic bar */ + t_canvas *x_canvas; /* remember canvas */ + t_int x_nbwaitloops; /* number of loops to wait */ + t_int x_nbloops; /* number of loops processed */ + t_int x_blocksize; /* size of a dsp block */ + t_int x_resample; /* resampling factor (pd's sr / stream sr) */ + t_int x_dsp; /* number of dsp calls, used to measure time */ + t_int x_standby; /* flag to freeze decoding */ + t_int x_nooutput; /* flag to avoid output of connection state */ + +#ifdef UNIX + unsigned char *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ +#else + char *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ +#endif + + t_int x_inwriteposition; + t_int x_inbuffersize; + t_int x_offset; /* offset used for start of decoding */ + + t_float *x_outbuffer; /* buffer to store audio decoded data */ + t_int x_outwriteposition; + t_int x_outreadposition; + t_int x_outunread; + t_int x_outbuffersize; + char x_out[DECODE_PACKET_SIZE]; + + /* mp3 stuff */ + t_int x_samplerate; + t_int x_bitrate; /* bitrate of mp3 stream read at connection time */ + t_int x_bitrateindex; /* bitrate index for each frame, might change dynamically */ + t_int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ + char* x_bcname; /* name of broadcast */ + char* x_bcurl; /* url of broadcast */ + char* x_bcgenre; /* genre of broadcast */ + char* x_bcaim; /* aim of broadcast */ + char* x_mountpoint; /* mountpoint for IceCast server */ + char* x_hostname; /* hostname to connect to */ + t_int x_port; /* port number to connect to */ + + t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ +} t_mp3amp; + +static void mp3amp_recv(t_mp3amp *x); +static void mp3amp_disconnect(t_mp3amp *x); +static void mp3amp_connect_url(t_mp3amp *x, t_symbol *url); + +static int strip_shout_header(char *head, int n) +{ + int i; + for (i = 0; i < (n - 2); i++) + { + if (head[i] == 10 && head[i + 1] == 13) + break; + if (head[i] == '\n' && head[i + 1] == '\n') + break; + } + head[i + 1] = '\0'; + return n - (i + 1); +} + +static int strip_ice_header(char *head, int n) +{ + int i; + for (i = 0; i < (n - 2); i++) + { + if ((head[i] == '\n') && (head[i + 1] == '\n')) + break; + } + head[i + 1] = '\0'; + return n - (i + 1); +} + +static void mp3amp_tilde_mpglib_init(t_mp3amp *x) +{ + int ret; + + InitMP3(&mps[x->x_instance]); +} + +static int mp3amp_decode_input(t_mp3amp *x) +{ + t_int i; + t_int alength = 0; + float resample = 0; + struct frame hframe; + unsigned int a,b,c,d; + unsigned long cheader; + signed short int *p = (signed short int *) x->x_out; + t_int pbytes; + t_int ret, totlength=0; + t_int pframes = 0; + + x->x_offset=0; + // search for an header to check dynamic bitrate + while ( x->x_offset < x->x_inwriteposition ) + { + /* decode first 4 bytes as the header */ + a = *((unsigned char*)x->x_inbuffer+x->x_offset); + b = *((unsigned char*)x->x_inbuffer+x->x_offset+1); + c = *((unsigned char*)x->x_inbuffer+x->x_offset+2); + d = *((unsigned char*)x->x_inbuffer+x->x_offset+3); + + cheader = 0; + cheader = a; + cheader <<= 8; + cheader |= b; + cheader <<= 8; + cheader |= c; + cheader <<= 8; + cheader |= d; + if ( head_check( cheader, 0 ) ) + { + decode_header( &hframe, cheader ); + if ( hframe.framesize == 0 ) + { + post( "mp3amp~: weird header ( frame size = 0 ) .... ignored" ); + x->x_offset++; + continue; + } + x->x_packetsize = hframe.framesize; + // print_header_compact( &hframe ); + // when the bitrate change, reinit decoder + if ( x->x_bitrateindex != hframe.bitrate_index ) + { + post( "mp3amp~: bitrate has changed, reinitialize decoder" ); + ExitMP3(&mps[x->x_instance]); + InitMP3(&mps[x->x_instance]); + x->x_bitrateindex = hframe.bitrate_index; + } + break; + } + x->x_offset++; + } + + if ( x->x_inframes > 0 ) + { + + ret = decodeMP3(&mps[x->x_instance], (unsigned char*)(x->x_inbuffer+x->x_offset), + hframe.framesize+sizeof( unsigned long), (char *) p, sizeof(x->x_out), &pbytes); + + switch (ret) + { + case MP3_OK: + switch (mps[x->x_instance].fr.stereo) { + case 1: + case 2: + alength = ((mps[x->x_instance].fr.stereo==1)?pbytes >> 1 : pbytes >> 2); + // post( "mp3amp~: stereo : %d", mps[x->x_instance].fr.stereo ); + // update outbuffer contents + for ( i=0; ix_outunread >= x->x_outbuffersize-2 ) + { + // post( "mp3amp~: decode : too much input ... ignored" ); + continue; + } + *(x->x_outbuffer+x->x_outwriteposition) = ((t_float)(*p++))/32767.0; + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + *(x->x_outbuffer+x->x_outwriteposition) = + ((mps[x->x_instance].fr.stereo==2)?((t_float)(*p++))/32767.0 : 0.0); + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + x->x_outunread+=2; + + if ( x->x_outunread >= MIN_AUDIO_INPUT && !x->x_stream ) + { + post("mp3amp~: stream connected" ); + x->x_resample = x->x_samplerate / freqs[hframe.sampling_frequency]; + if ( x->x_resample == 0 ) x->x_resample=1; + post("mp3amp~: resampling stream from %d to %d Hz (r=%d)", + freqs[hframe.sampling_frequency], x->x_samplerate, x->x_resample ); + x->x_stream = 1; + } + } + break; + default: + alength = -1; + break; + } + // roll buffer + if ( x->x_inwriteposition > hframe.framesize+ (int) sizeof( unsigned long ) + x->x_offset ) + // ^----- maybe the frame is not complete + { + x->x_inwriteposition -= hframe.framesize+sizeof( unsigned long )+x->x_offset; + memcpy( (void *)(x->x_inbuffer), + (void *)(x->x_inbuffer+x->x_offset+hframe.framesize+sizeof( unsigned long )), + x->x_inwriteposition); + x->x_offset = 0; + // post ( "mp3amp~: decoded frame %d", x->x_inframes ); + x->x_inframes--; + pframes++; + } + else // sorry, it will be ignored + { + // error( "mp3amp~: incomplete frame...ignored"); + // x->x_offset = 0; + // x->x_inwriteposition = 0; + // x->x_inframes = 0; + } + + totlength += alength; + break; + + case MP3_NEED_MORE: + if ( mps[x->x_instance].framesize == 0 && mps[x->x_instance].fsizeold != 0 ) + { + post( "mp3amp~: decoding done (totlength=%d).", totlength ); + } + else + { + post( "mp3amp~: retry lame decoding (more data needed)." ); + return -1; + } + break; + + case MP3_ERR: + post( "mp3amp~: lame decoding failed." ); + return ret; + break; + + } + + } + + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + /* update graphical read status */ + if ( x->x_inframes != x->x_dframes ) + { + char color[32]; + t_int width; + + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + SYS_VGUI3(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); + if ( x->x_inframes < (MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE) ) + { + strcpy( color, "red" ); + } + else + { + strcpy( color, "lightgreen" ); + } + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix+(x->x_inwriteposition*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix - 1, color, x ); + x->x_dframes = x->x_inframes; + } + } + return totlength; +} + +static void mp3amp_recv(t_mp3amp *x) +{ + int ret, i; + float resample = 0; + struct frame hframe; + unsigned int a,b,c,d; + unsigned long cheader; + +#ifdef UNIX + if ( ( ret = recv(x->x_fd, (void*) (x->x_inbuffer + x->x_inwriteposition), + (size_t)((x->x_inbuffersize-x->x_inwriteposition)), + MSG_NOSIGNAL) ) < 0 ) +#else + if(( ret = recv(x->x_fd, (char*)x->x_inbuffer + x->x_inwriteposition, + (x->x_inbuffersize-x->x_inwriteposition), 0)) < 0) +#endif + { + post( "mp3amp~: receive error" ); +#ifdef UNIX + perror( "recv" ); +#endif + mp3amp_disconnect(x); + return; + } + else + { + + // post( "mp3amp~: received %d bytes at %d on %d ( up to %d)", + // ret, x->x_inwriteposition, x->x_fd, + // x->x_inbuffersize-x->x_inwriteposition ); + + if ( ret == 0 && ( x->x_inbuffersize-x->x_inwriteposition != 0 ) ) + { + error("mp3amp~: stream lost..."); + mp3amp_disconnect(x); + } + else + { + // check if we should decode those packets + if ( x->x_standby ) + { + return; + } + // check we don't overflow input buffer + if ( ( x->x_inwriteposition + ret ) > x->x_inbuffersize*0.9 ) + { + post( "mp3streamin~ : too much input...resetting" ); + x->x_inwriteposition=0; + x->x_offset = 0; + x->x_inframes = 0; + return; + } + x->x_inwriteposition += ret; + x->x_offset = 0; + // check some parameters in the stream + while ( x->x_offset < x->x_inwriteposition ) + { + /* decode first 4 bytes as the header */ + a = *((unsigned char*)x->x_inbuffer+x->x_offset); + b = *((unsigned char*)x->x_inbuffer+x->x_offset+1); + c = *((unsigned char*)x->x_inbuffer+x->x_offset+2); + d = *((unsigned char*)x->x_inbuffer+x->x_offset+3); + + cheader = 0; + cheader = a; + cheader <<= 8; + cheader |= b; + cheader <<= 8; + cheader |= c; + cheader <<= 8; + cheader |= d; + if ( head_check( cheader, 0 ) ) + { + decode_header( &hframe, cheader ); + // print_header_compact( &hframe ); + x->x_packetsize = hframe.framesize; + if ( hframe.framesize == 0 ) + { + post( "mp3amp~: weird header ( frame size = 0 ) .... ignored" ); + x->x_inwriteposition -= ret; + return; + } + x->x_inframes += ret/x->x_packetsize; + // post( "mp3amp~: nb frames %d", x->x_inframes ); + break; + } + x->x_offset++; + } + } + } +} + +static t_int *mp3amp_perform(t_int *w) +{ + t_mp3amp *x = (t_mp3amp*) (w[1]); + t_float *out1 = (t_float *)(w[2]); + t_float *out2 = (t_float *)(w[3]); + int n = (int)(w[4]); + int ret; + int i = 0; + + x->x_blocksize = n; + x->x_nbwaitloops = LAME_AUDIO_CHUNK_SIZE/x->x_blocksize; + // post( "mp3mp3amp~ : will wait %d loops", x->x_nbwaitloops ); + x->x_dsp++; + + while( n-- ) + { + if(x->x_stream && !x->x_standby ) // check that the stream provides enough data + { + if(x->x_resample == 1) /* don't need to resample */ + { + *out1++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + *out2++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + x->x_outunread-=2; + } + else + { /* we just use the same sample x->x_resample times */ + *out1++=*(x->x_outbuffer+x->x_outreadposition); + *out2++=*(x->x_outbuffer+((x->x_outreadposition + 1)%x->x_outbuffersize)); + if((n%x->x_resample)== 0) + { + x->x_outreadposition = (x->x_outreadposition + 2)%x->x_outbuffersize; + x->x_outunread-=2; + } + } + if ( n == 1 ) x->x_pblocks++; + } + else + { + *out1++=0.0; + *out2++=0.0; + } + } + + if ( x->x_pblocks == LAME_AUDIO_CHUNK_SIZE/x->x_blocksize ) + { + x->x_pblocks = 0; + } + + /* check for readability, then fill the input buffer */ + if(( x->x_fd > 0 )&&(x->x_dsp >= 16)) /* determine how often we try to read */ + { + fd_set readset; + fd_set exceptset; + + FD_ZERO(&readset); + FD_ZERO(&exceptset); + FD_SET(x->x_fd, &readset ); + FD_SET(x->x_fd, &exceptset ); + + x->x_dsp = 0; + + if ( select( x->x_fd+1, &readset, NULL, &exceptset, &ztout ) >0 ) + { + if ( FD_ISSET( x->x_fd, &readset) || FD_ISSET( x->x_fd, &exceptset ) ) + { + /* receive data or error */ + mp3amp_recv(x); + } + } + } + + // check new incoming data + if ( x->x_fd > 0 && ( x->x_nbloops == 0 ) && ( x->x_inframes > 0 ) && ( !x->x_standby ) ) + { + mp3amp_decode_input(x); + } + if ( x->x_nbwaitloops != 0 ) + { + x->x_nbloops = (x->x_nbloops+1 ) % x->x_nbwaitloops; + } + return (w+5); +} + +static void mp3amp_dsp(t_mp3amp *x, t_signal **sp) +{ + dsp_add(mp3amp_perform, 4, x, sp[1]->s_vec, sp[2]->s_vec, sp[1]->s_n); +} + + + /* freeze decoding */ +static void mp3amp_standby(t_mp3amp *x, t_floatarg fstandby ) +{ + if ( fstandby == 0. ) + { + x->x_standby = 0; + } + else + { + x->x_standby = 1; + } +} + + /* connection main procedure executed by a thread */ +static void *mp3amp_do_connect(void *tdata ) +{ + t_mp3amp *x = (t_mp3amp*) tdata; + struct sockaddr_in server; + struct hostent *hp; + t_int portno = x->x_port; /* get port from message box */ + + /* variables used for communication with server */ + char *sptr = NULL; + char request[STRBUF_SIZE]; /* string to be send to server */ + char *url; /* used for relocation */ + fd_set fdset; + struct timeval tv; + t_int sockfd; /* socket to server */ + t_int relocate, numrelocs = 0; + t_int i, ret, rest, nanswers=0; + char *cpoint = NULL; + t_int offset = 0, endofheaders = 0; + + if (x->x_fd >= 0) + { + error("mp3amp~: already connected"); + return NULL; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("mp3amp~: internal error while attempting to open socket"); + return NULL; + } + + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(x->x_hostname); + if (hp == 0) + { + post("mp3amp~: bad host?"); + sys_closesocket(sockfd); + return NULL; + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("mp3amp~: connecting to http:/%s:%d/%s", x->x_hostname, x->x_port, x->x_mountpoint ); + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + error("mp3amp~: connection failed!\n"); + sys_closesocket(sockfd); + return NULL; + } + post("mp3amp~: connected : socket opened" ); + + /* sheck if we can read/write from/to the socket */ + FD_ZERO( &fdset); + FD_SET( sockfd, &fdset); + tv.tv_sec = 0; /* seconds */ + tv.tv_usec = 500; /* microseconds */ + + ret = select(sockfd + 1, &fdset, NULL, NULL, &tv); + if(ret != 0) + { + error("mp3amp~: can not read from socket"); + sys_closesocket(sockfd); + return NULL; + } + post("mp3amp~: select done" ); + + /* check mountpoint */ + if( strstr(x->x_mountpoint, "listen.pls") ) + { /* SHOUTcast playlist -> get / */ + x->x_mountpoint = ""; + } + + /* build up stuff we need to send to server */ + sprintf(request, "GET /%s HTTP/1.0 \r\nHost: %s\r\nUser-Agent: mp3amp~ 0.11\r\nAccept: */*\r\n\r\n", + x->x_mountpoint, x->x_hostname); + + if ( send(sockfd, request, strlen(request), 0) < 0 ) /* say hello to server */ + { + post( "mp3amp~: could not contact server... " ); +#ifdef UNIX + perror( "send" ); +#endif + return NULL; + } + post("mp3amp~: send done" ); + + relocate = FALSE; + memset( request, 0x00, STRBUF_SIZE ); + + // read all the answer + endofheaders=0; + while ( !endofheaders ) + { + if( ( ret = recv(sockfd, request+offset, STRBUF_SIZE, MSG_NOSIGNAL) ) <0) + { + error("mp3amp~: no response from server"); +#ifdef UNIX + perror( "recv" ); +#endif + return NULL; + } + post ( "mp3amp~ : received %d bytes at %d", ret, offset ); + for ( i=offset; ix_nooutput = 1; + mp3amp_connect_url(x, gensym(url)); + x->x_nooutput = 0; + return NULL; + // relocate = TRUE; + } + if( !(sptr = strstr(request, "200")) && !relocate ) + { + error("mp3amp~: cannot connect to the (default) stream"); + return NULL; + } + + post("mp3amp~: IceCast server detected"); + + // post("mp3amp~: server's header : %s", request ); + + // check what we got + if( cpoint = strstr(request, "x-audiocast-mount:")) + { + x->x_mountpoint = STRDUP(cpoint + 18); + for ( i=0; i<(int)strlen(x->x_mountpoint); i++ ) + { + if ( x->x_mountpoint[i] == '\n' ) + { + x->x_mountpoint[i] = '\0'; + break; + } + } + post(" mountpoint: %s", x->x_mountpoint); + } + if( cpoint = strstr(request, "x-audiocast-server-url:")) + { + sptr = STRDUP( cpoint + 24); + for ( i=0; i<(int)strlen(sptr); i++ ) + { + if ( sptr[i] == '\n' ) + { + sptr[i] = '\0'; + break; + } + } + post(" server-url: %s", sptr); + } + if( cpoint = strstr(request, "x-audiocast-location:")) + { + sptr = STRDUP( cpoint + 22); + for ( i=0; i<(int)strlen(sptr); i++ ) + { + if ( sptr[i] == '\n' ) + { + sptr[i] = '\0'; + break; + } + } + post(" location: %s", sptr); + } + if( cpoint = strstr(request, "x-audiocast-admin:")) + { + sptr = STRDUP( cpoint + 19); + for ( i=0; i<(int)strlen(sptr); i++ ) + { + if ( sptr[i] == '\n' ) + { + sptr[i] = '\0'; + break; + } + } + post(" admin: %s", sptr); + } + if( cpoint = strstr(request, "x-audiocast-name:")) + { + x->x_bcname = STRDUP( cpoint + 17); + for ( i=0; i<(int)strlen(x->x_bcname); i++ ) + { + if ( x->x_bcname[i] == '\n' ) + { + x->x_bcname[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if( cpoint = strstr(request, "x-audiocast-genre:")) + { + x->x_bcgenre = STRDUP( cpoint + 18); + for ( i=0; i<(int)strlen(x->x_bcgenre); i++ ) + { + if ( x->x_bcgenre[i] == '\n' ) + { + x->x_bcgenre[i] = '\0'; + break; + } + } + post(" genre: %s", x->x_bcgenre); + } + if( cpoint = strstr(request, "x-audiocast-url:")) + { + x->x_bcurl = STRDUP( cpoint + 16); + for ( i=0; i<(int)strlen(x->x_bcurl); i++ ) + { + if ( x->x_bcurl[i] == '\n' ) + { + x->x_bcurl[i] = '\0'; + break; + } + } + post(" url: %s", x->x_bcurl); + } + if( cpoint = strstr(request, "x-audiocast-public:1")) + { + post(" broadcast is public"); + } + else if( cpoint = strstr(request, "x-audiocast-public:0")) + { + post(" broadcast is NOT public"); + } + if( cpoint = strstr(request, "x-audiocast-bitrate:")) + { + sptr = STRDUP( cpoint + 20); + for ( i=0; i<(int)strlen(sptr); i++ ) + { + if ( sptr[i] == '\n' ) + { + sptr[i] = '\0'; + break; + } + } + if(!strncmp(sptr, "320", 3))x->x_bitrate = 320; + else if(!strncmp(sptr, "256", 3))x->x_bitrate = 256; + else if(!strncmp(sptr, "224", 3))x->x_bitrate = 224; + else if(!strncmp(sptr, "192", 3))x->x_bitrate = 192; + else if(!strncmp(sptr, "160", 3))x->x_bitrate = 160; + else if(!strncmp(sptr, "144", 3))x->x_bitrate = 144; + else if(!strncmp(sptr, "128", 3))x->x_bitrate = 128; + else if(!strncmp(sptr, "112", 3))x->x_bitrate = 112; + else if(!strncmp(sptr, "96", 2))x->x_bitrate = 96; + else if(!strncmp(sptr, "80", 2))x->x_bitrate = 80; + else if(!strncmp(sptr, "64", 2))x->x_bitrate = 64; + else if(!strncmp(sptr, "56", 2))x->x_bitrate = 56; + else if(!strncmp(sptr, "48", 2))x->x_bitrate = 48; + else if(!strncmp(sptr, "40", 2))x->x_bitrate = 40; + else if(!strncmp(sptr, "32", 2))x->x_bitrate = 32; + else if(!strncmp(sptr, "24", 2))x->x_bitrate = 24; + else if(!strncmp(sptr, "16", 2))x->x_bitrate = 16; + else if(!strncmp(sptr, "8", 1))x->x_bitrate = 8; + else + { + post("mp3amp~: unsupported bitrate! : %s", sptr); + return NULL; + } + post(" bitrate: %d", x->x_bitrate); + } + if( cpoint = strstr(request, "x-audiocast-udpport:")) + { + post("mp3amp~: sorry, server wants UDP connection!"); + return NULL; + } + } + else /* it is a SHOUTcast server */ + { + strip_shout_header (request, STRBUF_SIZE); + post("mp3amp~: SHOUTcast server detected"); + if(strstr(request, "ICY 401") != 0) + { + post("mp3amp~: ICY 401 Service Unavailable"); + return NULL; + } + if (strstr(request, "ICY 200 OK")) + { + /* recv and decode info about broadcast line by line */ + post("mp3amp~: connecting to stream..."); + i = ret; + /* check what we got */ + + if( cpoint = strstr(request, "icy-name:")) + { + x->x_bcname = STRDUP( cpoint + 10); + for ( i=0; i<(int)strlen(x->x_bcname); i++ ) + { + if ( x->x_bcname[i] == '\n' ) + { + x->x_bcname[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if( cpoint = strstr(request, "x-audiocast-name:")) + { + x->x_bcname = STRDUP( cpoint + 18); + for ( i=0; i<(int)strlen(x->x_bcname); i++ ) + { + if ( x->x_bcname[i] == '\n' ) + { + x->x_bcname[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if( cpoint = strstr(request, "icy-genre:")) + { + x->x_bcgenre = STRDUP( cpoint + 10); + for ( i=0; i<(int)strlen(x->x_bcgenre); i++ ) + { + if ( x->x_bcgenre[i] == '\n' ) + { + x->x_bcgenre[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if( cpoint = strstr(request, "icy-aim:")) + { + x->x_bcaim = STRDUP( cpoint + 8); + for ( i=0; i<(int)strlen(x->x_bcaim); i++ ) + { + if ( x->x_bcaim[i] == '\n' ) + { + x->x_bcaim[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if( cpoint = strstr(request, "icy-url:")) + { + x->x_bcurl = STRDUP( cpoint + 8); + for ( i=0; i<(int)strlen(x->x_bcurl); i++ ) + { + if ( x->x_bcurl[i] == '\n' ) + { + x->x_bcurl[i] = '\0'; + break; + } + } + post(" name: %s", x->x_bcname); + } + if(strstr(request, "icy-pub:1")) + { + post(" broadcast is public"); + } + else if(strstr(request, "icy-pub:0")) + { + post(" broadcast is NOT public"); + } + if( cpoint = strstr(request, "icy-br:")) + { + sptr = STRDUP( cpoint + 7); + if(!strncmp(sptr, "320", 3))x->x_bitrate = 320; + else if(!strncmp(sptr, "256", 3))x->x_bitrate = 256; + else if(!strncmp(sptr, "224", 3))x->x_bitrate = 224; + else if(!strncmp(sptr, "192", 3))x->x_bitrate = 192; + else if(!strncmp(sptr, "160", 3))x->x_bitrate = 160; + else if(!strncmp(sptr, "144", 3))x->x_bitrate = 144; + else if(!strncmp(sptr, "128", 3))x->x_bitrate = 128; + else if(!strncmp(sptr, "112", 3))x->x_bitrate = 112; + else if(!strncmp(sptr, "96", 2))x->x_bitrate = 96; + else if(!strncmp(sptr, "80", 2))x->x_bitrate = 80; + else if(!strncmp(sptr, "64", 2))x->x_bitrate = 64; + else if(!strncmp(sptr, "56", 2))x->x_bitrate = 56; + else if(!strncmp(sptr, "48", 2))x->x_bitrate = 48; + else if(!strncmp(sptr, "40", 2))x->x_bitrate = 40; + else if(!strncmp(sptr, "32", 2))x->x_bitrate = 32; + else if(!strncmp(sptr, "24", 2))x->x_bitrate = 24; + else if(!strncmp(sptr, "16", 2))x->x_bitrate = 16; + else if(!strncmp(sptr, "8", 2))x->x_bitrate = 8; + else + { + post("mp3amp~: unsupported bitrate! (%s)", sptr); + return NULL; + } + post(" bitrate: %d", x->x_bitrate); + } + if(strstr(request, "x-audiocast-udpport:")) + { + post("mp3amp~: sorry, server wants UDP connection!"); + return NULL; + } + } + else + { + post("mp3amp~: unknown response from server"); + return NULL; + } + relocate = FALSE; + } + if (relocate) { + error("mp3amp~: too many HTTP relocations"); + return NULL; + } + post("mp3amp~: connected to http://%s:%d/%s", hp->h_name, portno, x->x_mountpoint); + x->x_fd = sockfd; + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + t_int width; + + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + SYS_VGUI3(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); + } + + return NULL; +} + + /* launch the connection thread */ +static void mp3amp_connect(t_mp3amp *x, t_symbol *hostname, t_symbol *mountpoint, t_floatarg fportno ) +{ + pthread_attr_t update_child_attr; + pthread_t connectchild; + + // store data + x->x_hostname = (char*) getbytes( strlen( hostname->s_name ) + 1 ); // there's a memory leak here + strcpy( x->x_hostname, hostname->s_name ); + + x->x_mountpoint = (char*) getbytes( strlen( mountpoint->s_name ) + 1 ); // there's a memory leak here + strcpy( x->x_mountpoint, mountpoint->s_name ); + + x->x_port = fportno; + + // launch connection thread + if ( pthread_attr_init( &update_child_attr ) < 0 ) { + post( "mp3amp~ : could not launch connection thread" ); + perror( "pthread_attr_init" ); + return; + } + if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { + post( "mp3amp~ : could not launch connection thread" ); + perror( "pthread_attr_setdetachstate" ); + return; + } + if ( pthread_create( &connectchild, &update_child_attr, mp3amp_do_connect, x ) < 0 ) { + post( "mp3amp~ : could not launch connection thread" ); + perror( "pthread_create" ); + return; + } + else + { + // post( "cooled~ : drawing thread %d launched", (int)x->x_updatechild ); + } + + if ( !x->x_nooutput ) outlet_float(x->x_connection, 1); +} + + /* connect using url like "http://localhost:8000/mountpoint" */ +static void mp3amp_connect_url(t_mp3amp *x, t_symbol *url) +{ + char *hostptr = NULL, *p, *endhost = NULL, *hostname = NULL; + char *pathptr = NULL; + t_int portno = 8000; + + post( "mp3amp~ : connect url : %s", url->s_name ); + + /* strip http:// or ftp:// */ + p = url->s_name; + if (strncmp(p, "http://", 7) == 0) + p += 7; + + if (strncmp(p, "ftp://", 6) == 0) + p += 6; + + hostptr = p; + while (*p && *p != '/' && *p != ':') /* look for end of hostname: */ + p++; + + endhost = p; + switch ( *p ) + { + case ':' : + portno = atoi( p+1 ); + while (*p && *p != '/') p++; + pathptr = p+1; + break; + case '/' : + portno = 8000; + pathptr = p+1; + break; + default : + if ( ( p - url->s_name ) != (int)strlen( url->s_name ) ) + { + post( "mp3amp~ : wrong url : %s", hostptr ); + return; + } + pathptr = ""; + break; + } + + hostname=(char*)getbytes( (int)(endhost - hostptr) + 1); + strncpy( hostname, hostptr, (int)(endhost - hostptr) ); + hostname[ endhost - hostptr ] = '\0'; + + post ("mp3amp~ : connecting to host=%s port=%d path=%s", hostname, portno, pathptr ); + + /* call the 'normal' connection routine */ + mp3amp_connect(x, gensym(hostname), gensym(pathptr), portno); +} + + /* close connection to SHOUTcast server */ +static void mp3amp_disconnect(t_mp3amp *x) +{ + x->x_stream = 0; + x->x_inframes = 0; + x->x_dframes = 0; + x->x_inwriteposition = 0; + x->x_offset = 0; + if(x->x_fd >= 0) /* close socket */ + { + sys_closesocket(x->x_fd); + x->x_fd = -1; + } + ExitMP3(&mps[x->x_instance]); + InitMP3(&mps[x->x_instance]); + if ( x->x_graphic ) + { + SYS_VGUI3(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); + SYS_VGUI3(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); + } + post("mp3amp~: connection closed"); + outlet_float(x->x_connection, 0); +} + +static void mp3amp_free(t_mp3amp *x) +{ + if (x->x_fd > 0) { + post( "mp3amp~: closing socket" ); + sys_closesocket(x->x_fd); + x->x_fd = -1; + } + freebytes(x->x_inbuffer, INPUT_BUFFER_SIZE); + freebytes(x->x_outbuffer, OUTPUT_BUFFER_SIZE*sizeof(t_float)); +} + +static void *mp3amp_new(t_floatarg fdographics) +{ + t_mp3amp *x = NULL; + + if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) + { + post( "mp3amp~: error : constructor : mp3amp~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); + return NULL; + } + + x = (t_mp3amp *)pd_new(mp3amp_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + x->x_connection = outlet_new(&x->x_obj, gensym("float")); + + if ( nbinstances < MAX_DECODERS ) + { + x->x_instance = nbinstances++; + } + else + { + post( "mp3amp~: cannot create more decoders (memory issues), sorry" ); + return NULL; + } + + x->x_fd = -1; + x->x_stream = 0; + x->x_inframes = 0; + x->x_samplerate = sys_getsr(); + x->x_nbwaitloops = 1; + x->x_nbloops = 0; + x->x_dsp = 0; + + x->x_inbuffersize = INPUT_BUFFER_SIZE; + x->x_outbuffersize = OUTPUT_BUFFER_SIZE; + x->x_inbuffer = (unsigned char*) getbytes(INPUT_BUFFER_SIZE); + x->x_offset = 0; + x->x_outbuffer = (t_float*) getbytes(OUTPUT_BUFFER_SIZE*sizeof(t_float)); + + if ( !x->x_inbuffer || !x->x_outbuffer ) + { + post( "mp3amp~: could not allocate buffers" ); + return NULL; + } + memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); + memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); + + x->x_inwriteposition = 0; + x->x_outreadposition = 0; + x->x_outwriteposition = 0; + x->x_outunread = 0; + x->x_standby = 0; + x->x_resample = -1; + x->x_nooutput = 0; + + ztout.tv_sec = 0; + ztout.tv_usec = 0; + + x->x_graphic = (int)fdographics; + post( "mp3amp~: getting canvas" ); + x->x_canvas = canvas_getcurrent(); + + post( "mp3amp~: initializing decoder..." ); + /* init mpg123 decoder */ + mp3amp_tilde_mpglib_init(x); + + post(mp3amp_version); + + return (x); +} + + +void mp3amp_tilde_setup(void) +{ + mp3amp_class = class_new(gensym("mp3amp~"), + (t_newmethod) mp3amp_new, (t_method) mp3amp_free, + sizeof(t_mp3amp), 0, A_DEFFLOAT, A_NULL); + + class_addmethod(mp3amp_class, nullfn, gensym("signal"), 0); + class_addmethod(mp3amp_class, (t_method)mp3amp_dsp, gensym("dsp"), 0); + class_addmethod(mp3amp_class, (t_method)mp3amp_connect, gensym("connect"), A_SYMBOL, A_SYMBOL, A_FLOAT, 0); + class_addmethod(mp3amp_class, (t_method)mp3amp_connect_url, gensym("connecturl"), A_SYMBOL, 0); + class_addmethod(mp3amp_class, (t_method)mp3amp_standby, gensym("standby"), A_DEFFLOAT, 0); + class_addmethod(mp3amp_class, (t_method)mp3amp_disconnect, gensym("disconnect"), 0); +} diff --git a/mp3amp~/INSTALL b/mp3amp~/INSTALL deleted file mode 100644 index 8260a98..0000000 --- a/mp3amp~/INSTALL +++ /dev/null @@ -1,19 +0,0 @@ -You need to get lame > v3.90 installed first. -libmp3lame.so is searched in /usr/local/lib -( no time to write configure scripts ). -if it's installed elsewhere, change the Makefile, -you won't die from that. - -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/mp3amp~ - -make clean - -make - -make install - -thanks for getting here. - -Yves/ diff --git a/mp3amp~/graphic-mp3amp~-help.pd b/mp3amp~/graphic-mp3amp~-help.pd deleted file mode 100644 index 241a607..0000000 --- a/mp3amp~/graphic-mp3amp~-help.pd +++ /dev/null @@ -1,52 +0,0 @@ -#N canvas 171 33 789 555 10; -#X obj 115 265 dac~; -#X floatatom 164 265 5 0 0; -#X msg 29 150 disconnect; -#X text 208 267 connection status; -#X obj 458 48 loadbang; -#X msg 458 71 \; pd dsp 1; -#X msg 99 76 connect yves puredata 8000; -#X text 96 55 connect ; -#X text 38 18 constructor : mp3amp~ ; -#X text 151 127 connect to SHOUTcast server; -#X msg 157 145 connect localhost listen.pls 8000; -#X msg 176 165 connect localhost content/scpromo.mp3 8000; -#X text 399 141 <-- play livestream; -#X text 479 165 <-- play file; -#X msg 121 99 connect localhost kas 8000; -#X text 97 44 connect to ICEcast server; -#X text 38 7 mp3amp~ : an icecast/shoucast client for PD; -#X text 226 186 Another way of connecting; -#X msg 226 205 connecturl http://localhost:8000/kas; -#X msg 31 374 standby 0; -#X text 114 380 for CPU load reasons \,; -#X text 115 392 ability to freeze decoding; -#X text 114 405 ( packets are read and ignored ); -#X msg 31 399 standby 1; -#X obj 115 196 mp3amp~ 1; -#X msg 353 230 connecturl http://216.235.81.7:20690/play?session=panjabiradio:0&\;lid=-1-fra&\;SaneID=212.198.0.97-1030988754258 -; -#X msg 352 280 connecturl http://213.197.144.44:8000/; -#X msg 352 334 connecturl http://24.207.26.60:8000/; -#X msg 354 307 connecturl http://64.113.197.158:8000/; -#X msg 352 361 connecturl http://liveice.agria.hu:8000/radioeger-hq -; -#X text 406 511 Authors : Yves Degoyon ( ydegoyon@free.fr ); -#X connect 2 0 24 0; -#X connect 4 0 5 0; -#X connect 6 0 24 0; -#X connect 10 0 24 0; -#X connect 11 0 24 0; -#X connect 14 0 24 0; -#X connect 18 0 24 0; -#X connect 19 0 24 0; -#X connect 23 0 24 0; -#X connect 24 0 0 0; -#X connect 24 0 0 1; -#X connect 24 1 0 1; -#X connect 24 2 1 0; -#X connect 25 0 24 0; -#X connect 26 0 24 0; -#X connect 27 0 24 0; -#X connect 28 0 24 0; -#X connect 29 0 24 0; diff --git a/mp3amp~/interface.h b/mp3amp~/interface.h deleted file mode 100644 index de3136a..0000000 --- a/mp3amp~/interface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Copyright (C) 2000 Albert L. Faber -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef INTERFACE_H_INCLUDED -#define INTERFACE_H_INCLUDED - -// #include "common.h" -#include "interface.h" - -BOOL InitMP3(PMPSTR mp); -int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done); -void ExitMP3(PMPSTR mp); - -/* added remove_buf to support mpglib seeking */ -void remove_buf(PMPSTR mp); - -#endif diff --git a/mp3amp~/mp3amp~-help.pd b/mp3amp~/mp3amp~-help.pd deleted file mode 100644 index 47249b7..0000000 --- a/mp3amp~/mp3amp~-help.pd +++ /dev/null @@ -1,53 +0,0 @@ -#N canvas 125 102 789 555 10; -#X obj 115 265 dac~; -#X floatatom 164 265 5 0 0; -#X msg 29 150 disconnect; -#X text 208 267 connection status; -#X obj 458 48 loadbang; -#X msg 458 71 \; pd dsp 1; -#X msg 99 76 connect yves puredata 8000; -#X text 96 55 connect ; -#X text 38 18 constructor : mp3amp~ ; -#X text 151 127 connect to SHOUTcast server; -#X msg 157 145 connect localhost listen.pls 8000; -#X msg 176 165 connect localhost content/scpromo.mp3 8000; -#X text 399 141 <-- play livestream; -#X text 479 165 <-- play file; -#X msg 121 99 connect localhost kas 8000; -#X text 97 44 connect to ICEcast server; -#X text 38 7 mp3amp~ : an icecast/shoucast client for PD; -#X text 226 186 Another way of connecting; -#X msg 226 205 connecturl http://localhost:8000/kas; -#X msg 31 374 standby 0; -#X text 114 380 for CPU load reasons \,; -#X text 115 392 ability to freeze decoding; -#X text 114 405 ( packets are read and ignored ); -#X msg 31 399 standby 1; -#X msg 353 230 connecturl http://216.235.81.7:20690/play?session=panjabiradio:0&\;lid=-1-fra&\;SaneID=212.198.0.97-1030988754258 -; -#X msg 352 280 connecturl http://213.197.144.44:8000/; -#X msg 352 334 connecturl http://24.207.26.60:8000/; -#X msg 354 307 connecturl http://64.113.197.158:8000/; -#X msg 352 361 connecturl http://liveice.agria.hu:8000/radioeger-hq -; -#X text 406 511 Authors : Yves Degoyon ( ydegoyon@free.fr ); -#X obj 115 196 mp3amp~; -#X msg 354 384 connecturl http://www.deliciound.net:8000/; -#X connect 2 0 30 0; -#X connect 4 0 5 0; -#X connect 6 0 30 0; -#X connect 10 0 30 0; -#X connect 11 0 30 0; -#X connect 14 0 30 0; -#X connect 18 0 30 0; -#X connect 19 0 30 0; -#X connect 23 0 30 0; -#X connect 24 0 30 0; -#X connect 25 0 30 0; -#X connect 26 0 30 0; -#X connect 27 0 30 0; -#X connect 28 0 30 0; -#X connect 30 0 0 0; -#X connect 30 1 0 1; -#X connect 30 2 1 0; -#X connect 31 0 30 0; diff --git a/mp3amp~/mp3amp~.c b/mp3amp~/mp3amp~.c deleted file mode 100644 index 9dfc54e..0000000 --- a/mp3amp~/mp3amp~.c +++ /dev/null @@ -1,1262 +0,0 @@ -/* ------------------------- mp3amp~ ------------------------------------------ */ -/* */ -/* Tilde object to receive an mp3-stream from a shoutcast/icecast server. */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Get source at http://ydegoyon.free.fr */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU Lesser General Public */ -/* License as published by the Free Software Foundation; either */ -/* version 2 of the License, or (at your option) any later version. */ -/* */ -/* This library is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* Lesser General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU Lesser General Public */ -/* License along with this library; if not, write to the */ -/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ -/* Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 encoding library which can be found at */ -/* http://www.mp3dev.org */ -/* */ -/* ---------------------------------------------------------------------------- */ - -#include -#include "m_imp.h" -#include "g_canvas.h" -#include "s_stuff.h" -#include "pthread.h" - -#include -#include -#include -#include -#include -#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ -#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ -#include "interface.h" /* mpglib decoding library from lame 3.92 */ -#ifdef _WIN32 -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif /* _WIN32 */ - -#ifdef _MSC_VER -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4305 ) -#endif - -#if defined(__APPLE__) || defined(WIN32) -#define MSG_NOSIGNAL 0 -#endif -#ifdef UNIX -#define STRDUP strdup -#endif -#ifdef WIN32 -#define STRDUP _strdup -#define sys_closesocket closesocket -#endif - - -#define LAME_AUDIO_CHUNK_SIZE 1152 -#define MIN_AUDIO_INPUT 2*LAME_AUDIO_CHUNK_SIZE /* we must have at least n chunks to play a steady sound */ -#define INPUT_BUFFER_SIZE 131072 /* data received on the socket : 128k */ -#define OUTPUT_BUFFER_SIZE 131072 /* audio output buffer : 128k */ -#define DECODE_PACKET_SIZE 131072 /* size of the data returned by mpglib : 128k */ -#define STRBUF_SIZE 4096 /* char received from server on startup */ -#define MAX_DECODERS 50 -#define BARHEIGHT 10 - -static int guidebug=0; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h );\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - - - /* useful debugging functions from mpglib */ -extern int decode_header( struct frame* fr, unsigned long newhead ); -extern void print_header_compact( struct frame* fr ); -extern int head_check( unsigned long head, int check_layer ); - -static char *mp3amp_version = "mp3amp~: mp3 streaming client v0.12, written by Yves Degoyon"; - -/* ------------------------ mp3amp~ ----------------------------- */ - -static t_class *mp3amp_class; - -/* too bad, this needs to be static, - handling an array to enable several decoders in pd */ -static MPSTR mps[MAX_DECODERS]; /* decoder buffer */ -static int nbinstances = 0; - -extern const long freqs[9]; - -/* time-out used for select() call */ -static struct timeval ztout; - -typedef struct _mp3amp -{ - t_object x_obj; - t_int x_instance; /* instance of the object */ - t_outlet *x_connection; - t_int x_fd; /* the socket number */ - t_int x_inframes; /* number of waiting frames */ - t_int x_dframes; /* displayed frames in status bar */ - t_int x_packetsize; /* size of the packets */ - t_int x_pblocks; /* processed blocks */ - t_int x_graphic; /* indicates if we show a graphic bar */ - t_canvas *x_canvas; /* remember canvas */ - t_int x_nbwaitloops; /* number of loops to wait */ - t_int x_nbloops; /* number of loops processed */ - t_int x_blocksize; /* size of a dsp block */ - t_int x_resample; /* resampling factor (pd's sr / stream sr) */ - t_int x_dsp; /* number of dsp calls, used to measure time */ - t_int x_standby; /* flag to freeze decoding */ - t_int x_nooutput; /* flag to avoid output of connection state */ - -#ifdef UNIX - unsigned char *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ -#else - char *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ -#endif - - t_int x_inwriteposition; - t_int x_inbuffersize; - t_int x_offset; /* offset used for start of decoding */ - - t_float *x_outbuffer; /* buffer to store audio decoded data */ - t_int x_outwriteposition; - t_int x_outreadposition; - t_int x_outunread; - t_int x_outbuffersize; - char x_out[DECODE_PACKET_SIZE]; - - /* mp3 stuff */ - t_int x_samplerate; - t_int x_bitrate; /* bitrate of mp3 stream read at connection time */ - t_int x_bitrateindex; /* bitrate index for each frame, might change dynamically */ - t_int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ - char* x_bcname; /* name of broadcast */ - char* x_bcurl; /* url of broadcast */ - char* x_bcgenre; /* genre of broadcast */ - char* x_bcaim; /* aim of broadcast */ - char* x_mountpoint; /* mountpoint for IceCast server */ - char* x_hostname; /* hostname to connect to */ - t_int x_port; /* port number to connect to */ - - t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ -} t_mp3amp; - -static void mp3amp_recv(t_mp3amp *x); -static void mp3amp_disconnect(t_mp3amp *x); -static void mp3amp_connect_url(t_mp3amp *x, t_symbol *url); - -static int strip_shout_header(char *head, int n) -{ - int i; - for (i = 0; i < (n - 2); i++) - { - if (head[i] == 10 && head[i + 1] == 13) - break; - if (head[i] == '\n' && head[i + 1] == '\n') - break; - } - head[i + 1] = '\0'; - return n - (i + 1); -} - -static int strip_ice_header(char *head, int n) -{ - int i; - for (i = 0; i < (n - 2); i++) - { - if ((head[i] == '\n') && (head[i + 1] == '\n')) - break; - } - head[i + 1] = '\0'; - return n - (i + 1); -} - -static void mp3amp_tilde_mpglib_init(t_mp3amp *x) -{ - int ret; - - InitMP3(&mps[x->x_instance]); -} - -static int mp3amp_decode_input(t_mp3amp *x) -{ - t_int i; - t_int alength = 0; - float resample = 0; - struct frame hframe; - unsigned int a,b,c,d; - unsigned long cheader; - signed short int *p = (signed short int *) x->x_out; - t_int pbytes; - t_int ret, totlength=0; - t_int pframes = 0; - - x->x_offset=0; - // search for an header to check dynamic bitrate - while ( x->x_offset < x->x_inwriteposition ) - { - /* decode first 4 bytes as the header */ - a = *((unsigned char*)x->x_inbuffer+x->x_offset); - b = *((unsigned char*)x->x_inbuffer+x->x_offset+1); - c = *((unsigned char*)x->x_inbuffer+x->x_offset+2); - d = *((unsigned char*)x->x_inbuffer+x->x_offset+3); - - cheader = 0; - cheader = a; - cheader <<= 8; - cheader |= b; - cheader <<= 8; - cheader |= c; - cheader <<= 8; - cheader |= d; - if ( head_check( cheader, 0 ) ) - { - decode_header( &hframe, cheader ); - if ( hframe.framesize == 0 ) - { - post( "mp3amp~: weird header ( frame size = 0 ) .... ignored" ); - x->x_offset++; - continue; - } - x->x_packetsize = hframe.framesize; - // print_header_compact( &hframe ); - // when the bitrate change, reinit decoder - if ( x->x_bitrateindex != hframe.bitrate_index ) - { - post( "mp3amp~: bitrate has changed, reinitialize decoder" ); - ExitMP3(&mps[x->x_instance]); - InitMP3(&mps[x->x_instance]); - x->x_bitrateindex = hframe.bitrate_index; - } - break; - } - x->x_offset++; - } - - if ( x->x_inframes > 0 ) - { - - ret = decodeMP3(&mps[x->x_instance], (unsigned char*)(x->x_inbuffer+x->x_offset), - hframe.framesize+sizeof( unsigned long), (char *) p, sizeof(x->x_out), &pbytes); - - switch (ret) - { - case MP3_OK: - switch (mps[x->x_instance].fr.stereo) { - case 1: - case 2: - alength = ((mps[x->x_instance].fr.stereo==1)?pbytes >> 1 : pbytes >> 2); - // post( "mp3amp~: stereo : %d", mps[x->x_instance].fr.stereo ); - // update outbuffer contents - for ( i=0; ix_outunread >= x->x_outbuffersize-2 ) - { - // post( "mp3amp~: decode : too much input ... ignored" ); - continue; - } - *(x->x_outbuffer+x->x_outwriteposition) = ((t_float)(*p++))/32767.0; - x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; - *(x->x_outbuffer+x->x_outwriteposition) = - ((mps[x->x_instance].fr.stereo==2)?((t_float)(*p++))/32767.0 : 0.0); - x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; - x->x_outunread+=2; - - if ( x->x_outunread >= MIN_AUDIO_INPUT && !x->x_stream ) - { - post("mp3amp~: stream connected" ); - x->x_resample = x->x_samplerate / freqs[hframe.sampling_frequency]; - if ( x->x_resample == 0 ) x->x_resample=1; - post("mp3amp~: resampling stream from %d to %d Hz (r=%d)", - freqs[hframe.sampling_frequency], x->x_samplerate, x->x_resample ); - x->x_stream = 1; - } - } - break; - default: - alength = -1; - break; - } - // roll buffer - if ( x->x_inwriteposition > hframe.framesize+ (int) sizeof( unsigned long ) + x->x_offset ) - // ^----- maybe the frame is not complete - { - x->x_inwriteposition -= hframe.framesize+sizeof( unsigned long )+x->x_offset; - memcpy( (void *)(x->x_inbuffer), - (void *)(x->x_inbuffer+x->x_offset+hframe.framesize+sizeof( unsigned long )), - x->x_inwriteposition); - x->x_offset = 0; - // post ( "mp3amp~: decoded frame %d", x->x_inframes ); - x->x_inframes--; - pframes++; - } - else // sorry, it will be ignored - { - // error( "mp3amp~: incomplete frame...ignored"); - // x->x_offset = 0; - // x->x_inwriteposition = 0; - // x->x_inframes = 0; - } - - totlength += alength; - break; - - case MP3_NEED_MORE: - if ( mps[x->x_instance].framesize == 0 && mps[x->x_instance].fsizeold != 0 ) - { - post( "mp3amp~: decoding done (totlength=%d).", totlength ); - } - else - { - post( "mp3amp~: retry lame decoding (more data needed)." ); - return -1; - } - break; - - case MP3_ERR: - post( "mp3amp~: lame decoding failed." ); - return ret; - break; - - } - - } - - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - /* update graphical read status */ - if ( x->x_inframes != x->x_dframes ) - { - char color[32]; - t_int width; - - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - SYS_VGUI3(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); - if ( x->x_inframes < (MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE) ) - { - strcpy( color, "red" ); - } - else - { - strcpy( color, "lightgreen" ); - } - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix+(x->x_inwriteposition*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix - 1, color, x ); - x->x_dframes = x->x_inframes; - } - } - return totlength; -} - -static void mp3amp_recv(t_mp3amp *x) -{ - int ret, i; - float resample = 0; - struct frame hframe; - unsigned int a,b,c,d; - unsigned long cheader; - -#ifdef UNIX - if ( ( ret = recv(x->x_fd, (void*) (x->x_inbuffer + x->x_inwriteposition), - (size_t)((x->x_inbuffersize-x->x_inwriteposition)), - MSG_NOSIGNAL) ) < 0 ) -#else - if(( ret = recv(x->x_fd, (char*)x->x_inbuffer + x->x_inwriteposition, - (x->x_inbuffersize-x->x_inwriteposition), 0)) < 0) -#endif - { - post( "mp3amp~: receive error" ); -#ifdef UNIX - perror( "recv" ); -#endif - mp3amp_disconnect(x); - return; - } - else - { - - // post( "mp3amp~: received %d bytes at %d on %d ( up to %d)", - // ret, x->x_inwriteposition, x->x_fd, - // x->x_inbuffersize-x->x_inwriteposition ); - - if ( ret == 0 && ( x->x_inbuffersize-x->x_inwriteposition != 0 ) ) - { - error("mp3amp~: stream lost..."); - mp3amp_disconnect(x); - } - else - { - // check if we should decode those packets - if ( x->x_standby ) - { - return; - } - // check we don't overflow input buffer - if ( ( x->x_inwriteposition + ret ) > x->x_inbuffersize*0.9 ) - { - post( "mp3streamin~ : too much input...resetting" ); - x->x_inwriteposition=0; - x->x_offset = 0; - x->x_inframes = 0; - return; - } - x->x_inwriteposition += ret; - x->x_offset = 0; - // check some parameters in the stream - while ( x->x_offset < x->x_inwriteposition ) - { - /* decode first 4 bytes as the header */ - a = *((unsigned char*)x->x_inbuffer+x->x_offset); - b = *((unsigned char*)x->x_inbuffer+x->x_offset+1); - c = *((unsigned char*)x->x_inbuffer+x->x_offset+2); - d = *((unsigned char*)x->x_inbuffer+x->x_offset+3); - - cheader = 0; - cheader = a; - cheader <<= 8; - cheader |= b; - cheader <<= 8; - cheader |= c; - cheader <<= 8; - cheader |= d; - if ( head_check( cheader, 0 ) ) - { - decode_header( &hframe, cheader ); - // print_header_compact( &hframe ); - x->x_packetsize = hframe.framesize; - if ( hframe.framesize == 0 ) - { - post( "mp3amp~: weird header ( frame size = 0 ) .... ignored" ); - x->x_inwriteposition -= ret; - return; - } - x->x_inframes += ret/x->x_packetsize; - // post( "mp3amp~: nb frames %d", x->x_inframes ); - break; - } - x->x_offset++; - } - } - } -} - -static t_int *mp3amp_perform(t_int *w) -{ - t_mp3amp *x = (t_mp3amp*) (w[1]); - t_float *out1 = (t_float *)(w[2]); - t_float *out2 = (t_float *)(w[3]); - int n = (int)(w[4]); - int ret; - int i = 0; - - x->x_blocksize = n; - x->x_nbwaitloops = LAME_AUDIO_CHUNK_SIZE/x->x_blocksize; - // post( "mp3mp3amp~ : will wait %d loops", x->x_nbwaitloops ); - x->x_dsp++; - - while( n-- ) - { - if(x->x_stream && !x->x_standby ) // check that the stream provides enough data - { - if(x->x_resample == 1) /* don't need to resample */ - { - *out1++=*(x->x_outbuffer+x->x_outreadposition); - x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; - *out2++=*(x->x_outbuffer+x->x_outreadposition); - x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; - x->x_outunread-=2; - } - else - { /* we just use the same sample x->x_resample times */ - *out1++=*(x->x_outbuffer+x->x_outreadposition); - *out2++=*(x->x_outbuffer+((x->x_outreadposition + 1)%x->x_outbuffersize)); - if((n%x->x_resample)== 0) - { - x->x_outreadposition = (x->x_outreadposition + 2)%x->x_outbuffersize; - x->x_outunread-=2; - } - } - if ( n == 1 ) x->x_pblocks++; - } - else - { - *out1++=0.0; - *out2++=0.0; - } - } - - if ( x->x_pblocks == LAME_AUDIO_CHUNK_SIZE/x->x_blocksize ) - { - x->x_pblocks = 0; - } - - /* check for readability, then fill the input buffer */ - if(( x->x_fd > 0 )&&(x->x_dsp >= 16)) /* determine how often we try to read */ - { - fd_set readset; - fd_set exceptset; - - FD_ZERO(&readset); - FD_ZERO(&exceptset); - FD_SET(x->x_fd, &readset ); - FD_SET(x->x_fd, &exceptset ); - - x->x_dsp = 0; - - if ( select( x->x_fd+1, &readset, NULL, &exceptset, &ztout ) >0 ) - { - if ( FD_ISSET( x->x_fd, &readset) || FD_ISSET( x->x_fd, &exceptset ) ) - { - /* receive data or error */ - mp3amp_recv(x); - } - } - } - - // check new incoming data - if ( x->x_fd > 0 && ( x->x_nbloops == 0 ) && ( x->x_inframes > 0 ) && ( !x->x_standby ) ) - { - mp3amp_decode_input(x); - } - if ( x->x_nbwaitloops != 0 ) - { - x->x_nbloops = (x->x_nbloops+1 ) % x->x_nbwaitloops; - } - return (w+5); -} - -static void mp3amp_dsp(t_mp3amp *x, t_signal **sp) -{ - dsp_add(mp3amp_perform, 4, x, sp[1]->s_vec, sp[2]->s_vec, sp[1]->s_n); -} - - - /* freeze decoding */ -static void mp3amp_standby(t_mp3amp *x, t_floatarg fstandby ) -{ - if ( fstandby == 0. ) - { - x->x_standby = 0; - } - else - { - x->x_standby = 1; - } -} - - /* connection main procedure executed by a thread */ -static void *mp3amp_do_connect(void *tdata ) -{ - t_mp3amp *x = (t_mp3amp*) tdata; - struct sockaddr_in server; - struct hostent *hp; - t_int portno = x->x_port; /* get port from message box */ - - /* variables used for communication with server */ - char *sptr = NULL; - char request[STRBUF_SIZE]; /* string to be send to server */ - char *url; /* used for relocation */ - fd_set fdset; - struct timeval tv; - t_int sockfd; /* socket to server */ - t_int relocate, numrelocs = 0; - t_int i, ret, rest, nanswers=0; - char *cpoint = NULL; - t_int offset = 0, endofheaders = 0; - - if (x->x_fd >= 0) - { - error("mp3amp~: already connected"); - return NULL; - } - - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - error("mp3amp~: internal error while attempting to open socket"); - return NULL; - } - - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(x->x_hostname); - if (hp == 0) - { - post("mp3amp~: bad host?"); - sys_closesocket(sockfd); - return NULL; - } - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - server.sin_port = htons((unsigned short)portno); - - /* try to connect. */ - post("mp3amp~: connecting to http:/%s:%d/%s", x->x_hostname, x->x_port, x->x_mountpoint ); - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - error("mp3amp~: connection failed!\n"); - sys_closesocket(sockfd); - return NULL; - } - post("mp3amp~: connected : socket opened" ); - - /* sheck if we can read/write from/to the socket */ - FD_ZERO( &fdset); - FD_SET( sockfd, &fdset); - tv.tv_sec = 0; /* seconds */ - tv.tv_usec = 500; /* microseconds */ - - ret = select(sockfd + 1, &fdset, NULL, NULL, &tv); - if(ret != 0) - { - error("mp3amp~: can not read from socket"); - sys_closesocket(sockfd); - return NULL; - } - post("mp3amp~: select done" ); - - /* check mountpoint */ - if( strstr(x->x_mountpoint, "listen.pls") ) - { /* SHOUTcast playlist -> get / */ - x->x_mountpoint = ""; - } - - /* build up stuff we need to send to server */ - sprintf(request, "GET /%s HTTP/1.0 \r\nHost: %s\r\nUser-Agent: mp3amp~ 0.11\r\nAccept: */*\r\n\r\n", - x->x_mountpoint, x->x_hostname); - - if ( send(sockfd, request, strlen(request), 0) < 0 ) /* say hello to server */ - { - post( "mp3amp~: could not contact server... " ); -#ifdef UNIX - perror( "send" ); -#endif - return NULL; - } - post("mp3amp~: send done" ); - - relocate = FALSE; - memset( request, 0x00, STRBUF_SIZE ); - - // read all the answer - endofheaders=0; - while ( !endofheaders ) - { - if( ( ret = recv(sockfd, request+offset, STRBUF_SIZE, MSG_NOSIGNAL) ) <0) - { - error("mp3amp~: no response from server"); -#ifdef UNIX - perror( "recv" ); -#endif - return NULL; - } - post ( "mp3amp~ : received %d bytes at %d", ret, offset ); - for ( i=offset; ix_nooutput = 1; - mp3amp_connect_url(x, gensym(url)); - x->x_nooutput = 0; - return NULL; - // relocate = TRUE; - } - if( !(sptr = strstr(request, "200")) && !relocate ) - { - error("mp3amp~: cannot connect to the (default) stream"); - return NULL; - } - - post("mp3amp~: IceCast server detected"); - - // post("mp3amp~: server's header : %s", request ); - - // check what we got - if( cpoint = strstr(request, "x-audiocast-mount:")) - { - x->x_mountpoint = STRDUP(cpoint + 18); - for ( i=0; i<(int)strlen(x->x_mountpoint); i++ ) - { - if ( x->x_mountpoint[i] == '\n' ) - { - x->x_mountpoint[i] = '\0'; - break; - } - } - post(" mountpoint: %s", x->x_mountpoint); - } - if( cpoint = strstr(request, "x-audiocast-server-url:")) - { - sptr = STRDUP( cpoint + 24); - for ( i=0; i<(int)strlen(sptr); i++ ) - { - if ( sptr[i] == '\n' ) - { - sptr[i] = '\0'; - break; - } - } - post(" server-url: %s", sptr); - } - if( cpoint = strstr(request, "x-audiocast-location:")) - { - sptr = STRDUP( cpoint + 22); - for ( i=0; i<(int)strlen(sptr); i++ ) - { - if ( sptr[i] == '\n' ) - { - sptr[i] = '\0'; - break; - } - } - post(" location: %s", sptr); - } - if( cpoint = strstr(request, "x-audiocast-admin:")) - { - sptr = STRDUP( cpoint + 19); - for ( i=0; i<(int)strlen(sptr); i++ ) - { - if ( sptr[i] == '\n' ) - { - sptr[i] = '\0'; - break; - } - } - post(" admin: %s", sptr); - } - if( cpoint = strstr(request, "x-audiocast-name:")) - { - x->x_bcname = STRDUP( cpoint + 17); - for ( i=0; i<(int)strlen(x->x_bcname); i++ ) - { - if ( x->x_bcname[i] == '\n' ) - { - x->x_bcname[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if( cpoint = strstr(request, "x-audiocast-genre:")) - { - x->x_bcgenre = STRDUP( cpoint + 18); - for ( i=0; i<(int)strlen(x->x_bcgenre); i++ ) - { - if ( x->x_bcgenre[i] == '\n' ) - { - x->x_bcgenre[i] = '\0'; - break; - } - } - post(" genre: %s", x->x_bcgenre); - } - if( cpoint = strstr(request, "x-audiocast-url:")) - { - x->x_bcurl = STRDUP( cpoint + 16); - for ( i=0; i<(int)strlen(x->x_bcurl); i++ ) - { - if ( x->x_bcurl[i] == '\n' ) - { - x->x_bcurl[i] = '\0'; - break; - } - } - post(" url: %s", x->x_bcurl); - } - if( cpoint = strstr(request, "x-audiocast-public:1")) - { - post(" broadcast is public"); - } - else if( cpoint = strstr(request, "x-audiocast-public:0")) - { - post(" broadcast is NOT public"); - } - if( cpoint = strstr(request, "x-audiocast-bitrate:")) - { - sptr = STRDUP( cpoint + 20); - for ( i=0; i<(int)strlen(sptr); i++ ) - { - if ( sptr[i] == '\n' ) - { - sptr[i] = '\0'; - break; - } - } - if(!strncmp(sptr, "320", 3))x->x_bitrate = 320; - else if(!strncmp(sptr, "256", 3))x->x_bitrate = 256; - else if(!strncmp(sptr, "224", 3))x->x_bitrate = 224; - else if(!strncmp(sptr, "192", 3))x->x_bitrate = 192; - else if(!strncmp(sptr, "160", 3))x->x_bitrate = 160; - else if(!strncmp(sptr, "144", 3))x->x_bitrate = 144; - else if(!strncmp(sptr, "128", 3))x->x_bitrate = 128; - else if(!strncmp(sptr, "112", 3))x->x_bitrate = 112; - else if(!strncmp(sptr, "96", 2))x->x_bitrate = 96; - else if(!strncmp(sptr, "80", 2))x->x_bitrate = 80; - else if(!strncmp(sptr, "64", 2))x->x_bitrate = 64; - else if(!strncmp(sptr, "56", 2))x->x_bitrate = 56; - else if(!strncmp(sptr, "48", 2))x->x_bitrate = 48; - else if(!strncmp(sptr, "40", 2))x->x_bitrate = 40; - else if(!strncmp(sptr, "32", 2))x->x_bitrate = 32; - else if(!strncmp(sptr, "24", 2))x->x_bitrate = 24; - else if(!strncmp(sptr, "16", 2))x->x_bitrate = 16; - else if(!strncmp(sptr, "8", 1))x->x_bitrate = 8; - else - { - post("mp3amp~: unsupported bitrate! : %s", sptr); - return NULL; - } - post(" bitrate: %d", x->x_bitrate); - } - if( cpoint = strstr(request, "x-audiocast-udpport:")) - { - post("mp3amp~: sorry, server wants UDP connection!"); - return NULL; - } - } - else /* it is a SHOUTcast server */ - { - strip_shout_header (request, STRBUF_SIZE); - post("mp3amp~: SHOUTcast server detected"); - if(strstr(request, "ICY 401") != 0) - { - post("mp3amp~: ICY 401 Service Unavailable"); - return NULL; - } - if (strstr(request, "ICY 200 OK")) - { - /* recv and decode info about broadcast line by line */ - post("mp3amp~: connecting to stream..."); - i = ret; - /* check what we got */ - - if( cpoint = strstr(request, "icy-name:")) - { - x->x_bcname = STRDUP( cpoint + 10); - for ( i=0; i<(int)strlen(x->x_bcname); i++ ) - { - if ( x->x_bcname[i] == '\n' ) - { - x->x_bcname[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if( cpoint = strstr(request, "x-audiocast-name:")) - { - x->x_bcname = STRDUP( cpoint + 18); - for ( i=0; i<(int)strlen(x->x_bcname); i++ ) - { - if ( x->x_bcname[i] == '\n' ) - { - x->x_bcname[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if( cpoint = strstr(request, "icy-genre:")) - { - x->x_bcgenre = STRDUP( cpoint + 10); - for ( i=0; i<(int)strlen(x->x_bcgenre); i++ ) - { - if ( x->x_bcgenre[i] == '\n' ) - { - x->x_bcgenre[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if( cpoint = strstr(request, "icy-aim:")) - { - x->x_bcaim = STRDUP( cpoint + 8); - for ( i=0; i<(int)strlen(x->x_bcaim); i++ ) - { - if ( x->x_bcaim[i] == '\n' ) - { - x->x_bcaim[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if( cpoint = strstr(request, "icy-url:")) - { - x->x_bcurl = STRDUP( cpoint + 8); - for ( i=0; i<(int)strlen(x->x_bcurl); i++ ) - { - if ( x->x_bcurl[i] == '\n' ) - { - x->x_bcurl[i] = '\0'; - break; - } - } - post(" name: %s", x->x_bcname); - } - if(strstr(request, "icy-pub:1")) - { - post(" broadcast is public"); - } - else if(strstr(request, "icy-pub:0")) - { - post(" broadcast is NOT public"); - } - if( cpoint = strstr(request, "icy-br:")) - { - sptr = STRDUP( cpoint + 7); - if(!strncmp(sptr, "320", 3))x->x_bitrate = 320; - else if(!strncmp(sptr, "256", 3))x->x_bitrate = 256; - else if(!strncmp(sptr, "224", 3))x->x_bitrate = 224; - else if(!strncmp(sptr, "192", 3))x->x_bitrate = 192; - else if(!strncmp(sptr, "160", 3))x->x_bitrate = 160; - else if(!strncmp(sptr, "144", 3))x->x_bitrate = 144; - else if(!strncmp(sptr, "128", 3))x->x_bitrate = 128; - else if(!strncmp(sptr, "112", 3))x->x_bitrate = 112; - else if(!strncmp(sptr, "96", 2))x->x_bitrate = 96; - else if(!strncmp(sptr, "80", 2))x->x_bitrate = 80; - else if(!strncmp(sptr, "64", 2))x->x_bitrate = 64; - else if(!strncmp(sptr, "56", 2))x->x_bitrate = 56; - else if(!strncmp(sptr, "48", 2))x->x_bitrate = 48; - else if(!strncmp(sptr, "40", 2))x->x_bitrate = 40; - else if(!strncmp(sptr, "32", 2))x->x_bitrate = 32; - else if(!strncmp(sptr, "24", 2))x->x_bitrate = 24; - else if(!strncmp(sptr, "16", 2))x->x_bitrate = 16; - else if(!strncmp(sptr, "8", 2))x->x_bitrate = 8; - else - { - post("mp3amp~: unsupported bitrate! (%s)", sptr); - return NULL; - } - post(" bitrate: %d", x->x_bitrate); - } - if(strstr(request, "x-audiocast-udpport:")) - { - post("mp3amp~: sorry, server wants UDP connection!"); - return NULL; - } - } - else - { - post("mp3amp~: unknown response from server"); - return NULL; - } - relocate = FALSE; - } - if (relocate) { - error("mp3amp~: too many HTTP relocations"); - return NULL; - } - post("mp3amp~: connected to http://%s:%d/%s", hp->h_name, portno, x->x_mountpoint); - x->x_fd = sockfd; - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - t_int width; - - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - SYS_VGUI3(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); - } - - return NULL; -} - - /* launch the connection thread */ -static void mp3amp_connect(t_mp3amp *x, t_symbol *hostname, t_symbol *mountpoint, t_floatarg fportno ) -{ - pthread_attr_t update_child_attr; - pthread_t connectchild; - - // store data - x->x_hostname = (char*) getbytes( strlen( hostname->s_name ) + 1 ); // there's a memory leak here - strcpy( x->x_hostname, hostname->s_name ); - - x->x_mountpoint = (char*) getbytes( strlen( mountpoint->s_name ) + 1 ); // there's a memory leak here - strcpy( x->x_mountpoint, mountpoint->s_name ); - - x->x_port = fportno; - - // launch connection thread - if ( pthread_attr_init( &update_child_attr ) < 0 ) { - post( "mp3amp~ : could not launch connection thread" ); - perror( "pthread_attr_init" ); - return; - } - if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { - post( "mp3amp~ : could not launch connection thread" ); - perror( "pthread_attr_setdetachstate" ); - return; - } - if ( pthread_create( &connectchild, &update_child_attr, mp3amp_do_connect, x ) < 0 ) { - post( "mp3amp~ : could not launch connection thread" ); - perror( "pthread_create" ); - return; - } - else - { - // post( "cooled~ : drawing thread %d launched", (int)x->x_updatechild ); - } - - if ( !x->x_nooutput ) outlet_float(x->x_connection, 1); -} - - /* connect using url like "http://localhost:8000/mountpoint" */ -static void mp3amp_connect_url(t_mp3amp *x, t_symbol *url) -{ - char *hostptr = NULL, *p, *endhost = NULL, *hostname = NULL; - char *pathptr = NULL; - t_int portno = 8000; - - post( "mp3amp~ : connect url : %s", url->s_name ); - - /* strip http:// or ftp:// */ - p = url->s_name; - if (strncmp(p, "http://", 7) == 0) - p += 7; - - if (strncmp(p, "ftp://", 6) == 0) - p += 6; - - hostptr = p; - while (*p && *p != '/' && *p != ':') /* look for end of hostname: */ - p++; - - endhost = p; - switch ( *p ) - { - case ':' : - portno = atoi( p+1 ); - while (*p && *p != '/') p++; - pathptr = p+1; - break; - case '/' : - portno = 8000; - pathptr = p+1; - break; - default : - if ( ( p - url->s_name ) != (int)strlen( url->s_name ) ) - { - post( "mp3amp~ : wrong url : %s", hostptr ); - return; - } - pathptr = ""; - break; - } - - hostname=(char*)getbytes( (int)(endhost - hostptr) + 1); - strncpy( hostname, hostptr, (int)(endhost - hostptr) ); - hostname[ endhost - hostptr ] = '\0'; - - post ("mp3amp~ : connecting to host=%s port=%d path=%s", hostname, portno, pathptr ); - - /* call the 'normal' connection routine */ - mp3amp_connect(x, gensym(hostname), gensym(pathptr), portno); -} - - /* close connection to SHOUTcast server */ -static void mp3amp_disconnect(t_mp3amp *x) -{ - x->x_stream = 0; - x->x_inframes = 0; - x->x_dframes = 0; - x->x_inwriteposition = 0; - x->x_offset = 0; - if(x->x_fd >= 0) /* close socket */ - { - sys_closesocket(x->x_fd); - x->x_fd = -1; - } - ExitMP3(&mps[x->x_instance]); - InitMP3(&mps[x->x_instance]); - if ( x->x_graphic ) - { - SYS_VGUI3(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); - SYS_VGUI3(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); - } - post("mp3amp~: connection closed"); - outlet_float(x->x_connection, 0); -} - -static void mp3amp_free(t_mp3amp *x) -{ - if (x->x_fd > 0) { - post( "mp3amp~: closing socket" ); - sys_closesocket(x->x_fd); - x->x_fd = -1; - } - freebytes(x->x_inbuffer, INPUT_BUFFER_SIZE); - freebytes(x->x_outbuffer, OUTPUT_BUFFER_SIZE*sizeof(t_float)); -} - -static void *mp3amp_new(t_floatarg fdographics) -{ - t_mp3amp *x = NULL; - - if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) - { - post( "mp3amp~: error : constructor : mp3amp~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); - return NULL; - } - - x = (t_mp3amp *)pd_new(mp3amp_class); - outlet_new(&x->x_obj, gensym("signal")); - outlet_new(&x->x_obj, gensym("signal")); - x->x_connection = outlet_new(&x->x_obj, gensym("float")); - - if ( nbinstances < MAX_DECODERS ) - { - x->x_instance = nbinstances++; - } - else - { - post( "mp3amp~: cannot create more decoders (memory issues), sorry" ); - return NULL; - } - - x->x_fd = -1; - x->x_stream = 0; - x->x_inframes = 0; - x->x_samplerate = sys_getsr(); - x->x_nbwaitloops = 1; - x->x_nbloops = 0; - x->x_dsp = 0; - - x->x_inbuffersize = INPUT_BUFFER_SIZE; - x->x_outbuffersize = OUTPUT_BUFFER_SIZE; - x->x_inbuffer = (unsigned char*) getbytes(INPUT_BUFFER_SIZE); - x->x_offset = 0; - x->x_outbuffer = (t_float*) getbytes(OUTPUT_BUFFER_SIZE*sizeof(t_float)); - - if ( !x->x_inbuffer || !x->x_outbuffer ) - { - post( "mp3amp~: could not allocate buffers" ); - return NULL; - } - memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); - memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); - - x->x_inwriteposition = 0; - x->x_outreadposition = 0; - x->x_outwriteposition = 0; - x->x_outunread = 0; - x->x_standby = 0; - x->x_resample = -1; - x->x_nooutput = 0; - - ztout.tv_sec = 0; - ztout.tv_usec = 0; - - x->x_graphic = (int)fdographics; - post( "mp3amp~: getting canvas" ); - x->x_canvas = canvas_getcurrent(); - - post( "mp3amp~: initializing decoder..." ); - /* init mpg123 decoder */ - mp3amp_tilde_mpglib_init(x); - - post(mp3amp_version); - - return (x); -} - - -void mp3amp_tilde_setup(void) -{ - mp3amp_class = class_new(gensym("mp3amp~"), - (t_newmethod) mp3amp_new, (t_method) mp3amp_free, - sizeof(t_mp3amp), 0, A_DEFFLOAT, A_NULL); - - class_addmethod(mp3amp_class, nullfn, gensym("signal"), 0); - class_addmethod(mp3amp_class, (t_method)mp3amp_dsp, gensym("dsp"), 0); - class_addmethod(mp3amp_class, (t_method)mp3amp_connect, gensym("connect"), A_SYMBOL, A_SYMBOL, A_FLOAT, 0); - class_addmethod(mp3amp_class, (t_method)mp3amp_connect_url, gensym("connecturl"), A_SYMBOL, 0); - class_addmethod(mp3amp_class, (t_method)mp3amp_standby, gensym("standby"), A_DEFFLOAT, 0); - class_addmethod(mp3amp_class, (t_method)mp3amp_disconnect, gensym("disconnect"), 0); -} diff --git a/mp3amp~/mpglib.h b/mp3amp~/mpglib.h deleted file mode 100644 index 1f4ef9a..0000000 --- a/mp3amp~/mpglib.h +++ /dev/null @@ -1,65 +0,0 @@ -// #include "lame-analysis.h" - -#define NOANALYSIS - -#ifndef NOANALYSIS -extern plotting_data *mpg123_pinfo; -#endif - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -typedef struct mpstr_tag { - struct buf *head,*tail; - int vbr_header; /* 1 if valid Xing vbr header detected */ - int num_frames; /* set if vbr header present */ - int enc_delay; /* set if vbr header present */ - int enc_padding; /* set if vbr header present */ - int header_parsed; - int side_parsed; - int data_parsed; - int free_format; /* 1 = free format frame */ - int old_free_format; /* 1 = last frame was free format */ - int bsize; - int framesize; - int ssize; - int dsize; - int fsizeold; - int fsizeold_nopadding; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; - int sync_bitstream; - -} MPSTR, *PMPSTR; - - -#if ( defined(_MSC_VER) || defined(__BORLANDC__) ) - typedef int BOOL; /* windef.h contains the same definition */ -#else - #define BOOL int -#endif - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - - diff --git a/mp3cast~-help.pd b/mp3cast~-help.pd new file mode 100644 index 0000000..243570a --- /dev/null +++ b/mp3cast~-help.pd @@ -0,0 +1,65 @@ +#N canvas 1180 63 687 606 10; +#X floatatom 53 24 0 40 16000 0 - - -; +#X msg 351 547 \; pd dsp 1; +#X floatatom 48 537 0 0 0 0 - - -; +#X msg 181 88 disconnect; +#X text 266 63 <-- your password for the server; +#X text 317 75 (default passwd is "pd"); +#X text 257 87 <-- close connection; +#X text 313 45 <-- host and port; +#X text 349 218 <-- settings for mp3 stream; +#X text 372 248 bitrate: bitrate of stream \, def. 224kbit/s; +#X text 409 272 1 = joint stereo (default); +#X text 369 310 quality: 1 = high \, 9 = low; +#X text 370 230 (samplerate \, bitrate \, mode \, quality); +#X text 373 260 mode: 0 = stereo; +#X text 409 284 2 = dual channel; +#X text 409 297 3 = mono; +#X msg 6 439 print; +#X msg 417 547 \; pd dsp 0; +#X msg 204 129 icecast; +#X obj 53 51 osc~ 440; +#X msg 211 242 mpeg 8000 8 3 5; +#X msg 212 218 mpeg 44100 128 1 4; +#X obj 350 518 loadbang; +#X text 313 477 Author : Yves Degoyon ( ydegoyon@free.fr ); +#X msg 191 109 shoutcast; +#X msg 212 194 name mystream; +#X text 322 195 name of the stream; +#X text 260 107 <-- choose type of server ( default = icecast ); +#X msg 209 148 icecast2; +#X msg 180 365 isPublic 0; +#X msg 181 387 isPublic 1; +#X text 385 421 <-- stream description; +#X text 265 380 <-- publish stream info in the yellow pages; +#X text 269 438 <-- stream genre; +#X text 338 344 <-- stream url; +#X msg 164 66 passwd pd; +#X msg 151 45 connect localhost 8000; +#X msg 212 172 mountpoint live.mp3; +#X msg 179 343 url http://localhost; +#X msg 180 415 description hardcore; +#X msg 180 439 genre other; +#X text 313 490 Contributor : Ramiro Consentino; +#X obj 48 499 mp3cast~; +#X connect 0 0 19 0; +#X connect 3 0 42 0; +#X connect 16 0 42 0; +#X connect 18 0 42 0; +#X connect 19 0 42 0; +#X connect 19 0 42 1; +#X connect 20 0 42 0; +#X connect 21 0 42 0; +#X connect 22 0 1 0; +#X connect 24 0 42 0; +#X connect 25 0 42 0; +#X connect 28 0 42 0; +#X connect 29 0 42 0; +#X connect 30 0 42 0; +#X connect 35 0 42 0; +#X connect 36 0 42 0; +#X connect 37 0 42 0; +#X connect 38 0 42 0; +#X connect 39 0 42 0; +#X connect 40 0 42 0; +#X connect 42 0 2 0; diff --git a/mp3cast~.c b/mp3cast~.c new file mode 100644 index 0000000..0568443 --- /dev/null +++ b/mp3cast~.c @@ -0,0 +1,970 @@ +/* -------------------------- mp3cast~ ---------------------------------------- */ +/* */ +/* Tilde object to send mp3-stream to shoutcast/icecast server. */ +/* Written by Olaf Matthes (olaf.matthes@gmx.de). */ +/* Get source at http://www.akustische-kunst.de/puredata/ */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ +/* be found at http://www.cdex.n3.net. */ +/* */ +/* ---------------------------------------------------------------------------- */ + + + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include "m_pd.h" /* standard pd stuff */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __APPLE__ +#include +#endif + +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +#include /* lame encoder stuff */ +#include "mpg123.h" + + +#define MY_MP3_MALLOC_IN_SIZE 65536 + /* max size taken from lame readme */ +#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 + +#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ +#define STRBUF_SIZE 1024 + +static char *mp3cast_version = "mp3cast~: mp3 streamer version 0.5, written by Yves Degoyon"; + +static char base64table[65] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', +}; + +static t_class *mp3cast_class; + +typedef struct _mp3cast +{ + t_object x_obj; + + /* LAME stuff */ + int x_lame; /* info about encoder status */ + int x_lamechunk; /* chunk size for LAME encoder */ + int x_mp3size; /* number of returned mp3 samples */ + + /* buffer stuff */ + unsigned short x_inp; /* in position for buffer */ + unsigned short x_outp; /* out position for buffer*/ + short *x_mp3inbuf; /* data to be sent to LAME */ + char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ + short *x_buffer; /* data to be buffered */ + int x_bytesbuffered; /* number of unprocessed bytes in buffer */ + int x_start; + + /* mp3 format stuff */ + int x_samplerate; + int x_bitrate; /* bitrate of mp3 stream */ + int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ + int x_mp3quality; /* quality of encoding */ + + /* SHOUTcast server stuff */ + int x_fd; /* info about connection status */ + char* x_passwd; /* password for server */ + int x_icecast; /* tells if we use a IceCast server or SHOUTcast */ + /* special IceCast server stuff */ + char* x_mountpoint; + char* x_name; + char* x_url; + char* x_genre; + char* x_description; + int x_isPublic; + + t_float x_f; /* float needed for signal input */ + + lame_global_flags *lgfp; /* lame encoder configuration */ + +} t_mp3cast; + + + /* encode PCM data to mp3 stream */ +static void mp3cast_encode(t_mp3cast *x) +{ + unsigned short i, wp; + int err = -1; + int n = x->x_lamechunk; + +#ifdef UNIX + if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) +#else + if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) +#endif + { + error("not enough memory!"); + return; + } + + /* on start/reconnect set outpoint that it not interferes with inpoint */ + if(x->x_start == -1) + { + post("mp3cast~: initialising buffers"); + /* we try to keep 2.5 times the data the encoder needs in the buffer */ + if(x->x_inp > (2 * x->x_lamechunk)) + { + x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); + } + else if(x->x_inp < (2 * x->x_lamechunk)) + { + x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); + } + x->x_start = 1; + } + if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3cast~: buffers overlap!"); + + i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; + + /* read from buffer */ + if(x->x_lamechunk <= i) + { + /* enough data until end of buffer */ + for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ + { + x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; + } + x->x_outp += x->x_lamechunk; + } + else /* split data */ + { + for(wp = 0; wp < i; wp++) /* data at end of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; + } + + for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; + } + x->x_outp = x->x_lamechunk - i; + } + + /* encode mp3 data */ + x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, + x->x_lamechunk/lame_get_num_channels(x->lgfp), + x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + // post( "mp3cast~ : encoding returned %d frames", x->x_mp3size ); + + /* check result */ + if(x->x_mp3size<0) + { + lame_close( x->lgfp ); + error("mp3cast~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); + x->x_lame = -1; + } +} + + + /* stream mp3 to SHOUTcast server */ +static void mp3cast_stream(t_mp3cast *x) +{ + int err = -1, i; /* error return code */ + struct frame hframe; + + err = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, 0); + if(err < 0) + { + error("mp3cast~: could not send encoded data to server (%d)", err); + lame_close( x->lgfp ); + x->x_lame = -1; +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif /* _WIN32 */ + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + } + if((err > 0)&&(err != x->x_mp3size))error("mp3cast~: %d bytes skipped", x->x_mp3size - err); +} + + + /* buffer data as channel interleaved PCM */ +static t_int *mp3cast_perform(t_int *w) +{ + t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ + t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ + t_mp3cast *x = (t_mp3cast *)(w[3]); + int n = (int)(w[4]); /* number of samples */ + unsigned short i,wp; + float in; + + /* copy the data into the buffer */ + i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ + + n *= 2; /* two channels go into one buffer */ + + if( n <= i ) + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ + /* is big enough to hold the data */ + + for(wp = 0; wp < n; wp++) + { + if(wp%2) + { + in = *(in2++); /* right channel / inlet */ + } + else + { + in = *(in1++); /* left channel / inlet */ + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + x->x_inp += n; /* n more samples written to buffer */ + } + else + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ + /* big enough to hold the data */ + /* writing will take place in two turns, one from */ + /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ + + for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + for(wp = i; wp < n; wp++) /* write rest at start of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp - i] = (short) (32767.0 * in); + } + x->x_inp = n - i; /* new writeposition in buffer */ + } + + if((x->x_fd >= 0)&&(x->x_lame >= 0)) + { + /* count buffered samples when things are running */ + x->x_bytesbuffered += n; + + /* encode and send to server */ + if(x->x_bytesbuffered > x->x_lamechunk) + { + mp3cast_encode(x); /* encode to mp3 */ + mp3cast_stream(x); /* stream mp3 to server */ + x->x_bytesbuffered -= x->x_lamechunk; + } + } + else + { + x->x_start = -1; + } + return (w+5); +} + +static void mp3cast_dsp(t_mp3cast *x, t_signal **sp) +{ + dsp_add(mp3cast_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + + /* initialize the lame library */ +static void mp3cast_tilde_lame_init(t_mp3cast *x) +{ + int ret; + x->lgfp = lame_init(); /* set default parameters for now */ + +#ifdef _WIN32 + /* load lame_enc.dll library */ + HINSTANCE dll; + dll=LoadLibrary("lame_enc.dll"); + if(!dll) + { + error("mp3cast~: error loading lame_enc.dll"); + closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("mp3cast~: connection closed"); + return; + } +#endif /* _WIN32 */ + { + const char *lameVersion = get_lame_version(); + post( "mp3cast~ : using lame version : %s", lameVersion ); + } + + + /* setting lame parameters */ + lame_set_num_channels( x->lgfp, 2); + lame_set_in_samplerate( x->lgfp, sys_getsr() ); + lame_set_out_samplerate( x->lgfp, x->x_samplerate ); + lame_set_brate( x->lgfp, x->x_bitrate ); + lame_set_mode( x->lgfp, x->x_mp3mode ); + lame_set_quality( x->lgfp, x->x_mp3quality ); + lame_set_emphasis( x->lgfp, 1 ); + lame_set_original( x->lgfp, 1 ); + lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ + lame_set_disable_reservoir( x->lgfp, 0 ); + lame_set_padding_type( x->lgfp, PAD_NO ); + ret = lame_init_params( x->lgfp ); + if ( ret<0 ) { + post( "mp3cast~ : error : lame params initialization returned : %d", ret ); + } else { + x->x_lame=1; + /* magic formula copied from windows dll for MPEG-I */ + x->x_lamechunk = 2*1152; + + post( "mp3cast~ : lame initialization done. (%d)", x->x_lame ); + } + lame_init_bitstream( x->lgfp ); +} + +char *mp3cast_base64_encode(char *data) +{ + int len = strlen(data); + char *out = t_getbytes(len*4/3 + 4); + char *result = out; + int chunk; + + while(len > 0) { + chunk = (len >3)?3:len; + *out++ = base64table[(*data & 0xFC)>>2]; + *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)]; + + switch(chunk) { + case 3: + *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)]; + *out++ = base64table[(*(data+2)) & 0x3F]; + break; + case 2: + *out++ = base64table[((*(data+1) & 0x0F)<<2)]; + *out++ = '='; + break; + case 1: + *out++ = '='; + *out++ = '='; + break; + } + data += chunk; + len -= chunk; + } + *out = 0; + + return result; +} + + /* connect to server */ +static void mp3cast_connect(t_mp3cast *x, t_symbol *hostname, t_floatarg fportno) +{ + struct sockaddr_in server; + struct hostent *hp; + int portno = fportno; /* get port from message box */ + + /* information about this broadcast to be send to the server */ + const char *name = x->x_name; /* name of broadcast */ + const char *url = x->x_url; /* url of broadcast */ + const char *genre = x->x_genre; /* genre of broadcast */ + const char *description = x->x_description; /* description of broadcast */ + const char *aim = "N/A"; /* aim of broadcast */ + const char *irc = "#mp3cast"; /* ??? what's this ??? */ + const char *icq = ""; /* icq id of broadcaster */ + const char *mountpoint = x->x_mountpoint; /* mountpoint for IceCast server */ + int isPublic = x->x_isPublic; /* don't publish broadcast on www.shoutcast.com */ + + /* variables used for communication with server */ + const char * buf = 0; + char resp[STRBUF_SIZE]; + unsigned int len; + fd_set fdset; + struct timeval tv; + int sockfd; + int ret; + + if(x->x_icecast == 0)portno++; /* use SHOUTcast, portno is one higher */ + + if (x->x_fd >= 0) + { + error("mp3cast~: already connected"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("mp3cast~: internal error while attempting to open socket"); + return; + } + + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("mp3cast~: bad host?"); + close(sockfd); + return; + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("mp3cast~: connecting to port %d", portno); + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + error("mp3cast~: connection failed!\n"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif /* _WIN32 */ + return; + } + + /* sheck if we can read/write from/to the socket */ + FD_ZERO( &fdset); + FD_SET( sockfd, &fdset); + tv.tv_sec = 0; /* seconds */ + tv.tv_usec = 500; /* microseconds */ + + ret = select(sockfd + 1, &fdset, NULL, NULL, &tv); + if(ret < 0) + { + error("mp3cast~: can not read from socket"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif /* _WIN32 */ + return; + } +#ifndef _WIN32 + ret = select(sockfd + 1, NULL, &fdset, NULL, &tv); + if(ret < 0) + { + error("mp3cast~: can not write to socket"); + close(sockfd); + return; + } +#endif /* not _WIN32 */ + + if(x->x_icecast == 0) /* SHOUTCAST */ + { + /* now try to log in at SHOUTcast server */ + post("mp3cast~: logging in to SHOUTcast server..."); + + /* first line is the passwd */ + buf = x->x_passwd; + send(sockfd, buf, strlen(buf), 0); + buf = "\n"; + send(sockfd, buf, strlen(buf), 0); + + /* header for SHOUTcast server */ + buf = "icy-name:"; /* name of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = name; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-url:"; /* URL of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = url; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nicy-genre:"; /* genre of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = genre; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nicy-description:"; /* description of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = description; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nicy-irc:"; + send(sockfd, buf, strlen(buf), 0); + buf = irc; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-aim:"; + send(sockfd, buf, strlen(buf), 0); + buf = aim; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-icq:"; + send(sockfd, buf, strlen(buf), 0); + buf = icq; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-br:"; + send(sockfd, buf, strlen(buf), 0); + if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ + { + error("mp3cast~: wrong bitrate"); + } + send(sockfd, resp, strlen(resp), 0); + buf = "\nicy-pub:"; + send(sockfd, buf, strlen(buf), 0); + if(isPublic==0) /* set the public flag for broadcast */ + { + buf = "no"; + } + else + { + buf ="yes"; + } + send(sockfd, buf, strlen(buf), 0); + buf = "\n\n"; + send(sockfd, buf, strlen(buf), 0); + } + else if ( x->x_icecast == 1 ) /* IceCast */ + { + /* now try to log in at IceCast server */ + post("mp3cast~: logging in to IceCast server..."); + + /* send the request, a string like: + * "SOURCE /\n" */ + buf = "SOURCE "; + send(sockfd, buf, strlen(buf), 0); + buf = x->x_passwd; + send(sockfd, buf, strlen(buf), 0); + buf = " /"; + send(sockfd, buf, strlen(buf), 0); + buf = mountpoint; + send(sockfd, buf, strlen(buf), 0); + + /* send the x-audiocast headers */ + buf = "\nx-audiocast-bitrate: "; + send(sockfd, buf, strlen(buf), 0); + if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ + { + error("mp3cast~: wrong bitrate"); + } + send(sockfd, resp, strlen(resp), 0); + + buf = "\nx-audiocast-public: "; + send(sockfd, buf, strlen(buf), 0); + if(isPublic==0) /* set the public flag for broadcast */ + { + buf = "no"; + } + else + { + buf ="yes"; + } + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-name: "; + send(sockfd, buf, strlen(buf), 0); + buf = name; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-url: "; + send(sockfd, buf, strlen(buf), 0); + buf = url; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-genre: "; + send(sockfd, buf, strlen(buf), 0); + buf = genre; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-description: "; + send(sockfd, buf, strlen(buf), 0); + buf = description; + send(sockfd, buf, strlen(buf), 0); + + buf = "\n\n"; + send(sockfd, buf, strlen(buf), 0); + /* end login for IceCast */ + } + else if ( x->x_icecast == 2 ) /* Icecast 2 */ + { + char *base64; /* buffer to hold 64bit encoded strings */ + /* send the request, a string like: "SOURCE / HTTP/1.0\r\n" */ + buf = "SOURCE /"; + send(sockfd, buf, strlen(buf), 0); + buf = x->x_mountpoint; + send(sockfd, buf, strlen(buf), 0); + buf = " HTTP/1.0\r\n"; + send(sockfd, buf, strlen(buf), 0); + /* send basic authorization as base64 encoded string */ + sprintf(resp, "source:%s", x->x_passwd); + len = strlen(resp); + base64 = mp3cast_base64_encode(resp); + sprintf(resp, "Authorization: Basic %s\r\n", base64); + send(sockfd, resp, strlen(resp), 0); + t_freebytes(base64, len*4/3 + 4); + /* send application name */ + buf = "User-Agent: mp3cast~"; + send(sockfd, buf, strlen(buf), 0); + /* send content type: mpeg */ + buf = "\r\nContent-Type: audio/mpeg"; + send(sockfd, buf, strlen(buf), 0); + /* send the ice headers */ + /* name */ + buf = "\r\nice-name: "; + send(sockfd, buf, strlen(buf), 0); + buf = x->x_name; + send(sockfd, buf, strlen(buf), 0); + /* url */ + buf = "\r\nice-url: "; + send(sockfd, buf, strlen(buf), 0); + buf = x->x_url; + send(sockfd, buf, strlen(buf), 0); + /* genre */ + buf = "\r\nice-genre: "; + send(sockfd, buf, strlen(buf), 0); + buf = genre; + send(sockfd, buf, strlen(buf), 0); + /* public */ + buf = "\r\nice-public: "; + send(sockfd, buf, strlen(buf), 0); + if(isPublic==0) + { + buf = "0"; + } + else + { + buf = "1"; + } + send(sockfd, buf, strlen(buf), 0); + /* bitrate */ + if(sprintf(resp, "\r\nice-audio-info: bitrate=%d", x->x_bitrate) == -1) + { + error("shoutcast~: could not create audio-info"); + } + send(sockfd, resp, strlen(resp), 0); + /* description */ + buf = "\r\nice-description: "; + send(sockfd, buf, strlen(buf), 0); + buf = description; + send(sockfd, buf, strlen(buf), 0); + /* end of header: write an empty line */ + buf = "\r\n\r\n"; + send(sockfd, buf, strlen(buf), 0); + } + + /* read the anticipated response: "OK" */ + len = recv(sockfd, resp, STRBUF_SIZE, 0); + if ( strstr( resp, "OK" ) == NULL ) + { + post("mp3cast~: login failed!"); + if ( len>0 ) post("mp3cast~: server answered : %s", resp); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif /* _WIN32 */ + return; + } + + /* suck anything that the other side has to say */ + // while (len = recv(sockfd, resp, STRBUF_SIZE,0)) + // { + // post("mp3cast~: server answered : %s", resp); + // } + + x->x_fd = sockfd; + outlet_float(x->x_obj.ob_outlet, 1); + post("mp3cast~: logged in to %s", hp->h_name); + + mp3cast_tilde_lame_init(x); + +} + + /* close connection to SHOUTcast server */ +static void mp3cast_disconnect(t_mp3cast *x) +{ + int err = -1; + if(x->x_lame >= 0) + { + /* ignore remaining bytes */ + if ( x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, 0) < 0 ) { + post( "mp3cast~ : warning : remaining encoded bytes" ); + } + lame_close( x->lgfp ); + + x->x_lame = -1; + post("mp3cast~: encoder stream closed"); + } + + if(x->x_fd >= 0) /* close socket */ + { +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif /* _WIN32 */ + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("mp3cast~: connection closed"); + } +} + + /* set password for SHOUTcast server */ +static void mp3cast_password(t_mp3cast *x, t_symbol *password) +{ + post("mp3cast~ : setting password to %s", password->s_name ); + x->x_passwd = password->s_name; +} + + /* settings for mp3 encoding */ +static void mp3cast_mpeg(t_mp3cast *x, t_floatarg fsamplerate, t_floatarg fbitrate, + t_floatarg fmode, t_floatarg fquality) +{ + x->x_samplerate = fsamplerate; + if(fbitrate > MAXDATARATE) + { + fbitrate = MAXDATARATE; + } + x->x_bitrate = fbitrate; + x->x_mp3mode = fmode; + x->x_mp3quality = fquality; + post("mp3cast~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", + x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); + if(x->x_fd>=0)post("mp3cast~ : reconnect to make changes take effect! "); +} + + /* print settings */ +static void mp3cast_print(t_mp3cast *x) +{ + const char * buf = 0; + post(mp3cast_version); + post(" LAME mp3 settings:\n" + " output sample rate: %d Hz\n" + " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); + switch(x->x_mp3mode) + { + case 0 : + buf = "stereo"; + break; + case 1 : + buf = "joint stereo"; + break; + case 2 : + buf = "dual channel"; + break; + case 3 : + buf = "mono"; + break; + } + post(" mode: %s\n" + " quality: %d", buf, x->x_mp3quality); + post(" mp3 chunk size: %d", x->x_lamechunk); + if(x->x_samplerate!=sys_getsr()) + { + post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); + } + + if ( x->x_icecast == 0) + { + post(" server type is SHOUTcast"); + } + else if ( x->x_icecast == 1 ) + { + post(" server type is IceCast"); + } + else if ( x->x_icecast == 2 ) + { + post(" server type is IceCast 2"); + } +} + +static void mp3cast_icecast(t_mp3cast *x) +{ + x->x_icecast = 1; + post("mp3cast~: set server type to IceCast"); +} + +static void mp3cast_icecast2(t_mp3cast *x) +{ + x->x_icecast = 2; + post("mp3cast~: set server type to IceCast 2"); +} + +static void mp3cast_shoutcast(t_mp3cast *x) +{ + x->x_icecast = 0; + post("mp3cast~: set server type to SHOUTcast"); +} + + /* set mountpoint for IceCast server */ +static void mp3cast_mountpoint(t_mp3cast *x, t_symbol *mount) +{ + x->x_mountpoint = mount->s_name; + post("mp3cast~: mountpoint set to %s", x->x_mountpoint); +} + + /* set namle for IceCast server */ +static void mp3cast_name(t_mp3cast *x, t_symbol *name) +{ + x->x_name = name->s_name; + post("mp3cast~: name set to %s", x->x_name); +} + + /* set url for IceCast server */ +static void mp3cast_url(t_mp3cast *x, t_symbol *url) +{ + x->x_url = url->s_name; + post("mp3cast~: url set to %s", x->x_url); +} + + /* set genre for IceCast server */ +static void mp3cast_genre(t_mp3cast *x, t_symbol *genre) +{ + x->x_genre = genre->s_name; + post("mp3cast~: genre set to %s", x->x_genre); +} + + /* set isPublic for IceCast server */ +static void mp3cast_isPublic(t_mp3cast *x, t_floatarg isPublic) +{ + x->x_isPublic = isPublic; + char* isPublicStr; + if(isPublic==0) + { + isPublicStr = "no"; + } + else + { + isPublicStr = "yes"; + } + post("mp3cast~: isPublic set to %s", isPublicStr); +} + + /* set description for IceCast server */ +static void mp3cast_description(t_mp3cast *x, t_symbol *description) +{ + x->x_description = description->s_name; + post("mp3cast~: description set to %s", x->x_description); +} + + /* clean up */ +static void mp3cast_free(t_mp3cast *x) +{ + if(x->x_lame >= 0) + lame_close( x->lgfp ); + if(x->x_fd >= 0) +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif /* _WIN32 */ + freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); + freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); +} + +static void *mp3cast_new(void) +{ + t_mp3cast *x = (t_mp3cast *)pd_new(mp3cast_class); + inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); + outlet_new(&x->x_obj, gensym("float")); + x->x_fd = -1; + x->x_lame = -1; + x->x_passwd = "pd"; + x->x_samplerate = sys_getsr(); + x->x_bitrate = 224; + x->x_mp3mode = 1; + x->x_mp3quality = 5; + x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ + x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE*sizeof(char)); /* our mp3 stream */ + x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ + if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ + { + error("out of memory!"); + } + x->x_bytesbuffered = 0; + x->x_inp = 0; + x->x_outp = 0; + x->lgfp = NULL; + x->x_start = -1; + x->x_icecast = 1; + x->x_mountpoint = "puredata"; + x->x_name = "puredata"; + x->x_url = "http://puredata.info"; + x->x_genre = "experimental sound"; + x->x_isPublic = 1; + x->x_description = "playing with my patches"; + return(x); +} + +void mp3cast_tilde_setup(void) +{ + post(mp3cast_version); + mp3cast_class = class_new(gensym("mp3cast~"), (t_newmethod)mp3cast_new, (t_method)mp3cast_free, + sizeof(t_mp3cast), 0, 0); + CLASS_MAINSIGNALIN(mp3cast_class, t_mp3cast, x_f ); + class_addmethod(mp3cast_class, (t_method)mp3cast_dsp, gensym("dsp"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_disconnect, gensym("disconnect"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_password, gensym("passwd"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_print, gensym("print"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_icecast, gensym("icecast"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_icecast2, gensym("icecast2"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_shoutcast, gensym("shoutcast"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_mountpoint, gensym("mountpoint"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_name, gensym("name"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_url, gensym("url"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_genre, gensym("genre"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_isPublic, gensym("isPublic"), A_FLOAT, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_description, gensym("description"), A_SYMBOL, 0); +} + diff --git a/mp3cast~/INSTALL b/mp3cast~/INSTALL deleted file mode 100644 index 769e78e..0000000 --- a/mp3cast~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -You need to get lame > v3.90 installed first. -libmp3lame.so is searched in /usr/local/lib -( no time to write configure scripts ). -if it's installed elsewhere, change the Makefile, -you won't die from that. - -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/mp3cast~ - -make -f Makefile.linux - -make -f Makefile.linux install - -you're set !! diff --git a/mp3cast~/interface.h b/mp3cast~/interface.h deleted file mode 100644 index de3136a..0000000 --- a/mp3cast~/interface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Copyright (C) 2000 Albert L. Faber -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef INTERFACE_H_INCLUDED -#define INTERFACE_H_INCLUDED - -// #include "common.h" -#include "interface.h" - -BOOL InitMP3(PMPSTR mp); -int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done); -void ExitMP3(PMPSTR mp); - -/* added remove_buf to support mpglib seeking */ -void remove_buf(PMPSTR mp); - -#endif diff --git a/mp3cast~/mp3cast~-help.pd b/mp3cast~/mp3cast~-help.pd deleted file mode 100644 index 243570a..0000000 --- a/mp3cast~/mp3cast~-help.pd +++ /dev/null @@ -1,65 +0,0 @@ -#N canvas 1180 63 687 606 10; -#X floatatom 53 24 0 40 16000 0 - - -; -#X msg 351 547 \; pd dsp 1; -#X floatatom 48 537 0 0 0 0 - - -; -#X msg 181 88 disconnect; -#X text 266 63 <-- your password for the server; -#X text 317 75 (default passwd is "pd"); -#X text 257 87 <-- close connection; -#X text 313 45 <-- host and port; -#X text 349 218 <-- settings for mp3 stream; -#X text 372 248 bitrate: bitrate of stream \, def. 224kbit/s; -#X text 409 272 1 = joint stereo (default); -#X text 369 310 quality: 1 = high \, 9 = low; -#X text 370 230 (samplerate \, bitrate \, mode \, quality); -#X text 373 260 mode: 0 = stereo; -#X text 409 284 2 = dual channel; -#X text 409 297 3 = mono; -#X msg 6 439 print; -#X msg 417 547 \; pd dsp 0; -#X msg 204 129 icecast; -#X obj 53 51 osc~ 440; -#X msg 211 242 mpeg 8000 8 3 5; -#X msg 212 218 mpeg 44100 128 1 4; -#X obj 350 518 loadbang; -#X text 313 477 Author : Yves Degoyon ( ydegoyon@free.fr ); -#X msg 191 109 shoutcast; -#X msg 212 194 name mystream; -#X text 322 195 name of the stream; -#X text 260 107 <-- choose type of server ( default = icecast ); -#X msg 209 148 icecast2; -#X msg 180 365 isPublic 0; -#X msg 181 387 isPublic 1; -#X text 385 421 <-- stream description; -#X text 265 380 <-- publish stream info in the yellow pages; -#X text 269 438 <-- stream genre; -#X text 338 344 <-- stream url; -#X msg 164 66 passwd pd; -#X msg 151 45 connect localhost 8000; -#X msg 212 172 mountpoint live.mp3; -#X msg 179 343 url http://localhost; -#X msg 180 415 description hardcore; -#X msg 180 439 genre other; -#X text 313 490 Contributor : Ramiro Consentino; -#X obj 48 499 mp3cast~; -#X connect 0 0 19 0; -#X connect 3 0 42 0; -#X connect 16 0 42 0; -#X connect 18 0 42 0; -#X connect 19 0 42 0; -#X connect 19 0 42 1; -#X connect 20 0 42 0; -#X connect 21 0 42 0; -#X connect 22 0 1 0; -#X connect 24 0 42 0; -#X connect 25 0 42 0; -#X connect 28 0 42 0; -#X connect 29 0 42 0; -#X connect 30 0 42 0; -#X connect 35 0 42 0; -#X connect 36 0 42 0; -#X connect 37 0 42 0; -#X connect 38 0 42 0; -#X connect 39 0 42 0; -#X connect 40 0 42 0; -#X connect 42 0 2 0; diff --git a/mp3cast~/mp3cast~.c b/mp3cast~/mp3cast~.c deleted file mode 100644 index 0568443..0000000 --- a/mp3cast~/mp3cast~.c +++ /dev/null @@ -1,970 +0,0 @@ -/* -------------------------- mp3cast~ ---------------------------------------- */ -/* */ -/* Tilde object to send mp3-stream to shoutcast/icecast server. */ -/* Written by Olaf Matthes (olaf.matthes@gmx.de). */ -/* Get source at http://www.akustische-kunst.de/puredata/ */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ -/* be found at http://www.cdex.n3.net. */ -/* */ -/* ---------------------------------------------------------------------------- */ - - - -#ifdef _MSC_VER -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4305 ) -#endif - -#include "m_pd.h" /* standard pd stuff */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef __APPLE__ -#include -#endif - -#ifdef _WIN32 -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif - -#include /* lame encoder stuff */ -#include "mpg123.h" - - -#define MY_MP3_MALLOC_IN_SIZE 65536 - /* max size taken from lame readme */ -#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 - -#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ -#define STRBUF_SIZE 1024 - -static char *mp3cast_version = "mp3cast~: mp3 streamer version 0.5, written by Yves Degoyon"; - -static char base64table[65] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', -}; - -static t_class *mp3cast_class; - -typedef struct _mp3cast -{ - t_object x_obj; - - /* LAME stuff */ - int x_lame; /* info about encoder status */ - int x_lamechunk; /* chunk size for LAME encoder */ - int x_mp3size; /* number of returned mp3 samples */ - - /* buffer stuff */ - unsigned short x_inp; /* in position for buffer */ - unsigned short x_outp; /* out position for buffer*/ - short *x_mp3inbuf; /* data to be sent to LAME */ - char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ - short *x_buffer; /* data to be buffered */ - int x_bytesbuffered; /* number of unprocessed bytes in buffer */ - int x_start; - - /* mp3 format stuff */ - int x_samplerate; - int x_bitrate; /* bitrate of mp3 stream */ - int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ - int x_mp3quality; /* quality of encoding */ - - /* SHOUTcast server stuff */ - int x_fd; /* info about connection status */ - char* x_passwd; /* password for server */ - int x_icecast; /* tells if we use a IceCast server or SHOUTcast */ - /* special IceCast server stuff */ - char* x_mountpoint; - char* x_name; - char* x_url; - char* x_genre; - char* x_description; - int x_isPublic; - - t_float x_f; /* float needed for signal input */ - - lame_global_flags *lgfp; /* lame encoder configuration */ - -} t_mp3cast; - - - /* encode PCM data to mp3 stream */ -static void mp3cast_encode(t_mp3cast *x) -{ - unsigned short i, wp; - int err = -1; - int n = x->x_lamechunk; - -#ifdef UNIX - if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) -#else - if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) -#endif - { - error("not enough memory!"); - return; - } - - /* on start/reconnect set outpoint that it not interferes with inpoint */ - if(x->x_start == -1) - { - post("mp3cast~: initialising buffers"); - /* we try to keep 2.5 times the data the encoder needs in the buffer */ - if(x->x_inp > (2 * x->x_lamechunk)) - { - x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); - } - else if(x->x_inp < (2 * x->x_lamechunk)) - { - x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); - } - x->x_start = 1; - } - if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3cast~: buffers overlap!"); - - i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; - - /* read from buffer */ - if(x->x_lamechunk <= i) - { - /* enough data until end of buffer */ - for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ - { - x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; - } - x->x_outp += x->x_lamechunk; - } - else /* split data */ - { - for(wp = 0; wp < i; wp++) /* data at end of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; - } - - for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; - } - x->x_outp = x->x_lamechunk - i; - } - - /* encode mp3 data */ - x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, - x->x_lamechunk/lame_get_num_channels(x->lgfp), - x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - // post( "mp3cast~ : encoding returned %d frames", x->x_mp3size ); - - /* check result */ - if(x->x_mp3size<0) - { - lame_close( x->lgfp ); - error("mp3cast~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); - x->x_lame = -1; - } -} - - - /* stream mp3 to SHOUTcast server */ -static void mp3cast_stream(t_mp3cast *x) -{ - int err = -1, i; /* error return code */ - struct frame hframe; - - err = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, 0); - if(err < 0) - { - error("mp3cast~: could not send encoded data to server (%d)", err); - lame_close( x->lgfp ); - x->x_lame = -1; -#ifdef _WIN32 - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif /* _WIN32 */ - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - } - if((err > 0)&&(err != x->x_mp3size))error("mp3cast~: %d bytes skipped", x->x_mp3size - err); -} - - - /* buffer data as channel interleaved PCM */ -static t_int *mp3cast_perform(t_int *w) -{ - t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ - t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ - t_mp3cast *x = (t_mp3cast *)(w[3]); - int n = (int)(w[4]); /* number of samples */ - unsigned short i,wp; - float in; - - /* copy the data into the buffer */ - i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ - - n *= 2; /* two channels go into one buffer */ - - if( n <= i ) - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ - /* is big enough to hold the data */ - - for(wp = 0; wp < n; wp++) - { - if(wp%2) - { - in = *(in2++); /* right channel / inlet */ - } - else - { - in = *(in1++); /* left channel / inlet */ - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - x->x_inp += n; /* n more samples written to buffer */ - } - else - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ - /* big enough to hold the data */ - /* writing will take place in two turns, one from */ - /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ - - for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - for(wp = i; wp < n; wp++) /* write rest at start of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp - i] = (short) (32767.0 * in); - } - x->x_inp = n - i; /* new writeposition in buffer */ - } - - if((x->x_fd >= 0)&&(x->x_lame >= 0)) - { - /* count buffered samples when things are running */ - x->x_bytesbuffered += n; - - /* encode and send to server */ - if(x->x_bytesbuffered > x->x_lamechunk) - { - mp3cast_encode(x); /* encode to mp3 */ - mp3cast_stream(x); /* stream mp3 to server */ - x->x_bytesbuffered -= x->x_lamechunk; - } - } - else - { - x->x_start = -1; - } - return (w+5); -} - -static void mp3cast_dsp(t_mp3cast *x, t_signal **sp) -{ - dsp_add(mp3cast_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); -} - - /* initialize the lame library */ -static void mp3cast_tilde_lame_init(t_mp3cast *x) -{ - int ret; - x->lgfp = lame_init(); /* set default parameters for now */ - -#ifdef _WIN32 - /* load lame_enc.dll library */ - HINSTANCE dll; - dll=LoadLibrary("lame_enc.dll"); - if(!dll) - { - error("mp3cast~: error loading lame_enc.dll"); - closesocket(x->x_fd); - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - post("mp3cast~: connection closed"); - return; - } -#endif /* _WIN32 */ - { - const char *lameVersion = get_lame_version(); - post( "mp3cast~ : using lame version : %s", lameVersion ); - } - - - /* setting lame parameters */ - lame_set_num_channels( x->lgfp, 2); - lame_set_in_samplerate( x->lgfp, sys_getsr() ); - lame_set_out_samplerate( x->lgfp, x->x_samplerate ); - lame_set_brate( x->lgfp, x->x_bitrate ); - lame_set_mode( x->lgfp, x->x_mp3mode ); - lame_set_quality( x->lgfp, x->x_mp3quality ); - lame_set_emphasis( x->lgfp, 1 ); - lame_set_original( x->lgfp, 1 ); - lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ - lame_set_disable_reservoir( x->lgfp, 0 ); - lame_set_padding_type( x->lgfp, PAD_NO ); - ret = lame_init_params( x->lgfp ); - if ( ret<0 ) { - post( "mp3cast~ : error : lame params initialization returned : %d", ret ); - } else { - x->x_lame=1; - /* magic formula copied from windows dll for MPEG-I */ - x->x_lamechunk = 2*1152; - - post( "mp3cast~ : lame initialization done. (%d)", x->x_lame ); - } - lame_init_bitstream( x->lgfp ); -} - -char *mp3cast_base64_encode(char *data) -{ - int len = strlen(data); - char *out = t_getbytes(len*4/3 + 4); - char *result = out; - int chunk; - - while(len > 0) { - chunk = (len >3)?3:len; - *out++ = base64table[(*data & 0xFC)>>2]; - *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)]; - - switch(chunk) { - case 3: - *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)]; - *out++ = base64table[(*(data+2)) & 0x3F]; - break; - case 2: - *out++ = base64table[((*(data+1) & 0x0F)<<2)]; - *out++ = '='; - break; - case 1: - *out++ = '='; - *out++ = '='; - break; - } - data += chunk; - len -= chunk; - } - *out = 0; - - return result; -} - - /* connect to server */ -static void mp3cast_connect(t_mp3cast *x, t_symbol *hostname, t_floatarg fportno) -{ - struct sockaddr_in server; - struct hostent *hp; - int portno = fportno; /* get port from message box */ - - /* information about this broadcast to be send to the server */ - const char *name = x->x_name; /* name of broadcast */ - const char *url = x->x_url; /* url of broadcast */ - const char *genre = x->x_genre; /* genre of broadcast */ - const char *description = x->x_description; /* description of broadcast */ - const char *aim = "N/A"; /* aim of broadcast */ - const char *irc = "#mp3cast"; /* ??? what's this ??? */ - const char *icq = ""; /* icq id of broadcaster */ - const char *mountpoint = x->x_mountpoint; /* mountpoint for IceCast server */ - int isPublic = x->x_isPublic; /* don't publish broadcast on www.shoutcast.com */ - - /* variables used for communication with server */ - const char * buf = 0; - char resp[STRBUF_SIZE]; - unsigned int len; - fd_set fdset; - struct timeval tv; - int sockfd; - int ret; - - if(x->x_icecast == 0)portno++; /* use SHOUTcast, portno is one higher */ - - if (x->x_fd >= 0) - { - error("mp3cast~: already connected"); - return; - } - - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - error("mp3cast~: internal error while attempting to open socket"); - return; - } - - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) - { - post("mp3cast~: bad host?"); - close(sockfd); - return; - } - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - server.sin_port = htons((unsigned short)portno); - - /* try to connect. */ - post("mp3cast~: connecting to port %d", portno); - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - error("mp3cast~: connection failed!\n"); -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif /* _WIN32 */ - return; - } - - /* sheck if we can read/write from/to the socket */ - FD_ZERO( &fdset); - FD_SET( sockfd, &fdset); - tv.tv_sec = 0; /* seconds */ - tv.tv_usec = 500; /* microseconds */ - - ret = select(sockfd + 1, &fdset, NULL, NULL, &tv); - if(ret < 0) - { - error("mp3cast~: can not read from socket"); -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif /* _WIN32 */ - return; - } -#ifndef _WIN32 - ret = select(sockfd + 1, NULL, &fdset, NULL, &tv); - if(ret < 0) - { - error("mp3cast~: can not write to socket"); - close(sockfd); - return; - } -#endif /* not _WIN32 */ - - if(x->x_icecast == 0) /* SHOUTCAST */ - { - /* now try to log in at SHOUTcast server */ - post("mp3cast~: logging in to SHOUTcast server..."); - - /* first line is the passwd */ - buf = x->x_passwd; - send(sockfd, buf, strlen(buf), 0); - buf = "\n"; - send(sockfd, buf, strlen(buf), 0); - - /* header for SHOUTcast server */ - buf = "icy-name:"; /* name of broadcast */ - send(sockfd, buf, strlen(buf), 0); - buf = name; - send(sockfd, buf, strlen(buf), 0); - buf = "\nicy-url:"; /* URL of broadcast */ - send(sockfd, buf, strlen(buf), 0); - buf = url; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nicy-genre:"; /* genre of broadcast */ - send(sockfd, buf, strlen(buf), 0); - buf = genre; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nicy-description:"; /* description of broadcast */ - send(sockfd, buf, strlen(buf), 0); - buf = description; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nicy-irc:"; - send(sockfd, buf, strlen(buf), 0); - buf = irc; - send(sockfd, buf, strlen(buf), 0); - buf = "\nicy-aim:"; - send(sockfd, buf, strlen(buf), 0); - buf = aim; - send(sockfd, buf, strlen(buf), 0); - buf = "\nicy-icq:"; - send(sockfd, buf, strlen(buf), 0); - buf = icq; - send(sockfd, buf, strlen(buf), 0); - buf = "\nicy-br:"; - send(sockfd, buf, strlen(buf), 0); - if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ - { - error("mp3cast~: wrong bitrate"); - } - send(sockfd, resp, strlen(resp), 0); - buf = "\nicy-pub:"; - send(sockfd, buf, strlen(buf), 0); - if(isPublic==0) /* set the public flag for broadcast */ - { - buf = "no"; - } - else - { - buf ="yes"; - } - send(sockfd, buf, strlen(buf), 0); - buf = "\n\n"; - send(sockfd, buf, strlen(buf), 0); - } - else if ( x->x_icecast == 1 ) /* IceCast */ - { - /* now try to log in at IceCast server */ - post("mp3cast~: logging in to IceCast server..."); - - /* send the request, a string like: - * "SOURCE /\n" */ - buf = "SOURCE "; - send(sockfd, buf, strlen(buf), 0); - buf = x->x_passwd; - send(sockfd, buf, strlen(buf), 0); - buf = " /"; - send(sockfd, buf, strlen(buf), 0); - buf = mountpoint; - send(sockfd, buf, strlen(buf), 0); - - /* send the x-audiocast headers */ - buf = "\nx-audiocast-bitrate: "; - send(sockfd, buf, strlen(buf), 0); - if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ - { - error("mp3cast~: wrong bitrate"); - } - send(sockfd, resp, strlen(resp), 0); - - buf = "\nx-audiocast-public: "; - send(sockfd, buf, strlen(buf), 0); - if(isPublic==0) /* set the public flag for broadcast */ - { - buf = "no"; - } - else - { - buf ="yes"; - } - send(sockfd, buf, strlen(buf), 0); - - buf = "\nx-audiocast-name: "; - send(sockfd, buf, strlen(buf), 0); - buf = name; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nx-audiocast-url: "; - send(sockfd, buf, strlen(buf), 0); - buf = url; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nx-audiocast-genre: "; - send(sockfd, buf, strlen(buf), 0); - buf = genre; - send(sockfd, buf, strlen(buf), 0); - - buf = "\nx-audiocast-description: "; - send(sockfd, buf, strlen(buf), 0); - buf = description; - send(sockfd, buf, strlen(buf), 0); - - buf = "\n\n"; - send(sockfd, buf, strlen(buf), 0); - /* end login for IceCast */ - } - else if ( x->x_icecast == 2 ) /* Icecast 2 */ - { - char *base64; /* buffer to hold 64bit encoded strings */ - /* send the request, a string like: "SOURCE / HTTP/1.0\r\n" */ - buf = "SOURCE /"; - send(sockfd, buf, strlen(buf), 0); - buf = x->x_mountpoint; - send(sockfd, buf, strlen(buf), 0); - buf = " HTTP/1.0\r\n"; - send(sockfd, buf, strlen(buf), 0); - /* send basic authorization as base64 encoded string */ - sprintf(resp, "source:%s", x->x_passwd); - len = strlen(resp); - base64 = mp3cast_base64_encode(resp); - sprintf(resp, "Authorization: Basic %s\r\n", base64); - send(sockfd, resp, strlen(resp), 0); - t_freebytes(base64, len*4/3 + 4); - /* send application name */ - buf = "User-Agent: mp3cast~"; - send(sockfd, buf, strlen(buf), 0); - /* send content type: mpeg */ - buf = "\r\nContent-Type: audio/mpeg"; - send(sockfd, buf, strlen(buf), 0); - /* send the ice headers */ - /* name */ - buf = "\r\nice-name: "; - send(sockfd, buf, strlen(buf), 0); - buf = x->x_name; - send(sockfd, buf, strlen(buf), 0); - /* url */ - buf = "\r\nice-url: "; - send(sockfd, buf, strlen(buf), 0); - buf = x->x_url; - send(sockfd, buf, strlen(buf), 0); - /* genre */ - buf = "\r\nice-genre: "; - send(sockfd, buf, strlen(buf), 0); - buf = genre; - send(sockfd, buf, strlen(buf), 0); - /* public */ - buf = "\r\nice-public: "; - send(sockfd, buf, strlen(buf), 0); - if(isPublic==0) - { - buf = "0"; - } - else - { - buf = "1"; - } - send(sockfd, buf, strlen(buf), 0); - /* bitrate */ - if(sprintf(resp, "\r\nice-audio-info: bitrate=%d", x->x_bitrate) == -1) - { - error("shoutcast~: could not create audio-info"); - } - send(sockfd, resp, strlen(resp), 0); - /* description */ - buf = "\r\nice-description: "; - send(sockfd, buf, strlen(buf), 0); - buf = description; - send(sockfd, buf, strlen(buf), 0); - /* end of header: write an empty line */ - buf = "\r\n\r\n"; - send(sockfd, buf, strlen(buf), 0); - } - - /* read the anticipated response: "OK" */ - len = recv(sockfd, resp, STRBUF_SIZE, 0); - if ( strstr( resp, "OK" ) == NULL ) - { - post("mp3cast~: login failed!"); - if ( len>0 ) post("mp3cast~: server answered : %s", resp); -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif /* _WIN32 */ - return; - } - - /* suck anything that the other side has to say */ - // while (len = recv(sockfd, resp, STRBUF_SIZE,0)) - // { - // post("mp3cast~: server answered : %s", resp); - // } - - x->x_fd = sockfd; - outlet_float(x->x_obj.ob_outlet, 1); - post("mp3cast~: logged in to %s", hp->h_name); - - mp3cast_tilde_lame_init(x); - -} - - /* close connection to SHOUTcast server */ -static void mp3cast_disconnect(t_mp3cast *x) -{ - int err = -1; - if(x->x_lame >= 0) - { - /* ignore remaining bytes */ - if ( x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, 0) < 0 ) { - post( "mp3cast~ : warning : remaining encoded bytes" ); - } - lame_close( x->lgfp ); - - x->x_lame = -1; - post("mp3cast~: encoder stream closed"); - } - - if(x->x_fd >= 0) /* close socket */ - { -#ifdef _WIN32 - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif /* _WIN32 */ - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - post("mp3cast~: connection closed"); - } -} - - /* set password for SHOUTcast server */ -static void mp3cast_password(t_mp3cast *x, t_symbol *password) -{ - post("mp3cast~ : setting password to %s", password->s_name ); - x->x_passwd = password->s_name; -} - - /* settings for mp3 encoding */ -static void mp3cast_mpeg(t_mp3cast *x, t_floatarg fsamplerate, t_floatarg fbitrate, - t_floatarg fmode, t_floatarg fquality) -{ - x->x_samplerate = fsamplerate; - if(fbitrate > MAXDATARATE) - { - fbitrate = MAXDATARATE; - } - x->x_bitrate = fbitrate; - x->x_mp3mode = fmode; - x->x_mp3quality = fquality; - post("mp3cast~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", - x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); - if(x->x_fd>=0)post("mp3cast~ : reconnect to make changes take effect! "); -} - - /* print settings */ -static void mp3cast_print(t_mp3cast *x) -{ - const char * buf = 0; - post(mp3cast_version); - post(" LAME mp3 settings:\n" - " output sample rate: %d Hz\n" - " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); - switch(x->x_mp3mode) - { - case 0 : - buf = "stereo"; - break; - case 1 : - buf = "joint stereo"; - break; - case 2 : - buf = "dual channel"; - break; - case 3 : - buf = "mono"; - break; - } - post(" mode: %s\n" - " quality: %d", buf, x->x_mp3quality); - post(" mp3 chunk size: %d", x->x_lamechunk); - if(x->x_samplerate!=sys_getsr()) - { - post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); - } - - if ( x->x_icecast == 0) - { - post(" server type is SHOUTcast"); - } - else if ( x->x_icecast == 1 ) - { - post(" server type is IceCast"); - } - else if ( x->x_icecast == 2 ) - { - post(" server type is IceCast 2"); - } -} - -static void mp3cast_icecast(t_mp3cast *x) -{ - x->x_icecast = 1; - post("mp3cast~: set server type to IceCast"); -} - -static void mp3cast_icecast2(t_mp3cast *x) -{ - x->x_icecast = 2; - post("mp3cast~: set server type to IceCast 2"); -} - -static void mp3cast_shoutcast(t_mp3cast *x) -{ - x->x_icecast = 0; - post("mp3cast~: set server type to SHOUTcast"); -} - - /* set mountpoint for IceCast server */ -static void mp3cast_mountpoint(t_mp3cast *x, t_symbol *mount) -{ - x->x_mountpoint = mount->s_name; - post("mp3cast~: mountpoint set to %s", x->x_mountpoint); -} - - /* set namle for IceCast server */ -static void mp3cast_name(t_mp3cast *x, t_symbol *name) -{ - x->x_name = name->s_name; - post("mp3cast~: name set to %s", x->x_name); -} - - /* set url for IceCast server */ -static void mp3cast_url(t_mp3cast *x, t_symbol *url) -{ - x->x_url = url->s_name; - post("mp3cast~: url set to %s", x->x_url); -} - - /* set genre for IceCast server */ -static void mp3cast_genre(t_mp3cast *x, t_symbol *genre) -{ - x->x_genre = genre->s_name; - post("mp3cast~: genre set to %s", x->x_genre); -} - - /* set isPublic for IceCast server */ -static void mp3cast_isPublic(t_mp3cast *x, t_floatarg isPublic) -{ - x->x_isPublic = isPublic; - char* isPublicStr; - if(isPublic==0) - { - isPublicStr = "no"; - } - else - { - isPublicStr = "yes"; - } - post("mp3cast~: isPublic set to %s", isPublicStr); -} - - /* set description for IceCast server */ -static void mp3cast_description(t_mp3cast *x, t_symbol *description) -{ - x->x_description = description->s_name; - post("mp3cast~: description set to %s", x->x_description); -} - - /* clean up */ -static void mp3cast_free(t_mp3cast *x) -{ - if(x->x_lame >= 0) - lame_close( x->lgfp ); - if(x->x_fd >= 0) -#ifdef _WIN32 - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif /* _WIN32 */ - freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); - freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); -} - -static void *mp3cast_new(void) -{ - t_mp3cast *x = (t_mp3cast *)pd_new(mp3cast_class); - inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); - outlet_new(&x->x_obj, gensym("float")); - x->x_fd = -1; - x->x_lame = -1; - x->x_passwd = "pd"; - x->x_samplerate = sys_getsr(); - x->x_bitrate = 224; - x->x_mp3mode = 1; - x->x_mp3quality = 5; - x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ - x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE*sizeof(char)); /* our mp3 stream */ - x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ - if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ - { - error("out of memory!"); - } - x->x_bytesbuffered = 0; - x->x_inp = 0; - x->x_outp = 0; - x->lgfp = NULL; - x->x_start = -1; - x->x_icecast = 1; - x->x_mountpoint = "puredata"; - x->x_name = "puredata"; - x->x_url = "http://puredata.info"; - x->x_genre = "experimental sound"; - x->x_isPublic = 1; - x->x_description = "playing with my patches"; - return(x); -} - -void mp3cast_tilde_setup(void) -{ - post(mp3cast_version); - mp3cast_class = class_new(gensym("mp3cast~"), (t_newmethod)mp3cast_new, (t_method)mp3cast_free, - sizeof(t_mp3cast), 0, 0); - CLASS_MAINSIGNALIN(mp3cast_class, t_mp3cast, x_f ); - class_addmethod(mp3cast_class, (t_method)mp3cast_dsp, gensym("dsp"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_disconnect, gensym("disconnect"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_password, gensym("passwd"), A_SYMBOL, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_print, gensym("print"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_icecast, gensym("icecast"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_icecast2, gensym("icecast2"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_shoutcast, gensym("shoutcast"), 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_mountpoint, gensym("mountpoint"), A_SYMBOL, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_name, gensym("name"), A_SYMBOL, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_url, gensym("url"), A_SYMBOL, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_genre, gensym("genre"), A_SYMBOL, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_isPublic, gensym("isPublic"), A_FLOAT, 0); - class_addmethod(mp3cast_class, (t_method)mp3cast_description, gensym("description"), A_SYMBOL, 0); -} - diff --git a/mp3cast~/mpglib.h b/mp3cast~/mpglib.h deleted file mode 100644 index 1f4ef9a..0000000 --- a/mp3cast~/mpglib.h +++ /dev/null @@ -1,65 +0,0 @@ -// #include "lame-analysis.h" - -#define NOANALYSIS - -#ifndef NOANALYSIS -extern plotting_data *mpg123_pinfo; -#endif - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -typedef struct mpstr_tag { - struct buf *head,*tail; - int vbr_header; /* 1 if valid Xing vbr header detected */ - int num_frames; /* set if vbr header present */ - int enc_delay; /* set if vbr header present */ - int enc_padding; /* set if vbr header present */ - int header_parsed; - int side_parsed; - int data_parsed; - int free_format; /* 1 = free format frame */ - int old_free_format; /* 1 = last frame was free format */ - int bsize; - int framesize; - int ssize; - int dsize; - int fsizeold; - int fsizeold_nopadding; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; - int sync_bitstream; - -} MPSTR, *PMPSTR; - - -#if ( defined(_MSC_VER) || defined(__BORLANDC__) ) - typedef int BOOL; /* windef.h contains the same definition */ -#else - #define BOOL int -#endif - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - - diff --git a/mp3fileout~.c b/mp3fileout~.c new file mode 100644 index 0000000..a24b448 --- /dev/null +++ b/mp3fileout~.c @@ -0,0 +1,558 @@ +/* ------------------------ mp3fileout~ --------------------------------------- */ +/* */ +/* Tilde object to send an mp3 file to a peer using mp3streamin~ */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates @ http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ +/* be found at http://www.cdex.n3.net. */ +/* */ +/* "See mass murder on a scale you've never seen" */ +/* "And all the one who tried hard to succeed" */ +/* You know who, don't you ??? */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include + +#include +#include +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif /* _WIN32 */ + +#if defined(__APPLE__) || defined(_WIN32) +#define MSG_NOSIGNAL 0 +#endif + + +#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ +#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ +#include "interface.h" /* mpglib decoding library from lame 3.92 */ + +#define INPUT_BUFFER_SIZE 32768 +#define OUTPUT_BUFFER_SIZE 32768 +#define MAX_FRAME_SIZE 1152 + +/* useful debugging functions from mpglib */ +extern int decode_header( struct frame* fr, unsigned long newhead ); +extern void print_header_compact( struct frame* fr ); +extern int head_check( unsigned long head, int check_layer ); + +/* time-out used for select() call */ +static struct timeval ztout; + +static char *mp3fileout_version = "mp3fileout~: mp3 file streamer version 0.2, written by ydegoyon@free.fr"; + +extern void sys_sockerror(char *s); + +void mp3fileout_closesocket(int fd) +{ +#ifdef UNIX + if ( close(fd) < 0 ) + { + perror( "close" ); + } + else + { + post( "mp3fileout~ : closed socket : %d", fd ); + } +#endif +#ifdef NT + closesocket(fd); +#else + sys_rmpollfn(fd); +#endif +} + +/* ------------------------ mp3fileout~ ----------------------------- */ + +static t_class *mp3fileout_class; + +typedef struct _mp3fileout +{ + t_object x_obj; + t_int x_socket; + t_int x_fd; /* file descriptor for the mp3 file */ + t_int x_eof; /* end of file is reached */ + t_int x_emit; /* indicates the ability to emit */ + t_int x_nbwaitloops;/* synchronization cycles count */ + t_int x_blocksize; /* actual blocksize */ + + void *x_inbuffer; /* accumulation buffer for read mp3 frames */ + t_int x_inwriteposition; + t_int x_inbuffersize; + t_int x_framesize; + t_int x_offset; /* offset used for decoding */ + t_int x_nbloops; /* number of perform loops */ + + void *x_outbuffer; /* buffer to be emitted */ + t_int x_outframes; /* number of frames emitted */ + t_int x_outbuffersize; + t_int x_outavable; /* number of available bytes to emit */ + + t_canvas *x_canvas; + + t_outlet *x_connected; /* indicates state of the connection */ + t_outlet *x_endreached;/* indicates the end of file */ + t_outlet *x_frames; /* indicates the number of frames emitted */ + +} t_mp3fileout; + +static int mp3fileout_search_header(t_mp3fileout *x) +{ + t_int i; + t_int length = 0; + struct frame hframe; + unsigned long cheader; + t_int ret = sizeof( unsigned long); + t_int foffset = 0; + unsigned int a,b,c,d; + unsigned char buf[sizeof(unsigned long)]; + t_float nbsamplesframe = 0; + + while( ret>0 ) + { + ret = read( x->x_fd, (void *)buf, sizeof( unsigned long ) ); + + foffset+=ret; + + if ( ret>0 ) + { + /* check for a valid header */ + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + cheader = 0; + cheader = a; + cheader <<= 8; + cheader |= b; + cheader <<= 8; + cheader |= c; + cheader <<= 8; + cheader |= d; + if ( head_check( cheader, 0 ) ) + { + decode_header( &hframe, cheader ); + // print_header_compact( &hframe ); + x->x_framesize = hframe.framesize; + nbsamplesframe = ( hframe.mpeg25 ? 576 : 1152 ); + x->x_nbwaitloops = (int)(nbsamplesframe/x->x_blocksize); + if ( x->x_nbwaitloops == 0 ) x->x_nbwaitloops = 1; + // post ( "mp3fileout~ : will wait %d loops", x->x_nbwaitloops ); + + // rewind file to the start of the frame + if ( lseek( x->x_fd, -sizeof(unsigned long), SEEK_CUR ) < 0 ) + { + post( "mp3fileout~ : could not rewind file." ); + } + if ( x->x_outframes == 0 ) + { + post( "mp3fileout~ : found firstframe @ %d", foffset ); + } + break; + } + // post( "mp3fileout~ : read %d bytes.", ret ); + } + else + { + if ( ret < 0 ) + { + post( "mp3fileout~ : error encountered ( ret=%d )...file reading done.", ret ); + perror( "read" ); + x->x_eof = 1; + } + else + { + post( "mp3fileout~ : file reading done.", ret ); + x->x_eof = 1; + outlet_bang( x->x_endreached ); + } + return -1; + } + + } + + return x->x_framesize; +} + +static int mp3fileout_read_frame(t_mp3fileout *x) +{ + int size, ret; + + if ( x->x_fd > 0 && !x->x_eof) + { + if ( ( size = mp3fileout_search_header( x ) ) > 0 ) + { + if ( size+sizeof(unsigned long) > INPUT_BUFFER_SIZE ) + { + post( "mp3fileout~ : cannot read frame : size too big : %d", size ); + return -1; + } + // post( "mp3fileout~ : reading a frame : size : %d", size ); + ret = read( x->x_fd, x->x_inbuffer, size+sizeof(unsigned long) ); + + if ( ret>0 ) + { + memcpy( x->x_outbuffer, x->x_inbuffer, ret ); + x->x_outavable += ret; + return ret; + } + else + { + return -1; + } + } + else + { + return -1; + } + } + else + { + return -1; + } +} + +static int mp3fileout_send_frame(t_mp3fileout *x) +{ + int ret=0; + + if ( x->x_socket > 0 && x->x_emit ) + { + if ( ( ret = send( x->x_socket, x->x_outbuffer, x->x_outavable, MSG_NOSIGNAL ) ) < 0 ) + { + post( "mp3fileout~ : connection lost." ); + perror( "send" ); + x->x_socket = -1; + x->x_emit = 0; + return -1; + } + else + { + memcpy( x->x_outbuffer, x->x_outbuffer+ret, x->x_outbuffersize-ret ); + x->x_outavable -= ret; + x->x_outframes++; + outlet_float( x->x_frames, x->x_outframes ); + // post( "mp3fileout~ : sent %d bytes, x->x_outavable : %d", ret, x->x_outavable ); + } + + } + else + { + // artificially empty buffer + x->x_outavable = 0; + } + return ret; +} + +static void mp3fileout_free(t_mp3fileout *x) +{ + if (x->x_socket > 0) { + post( "mp3fileout~ : closing socket" ); + mp3fileout_closesocket(x->x_socket); + x->x_socket = -1; + } + if ( x->x_fd > 0 ) + { + if ( close( x->x_fd ) < 0 ) + { + post( "mp3fileout~ : could not close file." ); + perror( "close" ); + } + } + if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); +} + +static t_int *mp3fileout_perform(t_int *w) +{ + t_mp3fileout *x = (t_mp3fileout*) (w[1]); + int ret; + int i = 0; + + x->x_blocksize = (t_int)(w[2]); + // check new incoming data + if ( x->x_socket > 0 ) + { + if ( x->x_nbloops % x->x_nbwaitloops == 0 ) + { + /* read a frame in the file */ + if ( mp3fileout_read_frame(x) > 0 ) + { + /* send the frame to the peer */ + mp3fileout_send_frame(x); + } + } + x->x_nbloops = ( x->x_nbloops+1 ) % x->x_nbwaitloops; + } + return (w+3); +} + +static void mp3fileout_dsp(t_mp3fileout *x, t_signal **sp) +{ + dsp_add(mp3fileout_perform, 2, x, sp[0]->s_n); +} + + /* start streaming */ +static void mp3fileout_start(t_mp3fileout *x) +{ + x->x_emit = 1; + if ( x->x_fd > 0 ) + { + // reset file pointer + if ( lseek( x->x_fd, 0, SEEK_SET ) < 0 ) + { + post ( "mp3fileout~ : could not reset file pointer."); + x->x_eof = 1; + return; + } + x->x_eof = 0; + x->x_outframes = 0; + outlet_float( x->x_frames, x->x_outframes ); + } +} + + /* resume file reading */ +static void mp3fileout_resume(t_mp3fileout *x) +{ + x->x_emit = 1; +} + + /* seek in file */ +static void mp3fileout_seek(t_mp3fileout *x, t_floatarg foffset) +{ + if ( foffset < 0 ) + { + post( "mp3fileout~ : wrong offset."); + return; + } + if ( x->x_fd > 0 ) + { + // reset file pointer + if ( lseek( x->x_fd, (int)foffset, SEEK_SET ) < 0 ) + { + post ( "mp3fileout~ : could not reset file pointer."); + x->x_eof = 1; + return; + } + x->x_eof = 0; + } +} + + /* stop streaming */ +static void mp3fileout_stop(t_mp3fileout *x) +{ + x->x_emit = 0; +} + + /* open mp3 file */ +static void mp3fileout_open(t_mp3fileout *x, t_symbol *filename) +{ + // first close previous file + if ( x->x_fd > 0 ) + { + if ( close( x->x_fd ) < 0 ) + { + post( "mp3fileout~ : could not close file." ); + perror( "close" ); + } + x->x_outframes = 0; + outlet_float( x->x_frames, x->x_outframes ); + } + + if ( ( x->x_fd = open( filename->s_name, O_RDONLY ) ) < 0 ) + { + post( "mp3fileout~ : could not open file : %s", filename->s_name ); + perror( "open" ); + x->x_eof = 1; + } + else + { + x->x_eof = 0; + post( "mp3fileout~ : opened file : %s ( fd = %d )", filename->s_name, x->x_fd ); + } +} + + /* connect to the peer */ +static void mp3fileout_connect(t_mp3fileout *x, t_symbol *hostname, t_floatarg fportno) +{ + struct sockaddr_in csocket; + struct hostent *hp; + int portno = fportno; /* get port from message box */ + + /* variables used for communication with the peer */ + unsigned int len; + int sockfd; + +#ifdef _WIN32 + unsigned int ret; +#else + int ret; +#endif + + if (x->x_socket >= 0) + { + error("mp3fileout~: already connected"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("mp3fileout~: internal error while attempting to open socket"); + return; + } + + /* connect socket using hostname provided in command line */ + csocket.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("mp3fileout~: bad host?"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + csocket.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("mp3fileout~: connecting to port %d", portno); + if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) + { + error("mp3fileout~: connection failed!\n"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + x->x_socket = sockfd; + x->x_outframes = 0; + outlet_float( x->x_frames, x->x_outframes ); + outlet_float( x->x_connected, 1 ); + post( "mp3fileout~ : connected to peer" ); + +} + + /* close connection to the peer */ +static void mp3fileout_disconnect(t_mp3fileout *x) +{ + + int err = -1; + if(x->x_socket >= 0) /* close socket */ + { +#ifdef _WIN32 + closesocket(x->x_socket); +#else + close(x->x_socket); +#endif + x->x_socket = -1; + outlet_float( x->x_connected, 0 ); + x->x_outframes = 0; + outlet_float( x->x_frames, x->x_outframes ); + post("mp3fileout~: connection closed"); + } +} + +static void *mp3fileout_new(void) +{ + t_mp3fileout *x; + int i; + + x = (t_mp3fileout *)pd_new(mp3fileout_class); + x->x_connected = outlet_new( &x->x_obj, &s_float ); + x->x_frames = outlet_new( &x->x_obj, &s_float ); + x->x_endreached = outlet_new( &x->x_obj, &s_bang ); + + x->x_socket = -1; + x->x_fd = -1; + x->x_eof = 0; + x->x_canvas = canvas_getcurrent(); + + x->x_offset = 0; + x->x_inbuffersize = INPUT_BUFFER_SIZE; + x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); + if ( !x->x_inbuffer ) + { + post( "mp3fileout~ : could not allocate buffers." ); + return NULL; + } + memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); + + x->x_outbuffersize = OUTPUT_BUFFER_SIZE; + x->x_outbuffer = (char*) getbytes( x->x_outbuffersize ); + if ( !x->x_outbuffer ) + { + post( "mp3fileout~ : could not allocate buffers." ); + return NULL; + } + memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); + x->x_outavable = 0; + + x->x_inwriteposition = 0; + x->x_nbloops = 0; + x->x_nbwaitloops = 1; + + return (x); +} + +void mp3fileout_tilde_setup(void) +{ + post( mp3fileout_version ); + mp3fileout_class = class_new(gensym("mp3fileout~"), + (t_newmethod) mp3fileout_new, (t_method) mp3fileout_free, + sizeof(t_mp3fileout), 0, A_NULL); + + class_addmethod(mp3fileout_class, nullfn, gensym("signal"), 0); + class_addmethod(mp3fileout_class, (t_method) mp3fileout_dsp, gensym("dsp"), 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_open, gensym("open"), A_SYMBOL, 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_disconnect, gensym("disconnect"), 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_start, gensym("start"), 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_resume, gensym("resume"), 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_seek, gensym("seek"), A_DEFFLOAT, 0); + class_addmethod(mp3fileout_class, (t_method)mp3fileout_stop, gensym("stop"), 0); +} diff --git a/mp3live~-help.pd b/mp3live~-help.pd new file mode 100644 index 0000000..ac68464 --- /dev/null +++ b/mp3live~-help.pd @@ -0,0 +1,118 @@ +#N canvas 11 -3 941 684 10; +#X msg 35 594 \; pd dsp 1; +#X text 432 123 <-- settings for mp3 stream; +#X text 492 177 1 = joint stereo (default); +#X text 456 165 mode: 0 = stereo; +#X text 492 189 2 = dual channel; +#X msg 101 594 \; pd dsp 0; +#X obj 551 317 dac~; +#X msg 368 80 disconnect; +#X floatatom 221 227 5 0 0; +#X obj 221 199 mp3streamout~; +#X msg 367 54 connect localhost 5000; +#X msg 767 69 bang; +#X obj 767 89 openpanel; +#X obj 766 186 soundfiler; +#X floatatom 767 210 10 0 0; +#X obj 767 111 t s b; +#X obj 767 148 pack s s; +#X msg 766 169 read -resize \$1 \$2; +#X obj 803 111 float \$0; +#X text 755 50 Step 1 : Load a sound file; +#X obj 767 128 route float; +#X obj 123 149 tabplay~ \$0-sample; +#X msg 123 120 bang; +#X obj 114 627 table \$0-sample; +#X obj 821 148 makefilename %d-sample; +#X text 371 34 Step 2 : connect the streamer; +#X text 8 100 Step 3 : emit a sound through the streamer; +#X obj 234 276 env~; +#X obj 67 310 timer; +#X obj 207 276 > 0; +#X obj 159 276 route 1; +#X obj 122 276 t b f; +#X floatatom 121 340 5 0 0; +#X obj 80 276 spigot; +#X msg 102 256 0; +#X msg 130 256 1; +#X text 453 135 (bitrate \, mode \, quality); +#X text 453 227 Note : resampling is not supported for now; +#X text 454 238 Note : see the README for allowed bitrate; +#X text 30 9 mp3live~ : mp3streamout~ / mp3streamin~; +#X text 30 20 peer-to-peer mp3 streaming \, written by ydegoyon@free.fr +; +#X msg 342 147 mpeg 32 2 9; +#X text 492 202 3 = mono ( not supported ); +#X text 455 153 bitrate: bitrate of stream \, def. 128kbit/s; +#X text 452 215 quality: 5 = high \, 9 = low; +#X text 85 360 streamer latency (ms); +#X obj 35 573 loadbang; +#X msg 343 123 mpeg 128 0 5; +#X obj 536 270 mp3streamin~ 5000 1; +#X symbolatom 639 300 10 0 0; +#X text 622 316 Incomer's address; +#X floatatom 229 496 5 0 0; +#X floatatom 327 498 5 0 0; +#X text 282 366 Step 3 bis : emit a file through the streamer; +#X msg 298 386 bang; +#X msg 299 423 open \$1; +#X msg 393 410 disconnect; +#X msg 393 391 connect localhost 5000; +#X msg 393 429 start; +#X msg 438 430 stop; +#X obj 298 406 openpanel; +#X text 292 522 Number of frames emitted; +#X text 160 515 Connection state; +#X text 31 36 Warning : mp3fileout~ will not read ANY mp3 file \,; +#X text 30 46 but \, at least \, those produced with mp3write~.; +#X msg 474 430 resume; +#X msg 524 429 seek 10000; +#X text 391 503 A bang is emitted at the end of the file; +#X obj 301 454 mp3fileout~; +#X obj 389 485 print thisistheend; +#X connect 7 0 9 0; +#X connect 9 0 8 0; +#X connect 10 0 9 0; +#X connect 11 0 12 0; +#X connect 12 0 15 0; +#X connect 13 0 14 0; +#X connect 15 0 16 0; +#X connect 15 1 18 0; +#X connect 16 0 17 0; +#X connect 17 0 13 0; +#X connect 18 0 20 0; +#X connect 20 0 24 0; +#X connect 21 0 9 0; +#X connect 21 0 9 1; +#X connect 22 0 21 0; +#X connect 22 0 28 0; +#X connect 22 0 35 0; +#X connect 24 0 16 1; +#X connect 27 0 29 0; +#X connect 28 0 32 0; +#X connect 29 0 30 0; +#X connect 30 0 31 0; +#X connect 31 0 33 0; +#X connect 32 0 34 0; +#X connect 33 0 28 1; +#X connect 34 0 33 1; +#X connect 35 0 33 1; +#X connect 41 0 9 0; +#X connect 46 0 0 0; +#X connect 47 0 9 0; +#X connect 48 0 6 0; +#X connect 48 0 27 0; +#X connect 48 1 6 1; +#X connect 48 2 49 0; +#X connect 54 0 60 0; +#X connect 55 0 68 0; +#X connect 56 0 68 0; +#X connect 57 0 68 0; +#X connect 58 0 68 0; +#X connect 59 0 68 0; +#X connect 60 0 55 0; +#X connect 65 0 68 0; +#X connect 66 0 68 0; +#X connect 68 0 51 0; +#X connect 68 1 52 0; +#X connect 68 2 69 0; diff --git a/mp3live~/INSTALL b/mp3live~/INSTALL deleted file mode 100644 index 63db4c7..0000000 --- a/mp3live~/INSTALL +++ /dev/null @@ -1,21 +0,0 @@ -You need to get lame > v3.90 installed first. -libmp3lame.so is searched in /usr/local/lib -( no time to write configure scripts ). -if it's installed elsewhere, change the Makefile, -you won't die from that. - -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/mp3live~ - -make clean - -make - -make install - -open help-mp3live~.pd - -Thanx for getting here. - -Yves/ diff --git a/mp3live~/interface.h b/mp3live~/interface.h deleted file mode 100644 index de3136a..0000000 --- a/mp3live~/interface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Copyright (C) 2000 Albert L. Faber -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef INTERFACE_H_INCLUDED -#define INTERFACE_H_INCLUDED - -// #include "common.h" -#include "interface.h" - -BOOL InitMP3(PMPSTR mp); -int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done); -void ExitMP3(PMPSTR mp); - -/* added remove_buf to support mpglib seeking */ -void remove_buf(PMPSTR mp); - -#endif diff --git a/mp3live~/mp3fileout~.c b/mp3live~/mp3fileout~.c deleted file mode 100644 index bd2d431..0000000 --- a/mp3live~/mp3fileout~.c +++ /dev/null @@ -1,558 +0,0 @@ -/* ------------------------ mp3fileout~ --------------------------------------- */ -/* */ -/* Tilde object to send an mp3 file to a peer using mp3streamin~ */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates @ http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ -/* be found at http://www.cdex.n3.net. */ -/* */ -/* "See mass murder on a scale you've never seen" */ -/* "And all the one who tried hard to succeed" */ -/* You know who, don't you ??? */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include - -#include -#include -#ifdef _WIN32 -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif /* _WIN32 */ - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#endif - - -#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ -#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ -#include "interface.h" /* mpglib decoding library from lame 3.92 */ - -#define INPUT_BUFFER_SIZE 32768 -#define OUTPUT_BUFFER_SIZE 32768 -#define MAX_FRAME_SIZE 1152 - -/* useful debugging functions from mpglib */ -extern int decode_header( struct frame* fr, unsigned long newhead ); -extern void print_header_compact( struct frame* fr ); -extern int head_check( unsigned long head, int check_layer ); - -/* time-out used for select() call */ -static struct timeval ztout; - -static char *mp3fileout_version = "mp3fileout~: mp3 file streamer version 0.2, written by ydegoyon@free.fr"; - -extern void sys_sockerror(char *s); - -void mp3fileout_closesocket(int fd) -{ -#ifdef UNIX - if ( close(fd) < 0 ) - { - perror( "close" ); - } - else - { - post( "mp3fileout~ : closed socket : %d", fd ); - } -#endif -#ifdef NT - closesocket(fd); -#else - sys_rmpollfn(fd); -#endif -} - -/* ------------------------ mp3fileout~ ----------------------------- */ - -static t_class *mp3fileout_class; - -typedef struct _mp3fileout -{ - t_object x_obj; - t_int x_socket; - t_int x_fd; /* file descriptor for the mp3 file */ - t_int x_eof; /* end of file is reached */ - t_int x_emit; /* indicates the ability to emit */ - t_int x_nbwaitloops;/* synchronization cycles count */ - t_int x_blocksize; /* actual blocksize */ - - void *x_inbuffer; /* accumulation buffer for read mp3 frames */ - t_int x_inwriteposition; - t_int x_inbuffersize; - t_int x_framesize; - t_int x_offset; /* offset used for decoding */ - t_int x_nbloops; /* number of perform loops */ - - void *x_outbuffer; /* buffer to be emitted */ - t_int x_outframes; /* number of frames emitted */ - t_int x_outbuffersize; - t_int x_outavable; /* number of available bytes to emit */ - - t_canvas *x_canvas; - - t_outlet *x_connected; /* indicates state of the connection */ - t_outlet *x_endreached;/* indicates the end of file */ - t_outlet *x_frames; /* indicates the number of frames emitted */ - -} t_mp3fileout; - -static int mp3fileout_search_header(t_mp3fileout *x) -{ - t_int i; - t_int length = 0; - struct frame hframe; - unsigned long cheader; - t_int ret = sizeof( unsigned long); - t_int foffset = 0; - unsigned int a,b,c,d; - unsigned char buf[sizeof(unsigned long)]; - t_float nbsamplesframe = 0; - - while( ret>0 ) - { - ret = read( x->x_fd, (void *)buf, sizeof( unsigned long ) ); - - foffset+=ret; - - if ( ret>0 ) - { - /* check for a valid header */ - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - cheader = 0; - cheader = a; - cheader <<= 8; - cheader |= b; - cheader <<= 8; - cheader |= c; - cheader <<= 8; - cheader |= d; - if ( head_check( cheader, 0 ) ) - { - decode_header( &hframe, cheader ); - // print_header_compact( &hframe ); - x->x_framesize = hframe.framesize; - nbsamplesframe = ( hframe.mpeg25 ? 576 : 1152 ); - x->x_nbwaitloops = (int)(nbsamplesframe/x->x_blocksize); - if ( x->x_nbwaitloops == 0 ) x->x_nbwaitloops = 1; - // post ( "mp3fileout~ : will wait %d loops", x->x_nbwaitloops ); - - // rewind file to the start of the frame - if ( lseek( x->x_fd, -sizeof(unsigned long), SEEK_CUR ) < 0 ) - { - post( "mp3fileout~ : could not rewind file." ); - } - if ( x->x_outframes == 0 ) - { - post( "mp3fileout~ : found firstframe @ %d", foffset ); - } - break; - } - // post( "mp3fileout~ : read %d bytes.", ret ); - } - else - { - if ( ret < 0 ) - { - post( "mp3fileout~ : error encountered ( ret=%d )...file reading done.", ret ); - perror( "read" ); - x->x_eof = 1; - } - else - { - post( "mp3fileout~ : file reading done.", ret ); - x->x_eof = 1; - outlet_bang( x->x_endreached ); - } - return -1; - } - - } - - return x->x_framesize; -} - -static int mp3fileout_read_frame(t_mp3fileout *x) -{ - int size, ret; - - if ( x->x_fd > 0 && !x->x_eof) - { - if ( ( size = mp3fileout_search_header( x ) ) > 0 ) - { - if ( size+sizeof(unsigned long) > INPUT_BUFFER_SIZE ) - { - post( "mp3fileout~ : cannot read frame : size too big : %d", size ); - return -1; - } - // post( "mp3fileout~ : reading a frame : size : %d", size ); - ret = read( x->x_fd, x->x_inbuffer, size+sizeof(unsigned long) ); - - if ( ret>0 ) - { - memcpy( x->x_outbuffer, x->x_inbuffer, ret ); - x->x_outavable += ret; - return ret; - } - else - { - return -1; - } - } - else - { - return -1; - } - } - else - { - return -1; - } -} - -static int mp3fileout_send_frame(t_mp3fileout *x) -{ - int ret=0; - - if ( x->x_socket > 0 && x->x_emit ) - { - if ( ( ret = send( x->x_socket, x->x_outbuffer, x->x_outavable, MSG_NOSIGNAL ) ) < 0 ) - { - post( "mp3fileout~ : connection lost." ); - perror( "send" ); - x->x_socket = -1; - x->x_emit = 0; - return -1; - } - else - { - memcpy( x->x_outbuffer, x->x_outbuffer+ret, x->x_outbuffersize-ret ); - x->x_outavable -= ret; - x->x_outframes++; - outlet_float( x->x_frames, x->x_outframes ); - // post( "mp3fileout~ : sent %d bytes, x->x_outavable : %d", ret, x->x_outavable ); - } - - } - else - { - // artificially empty buffer - x->x_outavable = 0; - } - return ret; -} - -static void mp3fileout_free(t_mp3fileout *x) -{ - if (x->x_socket > 0) { - post( "mp3fileout~ : closing socket" ); - mp3fileout_closesocket(x->x_socket); - x->x_socket = -1; - } - if ( x->x_fd > 0 ) - { - if ( close( x->x_fd ) < 0 ) - { - post( "mp3fileout~ : could not close file." ); - perror( "close" ); - } - } - if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); -} - -static t_int *mp3fileout_perform(t_int *w) -{ - t_mp3fileout *x = (t_mp3fileout*) (w[1]); - int ret; - int i = 0; - - x->x_blocksize = (t_int)(w[2]); - // check new incoming data - if ( x->x_socket > 0 ) - { - if ( x->x_nbloops % x->x_nbwaitloops == 0 ) - { - /* read a frame in the file */ - if ( mp3fileout_read_frame(x) > 0 ) - { - /* send the frame to the peer */ - mp3fileout_send_frame(x); - } - } - x->x_nbloops = ( x->x_nbloops+1 ) % x->x_nbwaitloops; - } - return (w+3); -} - -static void mp3fileout_dsp(t_mp3fileout *x, t_signal **sp) -{ - dsp_add(mp3fileout_perform, 2, x, sp[0]->s_n); -} - - /* start streaming */ -static void mp3fileout_start(t_mp3fileout *x) -{ - x->x_emit = 1; - if ( x->x_fd > 0 ) - { - // reset file pointer - if ( lseek( x->x_fd, 0, SEEK_SET ) < 0 ) - { - post ( "mp3fileout~ : could not reset file pointer."); - x->x_eof = 1; - return; - } - x->x_eof = 0; - x->x_outframes = 0; - outlet_float( x->x_frames, x->x_outframes ); - } -} - - /* resume file reading */ -static void mp3fileout_resume(t_mp3fileout *x) -{ - x->x_emit = 1; -} - - /* seek in file */ -static void mp3fileout_seek(t_mp3fileout *x, t_floatarg foffset) -{ - if ( foffset < 0 ) - { - post( "mp3fileout~ : wrong offset."); - return; - } - if ( x->x_fd > 0 ) - { - // reset file pointer - if ( lseek( x->x_fd, (int)foffset, SEEK_SET ) < 0 ) - { - post ( "mp3fileout~ : could not reset file pointer."); - x->x_eof = 1; - return; - } - x->x_eof = 0; - } -} - - /* stop streaming */ -static void mp3fileout_stop(t_mp3fileout *x) -{ - x->x_emit = 0; -} - - /* open mp3 file */ -static void mp3fileout_open(t_mp3fileout *x, t_symbol *filename) -{ - // first close previous file - if ( x->x_fd > 0 ) - { - if ( close( x->x_fd ) < 0 ) - { - post( "mp3fileout~ : could not close file." ); - perror( "close" ); - } - x->x_outframes = 0; - outlet_float( x->x_frames, x->x_outframes ); - } - - if ( ( x->x_fd = open( filename->s_name, O_RDONLY ) ) < 0 ) - { - post( "mp3fileout~ : could not open file : %s", filename->s_name ); - perror( "open" ); - x->x_eof = 1; - } - else - { - x->x_eof = 0; - post( "mp3fileout~ : opened file : %s ( fd = %d )", filename->s_name, x->x_fd ); - } -} - - /* connect to the peer */ -static void mp3fileout_connect(t_mp3fileout *x, t_symbol *hostname, t_floatarg fportno) -{ - struct sockaddr_in csocket; - struct hostent *hp; - int portno = fportno; /* get port from message box */ - - /* variables used for communication with the peer */ - unsigned int len; - int sockfd; - -#ifndef UNIX - unsigned int ret; -#else - int ret; -#endif - - if (x->x_socket >= 0) - { - error("mp3fileout~: already connected"); - return; - } - - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - error("mp3fileout~: internal error while attempting to open socket"); - return; - } - - /* connect socket using hostname provided in command line */ - csocket.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) - { - post("mp3fileout~: bad host?"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - csocket.sin_port = htons((unsigned short)portno); - - /* try to connect. */ - post("mp3fileout~: connecting to port %d", portno); - if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) - { - error("mp3fileout~: connection failed!\n"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - - x->x_socket = sockfd; - x->x_outframes = 0; - outlet_float( x->x_frames, x->x_outframes ); - outlet_float( x->x_connected, 1 ); - post( "mp3fileout~ : connected to peer" ); - -} - - /* close connection to the peer */ -static void mp3fileout_disconnect(t_mp3fileout *x) -{ - - int err = -1; - if(x->x_socket >= 0) /* close socket */ - { -#ifndef UNIX - closesocket(x->x_socket); -#else - close(x->x_socket); -#endif - x->x_socket = -1; - outlet_float( x->x_connected, 0 ); - x->x_outframes = 0; - outlet_float( x->x_frames, x->x_outframes ); - post("mp3fileout~: connection closed"); - } -} - -static void *mp3fileout_new(void) -{ - t_mp3fileout *x; - int i; - - x = (t_mp3fileout *)pd_new(mp3fileout_class); - x->x_connected = outlet_new( &x->x_obj, &s_float ); - x->x_frames = outlet_new( &x->x_obj, &s_float ); - x->x_endreached = outlet_new( &x->x_obj, &s_bang ); - - x->x_socket = -1; - x->x_fd = -1; - x->x_eof = 0; - x->x_canvas = canvas_getcurrent(); - - x->x_offset = 0; - x->x_inbuffersize = INPUT_BUFFER_SIZE; - x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); - if ( !x->x_inbuffer ) - { - post( "mp3fileout~ : could not allocate buffers." ); - return NULL; - } - memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); - - x->x_outbuffersize = OUTPUT_BUFFER_SIZE; - x->x_outbuffer = (char*) getbytes( x->x_outbuffersize ); - if ( !x->x_outbuffer ) - { - post( "mp3fileout~ : could not allocate buffers." ); - return NULL; - } - memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); - x->x_outavable = 0; - - x->x_inwriteposition = 0; - x->x_nbloops = 0; - x->x_nbwaitloops = 1; - - return (x); -} - -void mp3fileout_tilde_setup(void) -{ - post( mp3fileout_version ); - mp3fileout_class = class_new(gensym("mp3fileout~"), - (t_newmethod) mp3fileout_new, (t_method) mp3fileout_free, - sizeof(t_mp3fileout), 0, A_NULL); - - class_addmethod(mp3fileout_class, nullfn, gensym("signal"), 0); - class_addmethod(mp3fileout_class, (t_method) mp3fileout_dsp, gensym("dsp"), 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_open, gensym("open"), A_SYMBOL, 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_disconnect, gensym("disconnect"), 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_start, gensym("start"), 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_resume, gensym("resume"), 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_seek, gensym("seek"), A_DEFFLOAT, 0); - class_addmethod(mp3fileout_class, (t_method)mp3fileout_stop, gensym("stop"), 0); -} diff --git a/mp3live~/mp3live~-help.pd b/mp3live~/mp3live~-help.pd deleted file mode 100644 index ac68464..0000000 --- a/mp3live~/mp3live~-help.pd +++ /dev/null @@ -1,118 +0,0 @@ -#N canvas 11 -3 941 684 10; -#X msg 35 594 \; pd dsp 1; -#X text 432 123 <-- settings for mp3 stream; -#X text 492 177 1 = joint stereo (default); -#X text 456 165 mode: 0 = stereo; -#X text 492 189 2 = dual channel; -#X msg 101 594 \; pd dsp 0; -#X obj 551 317 dac~; -#X msg 368 80 disconnect; -#X floatatom 221 227 5 0 0; -#X obj 221 199 mp3streamout~; -#X msg 367 54 connect localhost 5000; -#X msg 767 69 bang; -#X obj 767 89 openpanel; -#X obj 766 186 soundfiler; -#X floatatom 767 210 10 0 0; -#X obj 767 111 t s b; -#X obj 767 148 pack s s; -#X msg 766 169 read -resize \$1 \$2; -#X obj 803 111 float \$0; -#X text 755 50 Step 1 : Load a sound file; -#X obj 767 128 route float; -#X obj 123 149 tabplay~ \$0-sample; -#X msg 123 120 bang; -#X obj 114 627 table \$0-sample; -#X obj 821 148 makefilename %d-sample; -#X text 371 34 Step 2 : connect the streamer; -#X text 8 100 Step 3 : emit a sound through the streamer; -#X obj 234 276 env~; -#X obj 67 310 timer; -#X obj 207 276 > 0; -#X obj 159 276 route 1; -#X obj 122 276 t b f; -#X floatatom 121 340 5 0 0; -#X obj 80 276 spigot; -#X msg 102 256 0; -#X msg 130 256 1; -#X text 453 135 (bitrate \, mode \, quality); -#X text 453 227 Note : resampling is not supported for now; -#X text 454 238 Note : see the README for allowed bitrate; -#X text 30 9 mp3live~ : mp3streamout~ / mp3streamin~; -#X text 30 20 peer-to-peer mp3 streaming \, written by ydegoyon@free.fr -; -#X msg 342 147 mpeg 32 2 9; -#X text 492 202 3 = mono ( not supported ); -#X text 455 153 bitrate: bitrate of stream \, def. 128kbit/s; -#X text 452 215 quality: 5 = high \, 9 = low; -#X text 85 360 streamer latency (ms); -#X obj 35 573 loadbang; -#X msg 343 123 mpeg 128 0 5; -#X obj 536 270 mp3streamin~ 5000 1; -#X symbolatom 639 300 10 0 0; -#X text 622 316 Incomer's address; -#X floatatom 229 496 5 0 0; -#X floatatom 327 498 5 0 0; -#X text 282 366 Step 3 bis : emit a file through the streamer; -#X msg 298 386 bang; -#X msg 299 423 open \$1; -#X msg 393 410 disconnect; -#X msg 393 391 connect localhost 5000; -#X msg 393 429 start; -#X msg 438 430 stop; -#X obj 298 406 openpanel; -#X text 292 522 Number of frames emitted; -#X text 160 515 Connection state; -#X text 31 36 Warning : mp3fileout~ will not read ANY mp3 file \,; -#X text 30 46 but \, at least \, those produced with mp3write~.; -#X msg 474 430 resume; -#X msg 524 429 seek 10000; -#X text 391 503 A bang is emitted at the end of the file; -#X obj 301 454 mp3fileout~; -#X obj 389 485 print thisistheend; -#X connect 7 0 9 0; -#X connect 9 0 8 0; -#X connect 10 0 9 0; -#X connect 11 0 12 0; -#X connect 12 0 15 0; -#X connect 13 0 14 0; -#X connect 15 0 16 0; -#X connect 15 1 18 0; -#X connect 16 0 17 0; -#X connect 17 0 13 0; -#X connect 18 0 20 0; -#X connect 20 0 24 0; -#X connect 21 0 9 0; -#X connect 21 0 9 1; -#X connect 22 0 21 0; -#X connect 22 0 28 0; -#X connect 22 0 35 0; -#X connect 24 0 16 1; -#X connect 27 0 29 0; -#X connect 28 0 32 0; -#X connect 29 0 30 0; -#X connect 30 0 31 0; -#X connect 31 0 33 0; -#X connect 32 0 34 0; -#X connect 33 0 28 1; -#X connect 34 0 33 1; -#X connect 35 0 33 1; -#X connect 41 0 9 0; -#X connect 46 0 0 0; -#X connect 47 0 9 0; -#X connect 48 0 6 0; -#X connect 48 0 27 0; -#X connect 48 1 6 1; -#X connect 48 2 49 0; -#X connect 54 0 60 0; -#X connect 55 0 68 0; -#X connect 56 0 68 0; -#X connect 57 0 68 0; -#X connect 58 0 68 0; -#X connect 59 0 68 0; -#X connect 60 0 55 0; -#X connect 65 0 68 0; -#X connect 66 0 68 0; -#X connect 68 0 51 0; -#X connect 68 1 52 0; -#X connect 68 2 69 0; diff --git a/mp3live~/mp3streamin~.c b/mp3live~/mp3streamin~.c deleted file mode 100644 index b01a576..0000000 --- a/mp3live~/mp3streamin~.c +++ /dev/null @@ -1,671 +0,0 @@ -/* ------------------------ mp3streamin~ -------------------------------------- */ -/* */ -/* Tilde object to receive an mp3-stream sent by a peer using mp3streamout~. */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates @ http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ -/* be found at http://www.cdex.n3.net. */ -/* */ -/* "Repackage sex, your interests." */ -/* "Somehow, maintain the interest." */ -/* Gang Of Four -- Natural's Not In It */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include - -#if PD_MINOR_VERSION >=37 -#include "s_stuff.h" -#endif - -#include -#include -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif /* _WIN32 */ - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#define SOL_TCP IPPROTO_TCP -#endif - -#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ -#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ -#include "interface.h" /* mpglib decoding library from lame 3.92 */ - -#define MIN_AUDIO_INPUT 8064 // we must a least have 8 chunks to play a correct sound -#define INPUT_BUFFER_SIZE MIN_AUDIO_INPUT -#define OUTPUT_BUFFER_SIZE 131072 /* 128k*/ -#define LAME_AUDIO_CHUNK_SIZE 1152 -#define BARHEIGHT 10 -#define MAX_DECODERS 10 - -/* useful debugging functions from mpglib */ -extern int decode_header( struct frame* fr, unsigned long newhead ); -extern void print_header_compact( struct frame* fr ); -extern int head_check( unsigned long head, int check_layer ); - -/* time-out used for select() call */ -static struct timeval ztout; - -static char *mp3streamin_version = "mp3streamin~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr"; - -extern void sys_sockerror(char *s); - -void mp3streamin_closesocket(int fd) -{ -#ifdef UNIX - if ( close(fd) < 0 ) - { - perror( "close" ); - } - else - { - post( "mp3streamin~ : closed socket : %d", fd ); - } -#endif -#ifdef NT - closesocket(fd); -#endif - sys_rmpollfn(fd); -} - -int setsocketoptions(int sockfd) -{ - int sockopt = 1; - if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0) - { - post("mp3streamin~ : setsockopt TCP_NODELAY failed"); - perror( "setsockopt" ); - return -1; - } - else - { - post("mp3streamin~ : TCP_NODELAY set"); - } - -#ifdef UNIX - sockopt = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) - { - post("mp3streamin~ : setsockopt SO_REUSEADDR failed"); - perror( "setsockopt" ); - return -1; - } - else - { - post("mp3streamin~ : setsockopt SO_REUSEADDR done."); - } -#endif - return 0; -} - - -/* ------------------------ mp3streamin~ ----------------------------- */ - -static t_class *mp3streamin_class; - -typedef struct _mp3streamin -{ - t_object x_obj; - t_int x_instance; - t_int x_socket; - t_int x_shutdown; - t_outlet *x_connectionip; - t_int x_serversocket; - t_int x_inpackets; /* number of packets received */ - t_int x_dpacket; /* displayed packet in status bar */ - t_int x_packetsize; /* size of the packets */ - t_int x_pblocks; /* processed blocks */ - t_int x_graphic; /* indicates if we show a graphic bar */ - - void *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ - t_int x_inwriteposition; - t_int x_inbuffersize; - - t_float *x_outbuffer; /* buffer to store audio decoded data */ - t_int x_outwriteposition; - t_int x_outreadposition; - t_int x_outunread; - t_int x_outbuffersize; - - t_canvas *x_canvas; - - t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ - t_int x_newstream; /* at first, the stream must provide enough data to start */ - t_int x_bitrateindex; /* remember the bitrate index */ - -} t_mp3streamin; - -/* too bad, this needs to be static, - handling an array to enable several decoders in pd */ -static MPSTR mp[MAX_DECODERS]; /* decoder buffer */ -int nbinstances = 0; - -void mp3streamin_tilde_mpglib_init(t_mp3streamin *x) -{ - int ret; - - InitMP3(&mp[x->x_instance]); -} - -static int mp3streamin_decode_input(t_mp3streamin *x) -{ - int i; - int alength = 0; - struct frame hframe; - unsigned int a,b,c,d; - unsigned long cheader; - static char out[8192]; - signed short int *p = (signed short int *) out; - int pbytes; - int ret; - - if ( !x->x_shutdown ) - { - /* decode first 4 bytes as the header */ - a = *((unsigned char*)x->x_inbuffer); - b = *((unsigned char*)x->x_inbuffer+1); - c = *((unsigned char*)x->x_inbuffer+2); - d = *((unsigned char*)x->x_inbuffer+3); - - cheader = 0; - cheader = a; - cheader <<= 8; - cheader |= b; - cheader <<= 8; - cheader |= c; - cheader <<= 8; - cheader |= d; - if ( head_check( cheader, 0 ) ) - { - // post( "mp3streamin~ : valid header ( packet=%d)", x->x_inpackets ); - decode_header( &hframe, cheader ); - // print_header_compact( &hframe ); - // when the bitrate change, reinit decoder - if ( x->x_bitrateindex != hframe.bitrate_index ) - { - ExitMP3(&mp[x->x_instance]); - InitMP3(&mp[x->x_instance]); - x->x_bitrateindex = hframe.bitrate_index; - } - } - else - { - post( "mp3streamin~ : error : mp3 packet received without header" ); - // ignore data - x->x_inwriteposition = 0; - x->x_inpackets--; - return( -1 ); - } - - // post( "mp3streamin~ : decoding %d bytes framesize=%d", x->x_inwriteposition, hframe.framesize ); - ret = - decodeMP3(&mp[x->x_instance], (unsigned char*)x->x_inbuffer, - x->x_inwriteposition, (char *) p, sizeof(out), &pbytes); - - switch (ret) { - case MP3_OK: - switch (mp[x->x_instance].fr.stereo) { - case 1: - case 2: - alength = ((mp[x->x_instance].fr.stereo==1)?pbytes >> 1 : pbytes >> 2); - // post( "mp3streamin~ : processed %d samples", alength ); - // update outbuffer contents - for ( i=0; ix_outunread >= x->x_outbuffersize-2 ) - { - post( "mp3streamin~ : too much input ... ignored" ); - continue; - } - *(x->x_outbuffer+x->x_outwriteposition) = ((t_float)(*p++))/32767.0; - x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; - *(x->x_outbuffer+x->x_outwriteposition) = - ((mp[x->x_instance].fr.stereo==2)?((t_float)(*p++))/32767.0 : 0.0); - x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; - x->x_outunread+=2; - - if ( x->x_outunread > MIN_AUDIO_INPUT && !x->x_stream ) - { - post( "mp3streamin~ : stream connected." ); - x->x_stream = 1; - } - } - - break; - default: - alength = -1; - break; - } - break; - - case MP3_NEED_MORE: - post( "mp3streamin~ : retry lame decoding (more data needed)." ); - alength = 0; - break; - - case MP3_ERR: - post( "mp3streamin~ : lame decoding failed." ); - alength = -1; - break; - - } - - x->x_inwriteposition = 0; - } - else - { - if ( x->x_outunread == 0 ) - { - post( "mp3streamin~ : connection closed" ); - mp3streamin_closesocket(x->x_socket); - x->x_stream = 0; - x->x_newstream = 0; - x->x_inpackets = 0; - x->x_inwriteposition = 0; - x->x_bitrateindex = -1; - x->x_socket=-1; - outlet_symbol( x->x_connectionip, gensym("") ); - } - } - - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - /* update graphical read status */ - if ( x->x_inpackets != x->x_dpacket ) - { - char color[32]; - int minpackets = ( MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE )-2; // audio loop has eaten some already - - - sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); - sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); - if ( x->x_outunread > 0 ) - { - t_int width; - - if ( x->x_inpackets < (MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE)/2 ) - { - strcpy( color, "red" ); - } - else - { - strcpy( color, "lightgreen" ); - } - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix+(x->x_inpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix - 1, color, x ); - sys_vgui(".x%x.c create line %d %d %d %d -fill red -tags %xTHRESHOLD\n", - x->x_canvas, x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix-1, x ); - x->x_dpacket = x->x_inpackets; - } - else - { - if ( x->x_shutdown ) - { - x->x_shutdown=0; - sys_vgui(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); - sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); - } - } - } - } - return alength; -} - -static void mp3streamin_recv(t_mp3streamin *x) -{ - int ret; - - if ( ( ret = recv(x->x_socket, (void*) (x->x_inbuffer + x->x_inwriteposition), - (size_t)((x->x_inbuffersize-x->x_inwriteposition)), - MSG_NOSIGNAL) ) < 0 ) - { - post( "mp3_streamin~ : receive error" ); - perror( "recv" ); - return; - } - else - { - // post( "streamin~ : received %d bytes at %d on %d ( up to %d)", - // ret, x->x_inwriteposition, x->x_socket, - // x->x_inbuffersize-x->x_inwriteposition*sizeof( unsigned long) ); - - if ( ret == 0 ) - { - /* initiate the shutdown phase */ - x->x_shutdown=1; - } - else - { - // check we don't overflow input buffer - if ( (x->x_inpackets+1)*x->x_packetsize > x->x_inbuffersize ) - { - post( "mp3streamin~ : too much input...resetting" ); - x->x_inpackets=0; - x->x_inwriteposition=0; - return; - } - x->x_inpackets++; - x->x_packetsize=ret; - if ( x->x_inpackets % 100 == 0 ) - { - // post( "mp3streamin~ : received %d packets", x->x_inpackets ); - } - x->x_inwriteposition += ret; - } - - mp3streamin_decode_input(x); - } -} - -static void mp3streamin_acceptconnection(t_mp3streamin *x) -{ - struct sockaddr_in incomer_address; - int sockaddrl = (int) sizeof( struct sockaddr ); - - int fd = accept(x->x_serversocket, (struct sockaddr*)&incomer_address, &sockaddrl ); - - if (fd < 0) { - post("mp3streamin~: accept failed"); - return; - } - - if (x->x_socket > 0) { - sys_addpollfn(fd, (t_fdpollfn)mp3streamin_recv, x); - if ( x->x_outunread != 0 ) - { - post("mp3streamin~: still have some data to decode, retry later you %s.", - inet_ntoa( incomer_address.sin_addr )); - mp3streamin_closesocket( fd ); - return; - } - post("mp3streamin~: the source has changed to %s.", - inet_ntoa( incomer_address.sin_addr )); - mp3streamin_closesocket(x->x_socket); - } - - x->x_socket = fd; - sys_addpollfn(x->x_socket, (t_fdpollfn)mp3streamin_recv, x); - outlet_symbol( x->x_connectionip, gensym( inet_ntoa( incomer_address.sin_addr) ) ); - - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - t_int width; - - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - sys_vgui(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); - } - x->x_stream = 0; - x->x_newstream = 1; - -} - - -static int mp3streamin_startservice(t_mp3streamin* x, int portno) -{ - struct sockaddr_in server; - int sockfd; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) - { - sys_sockerror("socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - - /* assign server port number */ - server.sin_port = htons((u_short)portno); - post("listening to port number %d", portno); - - setsocketoptions(sockfd); - - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { - sys_sockerror("bind"); - mp3streamin_closesocket(sockfd); - return (0); - } - - if (listen(sockfd, 5) < 0) { - sys_sockerror("listen"); - mp3streamin_closesocket(sockfd); - } - else - { - x->x_serversocket = sockfd; - sys_addpollfn(x->x_serversocket, (t_fdpollfn)mp3streamin_acceptconnection, x); - } - - return 1; -} - -static void mp3streamin_free(t_mp3streamin *x) -{ - post( "mp3streamin~ : free %x", x ); - if (x->x_serversocket > 0) { - post( "mp3streamin~ : closing server socket" ); - mp3streamin_closesocket(x->x_serversocket); - x->x_serversocket = -1; - } - if (x->x_socket > 0) { - post( "mp3streamin~ : closing socket" ); - mp3streamin_closesocket(x->x_socket); - x->x_socket = -1; - } - if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); - if ( x->x_outbuffer ) freebytes( x->x_outbuffer, x->x_outbuffersize*sizeof(t_float) ); - if ( x->x_instance == nbinstances-1 ) - { - nbinstances--; - } -} - -static t_int *mp3streamin_perform(t_int *w) -{ - t_mp3streamin *x = (t_mp3streamin*) (w[1]); - t_float *out1 = (t_float *)(w[2]); - t_float *out2 = (t_float *)(w[3]); - int n = (int)(w[4]); - int bsize = n; - int ret; - int i = 0; - - while( n-- ) - { - if ( ( ( x->x_outunread > MIN_AUDIO_INPUT ) && x->x_newstream ) || // wait the buffer to load - ( ( x->x_shutdown ) && ( x->x_outunread >= 2 ) ) || // clean disconnection - ( x->x_stream ) // check that the stream provides enough data - ) - { - if ( x->x_newstream && !x->x_shutdown ) - { - x->x_newstream = 0; - x->x_stream = 1; - } - *out1++=*(x->x_outbuffer+x->x_outreadposition); - x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; - *out2++=*(x->x_outbuffer+x->x_outreadposition); - x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; - x->x_outunread-=2; - if ( n == 1 ) x->x_pblocks++; - } - else - { - *out1++=0.0; - *out2++=0.0; - } - } - - if ( ( x->x_outunread <= MIN_AUDIO_INPUT/10 ) && ( x->x_stream ) ) - { - post( "mp3streamin~ : stream lost (too little input)" ); - x->x_stream = 0; - x->x_newstream = 1; // waiting for a new stream - } - - if ( x->x_pblocks == LAME_AUDIO_CHUNK_SIZE/bsize ) - { - x->x_inpackets--; - x->x_pblocks = 0; - } - -#ifdef DO_MY_OWN_SELECT - // check new incoming data - if ( x->x_socket > 0 ) - { - fd_set readset; - fd_set exceptset; - - FD_ZERO(&readset); - FD_ZERO(&exceptset); - FD_SET(x->x_socket, &readset ); - FD_SET(x->x_socket, &exceptset ); - - if ( select( maxfd+1, &readset, NULL, &exceptset, &ztout ) >0 ) - { - if ( FD_ISSET( x->x_socket, &readset) || FD_ISSET( x->x_socket, &exceptset ) ) - { - /* receive data or error and decode it */ - mp3streamin_recv(x); - } - } - } -#endif - return (w+5); -} - -static void mp3streamin_dsp(t_mp3streamin *x, t_signal **sp) -{ - dsp_add(mp3streamin_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); -} - - -static void *mp3streamin_new(t_floatarg fportno, t_floatarg fdographics) -{ - t_mp3streamin *x; - int i; - - if ( fportno < 0 || fportno > 65535 ) - { - post( "mp3streamin~ : error : wrong portnumber : %d", (int)fportno ); - return NULL; - } - if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) - { - post( "mp3streamin~ : error : constructor : mp3streamin~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); - return NULL; - } - - x = (t_mp3streamin *)pd_new(mp3streamin_class); - post( "mp3streamin~ : new %x (instance = %d) %d", x, nbinstances, sizeof( MPSTR ) ); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); - - x->x_serversocket = -1; - x->x_socket = -1; - x->x_shutdown = 0; - x->x_inpackets = 0; - x->x_dpacket = -1; - - x->x_canvas = canvas_getcurrent(); - - x->x_inbuffersize = INPUT_BUFFER_SIZE; - x->x_outbuffersize = OUTPUT_BUFFER_SIZE; - x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); - memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); - x->x_outbuffer = (t_float*) getbytes( x->x_outbuffersize*sizeof(t_float) ); - memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); - - if ( !x->x_inbuffer || !x->x_outbuffer ) - { - post( "mp3streamin~ : could not allocate buffers." ); - return NULL; - } - - if ( nbinstances < MAX_DECODERS ) - { - x->x_instance = nbinstances++; - } - else - { - post( "mp3streamin~ : cannot create more decoders (memory issues), sorry" ); - return NULL; - } - - x->x_inwriteposition = 0; - x->x_outreadposition = 0; - x->x_outwriteposition = 0; - x->x_outunread = 0; - - ztout.tv_sec = 0; - ztout.tv_usec = 0; - - x->x_graphic = (int)fdographics; - - post( "mp3streamin~ : starting service on port %d", (int)fportno ); - mp3streamin_startservice(x, (int)fportno); - - // init lame decoder - mp3streamin_tilde_mpglib_init(x); - - return (x); -} - - -void mp3streamin_tilde_setup(void) -{ - post( mp3streamin_version ); - mp3streamin_class = class_new(gensym("mp3streamin~"), - (t_newmethod) mp3streamin_new, (t_method) mp3streamin_free, - sizeof(t_mp3streamin), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, A_NULL); - - class_addmethod(mp3streamin_class, nullfn, gensym("signal"), 0); - class_addmethod(mp3streamin_class, (t_method) mp3streamin_dsp, gensym("dsp"), 0); -} diff --git a/mp3live~/mp3streamout~.c b/mp3live~/mp3streamout~.c deleted file mode 100644 index 33555ce..0000000 --- a/mp3live~/mp3streamout~.c +++ /dev/null @@ -1,617 +0,0 @@ -/* ------------------------ mp3streamout~ ------------------------------------- */ -/* */ -/* Tilde object to send mp3-stream to a peer using mp3streamin~. */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates @ http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ -/* be found at http://www.cdex.n3.net. */ -/* */ -/* "I'd sell my soul to god" */ -/* "If it could take away the pain." */ -/* Theo Hakola -- */ -/* ---------------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef _WIN32 -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#endif - -#include /* lame encoder stuff */ - -#include "m_pd.h" /* standard pd stuff */ - -#include "mpg123.h" /* sub-library MPGLIB included in lame */ -/* useful debugging functions from mpglib */ -extern int decode_header( struct frame* fr, unsigned long newhead ); -extern void print_header_compact( struct frame* fr ); -extern int head_check( unsigned long head, int check_layer ); - -#define MY_MP3_MALLOC_IN_SIZE 65536 - /* max size taken from lame readme */ -#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 - -#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ -#define STRBUF_SIZE 32 - -static char *mp3streamout_version = "mp3streamout~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr"; - -static t_class *mp3streamout_class; - -typedef struct _mp3streamout -{ - t_object x_obj; - - /* LAME stuff */ - int x_lame; /* info about encoder status */ - int x_lamechunk; /* chunk size for LAME encoder */ - int x_mp3size; /* number of returned mp3 samples */ - - /* buffer stuff */ - unsigned short x_inp; /* in position for buffer */ - unsigned short x_outp; /* out position for buffer*/ - short *x_mp3inbuf; /* data to be sent to LAME */ - char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ - short *x_buffer; /* data to be buffered */ - int x_bytesbuffered; /* number of unprocessed bytes in buffer */ - int x_start; - - /* mp3 format stuff */ - int x_samplerate; - int x_bitrate; /* bitrate of mp3 stream */ - int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ - int x_mp3quality; /* quality of encoding */ - - /* connection data */ - int x_fd; /* info about connection status */ - int x_outpackets; /* mp3 packets sent */ - - t_float x_f; /* float needed for signal input */ - - lame_global_flags* lgfp; -} t_mp3streamout; - - - /* encode PCM data to mp3 stream */ -static void mp3streamout_encode(t_mp3streamout *x) -{ - unsigned short i, wp; - int err = -1; - int n = x->x_lamechunk; - -#ifdef UNIX - if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) -#else - if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) -#endif - { - error("not enough memory!"); - return; - } - - /* on start/reconnect set outpoint that it not interferes with inpoint */ - if(x->x_start == -1) - { - post("mp3streamout~: initializing buffers"); - /* we try to keep 2.5 times the data the encoder needs in the buffer */ - if(x->x_inp > (2 * x->x_lamechunk)) - { - x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); - } - else if(x->x_inp < (2 * x->x_lamechunk)) - { - x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); - } - x->x_start = 1; - } - if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3streamout~: buffers overlap!"); - - i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; - - /* read from buffer */ - if(x->x_lamechunk <= i) - { - /* enough data until end of buffer */ - for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ - { - x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; - } - x->x_outp += x->x_lamechunk; - } - else /* split data */ - { - for(wp = 0; wp < i; wp++) /* data at end of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; - } - - for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; - } - x->x_outp = x->x_lamechunk - i; - } - - /* encode mp3 data */ - - x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, - x->x_lamechunk/lame_get_num_channels(x->lgfp), - x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - x->x_mp3size+=lame_encode_flush( x->lgfp, x->x_mp3outbuf+x->x_mp3size, MY_MP3_MALLOC_OUT_SIZE-x->x_mp3size ); - // post( "mp3streamout~ : encoding returned %d frames", x->x_mp3size ); - - /* check result */ - if(x->x_mp3size<0) - { - lame_close( x->lgfp ); - error("mp3streamout~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); - x->x_lame = -1; - } -} - - /* stream mp3 to the peer */ -static void mp3streamout_stream(t_mp3streamout *x) -{ - int count = -1, i; - struct frame hframe; - - /* header needs to be included in each packet */ - - for( i=0; ix_mp3size; i++ ) - { - // track valid data - if ( head_check( *((unsigned long*)x->x_mp3outbuf+i), 3 ) ) - { - // post( "valid header emitted @ %d (byte %d)", i, i*sizeof(unsigned long) ); - } - } - - count = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, MSG_NOSIGNAL); - if(count < 0) - { - error("mp3streamout~: could not send encoded data to the peer (%d)", count); - lame_close( x->lgfp ); - x->x_lame = -1; -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - } - else - { - x->x_outpackets++; - if ( x->x_outpackets%100 == 0 ) - { - // post( "mp3streamout~ : emitted %d bytes (packets = %d)", count, x->x_outpackets ); - } - } - if((count > 0)&&(count != x->x_mp3size)) - { - error("mp3streamout~: %d bytes skipped", x->x_mp3size - count); - } -} - - - /* buffer data as channel interleaved PCM */ -static t_int *mp3streamout_perform(t_int *w) -{ - t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ - t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ - t_mp3streamout *x = (t_mp3streamout *)(w[3]); - int n = (int)(w[4]); /* number of samples */ - unsigned short i,wp; - float in; - - /* copy the data into the buffer */ - i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ - - n *= 2; /* two channels go into one buffer */ - - if( n <= i ) - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ - /* is big enough to hold the data */ - - for(wp = 0; wp < n; wp++) - { - if(wp%2) - { - in = *(in2++); /* right channel / inlet */ - } - else - { - in = *(in1++); /* left channel / inlet */ - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - x->x_inp += n; /* n more samples written to buffer */ - } - else - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ - /* big enough to hold the data */ - /* writing will take place in two turns, one from */ - /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ - - for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - for(wp = i; wp < n; wp++) /* write rest at start of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp - i] = (short) (32767.0 * in); - } - x->x_inp = n - i; /* new writeposition in buffer */ - } - - if((x->x_fd >= 0)&&(x->x_lame >= 0)) - { - /* count buffered samples when things are running */ - x->x_bytesbuffered += n; - - /* encode and send to the peer */ - if(x->x_bytesbuffered > x->x_lamechunk) - { - mp3streamout_encode(x); /* encode to mp3 */ - mp3streamout_stream(x); /* stream mp3 to the peer */ - x->x_bytesbuffered -= x->x_lamechunk; - } - } - else - { - x->x_start = -1; - } - return (w+5); -} - -static void mp3streamout_dsp(t_mp3streamout *x, t_signal **sp) -{ - dsp_add(mp3streamout_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); -} - - /* initialize the lame library */ -static void mp3streamout_tilde_lame_init(t_mp3streamout *x) -{ - int ret; - x->lgfp = lame_init(); /* set default parameters for now */ - -#ifndef UNIX - /* load lame_enc.dll library */ - HINSTANCE dll; - dll=LoadLibrary("lame_enc.dll"); - if(dll==NULL) - { - error("mp3streamout~: error loading lame_enc.dll"); - closesocket(x->x_fd); - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - post("mp3streamout~: connection closed"); - return; - } -#endif - { - const char *lameVersion = get_lame_version(); - post( "mp3streamout~ : using lame version : %s", lameVersion ); - } - - /* setting lame parameters */ - lame_set_num_channels( x->lgfp, 2); - lame_set_in_samplerate( x->lgfp, sys_getsr() ); - lame_set_out_samplerate( x->lgfp, x->x_samplerate ); - lame_set_brate( x->lgfp, x->x_bitrate ); - lame_set_mode( x->lgfp, x->x_mp3mode ); - lame_set_quality( x->lgfp, x->x_mp3quality ); - lame_set_emphasis( x->lgfp, 1 ); - lame_set_original( x->lgfp, 1 ); - lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ - lame_set_disable_reservoir( x->lgfp, 0 ); - lame_set_padding_type( x->lgfp, PAD_NO ); - ret = lame_init_params( x->lgfp ); - if ( ret<0 ) { - post( "mp3streamout~ : error : lame params initialization returned : %d", ret ); - } else { - x->x_lame=1; - /* magic formula copied from windows dll for MPEG-I */ - x->x_lamechunk = 2*1152; - - post( "mp3streamout~ : lame initialization done. (%d)", x->x_lame ); - } - lame_init_bitstream( x->lgfp ); -} - - /* connect to the peer */ -static void mp3streamout_connect(t_mp3streamout *x, t_symbol *hostname, t_floatarg fportno) -{ - struct sockaddr_in csocket; - struct hostent *hp; - int portno = fportno; /* get port from message box */ - - /* variables used for communication with the peer */ - const char *buf = 0; - char resp[STRBUF_SIZE]; - unsigned int len; - int sockfd; - -#ifndef UNIX - unsigned int ret; -#else - int ret; -#endif - - if (x->x_fd >= 0) - { - error("mp3streamout~: already connected"); - return; - } - - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - error("mp3streamout~: internal error while attempting to open socket"); - return; - } - - /* connect socket using hostname provided in command line */ - csocket.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) - { - post("mp3streamout~: bad host?"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - csocket.sin_port = htons((unsigned short)portno); - - /* try to connect. */ - post("mp3streamout~: connecting to port %d", portno); - if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) - { - error("mp3streamout~: connection failed!\n"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - - x->x_fd = sockfd; - x->x_outpackets = 0; - outlet_float( x->x_obj.ob_outlet, 1 ); - post( "mp3streamout~ : connected to peer" ); - - mp3streamout_tilde_lame_init(x); - -} - - /* close connection to the peer */ -static void mp3streamout_disconnect(t_mp3streamout *x) -{ - - int err = -1; - if(x->x_lame >= 0) - { - /* ignore remaining bytes */ - if ( x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, 0) < 0 ) { - post( "mp3streamout~ : warning : remaining encoded bytes" ); - } - lame_close( x->lgfp ); - x->x_lame = -1; - post("mp3streamout~: encoder stream closed"); - } - - if(x->x_fd >= 0) /* close socket */ - { -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - x->x_fd = -1; - outlet_float( x->x_obj.ob_outlet, 0 ); - post("mp3streamout~: connection closed"); - } -} - - /* settings for mp3 encoding */ -static void mp3streamout_mpeg(t_mp3streamout *x, t_floatarg fbitrate, - t_floatarg fmode, t_floatarg fquality) -{ - if ( fbitrate != 32 && fbitrate != 40 && fbitrate != 48 && fbitrate != 56 && - fbitrate != 64 && fbitrate != 80 && fbitrate != 96 && fbitrate != 112 && - fbitrate != 128 && fbitrate != 160 && fbitrate != 192 && fbitrate != 224 && - fbitrate != 256 && fbitrate != 320 ) { - post( "mp3streamout~ : wrong bitrate." ); - return; - } - if ( fmode <0 || fmode>2 ) { - post( "mp3streamout~ : wrong mp3 mode." ); - if ( fmode == 3 ) - { - post( "mp3streamout~ : mone is not supported by streamout~ for now." ); - } - return; - } - /* there is a bug in lame 3.92 and quality below 5 will not work */ - /* WAIT FOR A FIX */ - if ( fquality <5 || fquality>9 ) { - post( "mp3streamout~ : wrong quality." ); - return; - } - x->x_bitrate = fbitrate; - x->x_mp3mode = fmode; - x->x_mp3quality = (int)fquality; - post("mp3streamout~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", - x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); - mp3streamout_tilde_lame_init(x); -} - - /* print settings */ -static void mp3streamout_print(t_mp3streamout *x) -{ - const char * buf = 0; - - post(mp3streamout_version); - post(" LAME mp3 settings:\n" - " output sample rate: %d Hz\n" - " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); - switch(x->x_mp3mode) - { - case 0 : - buf = "stereo"; - break; - case 1 : - buf = "joint stereo"; - break; - case 2 : - buf = "dual channel"; - break; - case 3 : - buf = "mono"; - break; - } - post(" mode: %s\n" - " quality: %d", buf, x->x_mp3quality); -#ifndef UNIX - if(x->x_lamechunk!=0)post(" calculated mp3 chunk size: %d", x->x_lamechunk); -#else - post(" mp3 chunk size: %d", x->x_lamechunk); -#endif - if(x->x_samplerate!=sys_getsr()) - { - post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); - } -} - - /* clean up */ -static void mp3streamout_free(t_mp3streamout *x) -{ - - if(x->x_lame >= 0) - lame_close( x->lgfp ); - - if(x->x_fd >= 0) -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); - freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); -} - -static void *mp3streamout_new(void) -{ - t_mp3streamout *x = (t_mp3streamout *)pd_new(mp3streamout_class); - inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); - outlet_new( &x->x_obj, &s_float ); - x->lgfp = NULL; - x->x_fd = -1; - x->x_outpackets = 0; - x->x_lame = -1; - x->x_samplerate = sys_getsr(); - x->x_bitrate = 128; - x->x_mp3mode = 1; - x->x_mp3quality = 5; - x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ - x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE); /* our mp3 stream */ - x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ - if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ - { - error("out of memory!"); - } - x->x_bytesbuffered = 0; - x->x_inp = 0; - x->x_outp = 0; - x->x_start = -1; - return(x); -} - -void mp3streamout_tilde_setup(void) -{ - post(mp3streamout_version); - mp3streamout_class = class_new(gensym("mp3streamout~"), (t_newmethod)mp3streamout_new, (t_method)mp3streamout_free, - sizeof(t_mp3streamout), 0, 0); - CLASS_MAINSIGNALIN(mp3streamout_class, t_mp3streamout, x_f ); - class_addmethod(mp3streamout_class, (t_method)mp3streamout_dsp, gensym("dsp"), 0); - class_addmethod(mp3streamout_class, (t_method)mp3streamout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(mp3streamout_class, (t_method)mp3streamout_disconnect, gensym("disconnect"), 0); - class_addmethod(mp3streamout_class, (t_method)mp3streamout_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(mp3streamout_class, (t_method)mp3streamout_print, gensym("print"), 0); -} - diff --git a/mp3live~/mpglib.h b/mp3live~/mpglib.h deleted file mode 100644 index 1f4ef9a..0000000 --- a/mp3live~/mpglib.h +++ /dev/null @@ -1,65 +0,0 @@ -// #include "lame-analysis.h" - -#define NOANALYSIS - -#ifndef NOANALYSIS -extern plotting_data *mpg123_pinfo; -#endif - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -typedef struct mpstr_tag { - struct buf *head,*tail; - int vbr_header; /* 1 if valid Xing vbr header detected */ - int num_frames; /* set if vbr header present */ - int enc_delay; /* set if vbr header present */ - int enc_padding; /* set if vbr header present */ - int header_parsed; - int side_parsed; - int data_parsed; - int free_format; /* 1 = free format frame */ - int old_free_format; /* 1 = last frame was free format */ - int bsize; - int framesize; - int ssize; - int dsize; - int fsizeold; - int fsizeold_nopadding; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; - int sync_bitstream; - -} MPSTR, *PMPSTR; - - -#if ( defined(_MSC_VER) || defined(__BORLANDC__) ) - typedef int BOOL; /* windef.h contains the same definition */ -#else - #define BOOL int -#endif - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - - diff --git a/mp3live~/test-streaming-mp3.pd b/mp3live~/test-streaming-mp3.pd deleted file mode 100644 index e9e6b2e..0000000 --- a/mp3live~/test-streaming-mp3.pd +++ /dev/null @@ -1,96 +0,0 @@ -#N canvas 15 9 986 678 10; -#X msg 63 58 bang; -#X obj 63 78 openpanel; -#X obj 63 100 t s b; -#X obj 63 137 pack s s; -#X obj 99 100 float \$0; -#X text 51 39 Step 1 : Load a sound file; -#X obj 117 137 makefilename %d-sample; -#X msg 443 280 \; pd dsp 1; -#X msg 509 280 \; pd dsp 0; -#X obj 454 254 loadbang; -#X obj 62 217 mp3streamout~; -#X floatatom 63 240 5 0 0; -#X obj 62 181 readsf~; -#X msg 62 158 open \$1 \$2; -#X msg 33 148 1; -#X msg 265 185 disconnect; -#X obj 63 117 route float; -#X msg 569 47 bang; -#X obj 569 67 openpanel; -#X obj 569 89 t s b; -#X obj 569 126 pack s s; -#X obj 605 89 float \$0; -#X text 557 28 Step 1 : Load a sound file; -#X obj 623 126 makefilename %d-sample; -#X obj 568 206 mp3streamout~; -#X floatatom 569 229 5 0 0; -#X obj 568 170 readsf~; -#X msg 568 147 open \$1 \$2; -#X msg 539 137 1; -#X msg 784 177 disconnect; -#X obj 569 106 route float; -#X obj 364 462 dac~; -#X obj 361 438 *~; -#X floatatom 416 465 5 0 0; -#X symbolatom 459 437 15 0 0; -#X obj 407 440 / 100; -#X obj 122 470 dac~; -#X obj 119 446 *~; -#X floatatom 174 473 5 0 0; -#X symbolatom 217 445 10 0 0; -#X obj 165 448 / 100; -#X obj 96 419 mp3streamin~ 5001 1; -#X obj 345 410 mp3streamin~ 5000 1; -#X msg 777 149 connect yves 5001; -#X msg 246 228 mpeg 32 2 5; -#X msg 246 228 mpeg 32 2 5; -#X msg 246 264 mpeg 224 2 5; -#X msg 258 157 connect localhost 5000; -#X msg 263 125 connect dregs 5000; -#X connect 0 0 1 0; -#X connect 1 0 2 0; -#X connect 2 0 3 0; -#X connect 2 1 4 0; -#X connect 3 0 13 0; -#X connect 4 0 16 0; -#X connect 6 0 3 1; -#X connect 9 0 7 0; -#X connect 10 0 11 0; -#X connect 12 0 10 0; -#X connect 12 0 10 1; -#X connect 13 0 12 0; -#X connect 14 0 12 0; -#X connect 15 0 10 0; -#X connect 16 0 6 0; -#X connect 17 0 18 0; -#X connect 18 0 19 0; -#X connect 19 0 20 0; -#X connect 19 1 21 0; -#X connect 20 0 27 0; -#X connect 21 0 30 0; -#X connect 23 0 20 1; -#X connect 24 0 25 0; -#X connect 26 0 24 0; -#X connect 26 0 24 1; -#X connect 27 0 26 0; -#X connect 28 0 26 0; -#X connect 29 0 24 0; -#X connect 30 0 23 0; -#X connect 32 0 31 0; -#X connect 32 0 31 1; -#X connect 33 0 35 0; -#X connect 35 0 32 1; -#X connect 37 0 36 0; -#X connect 37 0 36 1; -#X connect 38 0 40 0; -#X connect 40 0 37 1; -#X connect 41 0 37 0; -#X connect 41 2 39 0; -#X connect 42 0 32 0; -#X connect 42 2 34 0; -#X connect 43 0 24 0; -#X connect 44 0 10 0; -#X connect 46 0 10 0; -#X connect 47 0 10 0; -#X connect 48 0 10 0; diff --git a/mp3streamin~.c b/mp3streamin~.c new file mode 100644 index 0000000..b01a576 --- /dev/null +++ b/mp3streamin~.c @@ -0,0 +1,671 @@ +/* ------------------------ mp3streamin~ -------------------------------------- */ +/* */ +/* Tilde object to receive an mp3-stream sent by a peer using mp3streamout~. */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates @ http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ +/* be found at http://www.cdex.n3.net. */ +/* */ +/* "Repackage sex, your interests." */ +/* "Somehow, maintain the interest." */ +/* Gang Of Four -- Natural's Not In It */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include + +#if PD_MINOR_VERSION >=37 +#include "s_stuff.h" +#endif + +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif /* _WIN32 */ + +#if defined(__APPLE__) || defined(_WIN32) +#define MSG_NOSIGNAL 0 +#define SOL_TCP IPPROTO_TCP +#endif + +#include "mpg123.h" /* mpg123 decoding library from lame 3.92 */ +#include "mpglib.h" /* mpglib decoding library from lame 3.92 */ +#include "interface.h" /* mpglib decoding library from lame 3.92 */ + +#define MIN_AUDIO_INPUT 8064 // we must a least have 8 chunks to play a correct sound +#define INPUT_BUFFER_SIZE MIN_AUDIO_INPUT +#define OUTPUT_BUFFER_SIZE 131072 /* 128k*/ +#define LAME_AUDIO_CHUNK_SIZE 1152 +#define BARHEIGHT 10 +#define MAX_DECODERS 10 + +/* useful debugging functions from mpglib */ +extern int decode_header( struct frame* fr, unsigned long newhead ); +extern void print_header_compact( struct frame* fr ); +extern int head_check( unsigned long head, int check_layer ); + +/* time-out used for select() call */ +static struct timeval ztout; + +static char *mp3streamin_version = "mp3streamin~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr"; + +extern void sys_sockerror(char *s); + +void mp3streamin_closesocket(int fd) +{ +#ifdef UNIX + if ( close(fd) < 0 ) + { + perror( "close" ); + } + else + { + post( "mp3streamin~ : closed socket : %d", fd ); + } +#endif +#ifdef NT + closesocket(fd); +#endif + sys_rmpollfn(fd); +} + +int setsocketoptions(int sockfd) +{ + int sockopt = 1; + if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0) + { + post("mp3streamin~ : setsockopt TCP_NODELAY failed"); + perror( "setsockopt" ); + return -1; + } + else + { + post("mp3streamin~ : TCP_NODELAY set"); + } + +#ifdef UNIX + sockopt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) + { + post("mp3streamin~ : setsockopt SO_REUSEADDR failed"); + perror( "setsockopt" ); + return -1; + } + else + { + post("mp3streamin~ : setsockopt SO_REUSEADDR done."); + } +#endif + return 0; +} + + +/* ------------------------ mp3streamin~ ----------------------------- */ + +static t_class *mp3streamin_class; + +typedef struct _mp3streamin +{ + t_object x_obj; + t_int x_instance; + t_int x_socket; + t_int x_shutdown; + t_outlet *x_connectionip; + t_int x_serversocket; + t_int x_inpackets; /* number of packets received */ + t_int x_dpacket; /* displayed packet in status bar */ + t_int x_packetsize; /* size of the packets */ + t_int x_pblocks; /* processed blocks */ + t_int x_graphic; /* indicates if we show a graphic bar */ + + void *x_inbuffer; /* accumulation buffer for incoming mp3 frames */ + t_int x_inwriteposition; + t_int x_inbuffersize; + + t_float *x_outbuffer; /* buffer to store audio decoded data */ + t_int x_outwriteposition; + t_int x_outreadposition; + t_int x_outunread; + t_int x_outbuffersize; + + t_canvas *x_canvas; + + t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ + t_int x_newstream; /* at first, the stream must provide enough data to start */ + t_int x_bitrateindex; /* remember the bitrate index */ + +} t_mp3streamin; + +/* too bad, this needs to be static, + handling an array to enable several decoders in pd */ +static MPSTR mp[MAX_DECODERS]; /* decoder buffer */ +int nbinstances = 0; + +void mp3streamin_tilde_mpglib_init(t_mp3streamin *x) +{ + int ret; + + InitMP3(&mp[x->x_instance]); +} + +static int mp3streamin_decode_input(t_mp3streamin *x) +{ + int i; + int alength = 0; + struct frame hframe; + unsigned int a,b,c,d; + unsigned long cheader; + static char out[8192]; + signed short int *p = (signed short int *) out; + int pbytes; + int ret; + + if ( !x->x_shutdown ) + { + /* decode first 4 bytes as the header */ + a = *((unsigned char*)x->x_inbuffer); + b = *((unsigned char*)x->x_inbuffer+1); + c = *((unsigned char*)x->x_inbuffer+2); + d = *((unsigned char*)x->x_inbuffer+3); + + cheader = 0; + cheader = a; + cheader <<= 8; + cheader |= b; + cheader <<= 8; + cheader |= c; + cheader <<= 8; + cheader |= d; + if ( head_check( cheader, 0 ) ) + { + // post( "mp3streamin~ : valid header ( packet=%d)", x->x_inpackets ); + decode_header( &hframe, cheader ); + // print_header_compact( &hframe ); + // when the bitrate change, reinit decoder + if ( x->x_bitrateindex != hframe.bitrate_index ) + { + ExitMP3(&mp[x->x_instance]); + InitMP3(&mp[x->x_instance]); + x->x_bitrateindex = hframe.bitrate_index; + } + } + else + { + post( "mp3streamin~ : error : mp3 packet received without header" ); + // ignore data + x->x_inwriteposition = 0; + x->x_inpackets--; + return( -1 ); + } + + // post( "mp3streamin~ : decoding %d bytes framesize=%d", x->x_inwriteposition, hframe.framesize ); + ret = + decodeMP3(&mp[x->x_instance], (unsigned char*)x->x_inbuffer, + x->x_inwriteposition, (char *) p, sizeof(out), &pbytes); + + switch (ret) { + case MP3_OK: + switch (mp[x->x_instance].fr.stereo) { + case 1: + case 2: + alength = ((mp[x->x_instance].fr.stereo==1)?pbytes >> 1 : pbytes >> 2); + // post( "mp3streamin~ : processed %d samples", alength ); + // update outbuffer contents + for ( i=0; ix_outunread >= x->x_outbuffersize-2 ) + { + post( "mp3streamin~ : too much input ... ignored" ); + continue; + } + *(x->x_outbuffer+x->x_outwriteposition) = ((t_float)(*p++))/32767.0; + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + *(x->x_outbuffer+x->x_outwriteposition) = + ((mp[x->x_instance].fr.stereo==2)?((t_float)(*p++))/32767.0 : 0.0); + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + x->x_outunread+=2; + + if ( x->x_outunread > MIN_AUDIO_INPUT && !x->x_stream ) + { + post( "mp3streamin~ : stream connected." ); + x->x_stream = 1; + } + } + + break; + default: + alength = -1; + break; + } + break; + + case MP3_NEED_MORE: + post( "mp3streamin~ : retry lame decoding (more data needed)." ); + alength = 0; + break; + + case MP3_ERR: + post( "mp3streamin~ : lame decoding failed." ); + alength = -1; + break; + + } + + x->x_inwriteposition = 0; + } + else + { + if ( x->x_outunread == 0 ) + { + post( "mp3streamin~ : connection closed" ); + mp3streamin_closesocket(x->x_socket); + x->x_stream = 0; + x->x_newstream = 0; + x->x_inpackets = 0; + x->x_inwriteposition = 0; + x->x_bitrateindex = -1; + x->x_socket=-1; + outlet_symbol( x->x_connectionip, gensym("") ); + } + } + + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + /* update graphical read status */ + if ( x->x_inpackets != x->x_dpacket ) + { + char color[32]; + int minpackets = ( MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE )-2; // audio loop has eaten some already + + + sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); + sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); + if ( x->x_outunread > 0 ) + { + t_int width; + + if ( x->x_inpackets < (MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE)/2 ) + { + strcpy( color, "red" ); + } + else + { + strcpy( color, "lightgreen" ); + } + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix+(x->x_inpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix - 1, color, x ); + sys_vgui(".x%x.c create line %d %d %d %d -fill red -tags %xTHRESHOLD\n", + x->x_canvas, x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix-1, x ); + x->x_dpacket = x->x_inpackets; + } + else + { + if ( x->x_shutdown ) + { + x->x_shutdown=0; + sys_vgui(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); + sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); + } + } + } + } + return alength; +} + +static void mp3streamin_recv(t_mp3streamin *x) +{ + int ret; + + if ( ( ret = recv(x->x_socket, (void*) (x->x_inbuffer + x->x_inwriteposition), + (size_t)((x->x_inbuffersize-x->x_inwriteposition)), + MSG_NOSIGNAL) ) < 0 ) + { + post( "mp3_streamin~ : receive error" ); + perror( "recv" ); + return; + } + else + { + // post( "streamin~ : received %d bytes at %d on %d ( up to %d)", + // ret, x->x_inwriteposition, x->x_socket, + // x->x_inbuffersize-x->x_inwriteposition*sizeof( unsigned long) ); + + if ( ret == 0 ) + { + /* initiate the shutdown phase */ + x->x_shutdown=1; + } + else + { + // check we don't overflow input buffer + if ( (x->x_inpackets+1)*x->x_packetsize > x->x_inbuffersize ) + { + post( "mp3streamin~ : too much input...resetting" ); + x->x_inpackets=0; + x->x_inwriteposition=0; + return; + } + x->x_inpackets++; + x->x_packetsize=ret; + if ( x->x_inpackets % 100 == 0 ) + { + // post( "mp3streamin~ : received %d packets", x->x_inpackets ); + } + x->x_inwriteposition += ret; + } + + mp3streamin_decode_input(x); + } +} + +static void mp3streamin_acceptconnection(t_mp3streamin *x) +{ + struct sockaddr_in incomer_address; + int sockaddrl = (int) sizeof( struct sockaddr ); + + int fd = accept(x->x_serversocket, (struct sockaddr*)&incomer_address, &sockaddrl ); + + if (fd < 0) { + post("mp3streamin~: accept failed"); + return; + } + + if (x->x_socket > 0) { + sys_addpollfn(fd, (t_fdpollfn)mp3streamin_recv, x); + if ( x->x_outunread != 0 ) + { + post("mp3streamin~: still have some data to decode, retry later you %s.", + inet_ntoa( incomer_address.sin_addr )); + mp3streamin_closesocket( fd ); + return; + } + post("mp3streamin~: the source has changed to %s.", + inet_ntoa( incomer_address.sin_addr )); + mp3streamin_closesocket(x->x_socket); + } + + x->x_socket = fd; + sys_addpollfn(x->x_socket, (t_fdpollfn)mp3streamin_recv, x); + outlet_symbol( x->x_connectionip, gensym( inet_ntoa( incomer_address.sin_addr) ) ); + + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + t_int width; + + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); + } + x->x_stream = 0; + x->x_newstream = 1; + +} + + +static int mp3streamin_startservice(t_mp3streamin* x, int portno) +{ + struct sockaddr_in server; + int sockfd; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + { + sys_sockerror("socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* assign server port number */ + server.sin_port = htons((u_short)portno); + post("listening to port number %d", portno); + + setsocketoptions(sockfd); + + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { + sys_sockerror("bind"); + mp3streamin_closesocket(sockfd); + return (0); + } + + if (listen(sockfd, 5) < 0) { + sys_sockerror("listen"); + mp3streamin_closesocket(sockfd); + } + else + { + x->x_serversocket = sockfd; + sys_addpollfn(x->x_serversocket, (t_fdpollfn)mp3streamin_acceptconnection, x); + } + + return 1; +} + +static void mp3streamin_free(t_mp3streamin *x) +{ + post( "mp3streamin~ : free %x", x ); + if (x->x_serversocket > 0) { + post( "mp3streamin~ : closing server socket" ); + mp3streamin_closesocket(x->x_serversocket); + x->x_serversocket = -1; + } + if (x->x_socket > 0) { + post( "mp3streamin~ : closing socket" ); + mp3streamin_closesocket(x->x_socket); + x->x_socket = -1; + } + if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); + if ( x->x_outbuffer ) freebytes( x->x_outbuffer, x->x_outbuffersize*sizeof(t_float) ); + if ( x->x_instance == nbinstances-1 ) + { + nbinstances--; + } +} + +static t_int *mp3streamin_perform(t_int *w) +{ + t_mp3streamin *x = (t_mp3streamin*) (w[1]); + t_float *out1 = (t_float *)(w[2]); + t_float *out2 = (t_float *)(w[3]); + int n = (int)(w[4]); + int bsize = n; + int ret; + int i = 0; + + while( n-- ) + { + if ( ( ( x->x_outunread > MIN_AUDIO_INPUT ) && x->x_newstream ) || // wait the buffer to load + ( ( x->x_shutdown ) && ( x->x_outunread >= 2 ) ) || // clean disconnection + ( x->x_stream ) // check that the stream provides enough data + ) + { + if ( x->x_newstream && !x->x_shutdown ) + { + x->x_newstream = 0; + x->x_stream = 1; + } + *out1++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + *out2++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + x->x_outunread-=2; + if ( n == 1 ) x->x_pblocks++; + } + else + { + *out1++=0.0; + *out2++=0.0; + } + } + + if ( ( x->x_outunread <= MIN_AUDIO_INPUT/10 ) && ( x->x_stream ) ) + { + post( "mp3streamin~ : stream lost (too little input)" ); + x->x_stream = 0; + x->x_newstream = 1; // waiting for a new stream + } + + if ( x->x_pblocks == LAME_AUDIO_CHUNK_SIZE/bsize ) + { + x->x_inpackets--; + x->x_pblocks = 0; + } + +#ifdef DO_MY_OWN_SELECT + // check new incoming data + if ( x->x_socket > 0 ) + { + fd_set readset; + fd_set exceptset; + + FD_ZERO(&readset); + FD_ZERO(&exceptset); + FD_SET(x->x_socket, &readset ); + FD_SET(x->x_socket, &exceptset ); + + if ( select( maxfd+1, &readset, NULL, &exceptset, &ztout ) >0 ) + { + if ( FD_ISSET( x->x_socket, &readset) || FD_ISSET( x->x_socket, &exceptset ) ) + { + /* receive data or error and decode it */ + mp3streamin_recv(x); + } + } + } +#endif + return (w+5); +} + +static void mp3streamin_dsp(t_mp3streamin *x, t_signal **sp) +{ + dsp_add(mp3streamin_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + + +static void *mp3streamin_new(t_floatarg fportno, t_floatarg fdographics) +{ + t_mp3streamin *x; + int i; + + if ( fportno < 0 || fportno > 65535 ) + { + post( "mp3streamin~ : error : wrong portnumber : %d", (int)fportno ); + return NULL; + } + if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) + { + post( "mp3streamin~ : error : constructor : mp3streamin~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); + return NULL; + } + + x = (t_mp3streamin *)pd_new(mp3streamin_class); + post( "mp3streamin~ : new %x (instance = %d) %d", x, nbinstances, sizeof( MPSTR ) ); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); + + x->x_serversocket = -1; + x->x_socket = -1; + x->x_shutdown = 0; + x->x_inpackets = 0; + x->x_dpacket = -1; + + x->x_canvas = canvas_getcurrent(); + + x->x_inbuffersize = INPUT_BUFFER_SIZE; + x->x_outbuffersize = OUTPUT_BUFFER_SIZE; + x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); + memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); + x->x_outbuffer = (t_float*) getbytes( x->x_outbuffersize*sizeof(t_float) ); + memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE ); + + if ( !x->x_inbuffer || !x->x_outbuffer ) + { + post( "mp3streamin~ : could not allocate buffers." ); + return NULL; + } + + if ( nbinstances < MAX_DECODERS ) + { + x->x_instance = nbinstances++; + } + else + { + post( "mp3streamin~ : cannot create more decoders (memory issues), sorry" ); + return NULL; + } + + x->x_inwriteposition = 0; + x->x_outreadposition = 0; + x->x_outwriteposition = 0; + x->x_outunread = 0; + + ztout.tv_sec = 0; + ztout.tv_usec = 0; + + x->x_graphic = (int)fdographics; + + post( "mp3streamin~ : starting service on port %d", (int)fportno ); + mp3streamin_startservice(x, (int)fportno); + + // init lame decoder + mp3streamin_tilde_mpglib_init(x); + + return (x); +} + + +void mp3streamin_tilde_setup(void) +{ + post( mp3streamin_version ); + mp3streamin_class = class_new(gensym("mp3streamin~"), + (t_newmethod) mp3streamin_new, (t_method) mp3streamin_free, + sizeof(t_mp3streamin), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, A_NULL); + + class_addmethod(mp3streamin_class, nullfn, gensym("signal"), 0); + class_addmethod(mp3streamin_class, (t_method) mp3streamin_dsp, gensym("dsp"), 0); +} diff --git a/mp3streamout~.c b/mp3streamout~.c new file mode 100644 index 0000000..f2ea966 --- /dev/null +++ b/mp3streamout~.c @@ -0,0 +1,617 @@ +/* ------------------------ mp3streamout~ ------------------------------------- */ +/* */ +/* Tilde object to send mp3-stream to a peer using mp3streamin~. */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates @ http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can */ +/* be found at http://www.cdex.n3.net. */ +/* */ +/* "I'd sell my soul to god" */ +/* "If it could take away the pain." */ +/* Theo Hakola -- */ +/* ---------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +#if defined(__APPLE__) || defined(_WIN32) +#define MSG_NOSIGNAL 0 +#endif + +#include /* lame encoder stuff */ + +#include "m_pd.h" /* standard pd stuff */ + +#include "mpg123.h" /* sub-library MPGLIB included in lame */ +/* useful debugging functions from mpglib */ +extern int decode_header( struct frame* fr, unsigned long newhead ); +extern void print_header_compact( struct frame* fr ); +extern int head_check( unsigned long head, int check_layer ); + +#define MY_MP3_MALLOC_IN_SIZE 65536 + /* max size taken from lame readme */ +#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 + +#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ +#define STRBUF_SIZE 32 + +static char *mp3streamout_version = "mp3streamout~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr"; + +static t_class *mp3streamout_class; + +typedef struct _mp3streamout +{ + t_object x_obj; + + /* LAME stuff */ + int x_lame; /* info about encoder status */ + int x_lamechunk; /* chunk size for LAME encoder */ + int x_mp3size; /* number of returned mp3 samples */ + + /* buffer stuff */ + unsigned short x_inp; /* in position for buffer */ + unsigned short x_outp; /* out position for buffer*/ + short *x_mp3inbuf; /* data to be sent to LAME */ + char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ + short *x_buffer; /* data to be buffered */ + int x_bytesbuffered; /* number of unprocessed bytes in buffer */ + int x_start; + + /* mp3 format stuff */ + int x_samplerate; + int x_bitrate; /* bitrate of mp3 stream */ + int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ + int x_mp3quality; /* quality of encoding */ + + /* connection data */ + int x_fd; /* info about connection status */ + int x_outpackets; /* mp3 packets sent */ + + t_float x_f; /* float needed for signal input */ + + lame_global_flags* lgfp; +} t_mp3streamout; + + + /* encode PCM data to mp3 stream */ +static void mp3streamout_encode(t_mp3streamout *x) +{ + unsigned short i, wp; + int err = -1; + int n = x->x_lamechunk; + +#ifdef UNIX + if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) +#else + if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) +#endif + { + error("not enough memory!"); + return; + } + + /* on start/reconnect set outpoint that it not interferes with inpoint */ + if(x->x_start == -1) + { + post("mp3streamout~: initializing buffers"); + /* we try to keep 2.5 times the data the encoder needs in the buffer */ + if(x->x_inp > (2 * x->x_lamechunk)) + { + x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); + } + else if(x->x_inp < (2 * x->x_lamechunk)) + { + x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); + } + x->x_start = 1; + } + if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3streamout~: buffers overlap!"); + + i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; + + /* read from buffer */ + if(x->x_lamechunk <= i) + { + /* enough data until end of buffer */ + for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ + { + x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; + } + x->x_outp += x->x_lamechunk; + } + else /* split data */ + { + for(wp = 0; wp < i; wp++) /* data at end of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; + } + + for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; + } + x->x_outp = x->x_lamechunk - i; + } + + /* encode mp3 data */ + + x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, + x->x_lamechunk/lame_get_num_channels(x->lgfp), + x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + x->x_mp3size+=lame_encode_flush( x->lgfp, x->x_mp3outbuf+x->x_mp3size, MY_MP3_MALLOC_OUT_SIZE-x->x_mp3size ); + // post( "mp3streamout~ : encoding returned %d frames", x->x_mp3size ); + + /* check result */ + if(x->x_mp3size<0) + { + lame_close( x->lgfp ); + error("mp3streamout~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); + x->x_lame = -1; + } +} + + /* stream mp3 to the peer */ +static void mp3streamout_stream(t_mp3streamout *x) +{ + int count = -1, i; + struct frame hframe; + + /* header needs to be included in each packet */ + + for( i=0; ix_mp3size; i++ ) + { + // track valid data + if ( head_check( *((unsigned long*)x->x_mp3outbuf+i), 3 ) ) + { + // post( "valid header emitted @ %d (byte %d)", i, i*sizeof(unsigned long) ); + } + } + + count = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, MSG_NOSIGNAL); + if(count < 0) + { + error("mp3streamout~: could not send encoded data to the peer (%d)", count); + lame_close( x->lgfp ); + x->x_lame = -1; +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + } + else + { + x->x_outpackets++; + if ( x->x_outpackets%100 == 0 ) + { + // post( "mp3streamout~ : emitted %d bytes (packets = %d)", count, x->x_outpackets ); + } + } + if((count > 0)&&(count != x->x_mp3size)) + { + error("mp3streamout~: %d bytes skipped", x->x_mp3size - count); + } +} + + + /* buffer data as channel interleaved PCM */ +static t_int *mp3streamout_perform(t_int *w) +{ + t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ + t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ + t_mp3streamout *x = (t_mp3streamout *)(w[3]); + int n = (int)(w[4]); /* number of samples */ + unsigned short i,wp; + float in; + + /* copy the data into the buffer */ + i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ + + n *= 2; /* two channels go into one buffer */ + + if( n <= i ) + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ + /* is big enough to hold the data */ + + for(wp = 0; wp < n; wp++) + { + if(wp%2) + { + in = *(in2++); /* right channel / inlet */ + } + else + { + in = *(in1++); /* left channel / inlet */ + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + x->x_inp += n; /* n more samples written to buffer */ + } + else + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ + /* big enough to hold the data */ + /* writing will take place in two turns, one from */ + /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ + + for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + for(wp = i; wp < n; wp++) /* write rest at start of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp - i] = (short) (32767.0 * in); + } + x->x_inp = n - i; /* new writeposition in buffer */ + } + + if((x->x_fd >= 0)&&(x->x_lame >= 0)) + { + /* count buffered samples when things are running */ + x->x_bytesbuffered += n; + + /* encode and send to the peer */ + if(x->x_bytesbuffered > x->x_lamechunk) + { + mp3streamout_encode(x); /* encode to mp3 */ + mp3streamout_stream(x); /* stream mp3 to the peer */ + x->x_bytesbuffered -= x->x_lamechunk; + } + } + else + { + x->x_start = -1; + } + return (w+5); +} + +static void mp3streamout_dsp(t_mp3streamout *x, t_signal **sp) +{ + dsp_add(mp3streamout_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + + /* initialize the lame library */ +static void mp3streamout_tilde_lame_init(t_mp3streamout *x) +{ + int ret; + x->lgfp = lame_init(); /* set default parameters for now */ + +#ifdef _WIN32 + /* load lame_enc.dll library */ + HINSTANCE dll; + dll=LoadLibrary("lame_enc.dll"); + if(dll==NULL) + { + error("mp3streamout~: error loading lame_enc.dll"); + closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("mp3streamout~: connection closed"); + return; + } +#endif + { + const char *lameVersion = get_lame_version(); + post( "mp3streamout~ : using lame version : %s", lameVersion ); + } + + /* setting lame parameters */ + lame_set_num_channels( x->lgfp, 2); + lame_set_in_samplerate( x->lgfp, sys_getsr() ); + lame_set_out_samplerate( x->lgfp, x->x_samplerate ); + lame_set_brate( x->lgfp, x->x_bitrate ); + lame_set_mode( x->lgfp, x->x_mp3mode ); + lame_set_quality( x->lgfp, x->x_mp3quality ); + lame_set_emphasis( x->lgfp, 1 ); + lame_set_original( x->lgfp, 1 ); + lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ + lame_set_disable_reservoir( x->lgfp, 0 ); + lame_set_padding_type( x->lgfp, PAD_NO ); + ret = lame_init_params( x->lgfp ); + if ( ret<0 ) { + post( "mp3streamout~ : error : lame params initialization returned : %d", ret ); + } else { + x->x_lame=1; + /* magic formula copied from windows dll for MPEG-I */ + x->x_lamechunk = 2*1152; + + post( "mp3streamout~ : lame initialization done. (%d)", x->x_lame ); + } + lame_init_bitstream( x->lgfp ); +} + + /* connect to the peer */ +static void mp3streamout_connect(t_mp3streamout *x, t_symbol *hostname, t_floatarg fportno) +{ + struct sockaddr_in csocket; + struct hostent *hp; + int portno = fportno; /* get port from message box */ + + /* variables used for communication with the peer */ + const char *buf = 0; + char resp[STRBUF_SIZE]; + unsigned int len; + int sockfd; + +#ifdef _WIN32 + unsigned int ret; +#else + int ret; +#endif + + if (x->x_fd >= 0) + { + error("mp3streamout~: already connected"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("mp3streamout~: internal error while attempting to open socket"); + return; + } + + /* connect socket using hostname provided in command line */ + csocket.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("mp3streamout~: bad host?"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + csocket.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("mp3streamout~: connecting to port %d", portno); + if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) + { + error("mp3streamout~: connection failed!\n"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + x->x_fd = sockfd; + x->x_outpackets = 0; + outlet_float( x->x_obj.ob_outlet, 1 ); + post( "mp3streamout~ : connected to peer" ); + + mp3streamout_tilde_lame_init(x); + +} + + /* close connection to the peer */ +static void mp3streamout_disconnect(t_mp3streamout *x) +{ + + int err = -1; + if(x->x_lame >= 0) + { + /* ignore remaining bytes */ + if ( x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, 0) < 0 ) { + post( "mp3streamout~ : warning : remaining encoded bytes" ); + } + lame_close( x->lgfp ); + x->x_lame = -1; + post("mp3streamout~: encoder stream closed"); + } + + if(x->x_fd >= 0) /* close socket */ + { +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + x->x_fd = -1; + outlet_float( x->x_obj.ob_outlet, 0 ); + post("mp3streamout~: connection closed"); + } +} + + /* settings for mp3 encoding */ +static void mp3streamout_mpeg(t_mp3streamout *x, t_floatarg fbitrate, + t_floatarg fmode, t_floatarg fquality) +{ + if ( fbitrate != 32 && fbitrate != 40 && fbitrate != 48 && fbitrate != 56 && + fbitrate != 64 && fbitrate != 80 && fbitrate != 96 && fbitrate != 112 && + fbitrate != 128 && fbitrate != 160 && fbitrate != 192 && fbitrate != 224 && + fbitrate != 256 && fbitrate != 320 ) { + post( "mp3streamout~ : wrong bitrate." ); + return; + } + if ( fmode <0 || fmode>2 ) { + post( "mp3streamout~ : wrong mp3 mode." ); + if ( fmode == 3 ) + { + post( "mp3streamout~ : mone is not supported by streamout~ for now." ); + } + return; + } + /* there is a bug in lame 3.92 and quality below 5 will not work */ + /* WAIT FOR A FIX */ + if ( fquality <5 || fquality>9 ) { + post( "mp3streamout~ : wrong quality." ); + return; + } + x->x_bitrate = fbitrate; + x->x_mp3mode = fmode; + x->x_mp3quality = (int)fquality; + post("mp3streamout~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", + x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); + mp3streamout_tilde_lame_init(x); +} + + /* print settings */ +static void mp3streamout_print(t_mp3streamout *x) +{ + const char * buf = 0; + + post(mp3streamout_version); + post(" LAME mp3 settings:\n" + " output sample rate: %d Hz\n" + " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); + switch(x->x_mp3mode) + { + case 0 : + buf = "stereo"; + break; + case 1 : + buf = "joint stereo"; + break; + case 2 : + buf = "dual channel"; + break; + case 3 : + buf = "mono"; + break; + } + post(" mode: %s\n" + " quality: %d", buf, x->x_mp3quality); +#ifdef _WIN32 + if(x->x_lamechunk!=0)post(" calculated mp3 chunk size: %d", x->x_lamechunk); +#else + post(" mp3 chunk size: %d", x->x_lamechunk); +#endif + if(x->x_samplerate!=sys_getsr()) + { + post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); + } +} + + /* clean up */ +static void mp3streamout_free(t_mp3streamout *x) +{ + + if(x->x_lame >= 0) + lame_close( x->lgfp ); + + if(x->x_fd >= 0) +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); + freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); +} + +static void *mp3streamout_new(void) +{ + t_mp3streamout *x = (t_mp3streamout *)pd_new(mp3streamout_class); + inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); + outlet_new( &x->x_obj, &s_float ); + x->lgfp = NULL; + x->x_fd = -1; + x->x_outpackets = 0; + x->x_lame = -1; + x->x_samplerate = sys_getsr(); + x->x_bitrate = 128; + x->x_mp3mode = 1; + x->x_mp3quality = 5; + x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ + x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE); /* our mp3 stream */ + x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ + if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ + { + error("out of memory!"); + } + x->x_bytesbuffered = 0; + x->x_inp = 0; + x->x_outp = 0; + x->x_start = -1; + return(x); +} + +void mp3streamout_tilde_setup(void) +{ + post(mp3streamout_version); + mp3streamout_class = class_new(gensym("mp3streamout~"), (t_newmethod)mp3streamout_new, (t_method)mp3streamout_free, + sizeof(t_mp3streamout), 0, 0); + CLASS_MAINSIGNALIN(mp3streamout_class, t_mp3streamout, x_f ); + class_addmethod(mp3streamout_class, (t_method)mp3streamout_dsp, gensym("dsp"), 0); + class_addmethod(mp3streamout_class, (t_method)mp3streamout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(mp3streamout_class, (t_method)mp3streamout_disconnect, gensym("disconnect"), 0); + class_addmethod(mp3streamout_class, (t_method)mp3streamout_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mp3streamout_class, (t_method)mp3streamout_print, gensym("print"), 0); +} + diff --git a/mp3write~-help.pd b/mp3write~-help.pd new file mode 100644 index 0000000..0e575ba --- /dev/null +++ b/mp3write~-help.pd @@ -0,0 +1,43 @@ +#N canvas 168 244 736 325 10; +#X floatatom 53 24 0 40 16000; +#X msg 168 278 \; pd dsp 1; +#X text 287 196 <-- settings for mp3 stream; +#X text 310 226 bitrate: bitrate of stream \, def. 224kbit/s; +#X text 347 250 1 = joint stereo (default); +#X text 307 288 quality: 1 = high \, 9 = low; +#X text 308 208 (samplerate \, bitrate \, mode \, quality); +#X text 311 238 mode: 0 = stereo; +#X text 347 262 2 = dual channel; +#X text 347 275 3 = mono; +#X msg 171 143 print; +#X msg 234 278 \; pd dsp 0; +#X obj 51 59 osc~ 440; +#X msg 169 174 mpeg 44100 128 1 4; +#X msg 171 121 truncate; +#X msg 171 98 append; +#X msg 170 72 stop; +#X msg 170 49 start; +#X text 370 24 Open a file before any operations; +#X text 228 95 Set recording mode to append ( which is the default +); +#X text 208 48 Start recording; +#X text 231 118 Set recording mode to truncate; +#X text 218 142 Print settings; +#X floatatom 116 258 10 0 0; +#X text 10 254 Bytes written; +#X text 208 71 Stop recording ( this also writes a tag ); +#X msg 169 198 mpeg 44100 8 3 5; +#X msg 170 25 open /tmp/track1.mp3; +#X obj 116 234 mp3write~; +#X connect 0 0 12 0; +#X connect 10 0 28 0; +#X connect 12 0 28 0; +#X connect 12 0 28 1; +#X connect 13 0 28 0; +#X connect 14 0 28 0; +#X connect 15 0 28 0; +#X connect 16 0 28 0; +#X connect 17 0 28 0; +#X connect 26 0 28 0; +#X connect 27 0 28 0; +#X connect 28 0 23 0; diff --git a/mp3write~.c b/mp3write~.c new file mode 100644 index 0000000..d16c427 --- /dev/null +++ b/mp3write~.c @@ -0,0 +1,608 @@ +/* ------------------------ mp3write~ ----------------------------------------- */ +/* */ +/* Tilde object to record audio in mp3 format */ +/* Note that it is, in no way, related to mp3play~ */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates at http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the LAME MPEG 1 Layer 3 version 3.92 */ +/* Get it via http://www.freshmeat.net */ +/* */ +/* "All this talk of blood and iron is the cause of all my kicking" */ +/* Gang Of Four - "Guns Before Butter" */ +/* ---------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif /* _WIN32 */ +#include +#include /* lame encoder stuff */ +#include "m_pd.h" /* standard pd stuff */ + +#define MY_MP3_MALLOC_IN_SIZE 65536 + /* max size taken from lame readme */ +#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 + +#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ +#define STRBUF_SIZE 32 + +static char *mp3write_version = "mp3write~: mp3 file recorder version 0.4, written by Yves Degoyon"; +static int sockfd; + +static t_class *mp3write_class; + +typedef struct _mp3write +{ + t_object x_obj; + + /* LAME stuff */ + int x_lame; /* info about encoder status */ + int x_lamechunk; /* chunk size for LAME encoder */ + + /* buffer stuff */ + unsigned short x_inp; /* in position for buffer */ + unsigned short x_outp; /* out position for buffer*/ + short *x_mp3inbuf; /* data to be sent to LAME */ + char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ + int x_mp3size; /* number of returned mp3 samples */ + short *x_buffer; /* data to be buffered */ + int x_bytesbuffered; /* number of unprocessed bytes in buffer */ + int x_start; + + /* mp3 format stuff */ + int x_samplerate; + int x_bitrate; /* bitrate of mp3 stream */ + int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ + int x_mp3quality; /* quality of encoding */ + + /* recording stuff */ + int x_fd; /* file descriptor of the mp3 output */ + int x_file_open_mode; /* file opening mode */ + int x_byteswritten; /* number of bytes written */ + int x_recflag; /* recording flag toggled by messages "start" and "stop" */ + + t_float x_f; /* float needed for signal input */ + char *x_title; /* title of the mp3 */ + + lame_global_flags *lgfp; /* lame encoder configuration */ +} t_mp3write; + + + /* encode PCM data to mp3 stream */ +static void mp3write_encode(t_mp3write *x) +{ + unsigned short i, wp; + int err = -1; + int n = x->x_lamechunk; + +#ifdef UNIX + if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) +#else + if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) +#endif + { + error("not enough memory!"); + return; + } + + /* on start/reconnect set outpoint so that it won't interfere with inpoint */ + if(x->x_start == -1) + { + post("mp3write~: reseting buffer positions"); + /* we try to keep 2.5 times the data the encoder needs in the buffer */ + if(x->x_inp > (2 * x->x_lamechunk)) + { + x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); + } + else if(x->x_inp < (2 * x->x_lamechunk)) + { + x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); + } + x->x_start = 1; + } + if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3write~: buffers overlap!"); + + i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; + + /* read from buffer */ + if(x->x_lamechunk <= i) + { + /* enough data until end of buffer */ + for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ + { + x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; + } + x->x_outp += x->x_lamechunk; + } + else /* split data */ + { + for(wp = 0; wp < i; wp++) /* data at end of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; + } + + for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ + { + x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; + } + x->x_outp = x->x_lamechunk - i; + } + + /* encode mp3 data */ + + x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, + x->x_lamechunk/lame_get_num_channels(x->lgfp), + x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + // post( "mp3write~ : encoding returned %d frames", x->x_mp3size ); + + /* check result */ + if(x->x_mp3size<0) + { + lame_close( x->lgfp ); + error("mp3write~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); + x->x_lame = -1; + } +} + + /* store mp3 frames in the file */ +static void mp3write_writeframes(t_mp3write *x) +{ + int err = -1; /* error return code */ + + if ( x->x_fd < 0 ) { + post( "mp3write~ : error : trying to write frames but no valid file is opened" ); + return; + } + +#ifdef _WIN32 + err = _write(x->x_fd, x->x_mp3outbuf, x->x_mp3size); +#else + err = write(x->x_fd, x->x_mp3outbuf, x->x_mp3size); +#endif + + if(err < 0) + { + error("mp3write~: could not write encoded data to file (%d)", err); + lame_close( x->lgfp ); + x->x_lame = -1; +#ifdef _WIN32 + error("mp3write~: writing data"); + _close(x->x_fd); +#else + perror("mp3write~: writing data"); + close(x->x_fd); +#endif + x->x_fd = -1; + } + else + { + x->x_byteswritten += err; + outlet_float( x->x_obj.ob_outlet, x->x_byteswritten ); + } + if((err > 0)&&(err != x->x_mp3size))error("mp3write~: %d bytes skipped", x->x_mp3size - err); +} + + + /* buffer data as channel interleaved PCM */ +static t_int *mp3write_perform(t_int *w) +{ + t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ + t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ + t_mp3write *x = (t_mp3write *)(w[3]); + int n = (int)(w[4]); /* number of samples */ + unsigned short i,wp; + float in; + + /* copy the data into the buffer */ + i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ + + n *= 2; /* two channels go into one buffer */ + + if( n <= i ) + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ + /* is big enough to hold the data */ + + for(wp = 0; wp < n; wp++) + { + if(wp%2) + { + in = *(in2++); /* right channel / inlet */ + } + else + { + in = *(in1++); /* left channel / inlet */ + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + x->x_inp += n; /* n more samples written to buffer */ + } + else + { + /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ + /* big enough to hold the data */ + /* writing will take place in two turns, one from */ + /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ + + for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); + } + for(wp = i; wp < n; wp++) /* write rest at start of buffer */ + { + if(wp%2) + { + in = *(in2++); + } + else + { + in = *(in1++); + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[wp - i] = (short) (32767.0 * in); + } + x->x_inp = n - i; /* new writeposition in buffer */ + } + + if((x->x_fd >= 0)&&(x->x_lame >= 0)&&(x->x_recflag)) + { + /* count buffered samples when things are running */ + x->x_bytesbuffered += n; + + /* encode and send to server */ + if(x->x_bytesbuffered > x->x_lamechunk) + { + mp3write_encode(x); /* encode to mp3 */ + mp3write_writeframes(x); /* write mp3 to file */ + x->x_bytesbuffered -= x->x_lamechunk; + } + } + else + { + x->x_start = -1; + } + return (w+5); +} + +static void mp3write_dsp(t_mp3write *x, t_signal **sp) +{ + dsp_add(mp3write_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + + /* initialize the lame library */ +static int mp3write_tilde_lame_init(t_mp3write *x) +{ + time_t now; + + int ret; + x->lgfp = lame_init(); /* set default parameters for now */ + +#ifdef _WIN32 + /* load lame_enc.dll library */ + HINSTANCE dll; + dll=LoadLibrary("lame_enc.dll"); + if(dll==NULL) + { + error("mp3write~: error loading lame_enc.dll"); + closesocket(x->x_fd); + x->x_fd = -1; + post("mp3write~: connection closed"); + return -1; + } +#endif + { + const char *lameVersion = get_lame_version(); + post( "mp3write~ : using lame version : %s", lameVersion ); + } + + /* setting lame parameters */ + lame_set_num_channels( x->lgfp, 2); + lame_set_in_samplerate( x->lgfp, sys_getsr() ); + lame_set_out_samplerate( x->lgfp, x->x_samplerate ); + lame_set_brate( x->lgfp, x->x_bitrate ); + lame_set_mode( x->lgfp, x->x_mp3mode ); + lame_set_quality( x->lgfp, x->x_mp3quality ); + lame_set_emphasis( x->lgfp, 1 ); + lame_set_original( x->lgfp, 1 ); + lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ + lame_set_disable_reservoir( x->lgfp, 0 ); + lame_set_padding_type( x->lgfp, PAD_NO ); + ret = lame_init_params( x->lgfp ); + if ( ret<0 ) { + post( "mp3write~ : error : lame params initialization returned : %d", ret ); + return -1; + } else { + x->x_lame=1; + /* magic formula copied from windows dll for MPEG-I */ + x->x_lamechunk = 2*1152; + + post( "mp3write~ : lame initialization done. (%d)", x->x_lame ); + } + lame_init_bitstream( x->lgfp ); + + /* setting tag information */ + id3tag_init(x->lgfp); + id3tag_v1_only(x->lgfp); + id3tag_space_v1(x->lgfp); + id3tag_set_artist(x->lgfp, "Pd Session"); + now=time(NULL); + sprintf( x->x_title, "Started at %s", ctime(&now) ); + id3tag_set_title(x->lgfp, x->x_title ); + + return 0; + +} + + /* open file and initialize lame */ +static void mp3write_open(t_mp3write *x, t_symbol *sfile) +{ + if ( mp3write_tilde_lame_init(x) < 0 ) { + error( "mp3write~ : lame initialization failed ... check parameters."); + return; + } + + /* closing previous file descriptor */ + if ( x->x_fd > 0 ) { +#ifdef _WIN32 + if(_close(x->x_fd) < 0 ) +#else + if(close(x->x_fd) < 0) +#endif + { + perror( "mp3write~ : closing file" ); + } + } + + if ( x->x_recflag ) { + x->x_recflag = 0; + } + +#ifdef _WIN32 + if ( ( x->x_fd = _open( sfile->s_name, x->x_file_open_mode, _S_IREAD|_S_IWRITE) ) < 0 ) +#else + if ( ( x->x_fd = open( sfile->s_name, x->x_file_open_mode, S_IRWXU|S_IRWXG|S_IRWXO ) ) < 0 ) +#endif + { + error( "mp3write~ : cannot open >%s<", sfile->s_name); + x->x_fd=-1; + return; + } + x->x_byteswritten = 0; + post( "mp3write~ : opened >%s< fd=%d", sfile->s_name, x->x_fd); +} + + /* setting file write mode to append */ +static void mp3write_append(t_mp3write *x) +{ +#ifdef _WIN32 + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; +#endif + if(x->x_fd>=0)post("mp3write~ : mode set to append : open a new file to make changes take effect! "); +} + + /* setting file write mode to truncate */ +static void mp3write_truncate(t_mp3write *x) +{ +#ifdef _WIN32 + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_TRUNC|O_NONBLOCK; +#endif + if(x->x_fd>=0)post("mp3write~ : mode set to truncate : open a new file to make changes take effect! "); +} + + /* settings for mp3 encoding */ +static void mp3write_mpeg(t_mp3write *x, t_floatarg fsamplerate, t_floatarg fbitrate, + t_floatarg fmode, t_floatarg fquality) +{ + x->x_samplerate = fsamplerate; + if(fbitrate > MAXDATARATE) + { + fbitrate = MAXDATARATE; + } + x->x_bitrate = fbitrate; + x->x_mp3mode = fmode; + x->x_mp3quality = fquality; + post("mp3write~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", + x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); + if(x->x_fd>=0)post("mp3write~ : restart recording to make changes take effect! "); +} + + /* print settings */ +static void mp3write_print(t_mp3write *x) +{ + const char * buf = 0; + post(mp3write_version); + post(" LAME mp3 settings:\n" + " output sample rate: %d Hz\n" + " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); + switch(x->x_mp3mode) + { + case 0 : + buf = "stereo"; + break; + case 1 : + buf = "joint stereo"; + break; + case 2 : + buf = "dual channel"; + break; + case 3 : + buf = "mono"; + break; + } + post(" mode: %s\n" + " quality: %d", buf, x->x_mp3quality); +#ifdef _WIN32 + if(x->x_lamechunk!=0)post(" calculated mp3 chunk size: %d", x->x_lamechunk); +#else + post(" mp3 chunk size: %d", x->x_lamechunk); +#endif + if(x->x_samplerate!=sys_getsr()) + { + post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); + } +} + + /* start recording */ +static void mp3write_start(t_mp3write *x) +{ + if ( x->x_fd < 0 ) { + post("mp3write~: start received but no file has been set ... ignored."); + return; + } + + if ( x->x_recflag == 1 ) { + post("mp3write~: start received but recording is started ... ignored."); + return; + } + + x->x_recflag = 1; + post("mp3write~: start recording"); +} + + /* stop recording */ +static void mp3write_stop(t_mp3write *x) +{ + int err = -1; + + if ( x->x_fd < 0 ) { + post("mp3write~: stop received but no file has been set ... ignored."); + return; + } + + if ( x->x_recflag == 0 ) { + post("mp3write~: stop received but recording is stopped ... ignored."); + return; + } + /* first stop recording / buffering and so on, than do the rest */ + x->x_recflag = 0; + + /* flushing remaining frames and tag */ + x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE ); + + mp3write_writeframes(x); /* write mp3 to file */ + + x->x_recflag = 0; + post("mp3write~: stop recording, flushed %d bytes", x->x_mp3size); +} + + /* clean up */ +static void mp3write_free(t_mp3write *x) +{ + if(x->x_lame >= 0) + lame_close( x->lgfp ); + if(x->x_fd >= 0) +#ifdef _WIN32 + _close(x->x_fd); +#else + close(x->x_fd); +#endif + freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); + freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); + freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); + freebytes( x->x_title, 255 ); +} + +static void *mp3write_new(void) +{ + t_mp3write *x = (t_mp3write *)pd_new(mp3write_class); + inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); + outlet_new (&x->x_obj, &s_float); + x->x_fd = -1; +#ifdef _WIN32 + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; +#endif + x->x_lame = -1; + x->x_samplerate = sys_getsr(); + x->x_bitrate = 128; + x->x_byteswritten = 0; + x->x_mp3mode = 1; + x->lgfp = NULL; + x->x_title = getbytes( 255 ); + x->x_mp3quality = 5; + x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ + x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE*sizeof(char)); /* our mp3 stream */ + x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ + if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ + { + error("mp3write~ : cannot allocate internal buffers"); + return NULL; + } + x->x_bytesbuffered = 0; + x->x_inp = 0; + x->x_outp = 0; + x->x_start = -1; + return(x); +} + +void mp3write_tilde_setup(void) +{ + post(mp3write_version); + mp3write_class = class_new(gensym("mp3write~"), (t_newmethod)mp3write_new, (t_method)mp3write_free, + sizeof(t_mp3write), 0, 0); + CLASS_MAINSIGNALIN(mp3write_class, t_mp3write, x_f ); + class_addmethod(mp3write_class, (t_method)mp3write_dsp, gensym("dsp"), 0); + class_addmethod(mp3write_class, (t_method)mp3write_open, gensym("open"), A_SYMBOL, 0); + class_addmethod(mp3write_class, (t_method)mp3write_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mp3write_class, (t_method)mp3write_start, gensym("start"), 0); + class_addmethod(mp3write_class, (t_method)mp3write_stop, gensym("stop"), 0); + class_addmethod(mp3write_class, (t_method)mp3write_print, gensym("print"), 0); + class_addmethod(mp3write_class, (t_method)mp3write_append, gensym("append"), 0); + class_addmethod(mp3write_class, (t_method)mp3write_truncate, gensym("truncate"), 0); +} diff --git a/mp3write~/INSTALL b/mp3write~/INSTALL deleted file mode 100644 index 75f5f91..0000000 --- a/mp3write~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -You need to get lame > v3.90 installed first. -libmp3lame.so is searched in /usr/local/lib -( no time to write configure scripts ). -if it's installed elsewhere, change the Makefile, -you won't die from that. - -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/mp3write~ - -make - -make install - -you're set !! diff --git a/mp3write~/interface.h b/mp3write~/interface.h deleted file mode 100644 index de3136a..0000000 --- a/mp3write~/interface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Copyright (C) 2000 Albert L. Faber -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef INTERFACE_H_INCLUDED -#define INTERFACE_H_INCLUDED - -// #include "common.h" -#include "interface.h" - -BOOL InitMP3(PMPSTR mp); -int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done); -void ExitMP3(PMPSTR mp); - -/* added remove_buf to support mpglib seeking */ -void remove_buf(PMPSTR mp); - -#endif diff --git a/mp3write~/mp3write~-help.pd b/mp3write~/mp3write~-help.pd deleted file mode 100644 index 0e575ba..0000000 --- a/mp3write~/mp3write~-help.pd +++ /dev/null @@ -1,43 +0,0 @@ -#N canvas 168 244 736 325 10; -#X floatatom 53 24 0 40 16000; -#X msg 168 278 \; pd dsp 1; -#X text 287 196 <-- settings for mp3 stream; -#X text 310 226 bitrate: bitrate of stream \, def. 224kbit/s; -#X text 347 250 1 = joint stereo (default); -#X text 307 288 quality: 1 = high \, 9 = low; -#X text 308 208 (samplerate \, bitrate \, mode \, quality); -#X text 311 238 mode: 0 = stereo; -#X text 347 262 2 = dual channel; -#X text 347 275 3 = mono; -#X msg 171 143 print; -#X msg 234 278 \; pd dsp 0; -#X obj 51 59 osc~ 440; -#X msg 169 174 mpeg 44100 128 1 4; -#X msg 171 121 truncate; -#X msg 171 98 append; -#X msg 170 72 stop; -#X msg 170 49 start; -#X text 370 24 Open a file before any operations; -#X text 228 95 Set recording mode to append ( which is the default -); -#X text 208 48 Start recording; -#X text 231 118 Set recording mode to truncate; -#X text 218 142 Print settings; -#X floatatom 116 258 10 0 0; -#X text 10 254 Bytes written; -#X text 208 71 Stop recording ( this also writes a tag ); -#X msg 169 198 mpeg 44100 8 3 5; -#X msg 170 25 open /tmp/track1.mp3; -#X obj 116 234 mp3write~; -#X connect 0 0 12 0; -#X connect 10 0 28 0; -#X connect 12 0 28 0; -#X connect 12 0 28 1; -#X connect 13 0 28 0; -#X connect 14 0 28 0; -#X connect 15 0 28 0; -#X connect 16 0 28 0; -#X connect 17 0 28 0; -#X connect 26 0 28 0; -#X connect 27 0 28 0; -#X connect 28 0 23 0; diff --git a/mp3write~/mp3write~.c b/mp3write~/mp3write~.c deleted file mode 100644 index b65abed..0000000 --- a/mp3write~/mp3write~.c +++ /dev/null @@ -1,608 +0,0 @@ -/* ------------------------ mp3write~ ----------------------------------------- */ -/* */ -/* Tilde object to record audio in mp3 format */ -/* Note that it is, in no way, related to mp3play~ */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates at http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the LAME MPEG 1 Layer 3 version 3.92 */ -/* Get it via http://www.freshmeat.net */ -/* */ -/* "All this talk of blood and iron is the cause of all my kicking" */ -/* Gang Of Four - "Guns Before Butter" */ -/* ---------------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef _WIN32 -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif /* _WIN32 */ -#include -#include /* lame encoder stuff */ -#include "m_pd.h" /* standard pd stuff */ - -#define MY_MP3_MALLOC_IN_SIZE 65536 - /* max size taken from lame readme */ -#define MY_MP3_MALLOC_OUT_SIZE 1.25*MY_MP3_MALLOC_IN_SIZE+7200 - -#define MAXDATARATE 320 /* maximum mp3 data rate is 320kbit/s */ -#define STRBUF_SIZE 32 - -static char *mp3write_version = "mp3write~: mp3 file recorder version 0.4, written by Yves Degoyon"; -static int sockfd; - -static t_class *mp3write_class; - -typedef struct _mp3write -{ - t_object x_obj; - - /* LAME stuff */ - int x_lame; /* info about encoder status */ - int x_lamechunk; /* chunk size for LAME encoder */ - - /* buffer stuff */ - unsigned short x_inp; /* in position for buffer */ - unsigned short x_outp; /* out position for buffer*/ - short *x_mp3inbuf; /* data to be sent to LAME */ - char *x_mp3outbuf; /* data returned by LAME -> our mp3 stream */ - int x_mp3size; /* number of returned mp3 samples */ - short *x_buffer; /* data to be buffered */ - int x_bytesbuffered; /* number of unprocessed bytes in buffer */ - int x_start; - - /* mp3 format stuff */ - int x_samplerate; - int x_bitrate; /* bitrate of mp3 stream */ - int x_mp3mode; /* mode (mono, joint stereo, stereo, dual mono) */ - int x_mp3quality; /* quality of encoding */ - - /* recording stuff */ - int x_fd; /* file descriptor of the mp3 output */ - int x_file_open_mode; /* file opening mode */ - int x_byteswritten; /* number of bytes written */ - int x_recflag; /* recording flag toggled by messages "start" and "stop" */ - - t_float x_f; /* float needed for signal input */ - char *x_title; /* title of the mp3 */ - - lame_global_flags *lgfp; /* lame encoder configuration */ -} t_mp3write; - - - /* encode PCM data to mp3 stream */ -static void mp3write_encode(t_mp3write *x) -{ - unsigned short i, wp; - int err = -1; - int n = x->x_lamechunk; - -#ifdef UNIX - if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf)) -#else - if(x->x_lamechunk < sizeof(x->x_mp3inbuf)) -#endif - { - error("not enough memory!"); - return; - } - - /* on start/reconnect set outpoint so that it won't interfere with inpoint */ - if(x->x_start == -1) - { - post("mp3write~: reseting buffer positions"); - /* we try to keep 2.5 times the data the encoder needs in the buffer */ - if(x->x_inp > (2 * x->x_lamechunk)) - { - x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk); - } - else if(x->x_inp < (2 * x->x_lamechunk)) - { - x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk); - } - x->x_start = 1; - } - if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3write~: buffers overlap!"); - - i = MY_MP3_MALLOC_IN_SIZE - x->x_outp; - - /* read from buffer */ - if(x->x_lamechunk <= i) - { - /* enough data until end of buffer */ - for(n = 0; n < x->x_lamechunk; n++) /* fill encode buffer */ - { - x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp]; - } - x->x_outp += x->x_lamechunk; - } - else /* split data */ - { - for(wp = 0; wp < i; wp++) /* data at end of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp]; - } - - for(wp = i; wp < x->x_lamechunk; wp++) /* write rest of data at beginning of buffer */ - { - x->x_mp3inbuf[wp] = x->x_buffer[wp - i]; - } - x->x_outp = x->x_lamechunk - i; - } - - /* encode mp3 data */ - - x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, - x->x_lamechunk/lame_get_num_channels(x->lgfp), - x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - // post( "mp3write~ : encoding returned %d frames", x->x_mp3size ); - - /* check result */ - if(x->x_mp3size<0) - { - lame_close( x->lgfp ); - error("mp3write~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); - x->x_lame = -1; - } -} - - /* store mp3 frames in the file */ -static void mp3write_writeframes(t_mp3write *x) -{ - int err = -1; /* error return code */ - - if ( x->x_fd < 0 ) { - post( "mp3write~ : error : trying to write frames but no valid file is opened" ); - return; - } - -#ifndef UNIX - err = _write(x->x_fd, x->x_mp3outbuf, x->x_mp3size); -#else - err = write(x->x_fd, x->x_mp3outbuf, x->x_mp3size); -#endif - - if(err < 0) - { - error("mp3write~: could not write encoded data to file (%d)", err); - lame_close( x->lgfp ); - x->x_lame = -1; -#ifndef UNIX - error("mp3write~: writing data"); - _close(x->x_fd); -#else - perror("mp3write~: writing data"); - close(x->x_fd); -#endif - x->x_fd = -1; - } - else - { - x->x_byteswritten += err; - outlet_float( x->x_obj.ob_outlet, x->x_byteswritten ); - } - if((err > 0)&&(err != x->x_mp3size))error("mp3write~: %d bytes skipped", x->x_mp3size - err); -} - - - /* buffer data as channel interleaved PCM */ -static t_int *mp3write_perform(t_int *w) -{ - t_float *in1 = (t_float *)(w[1]); /* left audio inlet */ - t_float *in2 = (t_float *)(w[2]); /* right audio inlet */ - t_mp3write *x = (t_mp3write *)(w[3]); - int n = (int)(w[4]); /* number of samples */ - unsigned short i,wp; - float in; - - /* copy the data into the buffer */ - i = MY_MP3_MALLOC_IN_SIZE - x->x_inp; /* space left at the end of buffer */ - - n *= 2; /* two channels go into one buffer */ - - if( n <= i ) - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE */ - /* is big enough to hold the data */ - - for(wp = 0; wp < n; wp++) - { - if(wp%2) - { - in = *(in2++); /* right channel / inlet */ - } - else - { - in = *(in1++); /* left channel / inlet */ - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - x->x_inp += n; /* n more samples written to buffer */ - } - else - { - /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */ - /* big enough to hold the data */ - /* writing will take place in two turns, one from */ - /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on */ - - for(wp = 0; wp < i; wp++) /* fill up to end of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in); - } - for(wp = i; wp < n; wp++) /* write rest at start of buffer */ - { - if(wp%2) - { - in = *(in2++); - } - else - { - in = *(in1++); - } - if (in > 1.0) { in = 1.0; } - if (in < -1.0) { in = -1.0; } - x->x_buffer[wp - i] = (short) (32767.0 * in); - } - x->x_inp = n - i; /* new writeposition in buffer */ - } - - if((x->x_fd >= 0)&&(x->x_lame >= 0)&&(x->x_recflag)) - { - /* count buffered samples when things are running */ - x->x_bytesbuffered += n; - - /* encode and send to server */ - if(x->x_bytesbuffered > x->x_lamechunk) - { - mp3write_encode(x); /* encode to mp3 */ - mp3write_writeframes(x); /* write mp3 to file */ - x->x_bytesbuffered -= x->x_lamechunk; - } - } - else - { - x->x_start = -1; - } - return (w+5); -} - -static void mp3write_dsp(t_mp3write *x, t_signal **sp) -{ - dsp_add(mp3write_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); -} - - /* initialize the lame library */ -static int mp3write_tilde_lame_init(t_mp3write *x) -{ - time_t now; - - int ret; - x->lgfp = lame_init(); /* set default parameters for now */ - -#ifndef UNIX - /* load lame_enc.dll library */ - HINSTANCE dll; - dll=LoadLibrary("lame_enc.dll"); - if(dll==NULL) - { - error("mp3write~: error loading lame_enc.dll"); - closesocket(x->x_fd); - x->x_fd = -1; - post("mp3write~: connection closed"); - return -1; - } -#endif - { - const char *lameVersion = get_lame_version(); - post( "mp3write~ : using lame version : %s", lameVersion ); - } - - /* setting lame parameters */ - lame_set_num_channels( x->lgfp, 2); - lame_set_in_samplerate( x->lgfp, sys_getsr() ); - lame_set_out_samplerate( x->lgfp, x->x_samplerate ); - lame_set_brate( x->lgfp, x->x_bitrate ); - lame_set_mode( x->lgfp, x->x_mp3mode ); - lame_set_quality( x->lgfp, x->x_mp3quality ); - lame_set_emphasis( x->lgfp, 1 ); - lame_set_original( x->lgfp, 1 ); - lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */ - lame_set_disable_reservoir( x->lgfp, 0 ); - lame_set_padding_type( x->lgfp, PAD_NO ); - ret = lame_init_params( x->lgfp ); - if ( ret<0 ) { - post( "mp3write~ : error : lame params initialization returned : %d", ret ); - return -1; - } else { - x->x_lame=1; - /* magic formula copied from windows dll for MPEG-I */ - x->x_lamechunk = 2*1152; - - post( "mp3write~ : lame initialization done. (%d)", x->x_lame ); - } - lame_init_bitstream( x->lgfp ); - - /* setting tag information */ - id3tag_init(x->lgfp); - id3tag_v1_only(x->lgfp); - id3tag_space_v1(x->lgfp); - id3tag_set_artist(x->lgfp, "Pd Session"); - now=time(NULL); - sprintf( x->x_title, "Started at %s", ctime(&now) ); - id3tag_set_title(x->lgfp, x->x_title ); - - return 0; - -} - - /* open file and initialize lame */ -static void mp3write_open(t_mp3write *x, t_symbol *sfile) -{ - if ( mp3write_tilde_lame_init(x) < 0 ) { - error( "mp3write~ : lame initialization failed ... check parameters."); - return; - } - - /* closing previous file descriptor */ - if ( x->x_fd > 0 ) { -#ifndef UNIX - if(_close(x->x_fd) < 0 ) -#else - if(close(x->x_fd) < 0) -#endif - { - perror( "mp3write~ : closing file" ); - } - } - - if ( x->x_recflag ) { - x->x_recflag = 0; - } - -#ifndef UNIX - if ( ( x->x_fd = _open( sfile->s_name, x->x_file_open_mode, _S_IREAD|_S_IWRITE) ) < 0 ) -#else - if ( ( x->x_fd = open( sfile->s_name, x->x_file_open_mode, S_IRWXU|S_IRWXG|S_IRWXO ) ) < 0 ) -#endif - { - error( "mp3write~ : cannot open >%s<", sfile->s_name); - x->x_fd=-1; - return; - } - x->x_byteswritten = 0; - post( "mp3write~ : opened >%s< fd=%d", sfile->s_name, x->x_fd); -} - - /* setting file write mode to append */ -static void mp3write_append(t_mp3write *x) -{ -#ifndef UNIX - x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; -#else - x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; -#endif - if(x->x_fd>=0)post("mp3write~ : mode set to append : open a new file to make changes take effect! "); -} - - /* setting file write mode to truncate */ -static void mp3write_truncate(t_mp3write *x) -{ -#ifndef UNIX - x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY; -#else - x->x_file_open_mode = O_CREAT|O_WRONLY|O_TRUNC|O_NONBLOCK; -#endif - if(x->x_fd>=0)post("mp3write~ : mode set to truncate : open a new file to make changes take effect! "); -} - - /* settings for mp3 encoding */ -static void mp3write_mpeg(t_mp3write *x, t_floatarg fsamplerate, t_floatarg fbitrate, - t_floatarg fmode, t_floatarg fquality) -{ - x->x_samplerate = fsamplerate; - if(fbitrate > MAXDATARATE) - { - fbitrate = MAXDATARATE; - } - x->x_bitrate = fbitrate; - x->x_mp3mode = fmode; - x->x_mp3quality = fquality; - post("mp3write~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", - x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); - if(x->x_fd>=0)post("mp3write~ : restart recording to make changes take effect! "); -} - - /* print settings */ -static void mp3write_print(t_mp3write *x) -{ - const char * buf = 0; - post(mp3write_version); - post(" LAME mp3 settings:\n" - " output sample rate: %d Hz\n" - " bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate); - switch(x->x_mp3mode) - { - case 0 : - buf = "stereo"; - break; - case 1 : - buf = "joint stereo"; - break; - case 2 : - buf = "dual channel"; - break; - case 3 : - buf = "mono"; - break; - } - post(" mode: %s\n" - " quality: %d", buf, x->x_mp3quality); -#ifndef UNIX - if(x->x_lamechunk!=0)post(" calculated mp3 chunk size: %d", x->x_lamechunk); -#else - post(" mp3 chunk size: %d", x->x_lamechunk); -#endif - if(x->x_samplerate!=sys_getsr()) - { - post(" resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate); - } -} - - /* start recording */ -static void mp3write_start(t_mp3write *x) -{ - if ( x->x_fd < 0 ) { - post("mp3write~: start received but no file has been set ... ignored."); - return; - } - - if ( x->x_recflag == 1 ) { - post("mp3write~: start received but recording is started ... ignored."); - return; - } - - x->x_recflag = 1; - post("mp3write~: start recording"); -} - - /* stop recording */ -static void mp3write_stop(t_mp3write *x) -{ - int err = -1; - - if ( x->x_fd < 0 ) { - post("mp3write~: stop received but no file has been set ... ignored."); - return; - } - - if ( x->x_recflag == 0 ) { - post("mp3write~: stop received but recording is stopped ... ignored."); - return; - } - /* first stop recording / buffering and so on, than do the rest */ - x->x_recflag = 0; - - /* flushing remaining frames and tag */ - x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE ); - - mp3write_writeframes(x); /* write mp3 to file */ - - x->x_recflag = 0; - post("mp3write~: stop recording, flushed %d bytes", x->x_mp3size); -} - - /* clean up */ -static void mp3write_free(t_mp3write *x) -{ - if(x->x_lame >= 0) - lame_close( x->lgfp ); - if(x->x_fd >= 0) -#ifndef UNIX - _close(x->x_fd); -#else - close(x->x_fd); -#endif - freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); - freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE); - freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short)); - freebytes( x->x_title, 255 ); -} - -static void *mp3write_new(void) -{ - t_mp3write *x = (t_mp3write *)pd_new(mp3write_class); - inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); - outlet_new (&x->x_obj, &s_float); - x->x_fd = -1; -#ifndef UNIX - x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; -#else - x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; -#endif - x->x_lame = -1; - x->x_samplerate = sys_getsr(); - x->x_bitrate = 128; - x->x_byteswritten = 0; - x->x_mp3mode = 1; - x->lgfp = NULL; - x->x_title = getbytes( 255 ); - x->x_mp3quality = 5; - x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* buffer for encoder input */ - x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE*sizeof(char)); /* our mp3 stream */ - x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short)); /* what we get from pd, converted to PCM */ - if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf)) /* check buffers... */ - { - error("mp3write~ : cannot allocate internal buffers"); - return NULL; - } - x->x_bytesbuffered = 0; - x->x_inp = 0; - x->x_outp = 0; - x->x_start = -1; - return(x); -} - -void mp3write_tilde_setup(void) -{ - post(mp3write_version); - mp3write_class = class_new(gensym("mp3write~"), (t_newmethod)mp3write_new, (t_method)mp3write_free, - sizeof(t_mp3write), 0, 0); - CLASS_MAINSIGNALIN(mp3write_class, t_mp3write, x_f ); - class_addmethod(mp3write_class, (t_method)mp3write_dsp, gensym("dsp"), 0); - class_addmethod(mp3write_class, (t_method)mp3write_open, gensym("open"), A_SYMBOL, 0); - class_addmethod(mp3write_class, (t_method)mp3write_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(mp3write_class, (t_method)mp3write_start, gensym("start"), 0); - class_addmethod(mp3write_class, (t_method)mp3write_stop, gensym("stop"), 0); - class_addmethod(mp3write_class, (t_method)mp3write_print, gensym("print"), 0); - class_addmethod(mp3write_class, (t_method)mp3write_append, gensym("append"), 0); - class_addmethod(mp3write_class, (t_method)mp3write_truncate, gensym("truncate"), 0); -} diff --git a/mp3write~/mpglib.h b/mp3write~/mpglib.h deleted file mode 100644 index 1f4ef9a..0000000 --- a/mp3write~/mpglib.h +++ /dev/null @@ -1,65 +0,0 @@ -// #include "lame-analysis.h" - -#define NOANALYSIS - -#ifndef NOANALYSIS -extern plotting_data *mpg123_pinfo; -#endif - -struct buf { - unsigned char *pnt; - long size; - long pos; - struct buf *next; - struct buf *prev; -}; - -struct framebuf { - struct buf *buf; - long pos; - struct frame *next; - struct frame *prev; -}; - -typedef struct mpstr_tag { - struct buf *head,*tail; - int vbr_header; /* 1 if valid Xing vbr header detected */ - int num_frames; /* set if vbr header present */ - int enc_delay; /* set if vbr header present */ - int enc_padding; /* set if vbr header present */ - int header_parsed; - int side_parsed; - int data_parsed; - int free_format; /* 1 = free format frame */ - int old_free_format; /* 1 = last frame was free format */ - int bsize; - int framesize; - int ssize; - int dsize; - int fsizeold; - int fsizeold_nopadding; - struct frame fr; - unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ - real hybrid_block[2][2][SBLIMIT*SSLIMIT]; - int hybrid_blc[2]; - unsigned long header; - int bsnum; - real synth_buffs[2][2][0x110]; - int synth_bo; - int sync_bitstream; - -} MPSTR, *PMPSTR; - - -#if ( defined(_MSC_VER) || defined(__BORLANDC__) ) - typedef int BOOL; /* windef.h contains the same definition */ -#else - #define BOOL int -#endif - -#define MP3_ERR -1 -#define MP3_OK 0 -#define MP3_NEED_MORE 1 - - - diff --git a/mpglib.h b/mpglib.h new file mode 100644 index 0000000..1f4ef9a --- /dev/null +++ b/mpglib.h @@ -0,0 +1,65 @@ +// #include "lame-analysis.h" + +#define NOANALYSIS + +#ifndef NOANALYSIS +extern plotting_data *mpg123_pinfo; +#endif + +struct buf { + unsigned char *pnt; + long size; + long pos; + struct buf *next; + struct buf *prev; +}; + +struct framebuf { + struct buf *buf; + long pos; + struct frame *next; + struct frame *prev; +}; + +typedef struct mpstr_tag { + struct buf *head,*tail; + int vbr_header; /* 1 if valid Xing vbr header detected */ + int num_frames; /* set if vbr header present */ + int enc_delay; /* set if vbr header present */ + int enc_padding; /* set if vbr header present */ + int header_parsed; + int side_parsed; + int data_parsed; + int free_format; /* 1 = free format frame */ + int old_free_format; /* 1 = last frame was free format */ + int bsize; + int framesize; + int ssize; + int dsize; + int fsizeold; + int fsizeold_nopadding; + struct frame fr; + unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ + real hybrid_block[2][2][SBLIMIT*SSLIMIT]; + int hybrid_blc[2]; + unsigned long header; + int bsnum; + real synth_buffs[2][2][0x110]; + int synth_bo; + int sync_bitstream; + +} MPSTR, *PMPSTR; + + +#if ( defined(_MSC_VER) || defined(__BORLANDC__) ) + typedef int BOOL; /* windef.h contains the same definition */ +#else + #define BOOL int +#endif + +#define MP3_ERR -1 +#define MP3_OK 0 +#define MP3_NEED_MORE 1 + + + diff --git a/mrandtab.pd b/mrandtab.pd new file mode 100644 index 0000000..157111c --- /dev/null +++ b/mrandtab.pd @@ -0,0 +1,6 @@ +#N canvas 187 22 737 487 10; +#X obj 138 151 dac~; +#X obj 136 114 randtab; +#X text 174 86 Everything is in the subpatch; +#X connect 1 0 0 0; +#X connect 1 0 0 1; diff --git a/pianoroll-help.pd b/pianoroll-help.pd new file mode 100644 index 0000000..809fec9 --- /dev/null +++ b/pianoroll-help.pd @@ -0,0 +1,80 @@ +#N canvas 90 41 827 643 10; +#X floatatom 71 402 5 0 0; +#X floatatom 258 400 5 0 0; +#X text 523 112 (invoke with Properties ); +#X text 524 101 You can set the following properties :; +#X text 548 141 * Width : graphical x size; +#X text 548 152 * Height : graphical y size; +#X text 488 548 bugs and comments @ ydegoyon@free.fr; +#X msg 587 271 \; pd dsp 0; +#X msg 653 271 \; pd dsp 1; +#X text 548 129 * Name; +#X text 119 401 Pitch; +#X text 304 399 Volume ( scaled to [0 \, 1] ); +#X text 547 164 * Pitch min : minimum value delivered by left outlet +; +#X text 547 176 * Pitch max : maximum value delivered by left outlet +; +#X text 547 200 * Step number : number of steps; +#X text 524 79 ( pitch & volume originally but \, really \, anything +you like ); +#X msg 238 87 transpose \$1; +#X floatatom 334 89 5 0 0; +#X text 240 104 You can transpose the melody ( ?? ); +#X text 241 115 with a float value; +#X text 548 211 * Default value : must be in [min \, max]; +#X obj 65 165 pianoroll pianoroll1 400 192 -15 15 32 16 0 0 1 -12.0968 +0.741935 -3.3871 0.16129 5.32258 0.16129 -4.35484 0.354839 6.29032 +0.322581 6.29032 1 5.32258 1 -12.0968 0.290323 -10.1613 0.290323 -8.22581 +0.580645 -5.32258 1 7.25807 1 -10.1613 0.580645 -15 0.612903 -15 0.580645 +-15 1; +#X msg 47 18 bang; +#X obj 46 80 f; +#X obj 76 80 + 1; +#X floatatom 9 104 5 0 0; +#X obj 47 44 metro 500; +#X text 527 65 Pianoroll controls two parameters for a sequencer; +#X text 548 188 * Pitch grades : number of grades for the pitch; +#X msg 82 18 stop; +#X floatatom 13 140 5 0 0; +#X text 57 1 forward; +#X text 144 0 backward; +#X msg 136 15 bang; +#X obj 135 77 f; +#X obj 136 41 metro 500; +#X msg 171 16 stop; +#X obj 165 77 - 1; +#X msg 239 59 init; +#X text 279 60 init to default values; +#X msg 241 33 load pattern#1; +#X text 352 19 load and save the patterns; +#X text 352 31 ( values as well as steps number .... ); +#X msg 241 10 save pattern#1; +#X text 544 383 you can set the pitch and; +#X text 544 397 the volume with messages; +#X text 544 409 ( positions start at zero ); +#X msg 541 358 volume 3 0.345; +#X msg 542 334 pitch 3 -5; +#X connect 16 0 21 0; +#X connect 17 0 16 0; +#X connect 21 0 0 0; +#X connect 21 1 1 0; +#X connect 22 0 26 0; +#X connect 23 0 21 0; +#X connect 23 0 24 0; +#X connect 23 0 25 0; +#X connect 24 0 23 1; +#X connect 26 0 23 0; +#X connect 29 0 26 0; +#X connect 30 0 21 0; +#X connect 33 0 35 0; +#X connect 34 0 37 0; +#X connect 34 0 21 0; +#X connect 35 0 34 0; +#X connect 36 0 35 0; +#X connect 37 0 34 1; +#X connect 38 0 21 0; +#X connect 40 0 21 0; +#X connect 43 0 21 0; +#X connect 47 0 21 0; +#X connect 48 0 21 0; diff --git a/pianoroll.c b/pianoroll.c new file mode 100644 index 0000000..c63d7cc --- /dev/null +++ b/pianoroll.c @@ -0,0 +1,817 @@ +/* Copyright (c) 1997-1999 Miller Puckette. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* pianoroll : a graphical object which enables */ +/* to control a sequencer ( pitch and volume ) */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "If you obey society's rules" */ +/* "You'll be society's fool" */ +/* Devo - Society's rules */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + +#include "pianoroll.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* needed to create a pianoroll from PD's menu +void canvas_objtext(t_glist *gl, int xpos, int ypos, int selected, t_binbuf *b); +void canvas_startmotion(t_canvas *x); +*/ + +#define DEFAULT_SEQUENCER_WIDTH 200 +#define DEFAULT_SEQUENCER_HEIGHT 200 +#define DEFAULT_SEQUENCER_STEPS 16 +#define DEFAULT_SEQUENCER_NBGRADES 31 +#define DEFAULT_SEQUENCER_PITCH_MIN -15 +#define DEFAULT_SEQUENCER_PITCH_MAX 15 + +static char *pianoroll_version = "pianoroll: a graphical sequencer controller, version 0.10 (ydegoyon@free.fr)"; + +t_widgetbehavior pianoroll_widgetbehavior; +static t_class *pianoroll_class; +static int pianorollcount=0; + +static int guidebug=0; +static int pointsize = 5; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +/* drawing functions */ +static void pianoroll_draw_update(t_pianoroll *x, t_glist *glist) +{ + t_int si; + t_canvas *canvas=glist_getcanvas(glist); + + for ( si=0; six_nbsteps; si++ ) + { + int vi = (int)((1.0-x->x_volumes[si])*(x->x_nbgrades-1)); + int pi = (int)((x->x_pmax-x->x_peaches[si])/(x->x_pmax-x->x_pmin)*(x->x_nbgrades-1)); + + x->x_ivolumes[ si ] = vi; + x->x_ipeaches[ si ] = pi; + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, si, pi); + SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, si, vi); + } +} + +static void pianoroll_draw_new(t_pianoroll *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + // draw the grid + { + int gi, gj; + t_float xgstep = x->x_width/x->x_nbsteps; + t_float ygstep = x->x_height/x->x_nbgrades; + for ( gi=0; gix_nbsteps; gi++ ) + { + for ( gj=0; gjx_nbgrades; gj++ ) + { + SYS_VGUI9(".x%x.c create rectangle %d %d %d %d -fill #771623 -outline #998121 -tags %xPITCH%.4d%.4d\n", + canvas, + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep), + text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), + text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep), + x, gi, gj ); + SYS_VGUI9(".x%x.c create rectangle %d %d %d %d -fill #562663 -outline #998121 -tags %xVOLUME%.4d%.4d\n", + canvas, + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), + text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), + text_xpix(&x->x_obj, glist)+(int)((gi+1)*xgstep), + text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep), + x, gi, gj ); + } + } + // adjust height and width + x->x_width = (int)((x->x_nbsteps)*xgstep); + x->x_height = (int)((x->x_nbgrades)*ygstep); + } + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xIN\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) - 1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist), + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xOUTL\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xOUTR\n", + canvas, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2, + x); + + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void pianoroll_draw_move(t_pianoroll *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + // move the grid + { + int gi, gj; + t_float xgstep = x->x_width/x->x_nbsteps; + t_float ygstep = x->x_height/x->x_nbgrades; + for ( gi=0; gix_nbsteps; gi++ ) + { + for ( gj=0; gjx_nbgrades; gj++ ) + { + SYS_VGUI9(".x%x.c coords %xPITCH%.4d%.4d %d %d %d %d\n", + canvas, x, gi, gj, + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep), + text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), + text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep) + ); + SYS_VGUI9(".x%x.c coords %xVOLUME%.4d%.4d %d %d %d %d\n", + canvas, x, gi, gj, + text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), + text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), + text_xpix(&x->x_obj, glist)+(int)((gi+1)*xgstep), + text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep) + ); + } + } + } + SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d \n", + canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) - 1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + ); + SYS_VGUI7(".x%x.c coords %xOUTL %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2 + ); + SYS_VGUI7(".x%x.c coords %xOUTR %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2 + ); + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void pianoroll_draw_erase(t_pianoroll* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + + SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xOUTL\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xOUTR\n", canvas, x); + // delete the grid + { + int gi, gj; + for ( gi=0; gix_nbsteps; gi++ ) + { + for ( gj=0; gjx_nbgrades; gj++ ) + { + SYS_VGUI5(".x%x.c delete %xPITCH%.4d%.4d\n", canvas, x, gi, gj); + SYS_VGUI5(".x%x.c delete %xVOLUME%.4d%.4d\n", canvas, x, gi, gj); + } + } + } +} + +static void pianoroll_draw_select(t_pianoroll* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + pd_bind(&x->x_obj.ob_pd, x->x_name); + /* sets the item in blue */ + } + else + { + pd_unbind(&x->x_obj.ob_pd, x->x_name); + } +} + +/* ------------------------ pianoroll widgetbehaviour----------------------------- */ + + +static void pianoroll_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_pianoroll* x = (t_pianoroll*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void pianoroll_save(t_gobj *z, t_binbuf *b) +{ + t_pianoroll *x = (t_pianoroll *)z; + t_int i; + + // post( "saving pianoroll : %s", x->x_name->s_name ); + binbuf_addv(b, "ssiissiiffiiifi", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_name, x->x_width, x->x_height, + x->x_pmin, x->x_pmax, + x->x_nbgrades, x->x_nbsteps, + x->x_defvalue, x->x_transpose, x->x_save + ); + if ( x->x_save ) + { + for ( i=0; ix_nbsteps; i++ ) + { + binbuf_addv(b, "ff", x->x_peaches[i], x->x_volumes[i] ); + } + } + binbuf_addv(b, ";"); +} + +static void pianoroll_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_pianoroll *x=(t_pianoroll *)z; + + sprintf(buf, "pdtk_pianoroll_dialog %%s %s %d %d %.2f %.2f %d %d %d %d\n", + x->x_name->s_name, x->x_width, x->x_height, x->x_pmin, x->x_pmax, + x->x_nbgrades, x->x_nbsteps, x->x_defvalue, x->x_save ); + // post("pianoroll_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void pianoroll_select(t_gobj *z, t_glist *glist, int selected) +{ + t_pianoroll *x = (t_pianoroll *)z; + + x->x_selected = selected; + pianoroll_draw_select( x, glist ); +} + +static void pianoroll_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_pianoroll *x = (t_pianoroll *)z; + t_rtext *y; + + // post("pianoroll_vis : %d", vis ); + if (vis) + { + pianoroll_draw_new( x, glist ); + pianoroll_draw_update( x, glist ); + } + else + { + pianoroll_draw_erase( x, glist ); + } +} + +static void pianoroll_dialog(t_pianoroll *x, t_symbol *s, int argc, t_atom *argv) +{ + int si, onbsteps; + t_float *newpeaches, *newvolumes; + + if ( !x ) { + post( "pianoroll : error :tried to set properties on an unexisting object" ); + } + if ( ( argv[5].a_w.w_float <= 0 ) || ( argv[5].a_w.w_float <= 0 ) ) { + post( "pianoroll : error : wrong number of steps or grades" ); + return; + } + if ( ( argv[3].a_w.w_float >= argv[4].a_w.w_float ) ) { + post( "pianoroll : error : min pitch is >= to max pitch" ); + return; + } + if ( argc != 9 ) + { + post( "pianoroll : error in the number of arguments ( %d )", argc ); + return; + } + if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || + argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || + argv[8].a_type != A_FLOAT + ) { + post( "pianoroll : wrong arguments" ); + return; + } + pianoroll_draw_erase(x, x->x_glist); + x->x_name = argv[0].a_w.w_symbol; + x->x_width = (int)argv[1].a_w.w_float; + x->x_height = (int)argv[2].a_w.w_float; + x->x_pmin = argv[3].a_w.w_float; + x->x_pmax = argv[4].a_w.w_float; + x->x_nbgrades = argv[5].a_w.w_float; + onbsteps = x->x_nbsteps; + x->x_nbsteps = argv[6].a_w.w_float; + x->x_defvalue = argv[7].a_w.w_float; + x->x_save = argv[8].a_w.w_float; + + if ( onbsteps != x->x_nbsteps ) + { + int cmindex = ( onbsteps > x->x_nbsteps ) ? x->x_nbsteps : onbsteps; + + newpeaches = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); + newvolumes = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); + for ( si=0; six_peaches[si]; + newvolumes[si] = x->x_volumes[si]; + } + freebytes( x->x_peaches, onbsteps*sizeof( t_float ) ); + freebytes( x->x_volumes, onbsteps*sizeof( t_float ) ); + x->x_peaches = newpeaches; + x->x_volumes = newvolumes; + for ( si=onbsteps; six_nbsteps; si++ ) + { + x->x_peaches[si] = x->x_defvalue; + x->x_volumes[si] = 1.0; + } + freebytes( x->x_ipeaches, onbsteps*sizeof( t_int ) ); + freebytes( x->x_ivolumes, onbsteps*sizeof( t_int ) ); + x->x_ipeaches = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_ivolumes = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); + } + pianoroll_draw_new(x, x->x_glist); + pianoroll_draw_update(x, x->x_glist); +} + +static void pianoroll_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void pianoroll_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_pianoroll *x = (t_pianoroll *)z; + int xold = text_xpix(&x->x_obj, glist); + int yold = text_ypix(&x->x_obj, glist); + + // post( "pianoroll_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) + { + pianoroll_draw_move(x, x->x_glist); + } +} + +static int pianoroll_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_pianoroll* x = (t_pianoroll *)z; + t_canvas *canvas=glist_getcanvas(glist); + + if ( doit) + { + // calculate position to update + { + int si, gi; + t_float xgstep = x->x_width/x->x_nbsteps; + t_float ygstep = x->x_height/x->x_nbgrades; + + si = ( xpix - text_xpix(&x->x_obj, glist) ) / xgstep; + gi = ( ypix - text_ypix(&x->x_obj, glist) ) / ygstep; + + // post( "pianoroll : step : %d : grade : %d", si, gi ); + + if ( ( xpix - text_xpix(&x->x_obj, glist) ) > ( si*xgstep+2*xgstep/3 ) ) + { + { + SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #562663\n", canvas, x, si, x->x_ivolumes[ si ] ); + } + + x->x_volumes[ si ] = (((float)x->x_nbgrades-1-(float)gi))/(float)(x->x_nbgrades-1); + SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, si, gi); + x->x_ivolumes[ si ] = gi; + } + else + { + { + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #761623\n", canvas, x, si, x->x_ipeaches[ si ]); + } + + x->x_peaches[ si ] = x->x_pmin+(float)(x->x_nbgrades-1-gi)/(float)(x->x_nbgrades-1)*(float)(x->x_pmax-x->x_pmin); + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, si, gi); + x->x_ipeaches[ si ] = gi; + } + } + + } + return (1); +} + +static void pianoroll_transpose(t_pianoroll *x, t_floatarg ftranspose) +{ + x->x_transpose = ftranspose; +} + +static void pianoroll_save_file(t_pianoroll *x, t_symbol *ffile) +{ + FILE *tmph; + t_int si; + + if ( ( tmph = fopen( ffile->s_name, "w" ) ) == NULL ) + { + post( "pianoroll : could not open file : %s for writing", ffile->s_name ); + return; + } + + // post( "saving pianoroll : %s", x->x_name->s_name ); + fprintf(tmph, "%d %d %f %f %d %d %d %f %d ", + x->x_width, x->x_height, + x->x_pmin, x->x_pmax, + x->x_nbgrades, x->x_nbsteps, + x->x_defvalue, x->x_transpose, x->x_save ); + for ( si=0; six_nbsteps; si++ ) + { + fprintf(tmph, "%f %f ", x->x_peaches[si], x->x_volumes[si] ); + } + + if ( fclose( tmph ) == -1 ) + { + post( "pianoroll : could not close file : %s ", ffile->s_name ); + return; + } +} + +static void pianoroll_load(t_pianoroll *x, t_symbol *ffile) +{ + FILE *tmph; + t_int si; + + if ( ( tmph = fopen( ffile->s_name, "r" ) ) == NULL ) + { + post( "pianoroll : could not open file : %s for reading", ffile->s_name ); + return; + } + + pianoroll_draw_erase(x, x->x_glist); + freebytes( x->x_peaches, x->x_nbsteps*sizeof( t_float ) ); + freebytes( x->x_volumes, x->x_nbsteps*sizeof( t_float ) ); + freebytes( x->x_ipeaches, x->x_nbsteps*sizeof( t_int ) ); + freebytes( x->x_ivolumes, x->x_nbsteps*sizeof( t_int ) ); + + if ( fscanf(tmph, "%d %d %f %f %d %d %d %f %d", + &x->x_width, &x->x_height, + &x->x_pmin, &x->x_pmax, + &x->x_nbgrades, &x->x_nbsteps, + &x->x_defvalue, &x->x_transpose, &x->x_save ) != 9 ) + { + post( "pianoroll : could not restore data from file : %s", ffile->s_name ); + return; + } + + x->x_peaches = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_volumes = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_ipeaches = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_ivolumes = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); + for ( si=0; six_nbsteps ; si++ ) + { + fscanf( tmph, "%f", &x->x_peaches[si] ); + fscanf( tmph, "%f", &x->x_volumes[si] ); + } + + pianoroll_draw_new(x, x->x_glist); + pianoroll_draw_update(x, x->x_glist); + + if ( fclose( tmph ) == -1 ) + { + post( "pianoroll : could not close file : %s ", ffile->s_name ); + return; + } +} + +static void pianoroll_init(t_pianoroll *x) +{ + t_int si; + + for ( si=0; six_nbsteps; si++ ) + { + x->x_peaches[si] = x->x_defvalue; + x->x_volumes[si] = 1.0; + } + pianoroll_draw_erase(x, x->x_glist ); + pianoroll_draw_new(x, x->x_glist ); + pianoroll_draw_update(x, x->x_glist ); +} + +static void pianoroll_pitch(t_pianoroll *x, t_floatarg fpos, t_floatarg fpitch) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int ipos; + + if ( ( ( (t_int) fpos ) < 0 ) || ( ( (t_int) fpos ) >= x->x_nbsteps ) ) + { + post( "pianoroll : wrong pitch position : %d", fpos ); + return; + } + ipos = (t_int) fpos; + if ( ( ( (t_int) fpitch ) < x->x_pmin ) || ( ( (t_int) fpitch ) > x->x_pmax ) ) + { + post( "pianoroll : wrong pitch value : %d", fpitch ); + return; + } + + { + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #761623\n", canvas, x, ipos, x->x_ipeaches[ ipos ]); + + x->x_ipeaches[ ipos ] = (t_int) ( ( ( x->x_pmax - fpitch ) / ( x->x_pmax - x->x_pmin ) ) * ( x->x_nbgrades - 1 ) ); + x->x_peaches[ ipos ] = x->x_pmin+(float)(x->x_nbgrades-1-x->x_ipeaches[ ipos ])/(float)(x->x_nbgrades-1)*(float)(x->x_pmax-x->x_pmin); + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, ipos, x->x_ipeaches[ ipos ]); + } +} + +static void pianoroll_volume(t_pianoroll *x, t_floatarg fpos, t_floatarg fvol) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int ipos; + + if ( ( ( (t_int) fpos ) < 0 ) || ( ( (t_int) fpos ) >= x->x_nbsteps ) ) + { + post( "pianoroll : wrong volume position : %d", fpos ); + return; + } + ipos = (t_int) fpos; + if ( ( ( (t_int) fvol ) < 0.0 ) || ( ( (t_int) fvol ) > 1.0 ) ) + { + post( "pianoroll : wrong volume value : %d", fvol ); + return; + } + + { + SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #562663\n", canvas, x, ipos, x->x_ivolumes[ ipos ] ); + + x->x_ivolumes[ ipos ] = (t_int) ( ( 1 - fvol ) * (x->x_nbgrades-1) ); + x->x_volumes[ ipos ] = (((float)x->x_nbgrades-1-(float)x->x_ivolumes[ ipos ]))/(float)(x->x_nbgrades-1); + SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, ipos, x->x_ivolumes[ ipos ] ); + } +} + +static void pianoroll_float(t_pianoroll *x, t_floatarg fposition) +{ + t_int pposition, rposition, rrposition; + t_float fpart; + t_int pi; + t_canvas *canvas; + + pposition = ( (int)fposition - 1 ) % x->x_nbsteps; + if ( pposition < 0 ) pposition += x->x_nbsteps; + rposition = ( (int)fposition ) % x->x_nbsteps; + if ( rposition < 0 ) rposition += x->x_nbsteps; + rrposition = ( (int)fposition +1 ) % x->x_nbsteps; + if ( rrposition < 0 ) rrposition += x->x_nbsteps; + + // post ( "pposition=%d rposition=%d rrposition=%d", pposition, rposition, rrposition ); + fpart = fposition - (int)fposition; + pi=-1; + canvas=glist_getcanvas(x->x_glist); + + outlet_float( x->x_pitch, x->x_peaches[ rposition ] + + fpart*(x->x_peaches[ rrposition ] - x->x_peaches[ rposition ] ) + + x->x_transpose ); + outlet_float( x->x_volume, x->x_volumes[ rposition ] + + fpart*(x->x_volumes[ rrposition ] - x->x_volumes[ rposition ] ) ); + + // graphical update + { + if ( x->x_scurrent != -1 ) + { + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, + x->x_scurrent, x->x_ipeaches[ x->x_scurrent ]); + } + x->x_scurrent = rposition; + SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #00FF00\n", canvas, x, + x->x_scurrent, x->x_ipeaches[ x->x_scurrent ]); + } +} + +static t_pianoroll *pianoroll_new(t_symbol *s, int argc, t_atom *argv) +{ + int si, i, zz; + t_pianoroll *x; + t_pd *x2; + char *str; + + // post( "pianoroll_new : create : %s argc =%d", s->s_name, argc ); + + x = (t_pianoroll *)pd_new(pianoroll_class); + // new pianoroll created from the gui + if ( argc != 0 ) + { + if ( argc < 10 ) + { + post( "pianoroll : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( ( argv[5].a_w.w_float <= 0 ) || ( argv[5].a_w.w_float <= 0 ) ) { + post( "pianoroll : error : wrong number of steps or grades" ); + return NULL; + } + if ( ( argv[3].a_w.w_float >= argv[4].a_w.w_float ) ) { + post( "pianoroll : error : min pitch is > to max pitch" ); + return NULL; + } + if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || + argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || + argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT ) { + post( "pianoroll : wrong arguments" ); + return NULL; + } + + // update pianoroll count + if (!strncmp((str = argv[0].a_w.w_symbol->s_name), "pianoroll", 9) + && (zz = atoi(str + 9)) > pianorollcount) + { + // post( "pianoroll : already %d objects", pianorollcount ); + pianorollcount = zz; + } + x->x_name = argv[0].a_w.w_symbol; + pd_bind(&x->x_obj.ob_pd, x->x_name); + x->x_width = argv[1].a_w.w_float; + x->x_height = argv[2].a_w.w_float; + x->x_pmin = argv[3].a_w.w_float; + x->x_pmax = argv[4].a_w.w_float; + x->x_nbgrades = argv[5].a_w.w_float; + x->x_nbsteps = argv[6].a_w.w_float; + x->x_peaches = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_ipeaches = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_volumes = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_ivolumes = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_defvalue = argv[7].a_w.w_float; + x->x_transpose = argv[8].a_w.w_float; + x->x_save = argv[9].a_w.w_float; + } + else + { + char buf[40]; + + sprintf(buf, "pianoroll%d", ++pianorollcount); + s = gensym(buf); + + x->x_name = s; + pd_bind(&x->x_obj.ob_pd, x->x_name); + + x->x_width = DEFAULT_SEQUENCER_WIDTH; + x->x_height = DEFAULT_SEQUENCER_HEIGHT; + x->x_pmin = DEFAULT_SEQUENCER_PITCH_MIN; + x->x_pmax = DEFAULT_SEQUENCER_PITCH_MAX; + x->x_nbgrades = DEFAULT_SEQUENCER_NBGRADES; + x->x_nbsteps = DEFAULT_SEQUENCER_STEPS; + x->x_peaches = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_ipeaches = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_volumes = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); + x->x_ivolumes = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); + x->x_defvalue = 0; + x->x_transpose = 0; + x->x_save = 1; + + } + + // common fields for new and restored pianorolls + x->x_selected = 0; + x->x_scurrent = -1; + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_pitch = outlet_new(&x->x_obj, &s_float ); + x->x_volume = outlet_new(&x->x_obj, &s_float ); + // post( "pianoroll : argc : %d", argc ); + if ( ( argc != 0 ) && ( x->x_save ) ) + { + int ai = 10; + int si = 0; + + while ( ai < argc ) + { + x->x_peaches[si] = argv[ai++].a_w.w_float; + if ( ai >= argc ) break; + x->x_volumes[si++] = argv[ai++].a_w.w_float; + } + } + else // following arguments are the values of pitch, volumes + { + for ( si=0; six_nbsteps; si++ ) + { + x->x_peaches[si] = x->x_defvalue; + x->x_volumes[si] = 1.0; + } + } + + // post( "pianoroll_new name : %s width: %d height : %d", x->x_name->s_name, x->x_width, x->x_height ); + + return (x); +} + +static void pianoroll_free(t_pianoroll *x) +{ + // post( "pianoroll~: pianoroll_free" ); + if ( x->x_peaches ) + { + freebytes( x->x_peaches, x->x_nbsteps*sizeof(t_float) ); + } + if ( x->x_ipeaches ) + { + freebytes( x->x_ipeaches, x->x_nbsteps*sizeof(t_int) ); + } + if ( x->x_volumes ) + { + freebytes( x->x_volumes, x->x_nbsteps*sizeof(t_float) ); + } + if ( x->x_ivolumes ) + { + freebytes( x->x_ivolumes, x->x_nbsteps*sizeof(t_int) ); + } +} + +void pianoroll_setup(void) +{ + post( pianoroll_version ); + pianoroll_class = class_new(gensym("pianoroll"), (t_newmethod)pianoroll_new, + (t_method)pianoroll_free, sizeof(t_pianoroll), 0, A_GIMME, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_float, &s_float, A_FLOAT, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_transpose, gensym("transpose"), + A_FLOAT, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_init, gensym("init"), 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_save_file, gensym("save"), A_SYMBOL, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_load, gensym("load"), A_SYMBOL, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_pitch, gensym("pitch"), A_FLOAT, A_FLOAT, 0); + class_addmethod(pianoroll_class, (t_method)pianoroll_volume, gensym("volume"), A_FLOAT, A_FLOAT, 0); + + + pianoroll_widgetbehavior.w_getrectfn = pianoroll_getrect; + pianoroll_widgetbehavior.w_displacefn = pianoroll_displace; + pianoroll_widgetbehavior.w_selectfn = pianoroll_select; + pianoroll_widgetbehavior.w_activatefn = NULL; + pianoroll_widgetbehavior.w_deletefn = pianoroll_delete; + pianoroll_widgetbehavior.w_visfn = pianoroll_vis; + pianoroll_widgetbehavior.w_clickfn = pianoroll_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(pianoroll_class, pianoroll_properties); + class_setsavefn(pianoroll_class, pianoroll_save); +#else + pianoroll_widgetbehavior.w_propertiesfn = pianoroll_properties; + pianoroll_widgetbehavior.w_savefn = pianoroll_save; +#endif + + class_setwidget(pianoroll_class, &pianoroll_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + pianoroll_class->c_externdir->s_name, + pianoroll_class->c_name->s_name); +} diff --git a/pianoroll.h b/pianoroll.h new file mode 100644 index 0000000..4f6a783 --- /dev/null +++ b/pianoroll.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2002 Yves Degoyon +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* a header for pianoroll which enables +* to control a sequencer ( pitch and volume ) +*/ + +#ifndef __G_PIANOROLL_H +#define __G_PIANOROLL_H + +typedef struct _pianoroll +{ + t_object x_obj; + t_glist *x_glist; + t_symbol *x_name; + t_outlet *x_pitch; + t_outlet *x_volume; + int x_height; /* height of the pianoroll */ + int x_width; /* width of the pianoroll */ + t_float x_pmin; /* minimum value of the pitch */ + t_float x_pmax; /* max value of the pitch */ + t_int x_nbgrades; /* number of grades for the pitch */ + t_int x_nbsteps; /* number of steps */ + t_int x_defvalue; /* default value for the pitch */ + t_float x_transpose;/* transposition value */ + t_float *x_peaches; /* pitch for each step */ + t_int *x_ipeaches; /* pitch index for each step */ + t_float *x_volumes; /* volume for each step */ + t_int *x_ivolumes; /* volume index for each step */ + int x_selected; /* stores selected state */ + int x_xlines; /* number of vertical lines */ + int x_ylines; /* number of horizontal lines */ + int x_scurrent; /* cureent step */ + int x_save; /* saving contents flag */ +} t_pianoroll; + +EXTERN t_rtext *rtext_new_without_senditup(t_glist *glist, t_text *who, t_rtext *next); + +#endif diff --git a/pianoroll.tcl b/pianoroll.tcl new file mode 100644 index 0000000..eccadce --- /dev/null +++ b/pianoroll.tcl @@ -0,0 +1,164 @@ +############ pianoroll procedures -- ydegoyon@free.fr ######### + +proc pianoroll_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_name [concat graph_name_$vid] + global $var_graph_name + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_pmin [concat graph_pmin_$vid] + global $var_graph_pmin + set var_graph_pmax [concat graph_pmax_$vid] + global $var_graph_pmax + set var_graph_nbgrades [concat graph_nbgrades_$vid] + global $var_graph_nbgrades + set var_graph_nbsteps [concat graph_nbsteps_$vid] + global $var_graph_nbsteps + set var_graph_defvalue [concat graph_defvalue_$vid] + global $var_graph_defvalue + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set cmd [concat $id dialog \ + [eval concat $$var_graph_name] \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_pmin] \ + [eval concat $$var_graph_pmax] \ + [eval concat $$var_graph_nbgrades] \ + [eval concat $$var_graph_nbsteps] \ + [eval concat $$var_graph_defvalue] \ + [eval concat $$var_graph_save] \;] + #puts stderr $cmd + pd $cmd +} + +proc pianoroll_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc pianoroll_ok {id} { + pianoroll_apply $id + pianoroll_cancel $id +} + +proc pdtk_pianoroll_dialog {id name width height pmin pmax nbgrades nbsteps defvalue save } { + set vid [string trimleft $id .] + set var_graph_name [concat graph_name_$vid] + global $var_graph_name + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_pmin [concat graph_pmin_$vid] + global $var_graph_pmin + set var_graph_pmax [concat graph_pmax_$vid] + global $var_graph_pmax + set var_graph_nbgrades [concat graph_nbgrades_$vid] + global $var_graph_nbgrades + set var_graph_nbsteps [concat graph_nbsteps_$vid] + global $var_graph_nbsteps + set var_graph_defvalue [concat graph_defvalue_$vid] + global $var_graph_defvalue + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set $var_graph_name $name + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_pmin $pmin + set $var_graph_pmax $pmax + set $var_graph_nbgrades $nbgrades + set $var_graph_nbsteps $nbsteps + set $var_graph_defvalue $defvalue + set $var_graph_save $save + + toplevel $id + wm title $id {pianoroll} + wm protocol $id WM_DELETE_WINDOW [concat pianoroll_cancel $id] + + label $id.label -text {PIANOROLL PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "pianoroll_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "pianoroll_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "pianoroll_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lname -text "Name :" + entry $id.1rangef.name -textvariable $var_graph_name -width 15 + pack $id.1rangef.lname $id.1rangef.name -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lwidth -text "Width :" + entry $id.2rangef.width -textvariable $var_graph_width -width 7 + pack $id.2rangef.lwidth $id.2rangef.width -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lheight -text "Height :" + entry $id.3rangef.height -textvariable $var_graph_height -width 7 + pack $id.3rangef.lheight $id.3rangef.height -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.lpmin -text "Pitch low :" + entry $id.4rangef.pmin -textvariable $var_graph_pmin -width 7 + pack $id.4rangef.lpmin $id.4rangef.pmin -side left + + frame $id.5rangef + pack $id.5rangef -side top + label $id.5rangef.lpmax -text "Pitch high :" + entry $id.5rangef.pmax -textvariable $var_graph_pmax -width 7 + pack $id.5rangef.lpmax $id.5rangef.pmax -side left + + frame $id.6rangef + pack $id.6rangef -side top + label $id.6rangef.lnbgrades -text "Grades :" + entry $id.6rangef.nbgrades -textvariable $var_graph_nbgrades -width 7 + pack $id.6rangef.lnbgrades $id.6rangef.nbgrades -side left + + frame $id.7rangef + pack $id.7rangef -side top + label $id.7rangef.lnbsteps -text "Steps :" + entry $id.7rangef.nbsteps -textvariable $var_graph_nbsteps -width 7 + pack $id.7rangef.lnbsteps $id.7rangef.nbsteps -side left + + frame $id.8rangef + pack $id.8rangef -side top + label $id.8rangef.ldefvalue -text "Default Value :" + entry $id.8rangef.defvalue -textvariable $var_graph_defvalue -width 7 + pack $id.8rangef.ldefvalue $id.8rangef.defvalue -side left + + checkbutton $id.save -text {Save contents} -variable $var_graph_save \ + -anchor w + pack $id.save -side top + + bind $id.1rangef.name [concat pianoroll_ok $id] + bind $id.2rangef.width [concat pianoroll_ok $id] + bind $id.3rangef.height [concat pianoroll_ok $id] + bind $id.4rangef.pmin [concat pianoroll_ok $id] + bind $id.5rangef.pmax [concat pianoroll_ok $id] + bind $id.6rangef.nbgrades [concat pianoroll_ok $id] + bind $id.7rangef.nbsteps [concat pianoroll_ok $id] + bind $id.8rangef.defvalue [concat pianoroll_ok $id] + focus $id.1rangef.name +} + +############ pianoroll procedures END -- ydegoyon@free.fr ######### diff --git a/pianoroll/INSTALL b/pianoroll/INSTALL deleted file mode 100644 index b7c38be..0000000 --- a/pianoroll/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/pianoroll - -make clean - -make - -make install - -open help-pianoroll.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/pianoroll/pianoroll-help.pd b/pianoroll/pianoroll-help.pd deleted file mode 100644 index 809fec9..0000000 --- a/pianoroll/pianoroll-help.pd +++ /dev/null @@ -1,80 +0,0 @@ -#N canvas 90 41 827 643 10; -#X floatatom 71 402 5 0 0; -#X floatatom 258 400 5 0 0; -#X text 523 112 (invoke with Properties ); -#X text 524 101 You can set the following properties :; -#X text 548 141 * Width : graphical x size; -#X text 548 152 * Height : graphical y size; -#X text 488 548 bugs and comments @ ydegoyon@free.fr; -#X msg 587 271 \; pd dsp 0; -#X msg 653 271 \; pd dsp 1; -#X text 548 129 * Name; -#X text 119 401 Pitch; -#X text 304 399 Volume ( scaled to [0 \, 1] ); -#X text 547 164 * Pitch min : minimum value delivered by left outlet -; -#X text 547 176 * Pitch max : maximum value delivered by left outlet -; -#X text 547 200 * Step number : number of steps; -#X text 524 79 ( pitch & volume originally but \, really \, anything -you like ); -#X msg 238 87 transpose \$1; -#X floatatom 334 89 5 0 0; -#X text 240 104 You can transpose the melody ( ?? ); -#X text 241 115 with a float value; -#X text 548 211 * Default value : must be in [min \, max]; -#X obj 65 165 pianoroll pianoroll1 400 192 -15 15 32 16 0 0 1 -12.0968 -0.741935 -3.3871 0.16129 5.32258 0.16129 -4.35484 0.354839 6.29032 -0.322581 6.29032 1 5.32258 1 -12.0968 0.290323 -10.1613 0.290323 -8.22581 -0.580645 -5.32258 1 7.25807 1 -10.1613 0.580645 -15 0.612903 -15 0.580645 --15 1; -#X msg 47 18 bang; -#X obj 46 80 f; -#X obj 76 80 + 1; -#X floatatom 9 104 5 0 0; -#X obj 47 44 metro 500; -#X text 527 65 Pianoroll controls two parameters for a sequencer; -#X text 548 188 * Pitch grades : number of grades for the pitch; -#X msg 82 18 stop; -#X floatatom 13 140 5 0 0; -#X text 57 1 forward; -#X text 144 0 backward; -#X msg 136 15 bang; -#X obj 135 77 f; -#X obj 136 41 metro 500; -#X msg 171 16 stop; -#X obj 165 77 - 1; -#X msg 239 59 init; -#X text 279 60 init to default values; -#X msg 241 33 load pattern#1; -#X text 352 19 load and save the patterns; -#X text 352 31 ( values as well as steps number .... ); -#X msg 241 10 save pattern#1; -#X text 544 383 you can set the pitch and; -#X text 544 397 the volume with messages; -#X text 544 409 ( positions start at zero ); -#X msg 541 358 volume 3 0.345; -#X msg 542 334 pitch 3 -5; -#X connect 16 0 21 0; -#X connect 17 0 16 0; -#X connect 21 0 0 0; -#X connect 21 1 1 0; -#X connect 22 0 26 0; -#X connect 23 0 21 0; -#X connect 23 0 24 0; -#X connect 23 0 25 0; -#X connect 24 0 23 1; -#X connect 26 0 23 0; -#X connect 29 0 26 0; -#X connect 30 0 21 0; -#X connect 33 0 35 0; -#X connect 34 0 37 0; -#X connect 34 0 21 0; -#X connect 35 0 34 0; -#X connect 36 0 35 0; -#X connect 37 0 34 1; -#X connect 38 0 21 0; -#X connect 40 0 21 0; -#X connect 43 0 21 0; -#X connect 47 0 21 0; -#X connect 48 0 21 0; diff --git a/pianoroll/pianoroll.c b/pianoroll/pianoroll.c deleted file mode 100644 index c71735c..0000000 --- a/pianoroll/pianoroll.c +++ /dev/null @@ -1,815 +0,0 @@ -/* Copyright (c) 1997-1999 Miller Puckette. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* pianoroll : a graphical object which enables */ -/* to control a sequencer ( pitch and volume ) */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "If you obey society's rules" */ -/* "You'll be society's fool" */ -/* Devo - Society's rules */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - -#include "pianoroll.h" - -#ifdef NT -#include -#else -#include -#endif - -/* needed to create a pianoroll from PD's menu -void canvas_objtext(t_glist *gl, int xpos, int ypos, int selected, t_binbuf *b); -void canvas_startmotion(t_canvas *x); -*/ - -#define DEFAULT_SEQUENCER_WIDTH 200 -#define DEFAULT_SEQUENCER_HEIGHT 200 -#define DEFAULT_SEQUENCER_STEPS 16 -#define DEFAULT_SEQUENCER_NBGRADES 31 -#define DEFAULT_SEQUENCER_PITCH_MIN -15 -#define DEFAULT_SEQUENCER_PITCH_MAX 15 - -static char *pianoroll_version = "pianoroll: a graphical sequencer controller, version 0.10 (ydegoyon@free.fr)"; - -t_widgetbehavior pianoroll_widgetbehavior; -static t_class *pianoroll_class; -static int pianorollcount=0; - -static int guidebug=0; -static int pointsize = 5; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -/* drawing functions */ -static void pianoroll_draw_update(t_pianoroll *x, t_glist *glist) -{ - t_int si; - t_canvas *canvas=glist_getcanvas(glist); - - for ( si=0; six_nbsteps; si++ ) - { - int vi = (int)((1.0-x->x_volumes[si])*(x->x_nbgrades-1)); - int pi = (int)((x->x_pmax-x->x_peaches[si])/(x->x_pmax-x->x_pmin)*(x->x_nbgrades-1)); - - x->x_ivolumes[ si ] = vi; - x->x_ipeaches[ si ] = pi; - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, si, pi); - SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, si, vi); - } -} - -static void pianoroll_draw_new(t_pianoroll *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - // draw the grid - { - int gi, gj; - t_float xgstep = x->x_width/x->x_nbsteps; - t_float ygstep = x->x_height/x->x_nbgrades; - for ( gi=0; gix_nbsteps; gi++ ) - { - for ( gj=0; gjx_nbgrades; gj++ ) - { - SYS_VGUI9(".x%x.c create rectangle %d %d %d %d -fill #771623 -outline #998121 -tags %xPITCH%.4d%.4d\n", - canvas, - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep), - text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), - text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep), - x, gi, gj ); - SYS_VGUI9(".x%x.c create rectangle %d %d %d %d -fill #562663 -outline #998121 -tags %xVOLUME%.4d%.4d\n", - canvas, - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), - text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), - text_xpix(&x->x_obj, glist)+(int)((gi+1)*xgstep), - text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep), - x, gi, gj ); - } - } - // adjust height and width - x->x_width = (int)((x->x_nbsteps)*xgstep); - x->x_height = (int)((x->x_nbgrades)*ygstep); - } - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xIN\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) - 1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist), - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xOUTL\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2, - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xOUTR\n", - canvas, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2, - x); - - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void pianoroll_draw_move(t_pianoroll *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - // move the grid - { - int gi, gj; - t_float xgstep = x->x_width/x->x_nbsteps; - t_float ygstep = x->x_height/x->x_nbgrades; - for ( gi=0; gix_nbsteps; gi++ ) - { - for ( gj=0; gjx_nbgrades; gj++ ) - { - SYS_VGUI9(".x%x.c coords %xPITCH%.4d%.4d %d %d %d %d\n", - canvas, x, gi, gj, - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep), - text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), - text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep) - ); - SYS_VGUI9(".x%x.c coords %xVOLUME%.4d%.4d %d %d %d %d\n", - canvas, x, gi, gj, - text_xpix(&x->x_obj, glist)+(int)(gi*xgstep)+(int)(2*xgstep/3), - text_ypix(&x->x_obj, glist)+(int)(gj*ygstep), - text_xpix(&x->x_obj, glist)+(int)((gi+1)*xgstep), - text_ypix(&x->x_obj, glist)+(int)((gj+1)*ygstep) - ); - } - } - } - SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d \n", - canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) - 1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) - ); - SYS_VGUI7(".x%x.c coords %xOUTL %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+7, text_ypix(&x->x_obj, glist) + x->x_height+2 - ); - SYS_VGUI7(".x%x.c coords %xOUTR %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist)+x->x_width-7, text_ypix(&x->x_obj, glist) + x->x_height+1, - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist) + x->x_height+2 - ); - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void pianoroll_draw_erase(t_pianoroll* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - - SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xOUTL\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xOUTR\n", canvas, x); - // delete the grid - { - int gi, gj; - for ( gi=0; gix_nbsteps; gi++ ) - { - for ( gj=0; gjx_nbgrades; gj++ ) - { - SYS_VGUI5(".x%x.c delete %xPITCH%.4d%.4d\n", canvas, x, gi, gj); - SYS_VGUI5(".x%x.c delete %xVOLUME%.4d%.4d\n", canvas, x, gi, gj); - } - } - } -} - -static void pianoroll_draw_select(t_pianoroll* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - pd_bind(&x->x_obj.ob_pd, x->x_name); - /* sets the item in blue */ - } - else - { - pd_unbind(&x->x_obj.ob_pd, x->x_name); - } -} - -/* ------------------------ pianoroll widgetbehaviour----------------------------- */ - - -static void pianoroll_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_pianoroll* x = (t_pianoroll*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void pianoroll_save(t_gobj *z, t_binbuf *b) -{ - t_pianoroll *x = (t_pianoroll *)z; - t_int i; - - // post( "saving pianoroll : %s", x->x_name->s_name ); - binbuf_addv(b, "ssiissiiffiiifi", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_name, x->x_width, x->x_height, - x->x_pmin, x->x_pmax, - x->x_nbgrades, x->x_nbsteps, - x->x_defvalue, x->x_transpose, x->x_save - ); - if ( x->x_save ) - { - for ( i=0; ix_nbsteps; i++ ) - { - binbuf_addv(b, "ff", x->x_peaches[i], x->x_volumes[i] ); - } - } - binbuf_addv(b, ";"); -} - -static void pianoroll_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_pianoroll *x=(t_pianoroll *)z; - - sprintf(buf, "pdtk_pianoroll_dialog %%s %s %d %d %.2f %.2f %d %d %d %d\n", - x->x_name->s_name, x->x_width, x->x_height, x->x_pmin, x->x_pmax, - x->x_nbgrades, x->x_nbsteps, x->x_defvalue, x->x_save ); - // post("pianoroll_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void pianoroll_select(t_gobj *z, t_glist *glist, int selected) -{ - t_pianoroll *x = (t_pianoroll *)z; - - x->x_selected = selected; - pianoroll_draw_select( x, glist ); -} - -static void pianoroll_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_pianoroll *x = (t_pianoroll *)z; - t_rtext *y; - - // post("pianoroll_vis : %d", vis ); - if (vis) - { - pianoroll_draw_new( x, glist ); - pianoroll_draw_update( x, glist ); - } - else - { - pianoroll_draw_erase( x, glist ); - } -} - -static void pianoroll_dialog(t_pianoroll *x, t_symbol *s, int argc, t_atom *argv) -{ - int si, onbsteps; - t_float *newpeaches, *newvolumes; - - if ( !x ) { - post( "pianoroll : error :tried to set properties on an unexisting object" ); - } - if ( ( argv[5].a_w.w_float <= 0 ) || ( argv[5].a_w.w_float <= 0 ) ) { - post( "pianoroll : error : wrong number of steps or grades" ); - return; - } - if ( ( argv[3].a_w.w_float >= argv[4].a_w.w_float ) ) { - post( "pianoroll : error : min pitch is >= to max pitch" ); - return; - } - if ( argc != 9 ) - { - post( "pianoroll : error in the number of arguments ( %d )", argc ); - return; - } - if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || - argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || - argv[8].a_type != A_FLOAT - ) { - post( "pianoroll : wrong arguments" ); - return; - } - pianoroll_draw_erase(x, x->x_glist); - x->x_name = argv[0].a_w.w_symbol; - x->x_width = (int)argv[1].a_w.w_float; - x->x_height = (int)argv[2].a_w.w_float; - x->x_pmin = argv[3].a_w.w_float; - x->x_pmax = argv[4].a_w.w_float; - x->x_nbgrades = argv[5].a_w.w_float; - onbsteps = x->x_nbsteps; - x->x_nbsteps = argv[6].a_w.w_float; - x->x_defvalue = argv[7].a_w.w_float; - x->x_save = argv[8].a_w.w_float; - - if ( onbsteps != x->x_nbsteps ) - { - int cmindex = ( onbsteps > x->x_nbsteps ) ? x->x_nbsteps : onbsteps; - - newpeaches = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); - newvolumes = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); - for ( si=0; six_peaches[si]; - newvolumes[si] = x->x_volumes[si]; - } - freebytes( x->x_peaches, onbsteps*sizeof( t_float ) ); - freebytes( x->x_volumes, onbsteps*sizeof( t_float ) ); - x->x_peaches = newpeaches; - x->x_volumes = newvolumes; - for ( si=onbsteps; six_nbsteps; si++ ) - { - x->x_peaches[si] = x->x_defvalue; - x->x_volumes[si] = 1.0; - } - freebytes( x->x_ipeaches, onbsteps*sizeof( t_int ) ); - freebytes( x->x_ivolumes, onbsteps*sizeof( t_int ) ); - x->x_ipeaches = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_ivolumes = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); - } - pianoroll_draw_new(x, x->x_glist); - pianoroll_draw_update(x, x->x_glist); -} - -static void pianoroll_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void pianoroll_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_pianoroll *x = (t_pianoroll *)z; - int xold = text_xpix(&x->x_obj, glist); - int yold = text_ypix(&x->x_obj, glist); - - // post( "pianoroll_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) - { - pianoroll_draw_move(x, x->x_glist); - } -} - -static int pianoroll_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_pianoroll* x = (t_pianoroll *)z; - t_canvas *canvas=glist_getcanvas(glist); - - if ( doit) - { - // calculate position to update - { - int si, gi; - t_float xgstep = x->x_width/x->x_nbsteps; - t_float ygstep = x->x_height/x->x_nbgrades; - - si = ( xpix - text_xpix(&x->x_obj, glist) ) / xgstep; - gi = ( ypix - text_ypix(&x->x_obj, glist) ) / ygstep; - - // post( "pianoroll : step : %d : grade : %d", si, gi ); - - if ( ( xpix - text_xpix(&x->x_obj, glist) ) > ( si*xgstep+2*xgstep/3 ) ) - { - { - SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #562663\n", canvas, x, si, x->x_ivolumes[ si ] ); - } - - x->x_volumes[ si ] = (((float)x->x_nbgrades-1-(float)gi))/(float)(x->x_nbgrades-1); - SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, si, gi); - x->x_ivolumes[ si ] = gi; - } - else - { - { - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #761623\n", canvas, x, si, x->x_ipeaches[ si ]); - } - - x->x_peaches[ si ] = x->x_pmin+(float)(x->x_nbgrades-1-gi)/(float)(x->x_nbgrades-1)*(float)(x->x_pmax-x->x_pmin); - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, si, gi); - x->x_ipeaches[ si ] = gi; - } - } - - } - return (1); -} - -static void pianoroll_transpose(t_pianoroll *x, t_floatarg ftranspose) -{ - x->x_transpose = ftranspose; -} - -static void pianoroll_save_file(t_pianoroll *x, t_symbol *ffile) -{ - FILE *tmph; - t_int si; - - if ( ( tmph = fopen( ffile->s_name, "w" ) ) == NULL ) - { - post( "pianoroll : could not open file : %s for writing", ffile->s_name ); - return; - } - - // post( "saving pianoroll : %s", x->x_name->s_name ); - fprintf(tmph, "%d %d %f %f %d %d %d %f %d ", - x->x_width, x->x_height, - x->x_pmin, x->x_pmax, - x->x_nbgrades, x->x_nbsteps, - x->x_defvalue, x->x_transpose, x->x_save ); - for ( si=0; six_nbsteps; si++ ) - { - fprintf(tmph, "%f %f ", x->x_peaches[si], x->x_volumes[si] ); - } - - if ( fclose( tmph ) == -1 ) - { - post( "pianoroll : could not close file : %s ", ffile->s_name ); - return; - } -} - -static void pianoroll_load(t_pianoroll *x, t_symbol *ffile) -{ - FILE *tmph; - t_int si; - - if ( ( tmph = fopen( ffile->s_name, "r" ) ) == NULL ) - { - post( "pianoroll : could not open file : %s for reading", ffile->s_name ); - return; - } - - pianoroll_draw_erase(x, x->x_glist); - freebytes( x->x_peaches, x->x_nbsteps*sizeof( t_float ) ); - freebytes( x->x_volumes, x->x_nbsteps*sizeof( t_float ) ); - freebytes( x->x_ipeaches, x->x_nbsteps*sizeof( t_int ) ); - freebytes( x->x_ivolumes, x->x_nbsteps*sizeof( t_int ) ); - - if ( fscanf(tmph, "%d %d %f %f %d %d %d %f %d", - &x->x_width, &x->x_height, - &x->x_pmin, &x->x_pmax, - &x->x_nbgrades, &x->x_nbsteps, - &x->x_defvalue, &x->x_transpose, &x->x_save ) != 9 ) - { - post( "pianoroll : could not restore data from file : %s", ffile->s_name ); - return; - } - - x->x_peaches = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_volumes = ( t_float* ) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_ipeaches = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_ivolumes = ( t_int* ) getbytes( x->x_nbsteps*sizeof(t_int) ); - for ( si=0; six_nbsteps ; si++ ) - { - fscanf( tmph, "%f", &x->x_peaches[si] ); - fscanf( tmph, "%f", &x->x_volumes[si] ); - } - - pianoroll_draw_new(x, x->x_glist); - pianoroll_draw_update(x, x->x_glist); - - if ( fclose( tmph ) == -1 ) - { - post( "pianoroll : could not close file : %s ", ffile->s_name ); - return; - } -} - -static void pianoroll_init(t_pianoroll *x) -{ - t_int si; - - for ( si=0; six_nbsteps; si++ ) - { - x->x_peaches[si] = x->x_defvalue; - x->x_volumes[si] = 1.0; - } - pianoroll_draw_erase(x, x->x_glist ); - pianoroll_draw_new(x, x->x_glist ); - pianoroll_draw_update(x, x->x_glist ); -} - -static void pianoroll_pitch(t_pianoroll *x, t_floatarg fpos, t_floatarg fpitch) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int ipos; - - if ( ( ( (t_int) fpos ) < 0 ) || ( ( (t_int) fpos ) >= x->x_nbsteps ) ) - { - post( "pianoroll : wrong pitch position : %d", fpos ); - return; - } - ipos = (t_int) fpos; - if ( ( ( (t_int) fpitch ) < x->x_pmin ) || ( ( (t_int) fpitch ) > x->x_pmax ) ) - { - post( "pianoroll : wrong pitch value : %d", fpitch ); - return; - } - - { - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #761623\n", canvas, x, ipos, x->x_ipeaches[ ipos ]); - - x->x_ipeaches[ ipos ] = (t_int) ( ( ( x->x_pmax - fpitch ) / ( x->x_pmax - x->x_pmin ) ) * ( x->x_nbgrades - 1 ) ); - x->x_peaches[ ipos ] = x->x_pmin+(float)(x->x_nbgrades-1-x->x_ipeaches[ ipos ])/(float)(x->x_nbgrades-1)*(float)(x->x_pmax-x->x_pmin); - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, ipos, x->x_ipeaches[ ipos ]); - } -} - -static void pianoroll_volume(t_pianoroll *x, t_floatarg fpos, t_floatarg fvol) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int ipos; - - if ( ( ( (t_int) fpos ) < 0 ) || ( ( (t_int) fpos ) >= x->x_nbsteps ) ) - { - post( "pianoroll : wrong volume position : %d", fpos ); - return; - } - ipos = (t_int) fpos; - if ( ( ( (t_int) fvol ) < 0.0 ) || ( ( (t_int) fvol ) > 1.0 ) ) - { - post( "pianoroll : wrong volume value : %d", fvol ); - return; - } - - { - SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #562663\n", canvas, x, ipos, x->x_ivolumes[ ipos ] ); - - x->x_ivolumes[ ipos ] = (t_int) ( ( 1 - fvol ) * (x->x_nbgrades-1) ); - x->x_volumes[ ipos ] = (((float)x->x_nbgrades-1-(float)x->x_ivolumes[ ipos ]))/(float)(x->x_nbgrades-1); - SYS_VGUI5(".x%x.c itemconfigure %xVOLUME%.4d%.4d -fill #FF0000\n", canvas, x, ipos, x->x_ivolumes[ ipos ] ); - } -} - -static void pianoroll_float(t_pianoroll *x, t_floatarg fposition) -{ - t_int pposition, rposition, rrposition; - t_float fpart; - t_int pi; - t_canvas *canvas; - - pposition = ( (int)fposition - 1 ) % x->x_nbsteps; - if ( pposition < 0 ) pposition += x->x_nbsteps; - rposition = ( (int)fposition ) % x->x_nbsteps; - if ( rposition < 0 ) rposition += x->x_nbsteps; - rrposition = ( (int)fposition +1 ) % x->x_nbsteps; - if ( rrposition < 0 ) rrposition += x->x_nbsteps; - - // post ( "pposition=%d rposition=%d rrposition=%d", pposition, rposition, rrposition ); - fpart = fposition - (int)fposition; - pi=-1; - canvas=glist_getcanvas(x->x_glist); - - outlet_float( x->x_pitch, x->x_peaches[ rposition ] + - fpart*(x->x_peaches[ rrposition ] - x->x_peaches[ rposition ] ) + - x->x_transpose ); - outlet_float( x->x_volume, x->x_volumes[ rposition ] + - fpart*(x->x_volumes[ rrposition ] - x->x_volumes[ rposition ] ) ); - - // graphical update - { - if ( x->x_scurrent != -1 ) - { - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #FFFF00\n", canvas, x, - x->x_scurrent, x->x_ipeaches[ x->x_scurrent ]); - } - x->x_scurrent = rposition; - SYS_VGUI5(".x%x.c itemconfigure %xPITCH%.4d%.4d -fill #00FF00\n", canvas, x, - x->x_scurrent, x->x_ipeaches[ x->x_scurrent ]); - } -} - -static t_pianoroll *pianoroll_new(t_symbol *s, int argc, t_atom *argv) -{ - int si, i, zz; - t_pianoroll *x; - t_pd *x2; - char *str; - - // post( "pianoroll_new : create : %s argc =%d", s->s_name, argc ); - - x = (t_pianoroll *)pd_new(pianoroll_class); - // new pianoroll created from the gui - if ( argc != 0 ) - { - if ( argc < 10 ) - { - post( "pianoroll : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( ( argv[5].a_w.w_float <= 0 ) || ( argv[5].a_w.w_float <= 0 ) ) { - post( "pianoroll : error : wrong number of steps or grades" ); - return NULL; - } - if ( ( argv[3].a_w.w_float >= argv[4].a_w.w_float ) ) { - post( "pianoroll : error : min pitch is > to max pitch" ); - return NULL; - } - if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_FLOAT || - argv[6].a_type != A_FLOAT || argv[7].a_type != A_FLOAT || - argv[8].a_type != A_FLOAT || argv[9].a_type != A_FLOAT ) { - post( "pianoroll : wrong arguments" ); - return NULL; - } - - // update pianoroll count - if (!strncmp((str = argv[0].a_w.w_symbol->s_name), "pianoroll", 9) - && (zz = atoi(str + 9)) > pianorollcount) - { - // post( "pianoroll : already %d objects", pianorollcount ); - pianorollcount = zz; - } - x->x_name = argv[0].a_w.w_symbol; - pd_bind(&x->x_obj.ob_pd, x->x_name); - x->x_width = argv[1].a_w.w_float; - x->x_height = argv[2].a_w.w_float; - x->x_pmin = argv[3].a_w.w_float; - x->x_pmax = argv[4].a_w.w_float; - x->x_nbgrades = argv[5].a_w.w_float; - x->x_nbsteps = argv[6].a_w.w_float; - x->x_peaches = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_ipeaches = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_volumes = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_ivolumes = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_defvalue = argv[7].a_w.w_float; - x->x_transpose = argv[8].a_w.w_float; - x->x_save = argv[9].a_w.w_float; - } - else - { - char buf[40]; - - sprintf(buf, "pianoroll%d", ++pianorollcount); - s = gensym(buf); - - x->x_name = s; - pd_bind(&x->x_obj.ob_pd, x->x_name); - - x->x_width = DEFAULT_SEQUENCER_WIDTH; - x->x_height = DEFAULT_SEQUENCER_HEIGHT; - x->x_pmin = DEFAULT_SEQUENCER_PITCH_MIN; - x->x_pmax = DEFAULT_SEQUENCER_PITCH_MAX; - x->x_nbgrades = DEFAULT_SEQUENCER_NBGRADES; - x->x_nbsteps = DEFAULT_SEQUENCER_STEPS; - x->x_peaches = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_ipeaches = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_volumes = (t_float*) getbytes( x->x_nbsteps*sizeof(t_float) ); - x->x_ivolumes = (t_int*) getbytes( x->x_nbsteps*sizeof(t_int) ); - x->x_defvalue = 0; - x->x_transpose = 0; - x->x_save = 1; - - } - - // common fields for new and restored pianorolls - x->x_selected = 0; - x->x_scurrent = -1; - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_pitch = outlet_new(&x->x_obj, &s_float ); - x->x_volume = outlet_new(&x->x_obj, &s_float ); - // post( "pianoroll : argc : %d", argc ); - if ( ( argc != 0 ) && ( x->x_save ) ) - { - int ai = 10; - int si = 0; - - while ( ai < argc ) - { - x->x_peaches[si] = argv[ai++].a_w.w_float; - if ( ai >= argc ) break; - x->x_volumes[si++] = argv[ai++].a_w.w_float; - } - } - else // following arguments are the values of pitch, volumes - { - for ( si=0; six_nbsteps; si++ ) - { - x->x_peaches[si] = x->x_defvalue; - x->x_volumes[si] = 1.0; - } - } - - // post( "pianoroll_new name : %s width: %d height : %d", x->x_name->s_name, x->x_width, x->x_height ); - - return (x); -} - -static void pianoroll_free(t_pianoroll *x) -{ - // post( "pianoroll~: pianoroll_free" ); - if ( x->x_peaches ) - { - freebytes( x->x_peaches, x->x_nbsteps*sizeof(t_float) ); - } - if ( x->x_ipeaches ) - { - freebytes( x->x_ipeaches, x->x_nbsteps*sizeof(t_int) ); - } - if ( x->x_volumes ) - { - freebytes( x->x_volumes, x->x_nbsteps*sizeof(t_float) ); - } - if ( x->x_ivolumes ) - { - freebytes( x->x_ivolumes, x->x_nbsteps*sizeof(t_int) ); - } -} - -void pianoroll_setup(void) -{ - post( pianoroll_version ); -#include "pianoroll.tk2c" - pianoroll_class = class_new(gensym("pianoroll"), (t_newmethod)pianoroll_new, - (t_method)pianoroll_free, sizeof(t_pianoroll), 0, A_GIMME, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_float, &s_float, A_FLOAT, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_transpose, gensym("transpose"), - A_FLOAT, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_init, gensym("init"), 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_save_file, gensym("save"), A_SYMBOL, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_load, gensym("load"), A_SYMBOL, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_pitch, gensym("pitch"), A_FLOAT, A_FLOAT, 0); - class_addmethod(pianoroll_class, (t_method)pianoroll_volume, gensym("volume"), A_FLOAT, A_FLOAT, 0); - - - pianoroll_widgetbehavior.w_getrectfn = pianoroll_getrect; - pianoroll_widgetbehavior.w_displacefn = pianoroll_displace; - pianoroll_widgetbehavior.w_selectfn = pianoroll_select; - pianoroll_widgetbehavior.w_activatefn = NULL; - pianoroll_widgetbehavior.w_deletefn = pianoroll_delete; - pianoroll_widgetbehavior.w_visfn = pianoroll_vis; - pianoroll_widgetbehavior.w_clickfn = pianoroll_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(pianoroll_class, pianoroll_properties); - class_setsavefn(pianoroll_class, pianoroll_save); -#else - pianoroll_widgetbehavior.w_propertiesfn = pianoroll_properties; - pianoroll_widgetbehavior.w_savefn = pianoroll_save; -#endif - - class_setwidget(pianoroll_class, &pianoroll_widgetbehavior); - -} diff --git a/pianoroll/pianoroll.h b/pianoroll/pianoroll.h deleted file mode 100644 index 4f6a783..0000000 --- a/pianoroll/pianoroll.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* a header for pianoroll which enables -* to control a sequencer ( pitch and volume ) -*/ - -#ifndef __G_PIANOROLL_H -#define __G_PIANOROLL_H - -typedef struct _pianoroll -{ - t_object x_obj; - t_glist *x_glist; - t_symbol *x_name; - t_outlet *x_pitch; - t_outlet *x_volume; - int x_height; /* height of the pianoroll */ - int x_width; /* width of the pianoroll */ - t_float x_pmin; /* minimum value of the pitch */ - t_float x_pmax; /* max value of the pitch */ - t_int x_nbgrades; /* number of grades for the pitch */ - t_int x_nbsteps; /* number of steps */ - t_int x_defvalue; /* default value for the pitch */ - t_float x_transpose;/* transposition value */ - t_float *x_peaches; /* pitch for each step */ - t_int *x_ipeaches; /* pitch index for each step */ - t_float *x_volumes; /* volume for each step */ - t_int *x_ivolumes; /* volume index for each step */ - int x_selected; /* stores selected state */ - int x_xlines; /* number of vertical lines */ - int x_ylines; /* number of horizontal lines */ - int x_scurrent; /* cureent step */ - int x_save; /* saving contents flag */ -} t_pianoroll; - -EXTERN t_rtext *rtext_new_without_senditup(t_glist *glist, t_text *who, t_rtext *next); - -#endif diff --git a/pianoroll/pianoroll.tk b/pianoroll/pianoroll.tk deleted file mode 100644 index eccadce..0000000 --- a/pianoroll/pianoroll.tk +++ /dev/null @@ -1,164 +0,0 @@ -############ pianoroll procedures -- ydegoyon@free.fr ######### - -proc pianoroll_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_name [concat graph_name_$vid] - global $var_graph_name - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_pmin [concat graph_pmin_$vid] - global $var_graph_pmin - set var_graph_pmax [concat graph_pmax_$vid] - global $var_graph_pmax - set var_graph_nbgrades [concat graph_nbgrades_$vid] - global $var_graph_nbgrades - set var_graph_nbsteps [concat graph_nbsteps_$vid] - global $var_graph_nbsteps - set var_graph_defvalue [concat graph_defvalue_$vid] - global $var_graph_defvalue - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set cmd [concat $id dialog \ - [eval concat $$var_graph_name] \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_pmin] \ - [eval concat $$var_graph_pmax] \ - [eval concat $$var_graph_nbgrades] \ - [eval concat $$var_graph_nbsteps] \ - [eval concat $$var_graph_defvalue] \ - [eval concat $$var_graph_save] \;] - #puts stderr $cmd - pd $cmd -} - -proc pianoroll_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc pianoroll_ok {id} { - pianoroll_apply $id - pianoroll_cancel $id -} - -proc pdtk_pianoroll_dialog {id name width height pmin pmax nbgrades nbsteps defvalue save } { - set vid [string trimleft $id .] - set var_graph_name [concat graph_name_$vid] - global $var_graph_name - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_pmin [concat graph_pmin_$vid] - global $var_graph_pmin - set var_graph_pmax [concat graph_pmax_$vid] - global $var_graph_pmax - set var_graph_nbgrades [concat graph_nbgrades_$vid] - global $var_graph_nbgrades - set var_graph_nbsteps [concat graph_nbsteps_$vid] - global $var_graph_nbsteps - set var_graph_defvalue [concat graph_defvalue_$vid] - global $var_graph_defvalue - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set $var_graph_name $name - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_pmin $pmin - set $var_graph_pmax $pmax - set $var_graph_nbgrades $nbgrades - set $var_graph_nbsteps $nbsteps - set $var_graph_defvalue $defvalue - set $var_graph_save $save - - toplevel $id - wm title $id {pianoroll} - wm protocol $id WM_DELETE_WINDOW [concat pianoroll_cancel $id] - - label $id.label -text {PIANOROLL PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "pianoroll_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "pianoroll_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "pianoroll_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lname -text "Name :" - entry $id.1rangef.name -textvariable $var_graph_name -width 15 - pack $id.1rangef.lname $id.1rangef.name -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lwidth -text "Width :" - entry $id.2rangef.width -textvariable $var_graph_width -width 7 - pack $id.2rangef.lwidth $id.2rangef.width -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lheight -text "Height :" - entry $id.3rangef.height -textvariable $var_graph_height -width 7 - pack $id.3rangef.lheight $id.3rangef.height -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.lpmin -text "Pitch low :" - entry $id.4rangef.pmin -textvariable $var_graph_pmin -width 7 - pack $id.4rangef.lpmin $id.4rangef.pmin -side left - - frame $id.5rangef - pack $id.5rangef -side top - label $id.5rangef.lpmax -text "Pitch high :" - entry $id.5rangef.pmax -textvariable $var_graph_pmax -width 7 - pack $id.5rangef.lpmax $id.5rangef.pmax -side left - - frame $id.6rangef - pack $id.6rangef -side top - label $id.6rangef.lnbgrades -text "Grades :" - entry $id.6rangef.nbgrades -textvariable $var_graph_nbgrades -width 7 - pack $id.6rangef.lnbgrades $id.6rangef.nbgrades -side left - - frame $id.7rangef - pack $id.7rangef -side top - label $id.7rangef.lnbsteps -text "Steps :" - entry $id.7rangef.nbsteps -textvariable $var_graph_nbsteps -width 7 - pack $id.7rangef.lnbsteps $id.7rangef.nbsteps -side left - - frame $id.8rangef - pack $id.8rangef -side top - label $id.8rangef.ldefvalue -text "Default Value :" - entry $id.8rangef.defvalue -textvariable $var_graph_defvalue -width 7 - pack $id.8rangef.ldefvalue $id.8rangef.defvalue -side left - - checkbutton $id.save -text {Save contents} -variable $var_graph_save \ - -anchor w - pack $id.save -side top - - bind $id.1rangef.name [concat pianoroll_ok $id] - bind $id.2rangef.width [concat pianoroll_ok $id] - bind $id.3rangef.height [concat pianoroll_ok $id] - bind $id.4rangef.pmin [concat pianoroll_ok $id] - bind $id.5rangef.pmax [concat pianoroll_ok $id] - bind $id.6rangef.nbgrades [concat pianoroll_ok $id] - bind $id.7rangef.nbsteps [concat pianoroll_ok $id] - bind $id.8rangef.defvalue [concat pianoroll_ok $id] - focus $id.1rangef.name -} - -############ pianoroll procedures END -- ydegoyon@free.fr ######### diff --git a/pianoroll/pianoroll.tk2c b/pianoroll/pianoroll.tk2c deleted file mode 100755 index 10f5645..0000000 --- a/pianoroll/pianoroll.tk2c +++ /dev/null @@ -1,131 +0,0 @@ -// ########### pianoroll procedures -- ydegoyon@free.fr ######### -sys_gui("proc pianoroll_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_name [concat graph_name_$vid]\n"); -sys_gui("global $var_graph_name\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_pmin [concat graph_pmin_$vid]\n"); -sys_gui("global $var_graph_pmin\n"); -sys_gui("set var_graph_pmax [concat graph_pmax_$vid]\n"); -sys_gui("global $var_graph_pmax\n"); -sys_gui("set var_graph_nbgrades [concat graph_nbgrades_$vid]\n"); -sys_gui("global $var_graph_nbgrades\n"); -sys_gui("set var_graph_nbsteps [concat graph_nbsteps_$vid]\n"); -sys_gui("global $var_graph_nbsteps\n"); -sys_gui("set var_graph_defvalue [concat graph_defvalue_$vid]\n"); -sys_gui("global $var_graph_defvalue\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_name] [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_pmin] [eval concat $$var_graph_pmax] [eval concat $$var_graph_nbgrades] [eval concat $$var_graph_nbsteps] [eval concat $$var_graph_defvalue] [eval concat $$var_graph_save] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc pianoroll_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc pianoroll_ok {id} {\n"); -sys_gui("pianoroll_apply $id\n"); -sys_gui("pianoroll_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_pianoroll_dialog {id name width height pmin pmax nbgrades nbsteps defvalue save } {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_name [concat graph_name_$vid]\n"); -sys_gui("global $var_graph_name\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_pmin [concat graph_pmin_$vid]\n"); -sys_gui("global $var_graph_pmin\n"); -sys_gui("set var_graph_pmax [concat graph_pmax_$vid]\n"); -sys_gui("global $var_graph_pmax\n"); -sys_gui("set var_graph_nbgrades [concat graph_nbgrades_$vid]\n"); -sys_gui("global $var_graph_nbgrades\n"); -sys_gui("set var_graph_nbsteps [concat graph_nbsteps_$vid]\n"); -sys_gui("global $var_graph_nbsteps\n"); -sys_gui("set var_graph_defvalue [concat graph_defvalue_$vid]\n"); -sys_gui("global $var_graph_defvalue\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set $var_graph_name $name\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_pmin $pmin\n"); -sys_gui("set $var_graph_pmax $pmax\n"); -sys_gui("set $var_graph_nbgrades $nbgrades\n"); -sys_gui("set $var_graph_nbsteps $nbsteps\n"); -sys_gui("set $var_graph_defvalue $defvalue\n"); -sys_gui("set $var_graph_save $save\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {pianoroll}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat pianoroll_cancel $id]\n"); -sys_gui("label $id.label -text {PIANOROLL PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"pianoroll_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"pianoroll_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"pianoroll_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lname -text \"Name :\"\n"); -sys_gui("entry $id.1rangef.name -textvariable $var_graph_name -width 15\n"); -sys_gui("pack $id.1rangef.lname $id.1rangef.name -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.2rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.2rangef.lwidth $id.2rangef.width -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.3rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.3rangef.lheight $id.3rangef.height -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.lpmin -text \"Pitch low :\"\n"); -sys_gui("entry $id.4rangef.pmin -textvariable $var_graph_pmin -width 7\n"); -sys_gui("pack $id.4rangef.lpmin $id.4rangef.pmin -side left\n"); -sys_gui("frame $id.5rangef\n"); -sys_gui("pack $id.5rangef -side top\n"); -sys_gui("label $id.5rangef.lpmax -text \"Pitch high :\"\n"); -sys_gui("entry $id.5rangef.pmax -textvariable $var_graph_pmax -width 7\n"); -sys_gui("pack $id.5rangef.lpmax $id.5rangef.pmax -side left\n"); -sys_gui("frame $id.6rangef\n"); -sys_gui("pack $id.6rangef -side top\n"); -sys_gui("label $id.6rangef.lnbgrades -text \"Grades :\"\n"); -sys_gui("entry $id.6rangef.nbgrades -textvariable $var_graph_nbgrades -width 7\n"); -sys_gui("pack $id.6rangef.lnbgrades $id.6rangef.nbgrades -side left\n"); -sys_gui("frame $id.7rangef\n"); -sys_gui("pack $id.7rangef -side top\n"); -sys_gui("label $id.7rangef.lnbsteps -text \"Steps :\"\n"); -sys_gui("entry $id.7rangef.nbsteps -textvariable $var_graph_nbsteps -width 7\n"); -sys_gui("pack $id.7rangef.lnbsteps $id.7rangef.nbsteps -side left\n"); -sys_gui("frame $id.8rangef\n"); -sys_gui("pack $id.8rangef -side top\n"); -sys_gui("label $id.8rangef.ldefvalue -text \"Default Value :\"\n"); -sys_gui("entry $id.8rangef.defvalue -textvariable $var_graph_defvalue -width 7\n"); -sys_gui("pack $id.8rangef.ldefvalue $id.8rangef.defvalue -side left\n"); -sys_gui("checkbutton $id.save -text {Save contents} -variable $var_graph_save -anchor w\n"); -sys_gui("pack $id.save -side top\n"); -sys_gui("bind $id.1rangef.name [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.2rangef.width [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.3rangef.height [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.4rangef.pmin [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.5rangef.pmax [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.6rangef.nbgrades [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.7rangef.nbsteps [concat pianoroll_ok $id]\n"); -sys_gui("bind $id.8rangef.defvalue [concat pianoroll_ok $id]\n"); -sys_gui("focus $id.1rangef.name\n"); -sys_gui("}\n"); -// ########### pianoroll procedures END -- ydegoyon@free.fr ######### diff --git a/pianoroll/tk2c.bash b/pianoroll/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/pianoroll/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/playlist-help.pd b/playlist-help.pd new file mode 100644 index 0000000..b035bc3 --- /dev/null +++ b/playlist-help.pd @@ -0,0 +1,64 @@ +#N canvas 96 132 817 563 10; +#X text 28 57 Constructor : playlist ; +#X text 88 95 playlist all 200 200; +#X text 88 107 playlist mp3 200 200; +#X text 30 78 Examples :; +#X text 72 507 Comments and bugs @ ydegoyon@free.fr; +#X symbolatom 363 437 50 0 0 0 - - -; +#X text 17 444 Note : you can scroll the list by dragging; +#X text 15 455 the mouse in the yellow area; +#X text 17 466 You can select and scroll in the blue area; +#X obj 360 221 playlist all 400 200 {Courier 12 bold} grey yellow black +red; +#X msg 373 77 seek \$1; +#X text 485 63 You can seek a file in the list; +#X text 485 74 It will skip the first two items ( '.' and '..'); +#X text 484 86 and behave like a round list; +#X text 28 14 Playlist lets you switch files in one click; +#X text 27 25 It's handling most non-alpha characters gracefully; +#X floatatom 435 79 5 0 0 0 - - -; +#X symbolatom 404 464 50 0 0 0 - - -; +#X symbolatom 450 491 50 0 0 0 - - -; +#X msg 151 163 location ..; +#X msg 150 140 location /tmp; +#X text 33 212 You can change change location; +#X text 33 222 with a message.; +#X text 33 234 Thus \, you can initialize the object; +#X text 32 243 in a particular folder.; +#X msg 151 185 location patches; +#X msg 334 106 sort \$1; +#X obj 395 107 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X text 499 110 Use alphabetical or creation time order; +#X obj 87 140 loadbang; +#X text 628 136 Change the font; +#X msg 300 136 font Helvetica normal 14; +#X msg 478 136 font Courier bold 24; +#X msg 379 163 scroll 200; +#X msg 460 163 scroll -200; +#X text 551 162 Scrolling by numbers for the laziest; +#X obj 526 191 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 +1; +#X msg 436 191 graphics \$1; +#X text 655 191 Show or hide graphics; +#X msg 549 190 1; +#X obj 582 191 loadbang; +#X connect 9 0 5 0; +#X connect 9 1 17 0; +#X connect 9 2 18 0; +#X connect 10 0 9 0; +#X connect 16 0 10 0; +#X connect 19 0 9 0; +#X connect 20 0 9 0; +#X connect 25 0 9 0; +#X connect 26 0 9 0; +#X connect 27 0 26 0; +#X connect 29 0 20 0; +#X connect 31 0 9 0; +#X connect 32 0 9 0; +#X connect 33 0 9 0; +#X connect 34 0 9 0; +#X connect 36 0 37 0; +#X connect 37 0 9 0; +#X connect 39 0 36 0; +#X connect 40 0 39 0; diff --git a/playlist.c b/playlist.c new file mode 100644 index 0000000..7311eec --- /dev/null +++ b/playlist.c @@ -0,0 +1,1074 @@ +/*------------------------ playlist~ ------------------------------------------ */ +/* */ +/* playlist~ : lets you choose a file with 1 click */ +/* or by sending a 'seek #' message */ +/* constructor : playlist */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "If a man's made of blood and iron" */ +/* "Doctor, doctor, what's in my chest ????" */ +/* Gang Of Four -- Guns Before Butter */ +/* ---------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" +#include + +#ifdef _WIN32 +#include +#include +#include + +int scandir(const char *dir, struct dirent ***namelist, + int (*select)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) { + DIR *d; + struct dirent *entry; + register int i=0; + size_t entrysize; + + if ((d=opendir(dir)) == NULL) + return(-1); + + *namelist=NULL; + while ((entry=readdir(d)) != NULL) + { + if (select == NULL || (select != NULL && (*select)(entry))) + { + *namelist=(struct dirent **)realloc((void *)(*namelist), + (size_t)((i+1)*sizeof(struct dirent *))); + if (*namelist == NULL) return(-1); + entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1; + (*namelist)[i]=(struct dirent *)malloc(entrysize); + if ((*namelist)[i] == NULL) return(-1); + memcpy((*namelist)[i], entry, entrysize); + i++; + } + } + if (closedir(d)) return(-1); + if (i == 0) return(-1); + if (compar != NULL) + qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar); + + return(i); +} + +int alphasort(const struct dirent **a, const struct dirent **b) { + return(strcmp((*a)->d_name, (*b)->d_name)); + } + +int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); +int alphasort(const struct dirent **, const struct dirent **); + +#else +#include +#endif + +t_widgetbehavior playlist_widgetbehavior; +static t_class *playlist_class; + +static int guidebug=0; + +static char *playlist_version = "playlist: 1 click file chooser : version 0.12, written by Yves Degoyon (ydegoyon@free.fr)"; + +#define MAX_DIR_LENGTH 2048 // maximum length for a directory name + +#define MIN(a,b) (a>b?b:a) + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + + +typedef struct _playlist +{ + t_object x_obj; + t_glist *x_glist; + t_outlet *x_fullpath; + t_outlet *x_file; + t_outlet *x_dir; + char *x_extension; /* extension to selected files */ + t_int x_height; /* height of the playlist */ + t_int x_width; /* width of the playlist */ + t_int x_itemselected; /* index of the selected item */ + t_int x_selected; /* stores selected state */ + t_int x_graphics; /* flag to draw graphics or not */ + char **x_dentries; /* directory entries */ + t_int x_nentries; /* number of entries in the current dir */ + t_int x_pnentries; /* previous size of entries list */ + t_int x_firstseen; /* first displayed entry */ + t_int x_lastseen; /* last displayed entry */ + t_int x_cdy; /* cumulated y drag */ + t_int x_sort; /* sorting option flag */ + char *x_curdir; /* current directory informations */ + char *x_font; /* font used for entries */ + t_int x_charheight; /* height of characters */ + t_int x_charwidth; /* width of characters */ + char *x_bgcolor; /* background color */ + char *x_sbcolor; /* scrollbar color */ + char *x_fgcolor; /* foreground color */ + char *x_secolor; /* selection color */ +} t_playlist; + + +static void playlist_update_dir(t_playlist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + char wrappedname[ MAX_DIR_LENGTH ]; + struct timespec tv; + + tv.tv_sec = 0; + tv.tv_nsec = 10000000; + + // set title + SYS_VGUI3(".x%x.c delete %xTITLE\n", canvas, x); + if ( x->x_graphics ) + { + SYS_VGUI8(".x%x.c create text %d %d -width %d -text \"%s\" -anchor w -font %s -tags %xTITLE\n", + canvas, + text_xpix(&x->x_obj, glist)+5, + text_ypix(&x->x_obj, glist)-10, + x->x_width, + x->x_curdir, + x->x_font, + x ); + } + + // delete previous entries + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); + } + + // display the content of current directory + { + t_int nentries, i; + struct dirent** dentries; /* all directory entries */ + + // post( "playlist : scandir : %s", x->x_curdir ); + if ( ( nentries = scandir(x->x_curdir, &dentries, NULL, (x->x_sort==1)?alphasort:NULL ) ) == -1 ) + { + post( "playlist : could not scan current directory ( where the hell are you ??? )" ); + perror( "scandir" ); + return; + } + + x->x_firstseen = 0; + if ( x->x_dentries ) + { + for ( i=0; ix_nentries; i++ ) + { + // post( "playlist : freeing entry %d size=%d : %s", i, strlen( x->x_dentries[i] ) + 1, x->x_dentries[i] ); + freebytes( x->x_dentries[i], strlen( x->x_dentries[i] ) + 1 ); + } + } + if ( x->x_pnentries != -1 ) + { + freebytes( x->x_dentries, x->x_pnentries*sizeof(char**) ); + } + + x->x_nentries = 0; + // post( "playlist : allocating dentries %d", nentries ); + x->x_dentries = (char **) getbytes( nentries*sizeof(char**) ) ; + x->x_pnentries = nentries; + for ( i=0; id_name ) ) != NULL ) ) || + ( strstr( dentries[i]->d_name, x->x_extension ) ) || + ( !strcmp( x->x_extension, "all" ) ) + ) + { + // close temporarily opened dir + if ( tmpdir ) + { + if ( closedir( tmpdir ) < 0 ) + { + post( "playlist : could not close directory %s", dentries[i]->d_name ); + } + } + + // post( "playlist : allocating entry %d %d : %s", x->x_nentries, strlen( dentries[i]->d_name ) + 1, dentries[i]->d_name ); + x->x_dentries[x->x_nentries] = ( char * ) getbytes( strlen( dentries[i]->d_name ) + 1 ); + strcpy( x->x_dentries[x->x_nentries], dentries[i]->d_name ); + + // display the entry if displayable + if ( x->x_nentries*x->x_charheight+5 < x->x_height ) + { + // nanosleep( &tv, NULL ); + x->x_lastseen = x->x_nentries; + strncpy( wrappedname, x->x_dentries[x->x_nentries], MIN(x->x_width/x->x_charwidth, MAX_DIR_LENGTH) ); + wrappedname[ x->x_width/x->x_charwidth ] = '\0'; + SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xENTRY%d\n", + canvas, + text_xpix(&x->x_obj, glist)+5, + text_ypix(&x->x_obj, glist)+5+(x->x_nentries-x->x_firstseen)*x->x_charheight, + x->x_fgcolor, + x->x_secolor, + x->x_width, + wrappedname, + x->x_font, + x, x->x_nentries ); + } + x->x_nentries++; + } + + } + + } +} + +static void playlist_output_current(t_playlist* x) +{ + // output the selected dir+file + // check that it's not a directory + if ( chdir( x->x_dentries[x->x_itemselected] ) == 0 ) + { + chdir( x->x_curdir ); + return; + } + + if ( x->x_dentries && x->x_itemselected < x->x_nentries && x->x_itemselected >= 0 ) + { + char* tmpstring = (char*) getbytes( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected]) + 2 ); + + sprintf( tmpstring, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); + outlet_symbol( x->x_dir, gensym( x->x_curdir ) ); + outlet_symbol( x->x_file, gensym( x->x_dentries[x->x_itemselected] ) ); + outlet_symbol( x->x_fullpath, gensym( tmpstring ) ); + freebytes( tmpstring, strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected]) + 2 ); + } +} + +static void playlist_sort(t_playlist* x, t_floatarg fsort) +{ + if ( ( (t_int)fsort != 0 ) && ( (t_int)fsort != 1 ) ) + { + post( "playlist : wrong argument to playlist message : %d", (t_int)fsort ); + return; + } + + x->x_sort = (t_int) fsort; + playlist_update_dir( x, x->x_glist ); +} + +static void playlist_font(t_playlist* x, t_symbol *fname, t_symbol *fcase, t_floatarg fsize) +{ + if ( (t_int)fsize <= 4 ) + { + post( "playlist : wrong font size in font message : %d", (t_int)fsize ); + return; + } + sprintf( x->x_font, "{%s %d %s}", fname->s_name, (int)fsize, fcase->s_name ); + x->x_charheight = (t_int)fsize; + x->x_charwidth = (2*x->x_charheight)/3; + post( "playlist : setting font to : %s", x->x_font ); + playlist_update_dir( x, x->x_glist ); +} + +static void playlist_draw_new(t_playlist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + x->x_glist = glist; + if ( x->x_graphics ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xPLAYLIST\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x->x_bgcolor, x); + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSCROLLLIST\n", + canvas, text_xpix(&x->x_obj, glist)+4*x->x_width/5, text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x->x_sbcolor, x); + } + playlist_update_dir( x, glist ); + +} + +static void playlist_draw_move(t_playlist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + struct timespec tv; + + tv.tv_sec = 0; + tv.tv_nsec = 10000000; + + if ( x->x_graphics ) + { + SYS_VGUI7(".x%x.c coords %xPLAYLIST %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, + text_ypix(&x->x_obj, glist)+x->x_height); + SYS_VGUI7(".x%x.c coords %xSCROLLLIST %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)+4*x->x_width/5, text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, + text_ypix(&x->x_obj, glist)+x->x_height); + SYS_VGUI5(".x%x.c coords %xTITLE %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)+5, text_ypix(&x->x_obj, glist)-10 ); + } + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + // nanosleep( &tv, NULL ); + SYS_VGUI6(".x%x.c coords %xENTRY%d %d %d\n", + canvas, x, i, + text_xpix(&x->x_obj, glist)+5, + text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight); + } + + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void playlist_draw_erase(t_playlist* x, t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + + if ( x->x_graphics ) + { + SYS_VGUI3(".x%x.c delete %xPLAYLIST\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xSCROLLLIST\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xTITLE\n", canvas, x); + } + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); + } +} + +static void playlist_draw_select(t_playlist* x, t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + // post( "playlist : select" ); + if(x->x_selected) + { + /* sets the item in blue */ + if (x->x_graphics) SYS_VGUI3(".x%x.c itemconfigure %xPLAYLIST -outline #0000FF\n", canvas, x); + } + else + { + if (x->x_graphics) SYS_VGUI3(".x%x.c itemconfigure %xPLAYLIST -outline #000000\n", canvas, x); + } +} + +/* ------------------------ playlist widgetbehaviour----------------------------- */ + + +static void playlist_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_playlist* x = (t_playlist*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void playlist_save(t_gobj *z, t_binbuf *b) +{ + t_playlist *x = (t_playlist *)z; + + // post( "saving playlist : %s", x->x_extension ); + binbuf_addv(b, "ssiissiisssss", gensym("#X"), gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + gensym("playlist"), gensym(x->x_extension), x->x_width, x->x_height, + gensym(x->x_font), gensym(x->x_bgcolor), gensym(x->x_sbcolor), + gensym(x->x_fgcolor), gensym(x->x_secolor) ); + binbuf_addv(b, ";"); +} + +static void playlist_select(t_gobj *z, t_glist *glist, int selected) +{ + t_playlist *x = (t_playlist *)z; + + x->x_selected = selected; + + playlist_draw_select( x, glist ); +} + +static void playlist_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_playlist *x = (t_playlist *)z; + + x->x_glist = glist; + if (vis) + { + playlist_draw_new( x, glist ); + } + else + { + playlist_draw_erase( x, glist ); + } +} + +static void playlist_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void playlist_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_playlist *x = (t_playlist *)z; + t_int xold = text_xpix(&x->x_obj, glist); + t_int yold = text_ypix(&x->x_obj, glist); + + // post( "playlist_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) + { + playlist_draw_move(x, glist); + } +} + +static void playlist_motion(t_playlist *x, t_floatarg dx, t_floatarg dy) +{ + t_int i; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_cdy+=dy; + + // check if we need to scroll + if ( ( x->x_lastseen < x->x_nentries ) ) + { + // eventually, move down + if ( x->x_cdy >= x->x_charheight ) + { + x->x_cdy = 0; + if ( x->x_firstseen < x->x_nentries - ( x->x_height/x->x_charheight ) ) + { + if ( x->x_firstseen + 1 < x->x_nentries ) + { + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); + } + x->x_firstseen++; + for ( i=x->x_firstseen; i< x->x_nentries; i++ ) + { + char *wrappedname = (char *) getbytes( x->x_width ); + + if ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) + { + x->x_lastseen = i; + strncpy( wrappedname, x->x_dentries[i], x->x_width/x->x_charwidth ); + wrappedname[ x->x_width/x->x_charwidth ] = '\0'; + SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xENTRY%d\n", + canvas, + text_xpix(&x->x_obj, x->x_glist)+5, + text_ypix(&x->x_obj, x->x_glist)+5+(i-x->x_firstseen)*x->x_charheight, + x->x_fgcolor, + x->x_secolor, + x->x_width, + wrappedname, + x->x_font, + x, i ); + } + else break; + } + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_secolor); + // post( "playlist : moved down first=%d last=%d", x->x_firstseen, x->x_lastseen ); + } + } + } + // eventually, move up + if ( x->x_cdy <= -x->x_charheight ) + { + x->x_cdy = 0; + if ( x->x_lastseen >= ( x->x_height/x->x_charheight ) ) + { + if ( x->x_firstseen - 1 >= 0 ) + { + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); + } + x->x_firstseen--; + for ( i=x->x_firstseen; i< x->x_nentries; i++ ) + { + char *wrappedname = (char *) getbytes( x->x_width ); + + if ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) + { + x->x_lastseen = i; + strncpy( wrappedname, x->x_dentries[i], x->x_width/x->x_charwidth ); + wrappedname[ x->x_width/x->x_charwidth ] = '\0'; + SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" \ + -anchor w -font %s -tags %xENTRY%d\n", + canvas, + text_xpix(&x->x_obj, x->x_glist)+5, + text_ypix(&x->x_obj, x->x_glist)+5+(i-x->x_firstseen)*x->x_charheight, + x->x_fgcolor, + x->x_secolor, + x->x_width, + wrappedname, + x->x_font, + x, i ); + } + else break; + } + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_secolor); + // post( "playlist : moved up first=%d last=%d", x->x_firstseen, x->x_lastseen ); + } + } + } + } // scroll test +} + +static void playlist_scroll(t_playlist *x, t_floatarg fdy) +{ + t_int nbsteps, si; + + nbsteps = (t_int)abs(fdy/x->x_charheight); + // post( "playlist : iterations %d", nbsteps ); + + for (si=0; six_charheight); + } +} + +static void playlist_graphics(t_playlist *x, t_floatarg fgraphics) +{ + if ( ( (t_int)fgraphics == 0 ) || ( (t_int)fgraphics == 1 ) ) + { + playlist_draw_erase(x, x->x_glist); + x->x_graphics = (t_int) fgraphics; + playlist_draw_new(x, x->x_glist); + } +} + +static int playlist_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_playlist* x = (t_playlist *)z; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (doit) + { + // leave a margin for scrolling without selection + if ( (xpix-text_xpix(&x->x_obj, glist)) < 4*x->x_width/5 ) + { + // deselect previously selected item + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_fgcolor); + x->x_itemselected = x->x_firstseen + (ypix-text_ypix(&x->x_obj, glist))/x->x_charheight; + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_secolor); + // post( "playlist : selected item : %d", x->x_itemselected ); + if ( x->x_dentries && ( x->x_itemselected < x->x_nentries ) ) + { + char *tmpstring = (char *) getbytes( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected] ) + 2 ); + sprintf( tmpstring, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); + // post( "playlist : chdir : %s", tmpstring ); + if ( chdir( tmpstring ) < 0 ) + { + playlist_output_current(x); + } + else + { + if ( !strcmp( x->x_dentries[ x->x_itemselected ], ".." ) ) + { + char *iamthelastslash; + + iamthelastslash = strrchr( x->x_curdir, '/' ); + *iamthelastslash = '\0'; + + if ( !strcmp( x->x_curdir, "" ) ) + { + strcpy( x->x_curdir, "/" ); + } + } + else + if ( !strcmp( x->x_dentries[ x->x_itemselected ], "." ) ) + { + // nothing + } + else + { + if ( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected] ) + 2 > MAX_DIR_LENGTH ) + { + post( "playlist : maximum dir length reached : cannot change directory" ); + return -1; + } + if ( strcmp( x->x_curdir, "/" ) ) + { + sprintf( x->x_curdir, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); + } + else + { + sprintf( x->x_curdir, "/%s", x->x_dentries[x->x_itemselected] ); + } + } + + playlist_update_dir( x, glist ); + } + } + } + x->x_glist = glist; + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)playlist_motion, + NULL, xpix, ypix ); + } + return (1); +} + +static void playlist_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_playlist *x=(t_playlist *)z; + + sprintf(buf, "pdtk_playlist_dialog %%s %s %d %d %s %s %s %s %s\n", + x->x_extension, (int)x->x_width, (int)x->x_height, + x->x_font, x->x_bgcolor, x->x_sbcolor, + x->x_fgcolor, x->x_secolor ); + // post("playlist_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void playlist_dialog(t_playlist *x, t_symbol *s, int argc, t_atom *argv) +{ + if ( !x ) { + post( "playlist : error :tried to set properties on an unexisting object" ); + } + if ( argc != 10 ) + { + post( "playlist : error in the number of arguments ( %d instead of 10 )", argc ); + return; + } + if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_SYMBOL || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_SYMBOL || + argv[6].a_type != A_SYMBOL || argv[7].a_type != A_SYMBOL || + argv[8].a_type != A_SYMBOL || argv[9].a_type != A_SYMBOL ) { + post( "playlist : wrong arguments" ); + return; + } + x->x_extension = argv[0].a_w.w_symbol->s_name; + x->x_width = (int)argv[1].a_w.w_float; + x->x_height = (int)argv[2].a_w.w_float; + sprintf( x->x_font, "{%s %d %s}", argv[3].a_w.w_symbol->s_name, + (int)argv[4].a_w.w_float, argv[5].a_w.w_symbol->s_name ); + x->x_charheight = (t_int)argv[4].a_w.w_float; + strcpy( x->x_bgcolor, argv[6].a_w.w_symbol->s_name ); + strcpy( x->x_sbcolor, argv[7].a_w.w_symbol->s_name ); + strcpy( x->x_fgcolor, argv[8].a_w.w_symbol->s_name ); + strcpy( x->x_secolor, argv[9].a_w.w_symbol->s_name ); + + playlist_draw_erase(x, x->x_glist); + playlist_draw_new(x, x->x_glist); +} + + +static t_playlist *playlist_new(t_symbol *s, int argc, t_atom *argv ) +{ + t_int i, argoffset=0; + t_playlist *x; + char *tmpcurdir; + + x = (t_playlist *)pd_new(playlist_class); + + x->x_extension = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_extension, "all" ); + x->x_width = 400; + x->x_height = 300; + x->x_font = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_font, "{Helvetica 10 bold}" ); + x->x_charheight = 10; + x->x_charwidth = (2*10)/3; + x->x_bgcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_bgcolor, "#457782" ); + x->x_sbcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_sbcolor, "yellow" ); + x->x_fgcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_fgcolor, "black" ); + x->x_secolor = ( char * ) getbytes( MAX_DIR_LENGTH ); + sprintf( x->x_secolor, "red" ); + + if ( argc >= 1 ) + { + if ( argv[0].a_type != A_SYMBOL ) + { + error( "playlist : wrong argument (extension : 1)" ); + return NULL; + } + if ( !strcmp( argv[0].a_w.w_symbol->s_name, "" ) ) + { + error( "playlist : no extension specified" ); + error( "playlist : usage : playlist " ); + return NULL; + } + strcpy( x->x_extension, argv[0].a_w.w_symbol->s_name ); + } + if ( argc >= 2 ) + { + if ( argv[1].a_type != A_FLOAT ) + { + error( "playlist : wrong argument (width : 2)" ); + return NULL; + } + if ( (int)argv[1].a_w.w_float <= 0 ) + { + error( "playlist : wrong width (%d)", (t_int)(int)argv[1].a_w.w_float ); + error( "playlist : usage : playlist " ); + return NULL; + } + x->x_width = (int)argv[1].a_w.w_float; + } + if ( argc >= 3 ) + { + if ( argv[2].a_type != A_FLOAT ) + { + error( "playlist : wrong argument (height : 3)" ); + return NULL; + } + if ( (int)argv[2].a_w.w_float <= 0 ) + { + error( "playlist : wrong height (%d)", (t_int)(int)argv[2].a_w.w_float ); + error( "playlist : usage : playlist " ); + return NULL; + } + x->x_height = (int)argv[2].a_w.w_float; + } + if ( argc >= 6 ) + { + if ( argv[3].a_type != A_SYMBOL || + argv[5].a_type != A_SYMBOL ) + { + error( "playlist : wrong arguments (font : 4,6)" ); + error( "argument types : %d %d", argv[3].a_type, argv[5].a_type ); + return NULL; + } + if ( argv[4].a_type != A_SYMBOL && + argv[4].a_type != A_FLOAT ) + { + error( "playlist : wrong arguments (font size : 5)" ); + error( "argument types : %d", argv[4].a_type ); + return NULL; + } + if ( argv[4].a_type == A_SYMBOL ) + { + sprintf( x->x_font, "%s", argv[3].a_w.w_symbol->s_name ); + x->x_charheight = (t_int)atoi( strstr( argv[3].a_w.w_symbol->s_name, " ") ); + argoffset=2; + } + if ( argv[4].a_type == A_FLOAT ) + { + x->x_charheight = (t_int)argv[4].a_w.w_float; + sprintf( x->x_font, "%s %d %s", argv[3].a_w.w_symbol->s_name, + (int)x->x_charheight, argv[5].a_w.w_symbol->s_name ); + argoffset=0; + } + post( "playlist : font : %s, size : %d", x->x_font, x->x_charheight ); + } + if ( argc >= 7-argoffset ) + { + if ( argv[6-argoffset].a_type != A_SYMBOL ) + { + error( "playlist : wrong arguments (background color : %d)", 7-argoffset ); + return NULL; + } + strcpy( x->x_bgcolor, argv[6-argoffset].a_w.w_symbol->s_name ); + } + if ( argc >= 8-argoffset ) + { + if ( argv[7-argoffset].a_type != A_SYMBOL ) + { + error( "playlist : wrong arguments (scrollbar color : %d)", 8-argoffset ); + return NULL; + } + strcpy( x->x_sbcolor, argv[7-argoffset].a_w.w_symbol->s_name ); + } + if ( argc >= 9-argoffset ) + { + if ( argv[8-argoffset].a_type != A_SYMBOL ) + { + error( "playlist : wrong arguments (foreground color : %d)", 9-argoffset ); + return NULL; + } + strcpy( x->x_fgcolor, argv[8-argoffset].a_w.w_symbol->s_name ); + } + if ( argc >= 10-argoffset ) + { + if ( argv[9-argoffset].a_type != A_SYMBOL ) + { + error( "playlist : wrong arguments (selection color : %d)", 10-argoffset ); + return NULL; + } + strcpy( x->x_secolor, argv[9-argoffset].a_w.w_symbol->s_name ); + } + + x->x_fullpath = outlet_new(&x->x_obj, &s_symbol ); + x->x_file = outlet_new(&x->x_obj, &s_symbol ); + x->x_dir = outlet_new(&x->x_obj, &s_symbol ); + + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_nentries = 0; + x->x_pnentries = 0; + x->x_dentries = NULL; + + // get current directory full path + x->x_curdir = ( char * ) getbytes( MAX_DIR_LENGTH ); + +#ifdef _WIN32 + char path[_MAX_DIR]; + + _getcwd (path, _MAX_DIR); + post ("Current directory is: %s", path); + tmpcurdir = path; + +#else + tmpcurdir = getenv( "PWD" ); +#endif + + if ( tmpcurdir == NULL ) + { + post( "playlist : could not get current directory ( where the hell are you ??? )" ); + return NULL; + } + strncpy( x->x_curdir, tmpcurdir, strlen( tmpcurdir ) ); + x->x_curdir[ strlen( tmpcurdir ) ] = '\0'; + + x->x_selected = 0; + x->x_itemselected = -1; + + x->x_sort = 1; + x->x_graphics = 1; + + // post( "playlist : built extension=%s width=%d height=%d", x->x_extension, x->x_width, x->x_height ); + + return (x); +} + +static void playlist_free(t_playlist *x) +{ + // post( "playlist : playlist_free" ); + if ( x->x_extension ) + { + freebytes( x->x_extension, MAX_DIR_LENGTH ); + } + if ( x->x_curdir ) + { + freebytes( x->x_curdir, MAX_DIR_LENGTH ); + } + if ( x->x_font ) + { + freebytes( x->x_font, MAX_DIR_LENGTH ); + } + if ( x->x_bgcolor ) + { + freebytes( x->x_bgcolor, MAX_DIR_LENGTH ); + } + if ( x->x_sbcolor ) + { + freebytes( x->x_sbcolor, MAX_DIR_LENGTH ); + } + if ( x->x_fgcolor ) + { + freebytes( x->x_fgcolor, MAX_DIR_LENGTH ); + } + if ( x->x_secolor ) + { + freebytes( x->x_secolor, MAX_DIR_LENGTH ); + } +} + +static void playlist_seek(t_playlist *x, t_floatarg fseeked) +{ + t_int iout=0; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( fseeked < 0 ) + { + post( "playlist : wrong searched file : %f", fseeked ); + return; + } + + if ( x->x_nentries > 2 ) + { + // do not select . or .. + iout = (int)fseeked % (x->x_nentries-2) + 2; + } + else + { + return; + } + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", canvas, x, x->x_itemselected, x->x_fgcolor); + x->x_itemselected = iout; + SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", canvas, x, x->x_itemselected, x->x_secolor); + playlist_output_current(x); +} + +static void playlist_location(t_playlist *x, t_symbol *flocation) +{ + int iout=0; + char olddir[ MAX_DIR_LENGTH ]; /* remember old location */ + + strcpy( olddir, x->x_curdir ); + + if ( !strcmp( flocation->s_name, ".." ) ) + { + char *iamthelastslash; + + iamthelastslash = strrchr( x->x_curdir, '/' ); + *iamthelastslash = '\0'; + + if ( !strcmp( x->x_curdir, "" ) ) + { + strcpy( x->x_curdir, "/" ); + } + } + else + if ( !strncmp( flocation->s_name, "/", 1 ) ) + { + // absolute path required + if ( strlen( flocation->s_name ) >= MAX_DIR_LENGTH ) + { + error( "playlist : maximum dir length reached : cannot change directory" ); + return; + } + strncpy( x->x_curdir, flocation->s_name, MAX_DIR_LENGTH ); + } + else + { + // relative path + if ( strlen( x->x_curdir ) + strlen( flocation->s_name ) + 2 > MAX_DIR_LENGTH ) + { + post( "playlist : maximum dir length reached : cannot change directory" ); + return; + } + if ( strcmp( x->x_curdir, "/" ) ) + { + sprintf( x->x_curdir, "%s/%s", x->x_curdir, flocation->s_name ); + } + else + { + sprintf( x->x_curdir, "/%s", flocation->s_name ); + } + } + + if ( chdir( x->x_curdir ) < 0 ) + { + error( "playlist : requested location >%s< is not a directory", x->x_curdir ); + strcpy( x->x_curdir, olddir ); + return; + } + + playlist_update_dir( x, x->x_glist ); +} + +void playlist_setup(void) +{ + post( playlist_version ); + playlist_class = class_new(gensym("playlist"), (t_newmethod)playlist_new, + (t_method)playlist_free, sizeof(t_playlist), + CLASS_DEFAULT, A_GIMME, 0); + class_addmethod(playlist_class, (t_method)playlist_seek, gensym("seek"), A_DEFFLOAT, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_location, gensym("location"), A_SYMBOL, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_dialog, gensym("dialog"), A_GIMME, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_sort, gensym("sort"), A_DEFFLOAT, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_graphics, gensym("graphics"), A_DEFFLOAT, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_scroll, gensym("scroll"), A_DEFFLOAT, A_NULL ); + class_addmethod(playlist_class, (t_method)playlist_font, gensym("font"), A_SYMBOL, + A_SYMBOL, A_DEFFLOAT, A_NULL ); + + playlist_widgetbehavior.w_getrectfn = playlist_getrect; + playlist_widgetbehavior.w_displacefn = playlist_displace; + playlist_widgetbehavior.w_selectfn = playlist_select; + playlist_widgetbehavior.w_activatefn = NULL; + playlist_widgetbehavior.w_deletefn = playlist_delete; + playlist_widgetbehavior.w_visfn = playlist_vis; + playlist_widgetbehavior.w_clickfn = playlist_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(playlist_class, playlist_properties); + class_setsavefn(playlist_class, playlist_save); +#else + playlist_widgetbehavior.w_propertiesfn = playlist_properties; + playlist_widgetbehavior.w_savefn = playlist_save; +#endif + + class_setwidget(playlist_class, &playlist_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + playlist_class->c_externdir->s_name, + playlist_class->c_name->s_name); +} diff --git a/playlist.tcl b/playlist.tcl new file mode 100644 index 0000000..5a22a05 --- /dev/null +++ b/playlist.tcl @@ -0,0 +1,154 @@ +############ playlist procedures -- ydegoyon@free.fr ######### + +proc playlist_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_extension [concat graph_extension_$vid] + global $var_graph_extension + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height$vid] + global $var_graph_height + set var_graph_font [concat graph_font$vid] + global $var_graph_font + set var_graph_bgcolor [concat graph_bgcolor$vid] + global $var_graph_bgcolor + set var_graph_sbcolor [concat graph_sbcolor$vid] + global $var_graph_sbcolor + set var_graph_fgcolor [concat graph_fgcolor$vid] + global $var_graph_fgcolor + set var_graph_secolor [concat graph_secolor$vid] + global $var_graph_secolor + + set cmd [concat $id dialog \ + [eval concat $$var_graph_extension] \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_font] \ + [eval concat $$var_graph_bgcolor] \ + [eval concat $$var_graph_sbcolor] \ + [eval concat $$var_graph_fgcolor] \ + [eval concat $$var_graph_secolor] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc playlist_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc playlist_ok {id} { + playlist_apply $id + playlist_cancel $id +} + +proc pdtk_playlist_dialog {id extension width height font bgcolor sbcolor fgcolor secolor} { + set vid [string trimleft $id .] + set var_graph_extension [concat graph_extension_$vid] + global $var_graph_extension + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height$vid] + global $var_graph_height + set var_graph_font [concat graph_font$vid] + global $var_graph_font + set var_graph_bgcolor [concat graph_bgcolor$vid] + global $var_graph_bgcolor + set var_graph_sbcolor [concat graph_sbcolor$vid] + global $var_graph_sbcolor + set var_graph_fgcolor [concat graph_fgcolor$vid] + global $var_graph_fgcolor + set var_graph_secolor [concat graph_secolor$vid] + global $var_graph_secolor + + set $var_graph_extension $extension + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_font $font + set $var_graph_bgcolor $bgcolor + set $var_graph_sbcolor $sbcolor + set $var_graph_fgcolor $fgcolor + set $var_graph_secolor $secolor + + toplevel $id + wm title $id {playlist} + wm protocol $id WM_DELETE_WINDOW [concat playlist_cancel $id] + + label $id.label -text {PLAYLIST PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "playlist_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "playlist_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "playlist_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lextension -text "Files Extension :" + entry $id.1rangef.extension -textvariable $var_graph_extension -width 7 + pack $id.1rangef.lextension $id.1rangef.extension -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lwidth -text "Width :" + entry $id.2rangef.width -textvariable $var_graph_width -width 7 + pack $id.2rangef.lwidth $id.2rangef.width -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lheight -text "Height :" + entry $id.3rangef.height -textvariable $var_graph_height -width 7 + pack $id.3rangef.lheight $id.3rangef.height -side left + + frame $id.3_5rangef + pack $id.3_5rangef -side top + label $id.3_5rangef.lfont -text "Font :" + entry $id.3_5rangef.font -textvariable $var_graph_font -width 30 + pack $id.3_5rangef.lfont $id.3_5rangef.font -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.lbgcolor -text "Background Color :" + entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7 + pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left + + frame $id.5rangef + pack $id.5rangef -side top + label $id.5rangef.lsbcolor -text "Scroll Bar Color :" + entry $id.5rangef.sbcolor -textvariable $var_graph_sbcolor -width 7 + pack $id.5rangef.lsbcolor $id.5rangef.sbcolor -side left + + frame $id.6rangef + pack $id.6rangef -side top + label $id.6rangef.lfgcolor -text "Foreground Color :" + entry $id.6rangef.fgcolor -textvariable $var_graph_fgcolor -width 7 + pack $id.6rangef.lfgcolor $id.6rangef.fgcolor -side left + + frame $id.7rangef + pack $id.7rangef -side top + label $id.7rangef.lsecolor -text "Selection Color :" + entry $id.7rangef.secolor -textvariable $var_graph_secolor -width 7 + pack $id.7rangef.lsecolor $id.7rangef.secolor -side left + + bind $id.1rangef.extension [concat playlist_ok $id] + bind $id.2rangef.width [concat playlist_ok $id] + bind $id.3rangef.height [concat playlist_ok $id] + bind $id.3_5rangef.font [concat playlist_ok $id] + bind $id.4rangef.bgcolor [concat playlist_ok $id] + bind $id.5rangef.sbcolor [concat playlist_ok $id] + bind $id.6rangef.fgcolor [concat playlist_ok $id] + bind $id.7rangef.secolor [concat playlist_ok $id] +} + +############ playlist procedures END -- ydegoyon@free.fr ######### diff --git a/playlist/INSTALL b/playlist/INSTALL deleted file mode 100644 index 972bba0..0000000 --- a/playlist/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/playlist - -make clean - -make - -make install - -open help-playlist.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/playlist/playlist-help.pd b/playlist/playlist-help.pd deleted file mode 100644 index b035bc3..0000000 --- a/playlist/playlist-help.pd +++ /dev/null @@ -1,64 +0,0 @@ -#N canvas 96 132 817 563 10; -#X text 28 57 Constructor : playlist ; -#X text 88 95 playlist all 200 200; -#X text 88 107 playlist mp3 200 200; -#X text 30 78 Examples :; -#X text 72 507 Comments and bugs @ ydegoyon@free.fr; -#X symbolatom 363 437 50 0 0 0 - - -; -#X text 17 444 Note : you can scroll the list by dragging; -#X text 15 455 the mouse in the yellow area; -#X text 17 466 You can select and scroll in the blue area; -#X obj 360 221 playlist all 400 200 {Courier 12 bold} grey yellow black -red; -#X msg 373 77 seek \$1; -#X text 485 63 You can seek a file in the list; -#X text 485 74 It will skip the first two items ( '.' and '..'); -#X text 484 86 and behave like a round list; -#X text 28 14 Playlist lets you switch files in one click; -#X text 27 25 It's handling most non-alpha characters gracefully; -#X floatatom 435 79 5 0 0 0 - - -; -#X symbolatom 404 464 50 0 0 0 - - -; -#X symbolatom 450 491 50 0 0 0 - - -; -#X msg 151 163 location ..; -#X msg 150 140 location /tmp; -#X text 33 212 You can change change location; -#X text 33 222 with a message.; -#X text 33 234 Thus \, you can initialize the object; -#X text 32 243 in a particular folder.; -#X msg 151 185 location patches; -#X msg 334 106 sort \$1; -#X obj 395 107 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X text 499 110 Use alphabetical or creation time order; -#X obj 87 140 loadbang; -#X text 628 136 Change the font; -#X msg 300 136 font Helvetica normal 14; -#X msg 478 136 font Courier bold 24; -#X msg 379 163 scroll 200; -#X msg 460 163 scroll -200; -#X text 551 162 Scrolling by numbers for the laziest; -#X obj 526 191 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 -1; -#X msg 436 191 graphics \$1; -#X text 655 191 Show or hide graphics; -#X msg 549 190 1; -#X obj 582 191 loadbang; -#X connect 9 0 5 0; -#X connect 9 1 17 0; -#X connect 9 2 18 0; -#X connect 10 0 9 0; -#X connect 16 0 10 0; -#X connect 19 0 9 0; -#X connect 20 0 9 0; -#X connect 25 0 9 0; -#X connect 26 0 9 0; -#X connect 27 0 26 0; -#X connect 29 0 20 0; -#X connect 31 0 9 0; -#X connect 32 0 9 0; -#X connect 33 0 9 0; -#X connect 34 0 9 0; -#X connect 36 0 37 0; -#X connect 37 0 9 0; -#X connect 39 0 36 0; -#X connect 40 0 39 0; diff --git a/playlist/playlist.c b/playlist/playlist.c deleted file mode 100644 index 4576267..0000000 --- a/playlist/playlist.c +++ /dev/null @@ -1,1072 +0,0 @@ -/*------------------------ playlist~ ------------------------------------------ */ -/* */ -/* playlist~ : lets you choose a file with 1 click */ -/* or by sending a 'seek #' message */ -/* constructor : playlist */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "If a man's made of blood and iron" */ -/* "Doctor, doctor, what's in my chest ????" */ -/* Gang Of Four -- Guns Before Butter */ -/* ---------------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" -#include - -#ifdef _WIN32 -#include -#include -#include - -int scandir(const char *dir, struct dirent ***namelist, - int (*select)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)) { - DIR *d; - struct dirent *entry; - register int i=0; - size_t entrysize; - - if ((d=opendir(dir)) == NULL) - return(-1); - - *namelist=NULL; - while ((entry=readdir(d)) != NULL) - { - if (select == NULL || (select != NULL && (*select)(entry))) - { - *namelist=(struct dirent **)realloc((void *)(*namelist), - (size_t)((i+1)*sizeof(struct dirent *))); - if (*namelist == NULL) return(-1); - entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1; - (*namelist)[i]=(struct dirent *)malloc(entrysize); - if ((*namelist)[i] == NULL) return(-1); - memcpy((*namelist)[i], entry, entrysize); - i++; - } - } - if (closedir(d)) return(-1); - if (i == 0) return(-1); - if (compar != NULL) - qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar); - - return(i); -} - -int alphasort(const struct dirent **a, const struct dirent **b) { - return(strcmp((*a)->d_name, (*b)->d_name)); - } - -int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); -int alphasort(const struct dirent **, const struct dirent **); - -#else -#include -#endif - -t_widgetbehavior playlist_widgetbehavior; -static t_class *playlist_class; - -static int guidebug=0; - -static char *playlist_version = "playlist: 1 click file chooser : version 0.12, written by Yves Degoyon (ydegoyon@free.fr)"; - -#define MAX_DIR_LENGTH 2048 // maximum length for a directory name - -#define MIN(a,b) (a>b?b:a) - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - - -typedef struct _playlist -{ - t_object x_obj; - t_glist *x_glist; - t_outlet *x_fullpath; - t_outlet *x_file; - t_outlet *x_dir; - char *x_extension; /* extension to selected files */ - t_int x_height; /* height of the playlist */ - t_int x_width; /* width of the playlist */ - t_int x_itemselected; /* index of the selected item */ - t_int x_selected; /* stores selected state */ - t_int x_graphics; /* flag to draw graphics or not */ - char **x_dentries; /* directory entries */ - t_int x_nentries; /* number of entries in the current dir */ - t_int x_pnentries; /* previous size of entries list */ - t_int x_firstseen; /* first displayed entry */ - t_int x_lastseen; /* last displayed entry */ - t_int x_cdy; /* cumulated y drag */ - t_int x_sort; /* sorting option flag */ - char *x_curdir; /* current directory informations */ - char *x_font; /* font used for entries */ - t_int x_charheight; /* height of characters */ - t_int x_charwidth; /* width of characters */ - char *x_bgcolor; /* background color */ - char *x_sbcolor; /* scrollbar color */ - char *x_fgcolor; /* foreground color */ - char *x_secolor; /* selection color */ -} t_playlist; - - -static void playlist_update_dir(t_playlist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - char wrappedname[ MAX_DIR_LENGTH ]; - struct timespec tv; - - tv.tv_sec = 0; - tv.tv_nsec = 10000000; - - // set title - SYS_VGUI3(".x%x.c delete %xTITLE\n", canvas, x); - if ( x->x_graphics ) - { - SYS_VGUI8(".x%x.c create text %d %d -width %d -text \"%s\" -anchor w -font %s -tags %xTITLE\n", - canvas, - text_xpix(&x->x_obj, glist)+5, - text_ypix(&x->x_obj, glist)-10, - x->x_width, - x->x_curdir, - x->x_font, - x ); - } - - // delete previous entries - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); - } - - // display the content of current directory - { - t_int nentries, i; - struct dirent** dentries; /* all directory entries */ - - // post( "playlist : scandir : %s", x->x_curdir ); - if ( ( nentries = scandir(x->x_curdir, &dentries, NULL, (x->x_sort==1)?alphasort:NULL ) ) == -1 ) - { - post( "playlist : could not scan current directory ( where the hell are you ??? )" ); - perror( "scandir" ); - return; - } - - x->x_firstseen = 0; - if ( x->x_dentries ) - { - for ( i=0; ix_nentries; i++ ) - { - // post( "playlist : freeing entry %d size=%d : %s", i, strlen( x->x_dentries[i] ) + 1, x->x_dentries[i] ); - freebytes( x->x_dentries[i], strlen( x->x_dentries[i] ) + 1 ); - } - } - if ( x->x_pnentries != -1 ) - { - freebytes( x->x_dentries, x->x_pnentries*sizeof(char**) ); - } - - x->x_nentries = 0; - // post( "playlist : allocating dentries %d", nentries ); - x->x_dentries = (char **) getbytes( nentries*sizeof(char**) ) ; - x->x_pnentries = nentries; - for ( i=0; id_name ) ) != NULL ) ) || - ( strstr( dentries[i]->d_name, x->x_extension ) ) || - ( !strcmp( x->x_extension, "all" ) ) - ) - { - // close temporarily opened dir - if ( tmpdir ) - { - if ( closedir( tmpdir ) < 0 ) - { - post( "playlist : could not close directory %s", dentries[i]->d_name ); - } - } - - // post( "playlist : allocating entry %d %d : %s", x->x_nentries, strlen( dentries[i]->d_name ) + 1, dentries[i]->d_name ); - x->x_dentries[x->x_nentries] = ( char * ) getbytes( strlen( dentries[i]->d_name ) + 1 ); - strcpy( x->x_dentries[x->x_nentries], dentries[i]->d_name ); - - // display the entry if displayable - if ( x->x_nentries*x->x_charheight+5 < x->x_height ) - { - // nanosleep( &tv, NULL ); - x->x_lastseen = x->x_nentries; - strncpy( wrappedname, x->x_dentries[x->x_nentries], MIN(x->x_width/x->x_charwidth, MAX_DIR_LENGTH) ); - wrappedname[ x->x_width/x->x_charwidth ] = '\0'; - SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xENTRY%d\n", - canvas, - text_xpix(&x->x_obj, glist)+5, - text_ypix(&x->x_obj, glist)+5+(x->x_nentries-x->x_firstseen)*x->x_charheight, - x->x_fgcolor, - x->x_secolor, - x->x_width, - wrappedname, - x->x_font, - x, x->x_nentries ); - } - x->x_nentries++; - } - - } - - } -} - -static void playlist_output_current(t_playlist* x) -{ - // output the selected dir+file - // check that it's not a directory - if ( chdir( x->x_dentries[x->x_itemselected] ) == 0 ) - { - chdir( x->x_curdir ); - return; - } - - if ( x->x_dentries && x->x_itemselected < x->x_nentries && x->x_itemselected >= 0 ) - { - char* tmpstring = (char*) getbytes( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected]) + 2 ); - - sprintf( tmpstring, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); - outlet_symbol( x->x_dir, gensym( x->x_curdir ) ); - outlet_symbol( x->x_file, gensym( x->x_dentries[x->x_itemselected] ) ); - outlet_symbol( x->x_fullpath, gensym( tmpstring ) ); - freebytes( tmpstring, strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected]) + 2 ); - } -} - -static void playlist_sort(t_playlist* x, t_floatarg fsort) -{ - if ( ( (t_int)fsort != 0 ) && ( (t_int)fsort != 1 ) ) - { - post( "playlist : wrong argument to playlist message : %d", (t_int)fsort ); - return; - } - - x->x_sort = (t_int) fsort; - playlist_update_dir( x, x->x_glist ); -} - -static void playlist_font(t_playlist* x, t_symbol *fname, t_symbol *fcase, t_floatarg fsize) -{ - if ( (t_int)fsize <= 4 ) - { - post( "playlist : wrong font size in font message : %d", (t_int)fsize ); - return; - } - sprintf( x->x_font, "{%s %d %s}", fname->s_name, (int)fsize, fcase->s_name ); - x->x_charheight = (t_int)fsize; - x->x_charwidth = (2*x->x_charheight)/3; - post( "playlist : setting font to : %s", x->x_font ); - playlist_update_dir( x, x->x_glist ); -} - -static void playlist_draw_new(t_playlist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - x->x_glist = glist; - if ( x->x_graphics ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xPLAYLIST\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, - x->x_bgcolor, x); - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSCROLLLIST\n", - canvas, text_xpix(&x->x_obj, glist)+4*x->x_width/5, text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, - x->x_sbcolor, x); - } - playlist_update_dir( x, glist ); - -} - -static void playlist_draw_move(t_playlist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - struct timespec tv; - - tv.tv_sec = 0; - tv.tv_nsec = 10000000; - - if ( x->x_graphics ) - { - SYS_VGUI7(".x%x.c coords %xPLAYLIST %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, - text_ypix(&x->x_obj, glist)+x->x_height); - SYS_VGUI7(".x%x.c coords %xSCROLLLIST %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)+4*x->x_width/5, text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, - text_ypix(&x->x_obj, glist)+x->x_height); - SYS_VGUI5(".x%x.c coords %xTITLE %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)+5, text_ypix(&x->x_obj, glist)-10 ); - } - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - // nanosleep( &tv, NULL ); - SYS_VGUI6(".x%x.c coords %xENTRY%d %d %d\n", - canvas, x, i, - text_xpix(&x->x_obj, glist)+5, - text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight); - } - - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void playlist_draw_erase(t_playlist* x, t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - - if ( x->x_graphics ) - { - SYS_VGUI3(".x%x.c delete %xPLAYLIST\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xSCROLLLIST\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xTITLE\n", canvas, x); - } - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); - } -} - -static void playlist_draw_select(t_playlist* x, t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - // post( "playlist : select" ); - if(x->x_selected) - { - /* sets the item in blue */ - if (x->x_graphics) SYS_VGUI3(".x%x.c itemconfigure %xPLAYLIST -outline #0000FF\n", canvas, x); - } - else - { - if (x->x_graphics) SYS_VGUI3(".x%x.c itemconfigure %xPLAYLIST -outline #000000\n", canvas, x); - } -} - -/* ------------------------ playlist widgetbehaviour----------------------------- */ - - -static void playlist_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_playlist* x = (t_playlist*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void playlist_save(t_gobj *z, t_binbuf *b) -{ - t_playlist *x = (t_playlist *)z; - - // post( "saving playlist : %s", x->x_extension ); - binbuf_addv(b, "ssiissiisssss", gensym("#X"), gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - gensym("playlist"), gensym(x->x_extension), x->x_width, x->x_height, - gensym(x->x_font), gensym(x->x_bgcolor), gensym(x->x_sbcolor), - gensym(x->x_fgcolor), gensym(x->x_secolor) ); - binbuf_addv(b, ";"); -} - -static void playlist_select(t_gobj *z, t_glist *glist, int selected) -{ - t_playlist *x = (t_playlist *)z; - - x->x_selected = selected; - - playlist_draw_select( x, glist ); -} - -static void playlist_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_playlist *x = (t_playlist *)z; - - x->x_glist = glist; - if (vis) - { - playlist_draw_new( x, glist ); - } - else - { - playlist_draw_erase( x, glist ); - } -} - -static void playlist_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void playlist_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_playlist *x = (t_playlist *)z; - t_int xold = text_xpix(&x->x_obj, glist); - t_int yold = text_ypix(&x->x_obj, glist); - - // post( "playlist_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) - { - playlist_draw_move(x, glist); - } -} - -static void playlist_motion(t_playlist *x, t_floatarg dx, t_floatarg dy) -{ - t_int i; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_cdy+=dy; - - // check if we need to scroll - if ( ( x->x_lastseen < x->x_nentries ) ) - { - // eventually, move down - if ( x->x_cdy >= x->x_charheight ) - { - x->x_cdy = 0; - if ( x->x_firstseen < x->x_nentries - ( x->x_height/x->x_charheight ) ) - { - if ( x->x_firstseen + 1 < x->x_nentries ) - { - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); - } - x->x_firstseen++; - for ( i=x->x_firstseen; i< x->x_nentries; i++ ) - { - char *wrappedname = (char *) getbytes( x->x_width ); - - if ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) - { - x->x_lastseen = i; - strncpy( wrappedname, x->x_dentries[i], x->x_width/x->x_charwidth ); - wrappedname[ x->x_width/x->x_charwidth ] = '\0'; - SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xENTRY%d\n", - canvas, - text_xpix(&x->x_obj, x->x_glist)+5, - text_ypix(&x->x_obj, x->x_glist)+5+(i-x->x_firstseen)*x->x_charheight, - x->x_fgcolor, - x->x_secolor, - x->x_width, - wrappedname, - x->x_font, - x, i ); - } - else break; - } - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_secolor); - // post( "playlist : moved down first=%d last=%d", x->x_firstseen, x->x_lastseen ); - } - } - } - // eventually, move up - if ( x->x_cdy <= -x->x_charheight ) - { - x->x_cdy = 0; - if ( x->x_lastseen >= ( x->x_height/x->x_charheight ) ) - { - if ( x->x_firstseen - 1 >= 0 ) - { - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xENTRY%d\n", canvas, x, i); - } - x->x_firstseen--; - for ( i=x->x_firstseen; i< x->x_nentries; i++ ) - { - char *wrappedname = (char *) getbytes( x->x_width ); - - if ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) - { - x->x_lastseen = i; - strncpy( wrappedname, x->x_dentries[i], x->x_width/x->x_charwidth ); - wrappedname[ x->x_width/x->x_charwidth ] = '\0'; - SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" \ - -anchor w -font %s -tags %xENTRY%d\n", - canvas, - text_xpix(&x->x_obj, x->x_glist)+5, - text_ypix(&x->x_obj, x->x_glist)+5+(i-x->x_firstseen)*x->x_charheight, - x->x_fgcolor, - x->x_secolor, - x->x_width, - wrappedname, - x->x_font, - x, i ); - } - else break; - } - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_secolor); - // post( "playlist : moved up first=%d last=%d", x->x_firstseen, x->x_lastseen ); - } - } - } - } // scroll test -} - -static void playlist_scroll(t_playlist *x, t_floatarg fdy) -{ - t_int nbsteps, si; - - nbsteps = (t_int)abs(fdy/x->x_charheight); - // post( "playlist : iterations %d", nbsteps ); - - for (si=0; six_charheight); - } -} - -static void playlist_graphics(t_playlist *x, t_floatarg fgraphics) -{ - if ( ( (t_int)fgraphics == 0 ) || ( (t_int)fgraphics == 1 ) ) - { - playlist_draw_erase(x, x->x_glist); - x->x_graphics = (t_int) fgraphics; - playlist_draw_new(x, x->x_glist); - } -} - -static int playlist_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_playlist* x = (t_playlist *)z; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (doit) - { - // leave a margin for scrolling without selection - if ( (xpix-text_xpix(&x->x_obj, glist)) < 4*x->x_width/5 ) - { - // deselect previously selected item - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_fgcolor); - x->x_itemselected = x->x_firstseen + (ypix-text_ypix(&x->x_obj, glist))/x->x_charheight; - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_secolor); - // post( "playlist : selected item : %d", x->x_itemselected ); - if ( x->x_dentries && ( x->x_itemselected < x->x_nentries ) ) - { - char *tmpstring = (char *) getbytes( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected] ) + 2 ); - sprintf( tmpstring, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); - // post( "playlist : chdir : %s", tmpstring ); - if ( chdir( tmpstring ) < 0 ) - { - playlist_output_current(x); - } - else - { - if ( !strcmp( x->x_dentries[ x->x_itemselected ], ".." ) ) - { - char *iamthelastslash; - - iamthelastslash = strrchr( x->x_curdir, '/' ); - *iamthelastslash = '\0'; - - if ( !strcmp( x->x_curdir, "" ) ) - { - strcpy( x->x_curdir, "/" ); - } - } - else - if ( !strcmp( x->x_dentries[ x->x_itemselected ], "." ) ) - { - // nothing - } - else - { - if ( strlen( x->x_curdir ) + strlen( x->x_dentries[x->x_itemselected] ) + 2 > MAX_DIR_LENGTH ) - { - post( "playlist : maximum dir length reached : cannot change directory" ); - return -1; - } - if ( strcmp( x->x_curdir, "/" ) ) - { - sprintf( x->x_curdir, "%s/%s", x->x_curdir, x->x_dentries[x->x_itemselected] ); - } - else - { - sprintf( x->x_curdir, "/%s", x->x_dentries[x->x_itemselected] ); - } - } - - playlist_update_dir( x, glist ); - } - } - } - x->x_glist = glist; - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)playlist_motion, - NULL, xpix, ypix ); - } - return (1); -} - -static void playlist_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_playlist *x=(t_playlist *)z; - - sprintf(buf, "pdtk_playlist_dialog %%s %s %d %d %s %s %s %s %s\n", - x->x_extension, (int)x->x_width, (int)x->x_height, - x->x_font, x->x_bgcolor, x->x_sbcolor, - x->x_fgcolor, x->x_secolor ); - // post("playlist_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void playlist_dialog(t_playlist *x, t_symbol *s, int argc, t_atom *argv) -{ - if ( !x ) { - post( "playlist : error :tried to set properties on an unexisting object" ); - } - if ( argc != 10 ) - { - post( "playlist : error in the number of arguments ( %d instead of 10 )", argc ); - return; - } - if ( argv[0].a_type != A_SYMBOL || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_SYMBOL || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_SYMBOL || - argv[6].a_type != A_SYMBOL || argv[7].a_type != A_SYMBOL || - argv[8].a_type != A_SYMBOL || argv[9].a_type != A_SYMBOL ) { - post( "playlist : wrong arguments" ); - return; - } - x->x_extension = argv[0].a_w.w_symbol->s_name; - x->x_width = (int)argv[1].a_w.w_float; - x->x_height = (int)argv[2].a_w.w_float; - sprintf( x->x_font, "{%s %d %s}", argv[3].a_w.w_symbol->s_name, - (int)argv[4].a_w.w_float, argv[5].a_w.w_symbol->s_name ); - x->x_charheight = (t_int)argv[4].a_w.w_float; - strcpy( x->x_bgcolor, argv[6].a_w.w_symbol->s_name ); - strcpy( x->x_sbcolor, argv[7].a_w.w_symbol->s_name ); - strcpy( x->x_fgcolor, argv[8].a_w.w_symbol->s_name ); - strcpy( x->x_secolor, argv[9].a_w.w_symbol->s_name ); - - playlist_draw_erase(x, x->x_glist); - playlist_draw_new(x, x->x_glist); -} - - -static t_playlist *playlist_new(t_symbol *s, int argc, t_atom *argv ) -{ - t_int i, argoffset=0; - t_playlist *x; - char *tmpcurdir; - - x = (t_playlist *)pd_new(playlist_class); - - x->x_extension = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_extension, "all" ); - x->x_width = 400; - x->x_height = 300; - x->x_font = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_font, "{Helvetica 10 bold}" ); - x->x_charheight = 10; - x->x_charwidth = (2*10)/3; - x->x_bgcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_bgcolor, "#457782" ); - x->x_sbcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_sbcolor, "yellow" ); - x->x_fgcolor = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_fgcolor, "black" ); - x->x_secolor = ( char * ) getbytes( MAX_DIR_LENGTH ); - sprintf( x->x_secolor, "red" ); - - if ( argc >= 1 ) - { - if ( argv[0].a_type != A_SYMBOL ) - { - error( "playlist : wrong argument (extension : 1)" ); - return NULL; - } - if ( !strcmp( argv[0].a_w.w_symbol->s_name, "" ) ) - { - error( "playlist : no extension specified" ); - error( "playlist : usage : playlist " ); - return NULL; - } - strcpy( x->x_extension, argv[0].a_w.w_symbol->s_name ); - } - if ( argc >= 2 ) - { - if ( argv[1].a_type != A_FLOAT ) - { - error( "playlist : wrong argument (width : 2)" ); - return NULL; - } - if ( (int)argv[1].a_w.w_float <= 0 ) - { - error( "playlist : wrong width (%d)", (t_int)(int)argv[1].a_w.w_float ); - error( "playlist : usage : playlist " ); - return NULL; - } - x->x_width = (int)argv[1].a_w.w_float; - } - if ( argc >= 3 ) - { - if ( argv[2].a_type != A_FLOAT ) - { - error( "playlist : wrong argument (height : 3)" ); - return NULL; - } - if ( (int)argv[2].a_w.w_float <= 0 ) - { - error( "playlist : wrong height (%d)", (t_int)(int)argv[2].a_w.w_float ); - error( "playlist : usage : playlist " ); - return NULL; - } - x->x_height = (int)argv[2].a_w.w_float; - } - if ( argc >= 6 ) - { - if ( argv[3].a_type != A_SYMBOL || - argv[5].a_type != A_SYMBOL ) - { - error( "playlist : wrong arguments (font : 4,6)" ); - error( "argument types : %d %d", argv[3].a_type, argv[5].a_type ); - return NULL; - } - if ( argv[4].a_type != A_SYMBOL && - argv[4].a_type != A_FLOAT ) - { - error( "playlist : wrong arguments (font size : 5)" ); - error( "argument types : %d", argv[4].a_type ); - return NULL; - } - if ( argv[4].a_type == A_SYMBOL ) - { - sprintf( x->x_font, "%s", argv[3].a_w.w_symbol->s_name ); - x->x_charheight = (t_int)atoi( strstr( argv[3].a_w.w_symbol->s_name, " ") ); - argoffset=2; - } - if ( argv[4].a_type == A_FLOAT ) - { - x->x_charheight = (t_int)argv[4].a_w.w_float; - sprintf( x->x_font, "%s %d %s", argv[3].a_w.w_symbol->s_name, - (int)x->x_charheight, argv[5].a_w.w_symbol->s_name ); - argoffset=0; - } - post( "playlist : font : %s, size : %d", x->x_font, x->x_charheight ); - } - if ( argc >= 7-argoffset ) - { - if ( argv[6-argoffset].a_type != A_SYMBOL ) - { - error( "playlist : wrong arguments (background color : %d)", 7-argoffset ); - return NULL; - } - strcpy( x->x_bgcolor, argv[6-argoffset].a_w.w_symbol->s_name ); - } - if ( argc >= 8-argoffset ) - { - if ( argv[7-argoffset].a_type != A_SYMBOL ) - { - error( "playlist : wrong arguments (scrollbar color : %d)", 8-argoffset ); - return NULL; - } - strcpy( x->x_sbcolor, argv[7-argoffset].a_w.w_symbol->s_name ); - } - if ( argc >= 9-argoffset ) - { - if ( argv[8-argoffset].a_type != A_SYMBOL ) - { - error( "playlist : wrong arguments (foreground color : %d)", 9-argoffset ); - return NULL; - } - strcpy( x->x_fgcolor, argv[8-argoffset].a_w.w_symbol->s_name ); - } - if ( argc >= 10-argoffset ) - { - if ( argv[9-argoffset].a_type != A_SYMBOL ) - { - error( "playlist : wrong arguments (selection color : %d)", 10-argoffset ); - return NULL; - } - strcpy( x->x_secolor, argv[9-argoffset].a_w.w_symbol->s_name ); - } - - x->x_fullpath = outlet_new(&x->x_obj, &s_symbol ); - x->x_file = outlet_new(&x->x_obj, &s_symbol ); - x->x_dir = outlet_new(&x->x_obj, &s_symbol ); - - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_nentries = 0; - x->x_pnentries = 0; - x->x_dentries = NULL; - - // get current directory full path - x->x_curdir = ( char * ) getbytes( MAX_DIR_LENGTH ); - -#ifdef _WIN32 - char path[_MAX_DIR]; - - _getcwd (path, _MAX_DIR); - post ("Current directory is: %s", path); - tmpcurdir = path; - -#else - tmpcurdir = getenv( "PWD" ); -#endif - - if ( tmpcurdir == NULL ) - { - post( "playlist : could not get current directory ( where the hell are you ??? )" ); - return NULL; - } - strncpy( x->x_curdir, tmpcurdir, strlen( tmpcurdir ) ); - x->x_curdir[ strlen( tmpcurdir ) ] = '\0'; - - x->x_selected = 0; - x->x_itemselected = -1; - - x->x_sort = 1; - x->x_graphics = 1; - - // post( "playlist : built extension=%s width=%d height=%d", x->x_extension, x->x_width, x->x_height ); - - return (x); -} - -static void playlist_free(t_playlist *x) -{ - // post( "playlist : playlist_free" ); - if ( x->x_extension ) - { - freebytes( x->x_extension, MAX_DIR_LENGTH ); - } - if ( x->x_curdir ) - { - freebytes( x->x_curdir, MAX_DIR_LENGTH ); - } - if ( x->x_font ) - { - freebytes( x->x_font, MAX_DIR_LENGTH ); - } - if ( x->x_bgcolor ) - { - freebytes( x->x_bgcolor, MAX_DIR_LENGTH ); - } - if ( x->x_sbcolor ) - { - freebytes( x->x_sbcolor, MAX_DIR_LENGTH ); - } - if ( x->x_fgcolor ) - { - freebytes( x->x_fgcolor, MAX_DIR_LENGTH ); - } - if ( x->x_secolor ) - { - freebytes( x->x_secolor, MAX_DIR_LENGTH ); - } -} - -static void playlist_seek(t_playlist *x, t_floatarg fseeked) -{ - t_int iout=0; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( fseeked < 0 ) - { - post( "playlist : wrong searched file : %f", fseeked ); - return; - } - - if ( x->x_nentries > 2 ) - { - // do not select . or .. - iout = (int)fseeked % (x->x_nentries-2) + 2; - } - else - { - return; - } - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", canvas, x, x->x_itemselected, x->x_fgcolor); - x->x_itemselected = iout; - SYS_VGUI5(".x%x.c itemconfigure %xENTRY%d -fill %s\n", canvas, x, x->x_itemselected, x->x_secolor); - playlist_output_current(x); -} - -static void playlist_location(t_playlist *x, t_symbol *flocation) -{ - int iout=0; - char olddir[ MAX_DIR_LENGTH ]; /* remember old location */ - - strcpy( olddir, x->x_curdir ); - - if ( !strcmp( flocation->s_name, ".." ) ) - { - char *iamthelastslash; - - iamthelastslash = strrchr( x->x_curdir, '/' ); - *iamthelastslash = '\0'; - - if ( !strcmp( x->x_curdir, "" ) ) - { - strcpy( x->x_curdir, "/" ); - } - } - else - if ( !strncmp( flocation->s_name, "/", 1 ) ) - { - // absolute path required - if ( strlen( flocation->s_name ) >= MAX_DIR_LENGTH ) - { - error( "playlist : maximum dir length reached : cannot change directory" ); - return; - } - strncpy( x->x_curdir, flocation->s_name, MAX_DIR_LENGTH ); - } - else - { - // relative path - if ( strlen( x->x_curdir ) + strlen( flocation->s_name ) + 2 > MAX_DIR_LENGTH ) - { - post( "playlist : maximum dir length reached : cannot change directory" ); - return; - } - if ( strcmp( x->x_curdir, "/" ) ) - { - sprintf( x->x_curdir, "%s/%s", x->x_curdir, flocation->s_name ); - } - else - { - sprintf( x->x_curdir, "/%s", flocation->s_name ); - } - } - - if ( chdir( x->x_curdir ) < 0 ) - { - error( "playlist : requested location >%s< is not a directory", x->x_curdir ); - strcpy( x->x_curdir, olddir ); - return; - } - - playlist_update_dir( x, x->x_glist ); -} - -void playlist_setup(void) -{ - post( playlist_version ); -#include "playlist.tk2c" - playlist_class = class_new(gensym("playlist"), (t_newmethod)playlist_new, - (t_method)playlist_free, sizeof(t_playlist), - CLASS_DEFAULT, A_GIMME, 0); - class_addmethod(playlist_class, (t_method)playlist_seek, gensym("seek"), A_DEFFLOAT, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_location, gensym("location"), A_SYMBOL, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_dialog, gensym("dialog"), A_GIMME, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_sort, gensym("sort"), A_DEFFLOAT, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_graphics, gensym("graphics"), A_DEFFLOAT, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_scroll, gensym("scroll"), A_DEFFLOAT, A_NULL ); - class_addmethod(playlist_class, (t_method)playlist_font, gensym("font"), A_SYMBOL, - A_SYMBOL, A_DEFFLOAT, A_NULL ); - - playlist_widgetbehavior.w_getrectfn = playlist_getrect; - playlist_widgetbehavior.w_displacefn = playlist_displace; - playlist_widgetbehavior.w_selectfn = playlist_select; - playlist_widgetbehavior.w_activatefn = NULL; - playlist_widgetbehavior.w_deletefn = playlist_delete; - playlist_widgetbehavior.w_visfn = playlist_vis; - playlist_widgetbehavior.w_clickfn = playlist_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(playlist_class, playlist_properties); - class_setsavefn(playlist_class, playlist_save); -#else - playlist_widgetbehavior.w_propertiesfn = playlist_properties; - playlist_widgetbehavior.w_savefn = playlist_save; -#endif - - class_setwidget(playlist_class, &playlist_widgetbehavior); - -} diff --git a/playlist/playlist.tk b/playlist/playlist.tk deleted file mode 100644 index 5a22a05..0000000 --- a/playlist/playlist.tk +++ /dev/null @@ -1,154 +0,0 @@ -############ playlist procedures -- ydegoyon@free.fr ######### - -proc playlist_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_extension [concat graph_extension_$vid] - global $var_graph_extension - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height$vid] - global $var_graph_height - set var_graph_font [concat graph_font$vid] - global $var_graph_font - set var_graph_bgcolor [concat graph_bgcolor$vid] - global $var_graph_bgcolor - set var_graph_sbcolor [concat graph_sbcolor$vid] - global $var_graph_sbcolor - set var_graph_fgcolor [concat graph_fgcolor$vid] - global $var_graph_fgcolor - set var_graph_secolor [concat graph_secolor$vid] - global $var_graph_secolor - - set cmd [concat $id dialog \ - [eval concat $$var_graph_extension] \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_font] \ - [eval concat $$var_graph_bgcolor] \ - [eval concat $$var_graph_sbcolor] \ - [eval concat $$var_graph_fgcolor] \ - [eval concat $$var_graph_secolor] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc playlist_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc playlist_ok {id} { - playlist_apply $id - playlist_cancel $id -} - -proc pdtk_playlist_dialog {id extension width height font bgcolor sbcolor fgcolor secolor} { - set vid [string trimleft $id .] - set var_graph_extension [concat graph_extension_$vid] - global $var_graph_extension - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height$vid] - global $var_graph_height - set var_graph_font [concat graph_font$vid] - global $var_graph_font - set var_graph_bgcolor [concat graph_bgcolor$vid] - global $var_graph_bgcolor - set var_graph_sbcolor [concat graph_sbcolor$vid] - global $var_graph_sbcolor - set var_graph_fgcolor [concat graph_fgcolor$vid] - global $var_graph_fgcolor - set var_graph_secolor [concat graph_secolor$vid] - global $var_graph_secolor - - set $var_graph_extension $extension - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_font $font - set $var_graph_bgcolor $bgcolor - set $var_graph_sbcolor $sbcolor - set $var_graph_fgcolor $fgcolor - set $var_graph_secolor $secolor - - toplevel $id - wm title $id {playlist} - wm protocol $id WM_DELETE_WINDOW [concat playlist_cancel $id] - - label $id.label -text {PLAYLIST PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "playlist_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "playlist_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "playlist_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lextension -text "Files Extension :" - entry $id.1rangef.extension -textvariable $var_graph_extension -width 7 - pack $id.1rangef.lextension $id.1rangef.extension -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lwidth -text "Width :" - entry $id.2rangef.width -textvariable $var_graph_width -width 7 - pack $id.2rangef.lwidth $id.2rangef.width -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lheight -text "Height :" - entry $id.3rangef.height -textvariable $var_graph_height -width 7 - pack $id.3rangef.lheight $id.3rangef.height -side left - - frame $id.3_5rangef - pack $id.3_5rangef -side top - label $id.3_5rangef.lfont -text "Font :" - entry $id.3_5rangef.font -textvariable $var_graph_font -width 30 - pack $id.3_5rangef.lfont $id.3_5rangef.font -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.lbgcolor -text "Background Color :" - entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7 - pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left - - frame $id.5rangef - pack $id.5rangef -side top - label $id.5rangef.lsbcolor -text "Scroll Bar Color :" - entry $id.5rangef.sbcolor -textvariable $var_graph_sbcolor -width 7 - pack $id.5rangef.lsbcolor $id.5rangef.sbcolor -side left - - frame $id.6rangef - pack $id.6rangef -side top - label $id.6rangef.lfgcolor -text "Foreground Color :" - entry $id.6rangef.fgcolor -textvariable $var_graph_fgcolor -width 7 - pack $id.6rangef.lfgcolor $id.6rangef.fgcolor -side left - - frame $id.7rangef - pack $id.7rangef -side top - label $id.7rangef.lsecolor -text "Selection Color :" - entry $id.7rangef.secolor -textvariable $var_graph_secolor -width 7 - pack $id.7rangef.lsecolor $id.7rangef.secolor -side left - - bind $id.1rangef.extension [concat playlist_ok $id] - bind $id.2rangef.width [concat playlist_ok $id] - bind $id.3rangef.height [concat playlist_ok $id] - bind $id.3_5rangef.font [concat playlist_ok $id] - bind $id.4rangef.bgcolor [concat playlist_ok $id] - bind $id.5rangef.sbcolor [concat playlist_ok $id] - bind $id.6rangef.fgcolor [concat playlist_ok $id] - bind $id.7rangef.secolor [concat playlist_ok $id] -} - -############ playlist procedures END -- ydegoyon@free.fr ######### diff --git a/playlist/playlist.tk2c b/playlist/playlist.tk2c deleted file mode 100644 index 8058827..0000000 --- a/playlist/playlist.tk2c +++ /dev/null @@ -1,123 +0,0 @@ -// ########### playlist procedures -- ydegoyon@free.fr ######### -sys_gui("proc playlist_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_extension [concat graph_extension_$vid]\n"); -sys_gui("global $var_graph_extension\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_font [concat graph_font$vid]\n"); -sys_gui("global $var_graph_font\n"); -sys_gui("set var_graph_bgcolor [concat graph_bgcolor$vid]\n"); -sys_gui("global $var_graph_bgcolor\n"); -sys_gui("set var_graph_sbcolor [concat graph_sbcolor$vid]\n"); -sys_gui("global $var_graph_sbcolor\n"); -sys_gui("set var_graph_fgcolor [concat graph_fgcolor$vid]\n"); -sys_gui("global $var_graph_fgcolor\n"); -sys_gui("set var_graph_secolor [concat graph_secolor$vid]\n"); -sys_gui("global $var_graph_secolor\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_extension] [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_font] [eval concat $$var_graph_bgcolor] [eval concat $$var_graph_sbcolor] [eval concat $$var_graph_fgcolor] [eval concat $$var_graph_secolor] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc playlist_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc playlist_ok {id} {\n"); -sys_gui("playlist_apply $id\n"); -sys_gui("playlist_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_playlist_dialog {id extension width height font bgcolor sbcolor fgcolor secolor} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_extension [concat graph_extension_$vid]\n"); -sys_gui("global $var_graph_extension\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_font [concat graph_font$vid]\n"); -sys_gui("global $var_graph_font\n"); -sys_gui("set var_graph_bgcolor [concat graph_bgcolor$vid]\n"); -sys_gui("global $var_graph_bgcolor\n"); -sys_gui("set var_graph_sbcolor [concat graph_sbcolor$vid]\n"); -sys_gui("global $var_graph_sbcolor\n"); -sys_gui("set var_graph_fgcolor [concat graph_fgcolor$vid]\n"); -sys_gui("global $var_graph_fgcolor\n"); -sys_gui("set var_graph_secolor [concat graph_secolor$vid]\n"); -sys_gui("global $var_graph_secolor\n"); -sys_gui("set $var_graph_extension $extension\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_font $font\n"); -sys_gui("set $var_graph_bgcolor $bgcolor\n"); -sys_gui("set $var_graph_sbcolor $sbcolor\n"); -sys_gui("set $var_graph_fgcolor $fgcolor\n"); -sys_gui("set $var_graph_secolor $secolor\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {playlist}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat playlist_cancel $id]\n"); -sys_gui("label $id.label -text {PLAYLIST PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"playlist_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"playlist_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"playlist_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lextension -text \"Files Extension :\"\n"); -sys_gui("entry $id.1rangef.extension -textvariable $var_graph_extension -width 7\n"); -sys_gui("pack $id.1rangef.lextension $id.1rangef.extension -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.2rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.2rangef.lwidth $id.2rangef.width -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.3rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.3rangef.lheight $id.3rangef.height -side left\n"); -sys_gui("frame $id.3_5rangef\n"); -sys_gui("pack $id.3_5rangef -side top\n"); -sys_gui("label $id.3_5rangef.lfont -text \"Font :\"\n"); -sys_gui("entry $id.3_5rangef.font -textvariable $var_graph_font -width 30\n"); -sys_gui("pack $id.3_5rangef.lfont $id.3_5rangef.font -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.lbgcolor -text \"Background Color :\"\n"); -sys_gui("entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7\n"); -sys_gui("pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left\n"); -sys_gui("frame $id.5rangef\n"); -sys_gui("pack $id.5rangef -side top\n"); -sys_gui("label $id.5rangef.lsbcolor -text \"Scroll Bar Color :\"\n"); -sys_gui("entry $id.5rangef.sbcolor -textvariable $var_graph_sbcolor -width 7\n"); -sys_gui("pack $id.5rangef.lsbcolor $id.5rangef.sbcolor -side left\n"); -sys_gui("frame $id.6rangef\n"); -sys_gui("pack $id.6rangef -side top\n"); -sys_gui("label $id.6rangef.lfgcolor -text \"Foreground Color :\"\n"); -sys_gui("entry $id.6rangef.fgcolor -textvariable $var_graph_fgcolor -width 7\n"); -sys_gui("pack $id.6rangef.lfgcolor $id.6rangef.fgcolor -side left\n"); -sys_gui("frame $id.7rangef\n"); -sys_gui("pack $id.7rangef -side top\n"); -sys_gui("label $id.7rangef.lsecolor -text \"Selection Color :\"\n"); -sys_gui("entry $id.7rangef.secolor -textvariable $var_graph_secolor -width 7\n"); -sys_gui("pack $id.7rangef.lsecolor $id.7rangef.secolor -side left\n"); -sys_gui("bind $id.1rangef.extension [concat playlist_ok $id]\n"); -sys_gui("bind $id.2rangef.width [concat playlist_ok $id]\n"); -sys_gui("bind $id.3rangef.height [concat playlist_ok $id]\n"); -sys_gui("bind $id.3_5rangef.font [concat playlist_ok $id]\n"); -sys_gui("bind $id.4rangef.bgcolor [concat playlist_ok $id]\n"); -sys_gui("bind $id.5rangef.sbcolor [concat playlist_ok $id]\n"); -sys_gui("bind $id.6rangef.fgcolor [concat playlist_ok $id]\n"); -sys_gui("bind $id.7rangef.secolor [concat playlist_ok $id]\n"); -sys_gui("}\n"); -// ########### playlist procedures END -- ydegoyon@free.fr ######### diff --git a/playlist/tk2c.bash b/playlist/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/playlist/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/playlist/xmms.pd b/playlist/xmms.pd deleted file mode 100644 index b9282cd..0000000 --- a/playlist/xmms.pd +++ /dev/null @@ -1,144 +0,0 @@ -#N canvas 146 29 755 574 10; -#X obj 411 144 mp3fileout~; -#X floatatom 411 165 5 0 0; -#X floatatom 456 165 5 0 0; -#X msg 409 113 open \$1; -#X msg 466 113 start; -#X msg 511 114 stop; -#X text 534 154 Number of frames emitted; -#X text 396 184 Connection state; -#X symbolatom 127 286 80 0 0; -#X floatatom 520 63 5 0 0; -#X obj 20 57 playlist mp3 300 200; -#X msg 651 37 bang; -#X text 23 17 Step 1 : point to your MP3s directory; -#X obj 357 513 dac~; -#X symbolatom 131 438 10 0 0; -#X text 127 452 Incomer's address; -#X obj 349 470 *~ 1; -#X floatatom 461 513 5 0 0; -#X obj 427 513 / 100; -#X obj 390 470 *~ 1; -#X text 501 515 Volume; -#X msg 336 38 connect localhost 5672; -#X obj 95 341 mp3streamin~ 5672 1; -#X text 295 15 Step 2 : connect to the streamer; -#X text 65 285 Playing :; -#X msg 463 64 seek \$1; -#X text 566 11 Step 3 :start random play; -#X obj 657 410 loadbang; -#X msg 656 434 \; pd dsp 1; -#X msg 379 220 seek \$1; -#X obj 437 219 hsl 128 15 0 1e+07 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 0; -#X msg 547 114 disconnect; -#X obj 573 37 random 1000; -#X msg 620 73 seed \$1; -#X floatatom 673 73 5 0 0; -#X msg 634 220 bang; -#X text 575 264 Step 3 bis :start seq play; -#X obj 592 220 countn; -#X obj 578 242 - 1; -#X floatatom 531 243 5 0 0; -#X obj 551 187 spigot; -#X obj 599 186 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 -1; -#X msg 624 186 1; -#X obj 618 95 spigot; -#X obj 666 94 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 1 -; -#X msg 691 94 1; -#X obj 362 441 ekwalizer --------------------------; -#X msg 544 315 100; -#X obj 385 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 7900 1; -#X obj 408 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 7900 1; -#X obj 432 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 7900 1; -#X obj 454 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 7900 1; -#X obj 477 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 498 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 516 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 534 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 552 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 573 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 579 315 loadbang; -#X obj 494 539 loadbang; -#X msg 463 539 50; -#X obj 259 486 compressor~; -#X floatatom 279 434 5 0 0; -#X obj 241 509 env~; -#X obj 266 463 / 100; -#X connect 0 0 1 0; -#X connect 0 1 2 0; -#X connect 0 2 40 0; -#X connect 0 2 43 0; -#X connect 3 0 0 0; -#X connect 4 0 0 0; -#X connect 5 0 0 0; -#X connect 10 0 8 0; -#X connect 10 0 3 0; -#X connect 11 0 32 0; -#X connect 11 0 45 0; -#X connect 16 0 61 0; -#X connect 17 0 18 0; -#X connect 18 0 16 1; -#X connect 18 0 19 1; -#X connect 19 0 61 0; -#X connect 21 0 0 0; -#X connect 21 0 4 0; -#X connect 22 0 46 0; -#X connect 22 1 46 0; -#X connect 22 2 14 0; -#X connect 25 0 10 0; -#X connect 27 0 28 0; -#X connect 29 0 0 0; -#X connect 30 0 29 0; -#X connect 31 0 0 0; -#X connect 32 0 9 0; -#X connect 32 0 25 0; -#X connect 33 0 32 0; -#X connect 34 0 33 0; -#X connect 35 0 37 0; -#X connect 35 0 42 0; -#X connect 37 0 38 0; -#X connect 38 0 25 0; -#X connect 38 0 39 0; -#X connect 40 0 37 0; -#X connect 41 0 40 1; -#X connect 42 0 41 0; -#X connect 43 0 32 0; -#X connect 44 0 43 1; -#X connect 45 0 44 0; -#X connect 46 0 19 0; -#X connect 46 0 16 0; -#X connect 47 0 48 0; -#X connect 47 0 49 0; -#X connect 47 0 50 0; -#X connect 47 0 51 0; -#X connect 48 0 46 1; -#X connect 49 0 46 2; -#X connect 50 0 46 3; -#X connect 51 0 46 4; -#X connect 52 0 46 5; -#X connect 53 0 46 6; -#X connect 54 0 46 7; -#X connect 55 0 46 8; -#X connect 56 0 46 9; -#X connect 57 0 46 10; -#X connect 58 0 47 0; -#X connect 59 0 60 0; -#X connect 60 0 17 0; -#X connect 61 0 13 0; -#X connect 61 0 13 1; -#X connect 61 0 63 0; -#X connect 62 0 64 0; -#X connect 64 0 61 1; diff --git a/probalizer-help.pd b/probalizer-help.pd new file mode 100644 index 0000000..b3baa89 --- /dev/null +++ b/probalizer-help.pd @@ -0,0 +1,53 @@ +#N canvas 191 -6 970 685 10; +#X text 374 167 (invoke with Properties ); +#X text 375 156 You can set the following properties :; +#X text 395 188 * Width : graphical x size; +#X text 395 200 * Height : graphical y size; +#X text 442 506 bugs and comments @ ydegoyon@free.fr; +#X msg 404 603 \; pd dsp 0; +#X msg 470 603 \; pd dsp 1; +#X text 376 110 Probalizer output serial of integers according to the +probability curve; +#X obj 470 581 loadbang; +#X obj 64 92 probalizer 200 200 10 100 1 0 42 1 66 2 86 3 67 4 36 5 +40 6 2 7 53 8 63 9 14; +#X text 395 213 * Values : number of values ( range is [ 1 \, nvalues +] ); +#X msg 93 54 bang; +#X msg 93 4 bang; +#X text 389 458 but without repetitions; +#X msg 295 16 zero; +#X msg 294 40 equi; +#X text 389 433 Note = If the probabilities are all equal to 1 \,; +#X msg 293 64 reset; +#X text 338 63 Reset output; +#X text 396 227 * Max Occurrences : max number of occurences in a serial +; +#X obj 68 358 probalizer 200 200 10 100 1 0 0 1 0 2 0 3 0 4 0 5 0 6 +0 7 0 8 0 9 0; +#X obj 193 331 loadbang; +#X msg 145 331 zero; +#X text 306 345 The output of first probalizer; +#X text 306 357 is stored in the second one; +#X floatatom 187 30 5 0 0; +#X msg 187 5 bang; +#X text 276 281 End of the serial; +#X text 390 445 probalizer behaves as a random object; +#X obj 276 308 print probalizer::end; +#X text 47 6 Start; +#X text 332 42 Set equal probabilities; +#X obj 93 29 metro 10; +#X connect 8 0 6 0; +#X connect 9 0 20 0; +#X connect 9 1 22 0; +#X connect 9 1 29 0; +#X connect 11 0 9 0; +#X connect 12 0 32 0; +#X connect 14 0 9 0; +#X connect 15 0 9 0; +#X connect 17 0 9 0; +#X connect 21 0 22 0; +#X connect 22 0 20 0; +#X connect 25 0 9 0; +#X connect 26 0 25 0; +#X connect 32 0 11 0; diff --git a/probalizer.c b/probalizer.c new file mode 100644 index 0000000..073314e --- /dev/null +++ b/probalizer.c @@ -0,0 +1,706 @@ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* */ +/* probalizer : outputs integer values according to a drawn probability curve */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* "I am a product, I am a sample" */ +/* "I'm hopeless, aimless" */ +/* Crass -- Feeding of the 5000 */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + +#include "probalizer.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define DEFAULT_PROBALIZER_WIDTH 200 +#define DEFAULT_PROBALIZER_HEIGHT 200 +#define DEFAULT_PROBALIZER_NBVALUES 100 +#define DEFAULT_PROBALIZER_NBOCCURRENCES 100 +#define DEFAULT_PROB_VALUE 10 + +static char *probalizer_version = "probalizer : outputs integer values according to a drawn probability curve , version 0.4 (ydegoyon@free.fr)"; + +t_widgetbehavior probalizer_widgetbehavior; +static t_class *probalizer_class; + +static int guidebug=0; +static int pointsize = 5; + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i);\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI13(a,b,c,d,e,f,g,h,i,j,k,l,m) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k,l,m);\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k,l,m) + +/* drawing functions */ +static void probalizer_draw_new(t_probalizer *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ei; + + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #6790E2 -tags %xPROBALIZER\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height, + x); + SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0\" -tags %xLTCAPTION\n", + canvas, text_xpix(&x->x_obj, glist)-15, text_ypix(&x->x_obj, glist) + x->x_height, x ); + SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%d\" -tags %xLBCAPTION\n", + canvas, text_xpix(&x->x_obj, glist)-15, text_ypix(&x->x_obj, glist), x->x_noccurrences, x ); + SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"1\" -tags %xBLCAPTION\n", + canvas, text_xpix(&x->x_obj, glist)+2, text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); + SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%d\" -tags %xBRCAPTION\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_width-5, text_ypix(&x->x_obj, glist) + x->x_height + 10, x->x_nvalues, x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN\n", + canvas, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) , + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT\n", + canvas, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT2\n", + canvas, text_xpix(&x->x_obj, glist) + x->x_width -5, + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height + 2, + x); + for ( ei=0; eix_nvalues; ei++ ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #118373 -tags %xPROB%d\n", + canvas, + text_xpix(&x->x_obj, glist) + ei * x->x_width/x->x_nvalues, + text_ypix(&x->x_obj, glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), + text_xpix(&x->x_obj, glist) + (ei+1) * x->x_width/x->x_nvalues, + text_ypix(&x->x_obj, glist) + x->x_height, + x, ei); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void probalizer_draw_update(t_probalizer *x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int ei; + + for ( ei=0; eix_nvalues; ei++ ) + { + SYS_VGUI8(".x%x.c coords %xPROB%d %d %d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, x->x_glist) + ei * x->x_width / x->x_nvalues, + text_ypix(&x->x_obj, x->x_glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), + text_xpix(&x->x_obj, x->x_glist) + (ei+1) * x->x_width / x->x_nvalues, + text_ypix(&x->x_obj, x->x_glist) + x->x_height ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void probalizer_draw_move(t_probalizer *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ei; + + SYS_VGUI7(".x%x.c coords %xPROBALIZER %d %d %d %d \n", + canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height + ); + SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) - 2, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + ); + SYS_VGUI7(".x%x.c coords %xOUT %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist), + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + 5, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + SYS_VGUI7(".x%x.c coords %xOUT2 %d %d %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist) + x->x_width - 5, + text_ypix(&x->x_obj, glist) + x->x_height, + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height + 2 + ); + SYS_VGUI5(".x%x.c coords %xLTCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist)-15, + text_ypix(&x->x_obj, glist) + x->x_height + ); + SYS_VGUI5(".x%x.c coords %xLBCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist)-15, + text_ypix(&x->x_obj, glist) + ); + SYS_VGUI5(".x%x.c coords %xBLCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist)+2, + text_ypix(&x->x_obj, glist) + x->x_height + 10 + ); + SYS_VGUI5(".x%x.c coords %xBRCAPTION %d %d\n", + canvas, x, text_xpix(&x->x_obj, glist) + x->x_width - 5, + text_ypix(&x->x_obj, glist) + x->x_height + 10 + ); + for ( ei=0; eix_nvalues; ei++ ) + { + SYS_VGUI8(".x%x.c coords %xPROB%d %d %d %d %d\n", + canvas, x, ei, + text_xpix(&x->x_obj, glist) + ei * x->x_width / x->x_nvalues, + text_ypix(&x->x_obj, glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), + text_xpix(&x->x_obj, glist) + (ei+1) * x->x_width / x->x_nvalues, + text_ypix(&x->x_obj, glist) + x->x_height ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void probalizer_draw_erase(t_probalizer* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + int i, ei, gi; + + SYS_VGUI3(".x%x.c delete %xPROBALIZER\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xOUT\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xOUT2\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xLTCAPTION\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xLBCAPTION\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xBLCAPTION\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xBRCAPTION\n", canvas, x ); + for ( ei=0; eix_nvalues; ei++ ) + { + SYS_VGUI4(".x%x.c delete %xPROB%d\n", canvas, x, ei ); + } +} + +static void probalizer_draw_select(t_probalizer* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_selected) + { + /* sets the main item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xPROBALIZER -outline #0000FF\n", glist_getcanvas(glist), x); + + } + else + { + /* sets the main item in black */ + SYS_VGUI3(".x%x.c itemconfigure %xPROBALIZER -outline #000000\n", glist_getcanvas(glist), x); + } +} + +/* ------------------------ probalizer widgetbehaviour----------------------------- */ + + +static void probalizer_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_probalizer* x = (t_probalizer*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void probalizer_save(t_gobj *z, t_binbuf *b) +{ + t_probalizer *x = (t_probalizer *)z; + int ei,gi; + + binbuf_addv(b, "ssiisiiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_width, x->x_height, + x->x_nvalues, x->x_noccurrences, x->x_save ); + if ( x->x_save ) + { + for ( ei=0; eix_nvalues; ei++ ) + { + // post( "probalizer : saving ( %d, %d )", ei, gi ); + binbuf_addv(b, "ii", ei, *(x->x_probs+ei) ); + } + } + binbuf_addv(b, ";"); +} + +static void probalizer_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_probalizer *x=(t_probalizer *)z; + + sprintf(buf, "pdtk_probalizer_dialog %%s %d %d %d %d %d\n", + x->x_width, x->x_height, x->x_nvalues, x->x_noccurrences, x->x_save ); + // post("probalizer_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void probalizer_select(t_gobj *z, t_glist *glist, int selected) +{ + t_probalizer *x = (t_probalizer *)z; + + x->x_selected = selected; + probalizer_draw_select( x, glist ); +} + +static void probalizer_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_probalizer *x = (t_probalizer *)z; + t_rtext *y; + + // post("probalizer_vis : %d", vis ); + if (vis) + { + probalizer_draw_new( x, glist ); + } + else + { + probalizer_draw_erase( x, glist ); + } +} + + /* handle parameters sent by the property dialog */ +static void probalizer_dialog(t_probalizer *x, t_symbol *s, int argc, t_atom *argv) +{ + t_int onvalues, owidth, ei, gi, bi; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( !x ) { + post( "probalizer : error :tried to set properties on an unexisting object" ); + } + onvalues = x->x_nvalues; + owidth = x->x_width; + probalizer_draw_erase(x, x->x_glist); + if ( argc < 5 ) + { + post( "probalizer : error in the number of arguments ( %d )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT ) + { + post( "probalizer : wrong arguments" ); + return; + } + + x->x_width = argv[0].a_w.w_float; + if ( x->x_width <= 0 ) x->x_width = 100; + x->x_height = argv[1].a_w.w_float; + if ( x->x_height <= 0 ) x->x_height = 100; + x->x_nvalues = argv[2].a_w.w_float; + if ( x->x_nvalues < 1 ) x->x_nvalues = 1; + x->x_noccurrences = argv[3].a_w.w_float; + if ( x->x_noccurrences < 1 ) x->x_noccurrences = 1; + x->x_save = argv[4].a_w.w_float; + + // re-allocate arrays of values + post( "probalizer : re-allocate values" ); + if ( onvalues != x->x_nvalues ) + { + t_int mvalues = ( onvalues > x->x_nvalues ) ? x->x_nvalues : onvalues; + t_int *newprobs, *newovalues; + + newprobs = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); + newovalues = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); + for ( ei=0; eix_nvalues; ei++ ) + { + *(newprobs+ei)=DEFAULT_PROB_VALUE; + } + memset( newovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + for ( ei=0; eix_probs+ei); + } + if ( x->x_probs ) + freebytes( x->x_probs, onvalues*sizeof(t_int) ); + x->x_probs = newprobs; + if ( x->x_ovalues ) + freebytes( x->x_ovalues, onvalues*sizeof(t_int) ); + x->x_ovalues = newovalues; + } + + probalizer_draw_new(x, x->x_glist); + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void probalizer_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void probalizer_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_probalizer *x = (t_probalizer *)z; + int xold = text_xpix(&x->x_obj, glist); + int yold = text_ypix(&x->x_obj, glist); + + // post( "probalizer_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) + { + probalizer_draw_move(x, x->x_glist); + } +} + +static int probalizer_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_probalizer* x = (t_probalizer *)z; + t_canvas *canvas=glist_getcanvas(glist); + t_int nevent, npix; + + if ( doit) + { + int nevent; + int newvalue; + + nevent = ((float)( xpix - text_xpix(&x->x_obj, glist) ))/((float)x->x_width/(float)x->x_nvalues); + newvalue = ((float)(text_ypix(&x->x_obj, glist) + x->x_height - ypix))/( (float)x->x_height/(float)x->x_noccurrences); + + // post( "changed %d to %d", nevent, newvalue ); + + // consistency check + if ( nevent < 0 ) + { + post( "probalizer : warning : negative event : %d", nevent ); + nevent = 0; + } + if ( nevent > x->x_nvalues - 1 ) + { + post( "probalizer : warning : event bigger than number of values: %d", nevent ); + nevent = x->x_nvalues - 1 ; + } + if ( newvalue < 0 ) + { + post( "probalizer : warning : negative value : %d", newvalue ); + newvalue = 0; + } + if ( newvalue > x->x_noccurrences ) + { + post( "probalizer : warning : value bigger than max occurrences : %d", newvalue ); + newvalue = x->x_noccurrences ; + } + + *( x->x_probs + nevent ) = newvalue; + // reset all counters + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + probalizer_draw_update( x ); + } + return (1); +} + +static t_probalizer *probalizer_new(t_symbol *s, int argc, t_atom *argv) +{ + int bi, i, ei; + t_probalizer *x; + t_pd *x2; + + // post( "probalizer_new : create : %s argc =%d", s->s_name, argc ); + + x = (t_probalizer *)pd_new(probalizer_class); + // create float output + outlet_new(&x->x_obj, &s_float); + // create bang output + x->x_endoutlet = outlet_new(&x->x_obj, &s_bang); + + // new probalizer created from the gui + if ( argc != 0 ) + { + if ( argc < 5 ) + { + post( "probalizer : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || + argv[4].a_type != A_FLOAT ) + { + post( "probalizer : wrong arguments" ); + return NULL; + } + + x->x_width = argv[0].a_w.w_float; + x->x_height = argv[1].a_w.w_float; + x->x_nvalues = argv[2].a_w.w_float; + if ( x->x_nvalues < 1 ) x->x_nvalues = 1; + x->x_noccurrences = argv[3].a_w.w_float; + if ( x->x_noccurrences < 1 ) x->x_noccurrences = 1; + x->x_save = argv[4].a_w.w_float; + } + else + { + x->x_width = DEFAULT_PROBALIZER_WIDTH; + x->x_height = DEFAULT_PROBALIZER_HEIGHT; + x->x_nvalues = DEFAULT_PROBALIZER_NBVALUES; + x->x_noccurrences = DEFAULT_PROBALIZER_NBOCCURRENCES; + x->x_save = 1; + } + // common fields for new and restored probalizers + x->x_probs = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); + if ( !x->x_probs ) + { + error( "probalizer : could not allocate buffer" ); + return NULL; + } + x->x_ovalues = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); + if ( !x->x_ovalues ) + { + error( "probalizer : could not allocate buffer" ); + return NULL; + } + for ( ei=0; eix_nvalues; ei++ ) + { + *(x->x_probs+ei)=DEFAULT_PROB_VALUE; + } + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + x->x_selected = 0; + x->x_glist = (t_glist *) canvas_getcurrent(); + + // post( "probalizer : argc : %d", argc ); + if ( ( argc != 0 ) && ( x->x_save ) ) + { + int ai = 5; + int si = 0; + + while ( ai < argc - 1 ) + { + *(x->x_probs + (int)argv[ai].a_w.w_float) = (int)argv[ai+1].a_w.w_float; + ai += 2; + } + } + // post( "probalizer_new width: %d height : %d", x->x_width, x->x_height ); + + return (x); +} + +/* zero counters */ +static void probalizer_zero(t_probalizer *x) +{ + t_int ei; + + for ( ei=0; eix_nvalues; ei++ ) + { + *(x->x_probs+ei)=0; + } + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + probalizer_draw_update( x ); +} + +/* the core of it, output an integer value out of the serial */ +static void probalizer_bang(t_probalizer *x) +{ + t_int ei, ci; + t_int *candidates; + t_int nbcandidates = 0; + t_int nevalues=0; + + // calculate number of eligible values + for ( ei=0; eix_nvalues; ei++ ) + { + nevalues += ( *(x->x_probs+ei) - *(x->x_ovalues+ei) ); + } + + if ( nevalues == 0 ) + { + error( "probalizer : probabilities are null, sorry" ); + return; + } + + candidates = ( t_int* ) getbytes( nevalues*sizeof( t_int ) ); + if ( !candidates ) + { + error( "probalizer : could not allocate buffer for internal computation" ); + return; + } + + // select eligible values + for ( ei=0; eix_nvalues; ei++ ) + { + if( *(x->x_ovalues+ei) < *(x->x_probs+ei) ) + { + for ( ci=0; ci<*(x->x_probs+ei) - *(x->x_ovalues+ei); ci++) + { + *(candidates+nbcandidates) = ei; + nbcandidates++; + } + } + } + + // output one of the values + { + int chosen = random() % nbcandidates; + int volue = *(candidates+chosen); + + outlet_float( x->x_obj.ob_outlet, volue+1 ); + *(x->x_ovalues+volue) = *(x->x_ovalues+volue) + 1; + // for ( ei=0; eix_ovalues+*(candidates+ei)) ); + // } + + // test end of the serial + if (nbcandidates == 1 ) + { + // post( "probalizer : end of the serial" ); + outlet_bang( x->x_endoutlet ); + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + } + } + + if ( candidates ) + { + freebytes( candidates, nevalues*sizeof( t_int ) ); + } +} + +/* increase a probability if possible */ +static void probalizer_float(t_probalizer *x, t_float fvalue) +{ + if ( ( (fvalue-1 ) < 0 ) || ( (fvalue-1 ) >= x->x_nvalues ) ) + { + post( "probalizer : wrong float value : %d", (int)fvalue ); + return; + } + if ( ( *(x->x_probs+(int)(fvalue-1))+1 ) <= x->x_noccurrences ) + { + *(x->x_probs+(int)(fvalue-1))+=1; + probalizer_draw_update( x ); + } +} + +/* reset output */ +static void probalizer_reset(t_probalizer *x) +{ + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); +} + +/* equi probability */ +static void probalizer_equi(t_probalizer *x) +{ + t_int ei; + + for ( ei=0; eix_nvalues; ei++ ) + { + *(x->x_probs+ei)=1; + } + memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); + probalizer_draw_update( x ); +} + +static void probalizer_free(t_probalizer *x) +{ + t_int ei; + + if ( x->x_probs ) + { + freebytes( x->x_probs, x->x_nvalues*sizeof(int) ); + } + if ( x->x_ovalues ) + { + freebytes( x->x_ovalues, x->x_nvalues*sizeof(int) ); + } +} + +void probalizer_setup(void) +{ + post( probalizer_version ); + probalizer_class = class_new(gensym("probalizer"), (t_newmethod)probalizer_new, + (t_method)probalizer_free, sizeof(t_probalizer), 0, A_GIMME, 0); + class_addmethod(probalizer_class, (t_method)probalizer_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(probalizer_class, (t_method)probalizer_float, &s_float, A_FLOAT, 0); + class_addmethod(probalizer_class, (t_method)probalizer_bang, &s_bang, 0); + class_addmethod(probalizer_class, (t_method)probalizer_zero, gensym("zero"), 0); + class_addmethod(probalizer_class, (t_method)probalizer_equi, gensym("equi"), 0); + class_addmethod(probalizer_class, (t_method)probalizer_reset, gensym("reset"), 0); + probalizer_widgetbehavior.w_getrectfn = probalizer_getrect; + probalizer_widgetbehavior.w_displacefn = probalizer_displace; + probalizer_widgetbehavior.w_selectfn = probalizer_select; + probalizer_widgetbehavior.w_activatefn = NULL; + probalizer_widgetbehavior.w_deletefn = probalizer_delete; + probalizer_widgetbehavior.w_visfn = probalizer_vis; + probalizer_widgetbehavior.w_clickfn = probalizer_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(probalizer_class, probalizer_properties); + class_setsavefn(probalizer_class, probalizer_save); +#else + probalizer_widgetbehavior.w_propertiesfn = probalizer_properties; + probalizer_widgetbehavior.w_savefn = probalizer_save; +#endif + + class_setwidget(probalizer_class, &probalizer_widgetbehavior); + + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + probalizer_class->c_externdir->s_name, + probalizer_class->c_name->s_name); +} diff --git a/probalizer.h b/probalizer.h new file mode 100644 index 0000000..51c9711 --- /dev/null +++ b/probalizer.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002 Yves Degoyon +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* probalizer : outputs integer values according to a drawn probability curve +*/ + +#ifndef __G_PROBALIZER_H +#define __G_PROBALIZER_H + +typedef struct _probalizer +{ + t_object x_obj; + t_glist *x_glist; + t_int x_height; /* height of the probalizer */ + t_int x_width; /* width of the probalizer */ + t_int x_nvalues; /* number of values */ + t_int x_noccurrences; /* max number of occurrences in a serial */ + t_int *x_probs; /* probability of each event */ + t_int *x_ovalues; /* number of outputs of each event */ + int x_selected; /* stores selected state */ + int x_save; /* saving contents flag */ + t_outlet *x_endoutlet; /* outlet to signal the end of the serial */ +} t_probalizer; + +#endif diff --git a/probalizer.tcl b/probalizer.tcl new file mode 100644 index 0000000..2f069e9 --- /dev/null +++ b/probalizer.tcl @@ -0,0 +1,113 @@ +############ probalizer procedures -- ydegoyon@free.fr ######### + +proc probalizer_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nvalues [concat graph_nvalues_$vid] + global $var_graph_nvalues + set var_graph_noccurrences [concat graph_noccurrences_$vid] + global $var_graph_noccurrences + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_nvalues] \ + [eval concat $$var_graph_noccurrences] \ + [eval concat $$var_graph_save] \;] + #puts stderr $cmd + pd $cmd +} + +proc probalizer_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc probalizer_ok {id} { + probalizer_apply $id + probalizer_cancel $id +} + +proc pdtk_probalizer_dialog {id width height nvalues noccurrences save } { + set vid [string trimleft $id .] + + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_nvalues [concat graph_nvalues_$vid] + global $var_graph_nvalues + set var_graph_noccurrences [concat graph_noccurrences_$vid] + global $var_graph_noccurrences + set var_graph_save [concat graph_save_$vid] + global $var_graph_save + + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_nvalues $nvalues + set $var_graph_noccurrences $noccurrences + set $var_graph_save $save + + toplevel $id + wm title $id {probalizer} + wm protocol $id WM_DELETE_WINDOW [concat probalizer_cancel $id] + + label $id.label -text {PROBALIZER PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "probalizer_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "probalizer_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "probalizer_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lnvalues -text "Values :" + entry $id.3rangef.nvalues -textvariable $var_graph_nvalues -width 7 + pack $id.3rangef.lnvalues $id.3rangef.nvalues -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.lnoccurrences -text "Max Occurrences :" + entry $id.4rangef.noccurrences -textvariable $var_graph_noccurrences -width 7 + pack $id.4rangef.lnoccurrences $id.4rangef.noccurrences -side left + + checkbutton $id.save -text {Save contents} -variable $var_graph_save \ + -anchor w + pack $id.save -side top + + bind $id.1rangef.width [concat probalizer_ok $id] + bind $id.2rangef.height [concat probalizer_ok $id] + bind $id.3rangef.nvalues [concat probalizer_ok $id] + bind $id.4rangef.noccurrences [concat probalizer_ok $id] + focus $id.1rangef.width +} + +############ probalizer procedures END -- ydegoyon@free.fr ######### diff --git a/probalizer/INSTALL b/probalizer/INSTALL deleted file mode 100644 index 17ecb34..0000000 --- a/probalizer/INSTALL +++ /dev/null @@ -1,14 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/probalizer - -make clean - -make - -make install - -open help-probalizer.pd - -comments and bugs @ ydegoyon@free.fr -Yves/ diff --git a/probalizer/probalizer-help.pd b/probalizer/probalizer-help.pd deleted file mode 100644 index b3baa89..0000000 --- a/probalizer/probalizer-help.pd +++ /dev/null @@ -1,53 +0,0 @@ -#N canvas 191 -6 970 685 10; -#X text 374 167 (invoke with Properties ); -#X text 375 156 You can set the following properties :; -#X text 395 188 * Width : graphical x size; -#X text 395 200 * Height : graphical y size; -#X text 442 506 bugs and comments @ ydegoyon@free.fr; -#X msg 404 603 \; pd dsp 0; -#X msg 470 603 \; pd dsp 1; -#X text 376 110 Probalizer output serial of integers according to the -probability curve; -#X obj 470 581 loadbang; -#X obj 64 92 probalizer 200 200 10 100 1 0 42 1 66 2 86 3 67 4 36 5 -40 6 2 7 53 8 63 9 14; -#X text 395 213 * Values : number of values ( range is [ 1 \, nvalues -] ); -#X msg 93 54 bang; -#X msg 93 4 bang; -#X text 389 458 but without repetitions; -#X msg 295 16 zero; -#X msg 294 40 equi; -#X text 389 433 Note = If the probabilities are all equal to 1 \,; -#X msg 293 64 reset; -#X text 338 63 Reset output; -#X text 396 227 * Max Occurrences : max number of occurences in a serial -; -#X obj 68 358 probalizer 200 200 10 100 1 0 0 1 0 2 0 3 0 4 0 5 0 6 -0 7 0 8 0 9 0; -#X obj 193 331 loadbang; -#X msg 145 331 zero; -#X text 306 345 The output of first probalizer; -#X text 306 357 is stored in the second one; -#X floatatom 187 30 5 0 0; -#X msg 187 5 bang; -#X text 276 281 End of the serial; -#X text 390 445 probalizer behaves as a random object; -#X obj 276 308 print probalizer::end; -#X text 47 6 Start; -#X text 332 42 Set equal probabilities; -#X obj 93 29 metro 10; -#X connect 8 0 6 0; -#X connect 9 0 20 0; -#X connect 9 1 22 0; -#X connect 9 1 29 0; -#X connect 11 0 9 0; -#X connect 12 0 32 0; -#X connect 14 0 9 0; -#X connect 15 0 9 0; -#X connect 17 0 9 0; -#X connect 21 0 22 0; -#X connect 22 0 20 0; -#X connect 25 0 9 0; -#X connect 26 0 25 0; -#X connect 32 0 11 0; diff --git a/probalizer/probalizer.c b/probalizer/probalizer.c deleted file mode 100644 index c6fe338..0000000 --- a/probalizer/probalizer.c +++ /dev/null @@ -1,703 +0,0 @@ -/* ---------------------------------------------------------------------------- */ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -/* */ -/* probalizer : outputs integer values according to a drawn probability curve */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* "I am a product, I am a sample" */ -/* "I'm hopeless, aimless" */ -/* Crass -- Feeding of the 5000 */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - -#include "probalizer.h" - -#ifdef NT -#include -#else -#include -#endif - -#define DEFAULT_PROBALIZER_WIDTH 200 -#define DEFAULT_PROBALIZER_HEIGHT 200 -#define DEFAULT_PROBALIZER_NBVALUES 100 -#define DEFAULT_PROBALIZER_NBOCCURRENCES 100 -#define DEFAULT_PROB_VALUE 10 - -static char *probalizer_version = "probalizer : outputs integer values according to a drawn probability curve , version 0.4 (ydegoyon@free.fr)"; - -t_widgetbehavior probalizer_widgetbehavior; -static t_class *probalizer_class; - -static int guidebug=0; -static int pointsize = 5; - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i);\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI13(a,b,c,d,e,f,g,h,i,j,k,l,m) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k,l,m);\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k,l,m) - -/* drawing functions */ -static void probalizer_draw_new(t_probalizer *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ei; - - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #6790E2 -tags %xPROBALIZER\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height, - x); - SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"0\" -tags %xLTCAPTION\n", - canvas, text_xpix(&x->x_obj, glist)-15, text_ypix(&x->x_obj, glist) + x->x_height, x ); - SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%d\" -tags %xLBCAPTION\n", - canvas, text_xpix(&x->x_obj, glist)-15, text_ypix(&x->x_obj, glist), x->x_noccurrences, x ); - SYS_VGUI5(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"1\" -tags %xBLCAPTION\n", - canvas, text_xpix(&x->x_obj, glist)+2, text_ypix(&x->x_obj, glist) + x->x_height + 10, x ); - SYS_VGUI6(".x%x.c create text %d %d -font -*-courier-bold--normal--10-* -text \"%d\" -tags %xBRCAPTION\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_width-5, text_ypix(&x->x_obj, glist) + x->x_height + 10, x->x_nvalues, x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xIN\n", - canvas, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) , - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT\n", - canvas, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #000000 -tags %xOUT2\n", - canvas, text_xpix(&x->x_obj, glist) + x->x_width -5, - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height + 2, - x); - for ( ei=0; eix_nvalues; ei++ ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -outline #000000 -fill #118373 -tags %xPROB%d\n", - canvas, - text_xpix(&x->x_obj, glist) + ei * x->x_width/x->x_nvalues, - text_ypix(&x->x_obj, glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), - text_xpix(&x->x_obj, glist) + (ei+1) * x->x_width/x->x_nvalues, - text_ypix(&x->x_obj, glist) + x->x_height, - x, ei); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void probalizer_draw_update(t_probalizer *x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int ei; - - for ( ei=0; eix_nvalues; ei++ ) - { - SYS_VGUI8(".x%x.c coords %xPROB%d %d %d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, x->x_glist) + ei * x->x_width / x->x_nvalues, - text_ypix(&x->x_obj, x->x_glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), - text_xpix(&x->x_obj, x->x_glist) + (ei+1) * x->x_width / x->x_nvalues, - text_ypix(&x->x_obj, x->x_glist) + x->x_height ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void probalizer_draw_move(t_probalizer *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ei; - - SYS_VGUI7(".x%x.c coords %xPROBALIZER %d %d %d %d \n", - canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, text_ypix(&x->x_obj, glist)+x->x_height - ); - SYS_VGUI7(".x%x.c coords %xIN %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) - 2, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) - ); - SYS_VGUI7(".x%x.c coords %xOUT %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist), - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + 5, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - SYS_VGUI7(".x%x.c coords %xOUT2 %d %d %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist) + x->x_width - 5, - text_ypix(&x->x_obj, glist) + x->x_height, - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height + 2 - ); - SYS_VGUI5(".x%x.c coords %xLTCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist)-15, - text_ypix(&x->x_obj, glist) + x->x_height - ); - SYS_VGUI5(".x%x.c coords %xLBCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist)-15, - text_ypix(&x->x_obj, glist) - ); - SYS_VGUI5(".x%x.c coords %xBLCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist)+2, - text_ypix(&x->x_obj, glist) + x->x_height + 10 - ); - SYS_VGUI5(".x%x.c coords %xBRCAPTION %d %d\n", - canvas, x, text_xpix(&x->x_obj, glist) + x->x_width - 5, - text_ypix(&x->x_obj, glist) + x->x_height + 10 - ); - for ( ei=0; eix_nvalues; ei++ ) - { - SYS_VGUI8(".x%x.c coords %xPROB%d %d %d %d %d\n", - canvas, x, ei, - text_xpix(&x->x_obj, glist) + ei * x->x_width / x->x_nvalues, - text_ypix(&x->x_obj, glist) + x->x_height - ( *(x->x_probs+ei) * x->x_height / x->x_noccurrences ), - text_xpix(&x->x_obj, glist) + (ei+1) * x->x_width / x->x_nvalues, - text_ypix(&x->x_obj, glist) + x->x_height ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void probalizer_draw_erase(t_probalizer* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - int i, ei, gi; - - SYS_VGUI3(".x%x.c delete %xPROBALIZER\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xIN\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xOUT\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xOUT2\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xLTCAPTION\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xLBCAPTION\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xBLCAPTION\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xBRCAPTION\n", canvas, x ); - for ( ei=0; eix_nvalues; ei++ ) - { - SYS_VGUI4(".x%x.c delete %xPROB%d\n", canvas, x, ei ); - } -} - -static void probalizer_draw_select(t_probalizer* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if(x->x_selected) - { - /* sets the main item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xPROBALIZER -outline #0000FF\n", glist_getcanvas(glist), x); - - } - else - { - /* sets the main item in black */ - SYS_VGUI3(".x%x.c itemconfigure %xPROBALIZER -outline #000000\n", glist_getcanvas(glist), x); - } -} - -/* ------------------------ probalizer widgetbehaviour----------------------------- */ - - -static void probalizer_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_probalizer* x = (t_probalizer*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void probalizer_save(t_gobj *z, t_binbuf *b) -{ - t_probalizer *x = (t_probalizer *)z; - int ei,gi; - - binbuf_addv(b, "ssiisiiiii", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_width, x->x_height, - x->x_nvalues, x->x_noccurrences, x->x_save ); - if ( x->x_save ) - { - for ( ei=0; eix_nvalues; ei++ ) - { - // post( "probalizer : saving ( %d, %d )", ei, gi ); - binbuf_addv(b, "ii", ei, *(x->x_probs+ei) ); - } - } - binbuf_addv(b, ";"); -} - -static void probalizer_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_probalizer *x=(t_probalizer *)z; - - sprintf(buf, "pdtk_probalizer_dialog %%s %d %d %d %d %d\n", - x->x_width, x->x_height, x->x_nvalues, x->x_noccurrences, x->x_save ); - // post("probalizer_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void probalizer_select(t_gobj *z, t_glist *glist, int selected) -{ - t_probalizer *x = (t_probalizer *)z; - - x->x_selected = selected; - probalizer_draw_select( x, glist ); -} - -static void probalizer_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_probalizer *x = (t_probalizer *)z; - t_rtext *y; - - // post("probalizer_vis : %d", vis ); - if (vis) - { - probalizer_draw_new( x, glist ); - } - else - { - probalizer_draw_erase( x, glist ); - } -} - - /* handle parameters sent by the property dialog */ -static void probalizer_dialog(t_probalizer *x, t_symbol *s, int argc, t_atom *argv) -{ - t_int onvalues, owidth, ei, gi, bi; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( !x ) { - post( "probalizer : error :tried to set properties on an unexisting object" ); - } - onvalues = x->x_nvalues; - owidth = x->x_width; - probalizer_draw_erase(x, x->x_glist); - if ( argc < 5 ) - { - post( "probalizer : error in the number of arguments ( %d )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT ) - { - post( "probalizer : wrong arguments" ); - return; - } - - x->x_width = argv[0].a_w.w_float; - if ( x->x_width <= 0 ) x->x_width = 100; - x->x_height = argv[1].a_w.w_float; - if ( x->x_height <= 0 ) x->x_height = 100; - x->x_nvalues = argv[2].a_w.w_float; - if ( x->x_nvalues < 1 ) x->x_nvalues = 1; - x->x_noccurrences = argv[3].a_w.w_float; - if ( x->x_noccurrences < 1 ) x->x_noccurrences = 1; - x->x_save = argv[4].a_w.w_float; - - // re-allocate arrays of values - post( "probalizer : re-allocate values" ); - if ( onvalues != x->x_nvalues ) - { - t_int mvalues = ( onvalues > x->x_nvalues ) ? x->x_nvalues : onvalues; - t_int *newprobs, *newovalues; - - newprobs = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); - newovalues = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); - for ( ei=0; eix_nvalues; ei++ ) - { - *(newprobs+ei)=DEFAULT_PROB_VALUE; - } - memset( newovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - for ( ei=0; eix_probs+ei); - } - if ( x->x_probs ) - freebytes( x->x_probs, onvalues*sizeof(t_int) ); - x->x_probs = newprobs; - if ( x->x_ovalues ) - freebytes( x->x_ovalues, onvalues*sizeof(t_int) ); - x->x_ovalues = newovalues; - } - - probalizer_draw_new(x, x->x_glist); - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void probalizer_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void probalizer_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_probalizer *x = (t_probalizer *)z; - int xold = text_xpix(&x->x_obj, glist); - int yold = text_ypix(&x->x_obj, glist); - - // post( "probalizer_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != x->x_obj.te_xpix || yold != x->x_obj.te_ypix) - { - probalizer_draw_move(x, x->x_glist); - } -} - -static int probalizer_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_probalizer* x = (t_probalizer *)z; - t_canvas *canvas=glist_getcanvas(glist); - t_int nevent, npix; - - if ( doit) - { - int nevent; - int newvalue; - - nevent = ((float)( xpix - text_xpix(&x->x_obj, glist) ))/((float)x->x_width/(float)x->x_nvalues); - newvalue = ((float)(text_ypix(&x->x_obj, glist) + x->x_height - ypix))/( (float)x->x_height/(float)x->x_noccurrences); - - // post( "changed %d to %d", nevent, newvalue ); - - // consistency check - if ( nevent < 0 ) - { - post( "probalizer : warning : negative event : %d", nevent ); - nevent = 0; - } - if ( nevent > x->x_nvalues - 1 ) - { - post( "probalizer : warning : event bigger than number of values: %d", nevent ); - nevent = x->x_nvalues - 1 ; - } - if ( newvalue < 0 ) - { - post( "probalizer : warning : negative value : %d", newvalue ); - newvalue = 0; - } - if ( newvalue > x->x_noccurrences ) - { - post( "probalizer : warning : value bigger than max occurrences : %d", newvalue ); - newvalue = x->x_noccurrences ; - } - - *( x->x_probs + nevent ) = newvalue; - // reset all counters - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - probalizer_draw_update( x ); - } - return (1); -} - -static t_probalizer *probalizer_new(t_symbol *s, int argc, t_atom *argv) -{ - int bi, i, ei; - t_probalizer *x; - t_pd *x2; - - // post( "probalizer_new : create : %s argc =%d", s->s_name, argc ); - - x = (t_probalizer *)pd_new(probalizer_class); - // create float output - outlet_new(&x->x_obj, &s_float); - // create bang output - x->x_endoutlet = outlet_new(&x->x_obj, &s_bang); - - // new probalizer created from the gui - if ( argc != 0 ) - { - if ( argc < 5 ) - { - post( "probalizer : error in the number of arguments ( %d )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_FLOAT || - argv[4].a_type != A_FLOAT ) - { - post( "probalizer : wrong arguments" ); - return NULL; - } - - x->x_width = argv[0].a_w.w_float; - x->x_height = argv[1].a_w.w_float; - x->x_nvalues = argv[2].a_w.w_float; - if ( x->x_nvalues < 1 ) x->x_nvalues = 1; - x->x_noccurrences = argv[3].a_w.w_float; - if ( x->x_noccurrences < 1 ) x->x_noccurrences = 1; - x->x_save = argv[4].a_w.w_float; - } - else - { - x->x_width = DEFAULT_PROBALIZER_WIDTH; - x->x_height = DEFAULT_PROBALIZER_HEIGHT; - x->x_nvalues = DEFAULT_PROBALIZER_NBVALUES; - x->x_noccurrences = DEFAULT_PROBALIZER_NBOCCURRENCES; - x->x_save = 1; - } - // common fields for new and restored probalizers - x->x_probs = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); - if ( !x->x_probs ) - { - error( "probalizer : could not allocate buffer" ); - return NULL; - } - x->x_ovalues = (t_int*) getbytes( x->x_nvalues*sizeof(t_int) ); - if ( !x->x_ovalues ) - { - error( "probalizer : could not allocate buffer" ); - return NULL; - } - for ( ei=0; eix_nvalues; ei++ ) - { - *(x->x_probs+ei)=DEFAULT_PROB_VALUE; - } - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - x->x_selected = 0; - x->x_glist = (t_glist *) canvas_getcurrent(); - - // post( "probalizer : argc : %d", argc ); - if ( ( argc != 0 ) && ( x->x_save ) ) - { - int ai = 5; - int si = 0; - - while ( ai < argc - 1 ) - { - *(x->x_probs + (int)argv[ai].a_w.w_float) = (int)argv[ai+1].a_w.w_float; - ai += 2; - } - } - // post( "probalizer_new width: %d height : %d", x->x_width, x->x_height ); - - return (x); -} - -/* zero counters */ -static void probalizer_zero(t_probalizer *x) -{ - t_int ei; - - for ( ei=0; eix_nvalues; ei++ ) - { - *(x->x_probs+ei)=0; - } - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - probalizer_draw_update( x ); -} - -/* the core of it, output an integer value out of the serial */ -static void probalizer_bang(t_probalizer *x) -{ - t_int ei, ci; - t_int *candidates; - t_int nbcandidates = 0; - t_int nevalues=0; - - // calculate number of eligible values - for ( ei=0; eix_nvalues; ei++ ) - { - nevalues += ( *(x->x_probs+ei) - *(x->x_ovalues+ei) ); - } - - if ( nevalues == 0 ) - { - error( "probalizer : probabilities are null, sorry" ); - return; - } - - candidates = ( t_int* ) getbytes( nevalues*sizeof( t_int ) ); - if ( !candidates ) - { - error( "probalizer : could not allocate buffer for internal computation" ); - return; - } - - // select eligible values - for ( ei=0; eix_nvalues; ei++ ) - { - if( *(x->x_ovalues+ei) < *(x->x_probs+ei) ) - { - for ( ci=0; ci<*(x->x_probs+ei) - *(x->x_ovalues+ei); ci++) - { - *(candidates+nbcandidates) = ei; - nbcandidates++; - } - } - } - - // output one of the values - { - int chosen = random() % nbcandidates; - int volue = *(candidates+chosen); - - outlet_float( x->x_obj.ob_outlet, volue+1 ); - *(x->x_ovalues+volue) = *(x->x_ovalues+volue) + 1; - // for ( ei=0; eix_ovalues+*(candidates+ei)) ); - // } - - // test end of the serial - if (nbcandidates == 1 ) - { - // post( "probalizer : end of the serial" ); - outlet_bang( x->x_endoutlet ); - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - } - } - - if ( candidates ) - { - freebytes( candidates, nevalues*sizeof( t_int ) ); - } -} - -/* increase a probability if possible */ -static void probalizer_float(t_probalizer *x, t_float fvalue) -{ - if ( ( (fvalue-1 ) < 0 ) || ( (fvalue-1 ) >= x->x_nvalues ) ) - { - post( "probalizer : wrong float value : %d", (int)fvalue ); - return; - } - if ( ( *(x->x_probs+(int)(fvalue-1))+1 ) <= x->x_noccurrences ) - { - *(x->x_probs+(int)(fvalue-1))+=1; - probalizer_draw_update( x ); - } -} - -/* reset output */ -static void probalizer_reset(t_probalizer *x) -{ - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); -} - -/* equi probability */ -static void probalizer_equi(t_probalizer *x) -{ - t_int ei; - - for ( ei=0; eix_nvalues; ei++ ) - { - *(x->x_probs+ei)=1; - } - memset( x->x_ovalues, 0x0, x->x_nvalues*sizeof(t_int) ); - probalizer_draw_update( x ); -} - -static void probalizer_free(t_probalizer *x) -{ - t_int ei; - - if ( x->x_probs ) - { - freebytes( x->x_probs, x->x_nvalues*sizeof(int) ); - } - if ( x->x_ovalues ) - { - freebytes( x->x_ovalues, x->x_nvalues*sizeof(int) ); - } -} - -void probalizer_setup(void) -{ - post( probalizer_version ); -#include "probalizer.tk2c" - probalizer_class = class_new(gensym("probalizer"), (t_newmethod)probalizer_new, - (t_method)probalizer_free, sizeof(t_probalizer), 0, A_GIMME, 0); - class_addmethod(probalizer_class, (t_method)probalizer_dialog, gensym("dialog"), A_GIMME, 0); - class_addmethod(probalizer_class, (t_method)probalizer_float, &s_float, A_FLOAT, 0); - class_addmethod(probalizer_class, (t_method)probalizer_bang, &s_bang, 0); - class_addmethod(probalizer_class, (t_method)probalizer_zero, gensym("zero"), 0); - class_addmethod(probalizer_class, (t_method)probalizer_equi, gensym("equi"), 0); - class_addmethod(probalizer_class, (t_method)probalizer_reset, gensym("reset"), 0); - probalizer_widgetbehavior.w_getrectfn = probalizer_getrect; - probalizer_widgetbehavior.w_displacefn = probalizer_displace; - probalizer_widgetbehavior.w_selectfn = probalizer_select; - probalizer_widgetbehavior.w_activatefn = NULL; - probalizer_widgetbehavior.w_deletefn = probalizer_delete; - probalizer_widgetbehavior.w_visfn = probalizer_vis; - probalizer_widgetbehavior.w_clickfn = probalizer_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(probalizer_class, probalizer_properties); - class_setsavefn(probalizer_class, probalizer_save); -#else - probalizer_widgetbehavior.w_propertiesfn = probalizer_properties; - probalizer_widgetbehavior.w_savefn = probalizer_save; -#endif - - class_setwidget(probalizer_class, &probalizer_widgetbehavior); - -} diff --git a/probalizer/probalizer.h b/probalizer/probalizer.h deleted file mode 100644 index 51c9711..0000000 --- a/probalizer/probalizer.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon -* For information on usage and redistribution, and for a DISCLAIMER OF ALL -* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -/* probalizer : outputs integer values according to a drawn probability curve -*/ - -#ifndef __G_PROBALIZER_H -#define __G_PROBALIZER_H - -typedef struct _probalizer -{ - t_object x_obj; - t_glist *x_glist; - t_int x_height; /* height of the probalizer */ - t_int x_width; /* width of the probalizer */ - t_int x_nvalues; /* number of values */ - t_int x_noccurrences; /* max number of occurrences in a serial */ - t_int *x_probs; /* probability of each event */ - t_int *x_ovalues; /* number of outputs of each event */ - int x_selected; /* stores selected state */ - int x_save; /* saving contents flag */ - t_outlet *x_endoutlet; /* outlet to signal the end of the serial */ -} t_probalizer; - -#endif diff --git a/probalizer/probalizer.tk b/probalizer/probalizer.tk deleted file mode 100644 index 2f069e9..0000000 --- a/probalizer/probalizer.tk +++ /dev/null @@ -1,113 +0,0 @@ -############ probalizer procedures -- ydegoyon@free.fr ######### - -proc probalizer_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nvalues [concat graph_nvalues_$vid] - global $var_graph_nvalues - set var_graph_noccurrences [concat graph_noccurrences_$vid] - global $var_graph_noccurrences - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set cmd [concat $id dialog \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_nvalues] \ - [eval concat $$var_graph_noccurrences] \ - [eval concat $$var_graph_save] \;] - #puts stderr $cmd - pd $cmd -} - -proc probalizer_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc probalizer_ok {id} { - probalizer_apply $id - probalizer_cancel $id -} - -proc pdtk_probalizer_dialog {id width height nvalues noccurrences save } { - set vid [string trimleft $id .] - - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - set var_graph_nvalues [concat graph_nvalues_$vid] - global $var_graph_nvalues - set var_graph_noccurrences [concat graph_noccurrences_$vid] - global $var_graph_noccurrences - set var_graph_save [concat graph_save_$vid] - global $var_graph_save - - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_nvalues $nvalues - set $var_graph_noccurrences $noccurrences - set $var_graph_save $save - - toplevel $id - wm title $id {probalizer} - wm protocol $id WM_DELETE_WINDOW [concat probalizer_cancel $id] - - label $id.label -text {PROBALIZER PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "probalizer_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "probalizer_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "probalizer_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lwidth -text "Width :" - entry $id.1rangef.width -textvariable $var_graph_width -width 7 - pack $id.1rangef.lwidth $id.1rangef.width -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lheight -text "Height :" - entry $id.2rangef.height -textvariable $var_graph_height -width 7 - pack $id.2rangef.lheight $id.2rangef.height -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lnvalues -text "Values :" - entry $id.3rangef.nvalues -textvariable $var_graph_nvalues -width 7 - pack $id.3rangef.lnvalues $id.3rangef.nvalues -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.lnoccurrences -text "Max Occurrences :" - entry $id.4rangef.noccurrences -textvariable $var_graph_noccurrences -width 7 - pack $id.4rangef.lnoccurrences $id.4rangef.noccurrences -side left - - checkbutton $id.save -text {Save contents} -variable $var_graph_save \ - -anchor w - pack $id.save -side top - - bind $id.1rangef.width [concat probalizer_ok $id] - bind $id.2rangef.height [concat probalizer_ok $id] - bind $id.3rangef.nvalues [concat probalizer_ok $id] - bind $id.4rangef.noccurrences [concat probalizer_ok $id] - focus $id.1rangef.width -} - -############ probalizer procedures END -- ydegoyon@free.fr ######### diff --git a/probalizer/probalizer.tk2c b/probalizer/probalizer.tk2c deleted file mode 100755 index b4a608c..0000000 --- a/probalizer/probalizer.tk2c +++ /dev/null @@ -1,87 +0,0 @@ -// ########### probalizer procedures -- ydegoyon@free.fr ######### -sys_gui("proc probalizer_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nvalues [concat graph_nvalues_$vid]\n"); -sys_gui("global $var_graph_nvalues\n"); -sys_gui("set var_graph_noccurrences [concat graph_noccurrences_$vid]\n"); -sys_gui("global $var_graph_noccurrences\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_nvalues] [eval concat $$var_graph_noccurrences] [eval concat $$var_graph_save] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc probalizer_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc probalizer_ok {id} {\n"); -sys_gui("probalizer_apply $id\n"); -sys_gui("probalizer_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_probalizer_dialog {id width height nvalues noccurrences save } {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_nvalues [concat graph_nvalues_$vid]\n"); -sys_gui("global $var_graph_nvalues\n"); -sys_gui("set var_graph_noccurrences [concat graph_noccurrences_$vid]\n"); -sys_gui("global $var_graph_noccurrences\n"); -sys_gui("set var_graph_save [concat graph_save_$vid]\n"); -sys_gui("global $var_graph_save\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_nvalues $nvalues\n"); -sys_gui("set $var_graph_noccurrences $noccurrences\n"); -sys_gui("set $var_graph_save $save\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {probalizer}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat probalizer_cancel $id]\n"); -sys_gui("label $id.label -text {PROBALIZER PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"probalizer_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"probalizer_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"probalizer_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.1rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.1rangef.lwidth $id.1rangef.width -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.2rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.2rangef.lheight $id.2rangef.height -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lnvalues -text \"Values :\"\n"); -sys_gui("entry $id.3rangef.nvalues -textvariable $var_graph_nvalues -width 7\n"); -sys_gui("pack $id.3rangef.lnvalues $id.3rangef.nvalues -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.lnoccurrences -text \"Max Occurrences :\"\n"); -sys_gui("entry $id.4rangef.noccurrences -textvariable $var_graph_noccurrences -width 7\n"); -sys_gui("pack $id.4rangef.lnoccurrences $id.4rangef.noccurrences -side left\n"); -sys_gui("checkbutton $id.save -text {Save contents} -variable $var_graph_save -anchor w\n"); -sys_gui("pack $id.save -side top\n"); -sys_gui("bind $id.1rangef.width [concat probalizer_ok $id]\n"); -sys_gui("bind $id.2rangef.height [concat probalizer_ok $id]\n"); -sys_gui("bind $id.3rangef.nvalues [concat probalizer_ok $id]\n"); -sys_gui("bind $id.4rangef.noccurrences [concat probalizer_ok $id]\n"); -sys_gui("focus $id.1rangef.width\n"); -sys_gui("}\n"); -// ########### probalizer procedures END -- ydegoyon@free.fr ######### diff --git a/probalizer/tk2c.bash b/probalizer/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/probalizer/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/randomblock~-help.pd b/randomblock~-help.pd new file mode 100644 index 0000000..d4b2e5d --- /dev/null +++ b/randomblock~-help.pd @@ -0,0 +1,15 @@ +#N canvas 194 211 575 337 10; +#X msg 361 263 \; pd dsp 1; +#X floatatom 192 112 5 0 0; +#X text 191 88 Set upper limit of random values; +#X text 107 123 Not used; +#X obj 121 179 print~; +#X msg 76 156 bang; +#X text 160 29 Generates an audio block starting at a random value +; +#X obj 121 143 randomblock~ 100; +#X text 161 42 This can be used to read a table randomly.; +#X text 161 54 This is illustrated in "mrandtab.pd".; +#X connect 1 0 7 1; +#X connect 5 0 4 0; +#X connect 7 0 4 0; diff --git a/randomblock~.c b/randomblock~.c new file mode 100644 index 0000000..34d2411 --- /dev/null +++ b/randomblock~.c @@ -0,0 +1,115 @@ +/* ------------------------ randomblock~ -------------------------------------- */ +/* */ +/* Generates a random signal block */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#include +#include +#include + +#include "m_pd.h" /* standard pd stuff */ + +static char *randomblock_version = "randomblock~: generates a random audio block : author : ydegoyon@free.fr"; + +static t_class *randomblock_class; + +typedef struct _randomblock +{ + t_object x_obj; + t_int x_limit; +} t_randomblock; + + /* clean up */ +static void randomblock_free(t_randomblock *x) +{ +} + +static void *randomblock_new(t_float flimit) +{ + t_randomblock *x = (t_randomblock *)pd_new(randomblock_class); + outlet_new(&x->x_obj, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("limit")); + if ( flimit <= 0 || flimit > RAND_MAX ) { + post( "randomblock~: wrong creation argument" ); + return NULL; + } + x->x_limit = (int) flimit; + return(x); +} + +static void *randomblock_limit(t_randomblock* x, t_float flimit) +{ + if ( flimit < 0 || flimit > RAND_MAX ) { + post( "randomblock~: wrong random limit" ); + return; + } else { + x->x_limit=(int)flimit; + } +} + +static t_int *randomblock_perform(t_int *w) +{ + t_float *out = (t_float*) w[1]; + int n = (int)(w[2]); + t_randomblock *x = (t_randomblock*) w[3]; + + int rvalue = rand(); + // post("random value : %d", rvalue ); + rvalue = rvalue%(x->x_limit-n); + // post("modulated by %d : %d", (x->x_limit-n), rvalue ); + if ( rvalue < 0 ) rvalue=0; + + while (n--) { + *(out)++=(float)rvalue++; + } + + return (w+4); +} + +static void randomblock_dsp(t_randomblock *x, t_signal **sp) +{ + dsp_add( randomblock_perform, 3, sp[0]->s_vec, sp[0]->s_n, x ) ; +} + +void randomblock_tilde_setup(void) +{ + post(randomblock_version); + randomblock_class = class_new(gensym("randomblock~"), (t_newmethod)randomblock_new, + (t_method)randomblock_free, + sizeof(t_randomblock), 0, A_DEFFLOAT, 0); + class_addmethod( randomblock_class, (t_method)randomblock_dsp, gensym("dsp"), 0); + class_addmethod( randomblock_class, (t_method)randomblock_limit, gensym("limit"), A_FLOAT, 0); +} diff --git a/randomblock~/INSTALL b/randomblock~/INSTALL deleted file mode 100644 index ae90f70..0000000 --- a/randomblock~/INSTALL +++ /dev/null @@ -1,7 +0,0 @@ -untar in /my/pd/dir/extra - -cd /my/pd/dir/extra/randomblock~ - -make - -you're set !! diff --git a/randomblock~/mrandtab.pd b/randomblock~/mrandtab.pd deleted file mode 100644 index 157111c..0000000 --- a/randomblock~/mrandtab.pd +++ /dev/null @@ -1,6 +0,0 @@ -#N canvas 187 22 737 487 10; -#X obj 138 151 dac~; -#X obj 136 114 randtab; -#X text 174 86 Everything is in the subpatch; -#X connect 1 0 0 0; -#X connect 1 0 0 1; diff --git a/randomblock~/randomblock~-help.pd b/randomblock~/randomblock~-help.pd deleted file mode 100644 index d4b2e5d..0000000 --- a/randomblock~/randomblock~-help.pd +++ /dev/null @@ -1,15 +0,0 @@ -#N canvas 194 211 575 337 10; -#X msg 361 263 \; pd dsp 1; -#X floatatom 192 112 5 0 0; -#X text 191 88 Set upper limit of random values; -#X text 107 123 Not used; -#X obj 121 179 print~; -#X msg 76 156 bang; -#X text 160 29 Generates an audio block starting at a random value -; -#X obj 121 143 randomblock~ 100; -#X text 161 42 This can be used to read a table randomly.; -#X text 161 54 This is illustrated in "mrandtab.pd".; -#X connect 1 0 7 1; -#X connect 5 0 4 0; -#X connect 7 0 4 0; diff --git a/randomblock~/randomblock~.c b/randomblock~/randomblock~.c deleted file mode 100644 index 34d2411..0000000 --- a/randomblock~/randomblock~.c +++ /dev/null @@ -1,115 +0,0 @@ -/* ------------------------ randomblock~ -------------------------------------- */ -/* */ -/* Generates a random signal block */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#include -#include -#include - -#include "m_pd.h" /* standard pd stuff */ - -static char *randomblock_version = "randomblock~: generates a random audio block : author : ydegoyon@free.fr"; - -static t_class *randomblock_class; - -typedef struct _randomblock -{ - t_object x_obj; - t_int x_limit; -} t_randomblock; - - /* clean up */ -static void randomblock_free(t_randomblock *x) -{ -} - -static void *randomblock_new(t_float flimit) -{ - t_randomblock *x = (t_randomblock *)pd_new(randomblock_class); - outlet_new(&x->x_obj, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("limit")); - if ( flimit <= 0 || flimit > RAND_MAX ) { - post( "randomblock~: wrong creation argument" ); - return NULL; - } - x->x_limit = (int) flimit; - return(x); -} - -static void *randomblock_limit(t_randomblock* x, t_float flimit) -{ - if ( flimit < 0 || flimit > RAND_MAX ) { - post( "randomblock~: wrong random limit" ); - return; - } else { - x->x_limit=(int)flimit; - } -} - -static t_int *randomblock_perform(t_int *w) -{ - t_float *out = (t_float*) w[1]; - int n = (int)(w[2]); - t_randomblock *x = (t_randomblock*) w[3]; - - int rvalue = rand(); - // post("random value : %d", rvalue ); - rvalue = rvalue%(x->x_limit-n); - // post("modulated by %d : %d", (x->x_limit-n), rvalue ); - if ( rvalue < 0 ) rvalue=0; - - while (n--) { - *(out)++=(float)rvalue++; - } - - return (w+4); -} - -static void randomblock_dsp(t_randomblock *x, t_signal **sp) -{ - dsp_add( randomblock_perform, 3, sp[0]->s_vec, sp[0]->s_n, x ) ; -} - -void randomblock_tilde_setup(void) -{ - post(randomblock_version); - randomblock_class = class_new(gensym("randomblock~"), (t_newmethod)randomblock_new, - (t_method)randomblock_free, - sizeof(t_randomblock), 0, A_DEFFLOAT, 0); - class_addmethod( randomblock_class, (t_method)randomblock_dsp, gensym("dsp"), 0); - class_addmethod( randomblock_class, (t_method)randomblock_limit, gensym("limit"), A_FLOAT, 0); -} diff --git a/randomblock~/randtab.pd b/randomblock~/randtab.pd deleted file mode 100644 index 089a86e..0000000 --- a/randomblock~/randtab.pd +++ /dev/null @@ -1,43 +0,0 @@ -#N canvas 187 22 737 487 10; -#X obj 143 114 soundfiler; -#X obj 110 354 *~; -#X msg 138 3 bang; -#X msg 142 92 read -resize \$1 \$2; -#X msg 215 12 bang; -#X obj 515 47 table \$0-music; -#X obj 144 66 pack s s; -#X obj 215 35 f \$0; -#X obj 231 56 makefilename %d-music; -#X symbolatom 247 35 40 0 0; -#X floatatom 163 244 10 0 0; -#X floatatom 142 353 5 0 0; -#X obj 110 303 tabread4~ \$0-music; -#X obj 20 331 print~; -#X msg 19 307 bang; -#X obj 138 29 opanel; -#X obj 109 330 /~ 100; -#X obj 34 235 randomblock~ 1000; -#X obj 241 325 print~; -#X msg 240 301 bang; -#X obj 110 401 outlet~; -#X obj 402 206 block~ 32768 1; -#X connect 0 0 10 0; -#X connect 0 0 17 1; -#X connect 1 0 20 0; -#X connect 2 0 15 0; -#X connect 3 0 0 0; -#X connect 4 0 7 0; -#X connect 6 0 3 0; -#X connect 7 0 8 0; -#X connect 8 0 6 1; -#X connect 11 0 1 1; -#X connect 12 0 16 0; -#X connect 12 0 18 0; -#X connect 14 0 13 0; -#X connect 15 0 4 0; -#X connect 15 0 6 0; -#X connect 15 0 9 0; -#X connect 16 0 1 0; -#X connect 17 0 12 0; -#X connect 17 0 13 0; -#X connect 19 0 18 0; diff --git a/randtab.pd b/randtab.pd new file mode 100644 index 0000000..089a86e --- /dev/null +++ b/randtab.pd @@ -0,0 +1,43 @@ +#N canvas 187 22 737 487 10; +#X obj 143 114 soundfiler; +#X obj 110 354 *~; +#X msg 138 3 bang; +#X msg 142 92 read -resize \$1 \$2; +#X msg 215 12 bang; +#X obj 515 47 table \$0-music; +#X obj 144 66 pack s s; +#X obj 215 35 f \$0; +#X obj 231 56 makefilename %d-music; +#X symbolatom 247 35 40 0 0; +#X floatatom 163 244 10 0 0; +#X floatatom 142 353 5 0 0; +#X obj 110 303 tabread4~ \$0-music; +#X obj 20 331 print~; +#X msg 19 307 bang; +#X obj 138 29 opanel; +#X obj 109 330 /~ 100; +#X obj 34 235 randomblock~ 1000; +#X obj 241 325 print~; +#X msg 240 301 bang; +#X obj 110 401 outlet~; +#X obj 402 206 block~ 32768 1; +#X connect 0 0 10 0; +#X connect 0 0 17 1; +#X connect 1 0 20 0; +#X connect 2 0 15 0; +#X connect 3 0 0 0; +#X connect 4 0 7 0; +#X connect 6 0 3 0; +#X connect 7 0 8 0; +#X connect 8 0 6 1; +#X connect 11 0 1 1; +#X connect 12 0 16 0; +#X connect 12 0 18 0; +#X connect 14 0 13 0; +#X connect 15 0 4 0; +#X connect 15 0 6 0; +#X connect 15 0 9 0; +#X connect 16 0 1 0; +#X connect 17 0 12 0; +#X connect 17 0 13 0; +#X connect 19 0 18 0; diff --git a/resynth-64.pd b/resynth-64.pd new file mode 100644 index 0000000..bb5a93d --- /dev/null +++ b/resynth-64.pd @@ -0,0 +1,285 @@ +#N canvas 36 14 971 657 10; +#X obj 56 522 *~ 1; +#X obj 103 522 / 100; +#X floatatom 147 522 5 0 0; +#X obj 272 280 filterbank~ 0 1920 64; +#X obj 31 62 t s b; +#X obj 80 68 float \$0; +#X obj 31 85 route float; +#X msg 336 250 bang; +#X obj 31 177 soundfiler; +#X obj 125 250 tabplay~ \$0-filterbank-sample; +#X obj 31 108 makefilename %d-filterbank-sample; +#X obj 31 131 pack s s; +#X msg 31 154 read -resize \$1 \$2; +#X msg 239 220 bang; +#X obj 28 220 tabplay~ \$0-filterbank-sample; +#X obj 72 599 table \$0-filterbank-sample; +#X msg 430 250 randomize 1; +#X obj 486 42 playlist all 200 200; +#X msg 359 35 location /Samples; +#X obj 359 12 loadbang; +#X obj 374 569 volpan; +#X msg 518 250 randomize 0; +#X obj 354 123 s fbstep; +#X floatatom 354 100 5 0 0; +#X msg 306 91 30; +#X obj 306 68 loadbang; +#X floatatom 229 42 5 0 0; +#X obj 210 68 s firstfreq; +#X msg 181 35 15; +#X obj 181 12 loadbang; +#X obj 107 314 setosc 0; +#X obj 107 337 setosc 1; +#X obj 107 360 setosc 2; +#X obj 107 383 setosc 3; +#X obj 107 406 setosc 4; +#X obj 107 429 setosc 5; +#X obj 107 452 setosc 6; +#X obj 108 476 setosc 7; +#X obj 199 521 *~ 1; +#X obj 246 521 / 100; +#X floatatom 290 521 5 0 0; +#X obj 250 313 setosc 8; +#X obj 250 336 setosc 9; +#X obj 250 359 setosc 10; +#X obj 250 382 setosc 11; +#X obj 250 405 setosc 12; +#X obj 250 428 setosc 13; +#X obj 250 451 setosc 14; +#X obj 251 475 setosc 15; +#X obj 339 519 *~ 1; +#X obj 386 519 / 100; +#X floatatom 430 519 5 0 0; +#X obj 390 311 setosc 16; +#X obj 390 334 setosc 17; +#X obj 390 357 setosc 18; +#X obj 390 380 setosc 19; +#X obj 390 403 setosc 20; +#X obj 390 426 setosc 21; +#X obj 390 449 setosc 22; +#X obj 391 473 setosc 23; +#X obj 479 519 *~ 1; +#X obj 526 519 / 100; +#X floatatom 570 519 5 0 0; +#X obj 530 311 setosc 24; +#X obj 530 334 setosc 25; +#X obj 530 357 setosc 26; +#X obj 530 380 setosc 27; +#X obj 530 403 setosc 28; +#X obj 530 426 setosc 29; +#X obj 530 449 setosc 30; +#X obj 531 473 setosc 31; +#X obj 621 518 *~ 1; +#X obj 668 518 / 100; +#X floatatom 712 518 5 0 0; +#X obj 672 310 setosc 32; +#X obj 672 333 setosc 33; +#X obj 672 356 setosc 34; +#X obj 672 379 setosc 35; +#X obj 672 402 setosc 36; +#X obj 672 425 setosc 37; +#X obj 672 448 setosc 38; +#X obj 673 472 setosc 39; +#X obj 762 519 *~ 1; +#X obj 809 519 / 100; +#X floatatom 853 519 5 0 0; +#X obj 813 311 setosc 40; +#X obj 813 334 setosc 41; +#X obj 813 357 setosc 42; +#X obj 813 380 setosc 43; +#X obj 813 403 setosc 44; +#X obj 813 426 setosc 45; +#X obj 813 449 setosc 46; +#X obj 814 473 setosc 47; +#X obj 903 519 *~ 1; +#X obj 950 519 / 100; +#X floatatom 994 519 5 0 0; +#X obj 954 311 setosc 48; +#X obj 954 334 setosc 49; +#X obj 954 357 setosc 50; +#X obj 954 380 setosc 51; +#X obj 954 403 setosc 52; +#X obj 954 426 setosc 53; +#X obj 954 449 setosc 54; +#X obj 955 473 setosc 55; +#X obj 1041 518 *~ 1; +#X obj 1088 518 / 100; +#X floatatom 1132 518 5 0 0; +#X obj 1092 310 setosc 56; +#X obj 1092 333 setosc 57; +#X obj 1092 356 setosc 58; +#X obj 1092 379 setosc 59; +#X obj 1092 402 setosc 60; +#X obj 1092 425 setosc 61; +#X obj 1092 448 setosc 62; +#X obj 1093 472 setosc 63; +#X connect 0 0 20 0; +#X connect 1 0 0 1; +#X connect 2 0 1 0; +#X connect 3 0 30 0; +#X connect 3 1 31 0; +#X connect 3 2 32 0; +#X connect 3 3 33 0; +#X connect 3 4 34 0; +#X connect 3 5 35 0; +#X connect 3 6 36 0; +#X connect 3 7 37 0; +#X connect 3 8 41 0; +#X connect 3 9 42 0; +#X connect 3 10 43 0; +#X connect 3 11 44 0; +#X connect 3 12 45 0; +#X connect 3 13 46 0; +#X connect 3 14 47 0; +#X connect 3 15 48 0; +#X connect 3 16 52 0; +#X connect 3 17 53 0; +#X connect 3 18 54 0; +#X connect 3 19 55 0; +#X connect 3 20 56 0; +#X connect 3 21 57 0; +#X connect 3 22 58 0; +#X connect 3 23 59 0; +#X connect 3 24 63 0; +#X connect 3 25 64 0; +#X connect 3 26 65 0; +#X connect 3 27 66 0; +#X connect 3 28 67 0; +#X connect 3 29 68 0; +#X connect 3 30 69 0; +#X connect 3 31 70 0; +#X connect 3 32 74 0; +#X connect 3 33 75 0; +#X connect 3 34 76 0; +#X connect 3 35 77 0; +#X connect 3 36 78 0; +#X connect 3 37 79 0; +#X connect 3 38 80 0; +#X connect 3 39 81 0; +#X connect 3 40 85 0; +#X connect 3 41 86 0; +#X connect 3 42 87 0; +#X connect 3 43 88 0; +#X connect 3 44 89 0; +#X connect 3 45 90 0; +#X connect 3 46 91 0; +#X connect 3 47 92 0; +#X connect 3 48 96 0; +#X connect 3 49 97 0; +#X connect 3 50 98 0; +#X connect 3 51 99 0; +#X connect 3 52 100 0; +#X connect 3 53 101 0; +#X connect 3 54 102 0; +#X connect 3 55 103 0; +#X connect 3 56 107 0; +#X connect 3 57 108 0; +#X connect 3 58 109 0; +#X connect 3 59 110 0; +#X connect 3 60 111 0; +#X connect 3 61 112 0; +#X connect 3 62 113 0; +#X connect 3 63 114 0; +#X connect 4 0 11 0; +#X connect 4 1 5 0; +#X connect 5 0 6 0; +#X connect 6 0 10 0; +#X connect 7 0 9 0; +#X connect 9 0 3 0; +#X connect 10 0 11 1; +#X connect 11 0 12 0; +#X connect 12 0 8 0; +#X connect 13 0 14 0; +#X connect 14 0 0 0; +#X connect 16 0 3 0; +#X connect 17 0 4 0; +#X connect 18 0 17 0; +#X connect 19 0 18 0; +#X connect 21 0 3 0; +#X connect 23 0 22 0; +#X connect 24 0 22 0; +#X connect 25 0 24 0; +#X connect 26 0 27 0; +#X connect 28 0 27 0; +#X connect 29 0 28 0; +#X connect 30 0 0 0; +#X connect 31 0 0 0; +#X connect 32 0 0 0; +#X connect 33 0 0 0; +#X connect 34 0 0 0; +#X connect 35 0 0 0; +#X connect 36 0 0 0; +#X connect 37 0 0 0; +#X connect 38 0 20 0; +#X connect 39 0 38 1; +#X connect 40 0 39 0; +#X connect 41 0 38 0; +#X connect 42 0 38 0; +#X connect 43 0 38 0; +#X connect 44 0 38 0; +#X connect 45 0 38 0; +#X connect 46 0 38 0; +#X connect 47 0 38 0; +#X connect 48 0 38 0; +#X connect 49 0 20 0; +#X connect 50 0 49 1; +#X connect 51 0 50 0; +#X connect 52 0 49 0; +#X connect 53 0 49 0; +#X connect 54 0 49 0; +#X connect 55 0 49 0; +#X connect 56 0 49 0; +#X connect 57 0 49 0; +#X connect 58 0 49 0; +#X connect 59 0 49 0; +#X connect 61 0 60 1; +#X connect 62 0 61 0; +#X connect 63 0 60 0; +#X connect 64 0 60 0; +#X connect 65 0 60 0; +#X connect 66 0 60 0; +#X connect 67 0 60 0; +#X connect 68 0 60 0; +#X connect 69 0 60 0; +#X connect 70 0 60 0; +#X connect 72 0 71 1; +#X connect 73 0 72 0; +#X connect 74 0 71 0; +#X connect 75 0 71 0; +#X connect 76 0 71 0; +#X connect 77 0 71 0; +#X connect 78 0 71 0; +#X connect 79 0 71 0; +#X connect 80 0 71 0; +#X connect 81 0 71 0; +#X connect 83 0 82 1; +#X connect 84 0 83 0; +#X connect 85 0 82 0; +#X connect 86 0 82 0; +#X connect 87 0 82 0; +#X connect 88 0 82 0; +#X connect 89 0 82 0; +#X connect 90 0 82 0; +#X connect 91 0 82 0; +#X connect 92 0 82 0; +#X connect 94 0 93 1; +#X connect 95 0 94 0; +#X connect 96 0 93 0; +#X connect 97 0 93 0; +#X connect 98 0 93 0; +#X connect 99 0 93 0; +#X connect 100 0 93 0; +#X connect 101 0 93 0; +#X connect 102 0 93 0; +#X connect 103 0 93 0; +#X connect 105 0 104 1; +#X connect 106 0 105 0; +#X connect 107 0 104 0; +#X connect 108 0 104 0; +#X connect 109 0 104 0; +#X connect 110 0 104 0; +#X connect 111 0 104 0; +#X connect 112 0 104 0; +#X connect 113 0 104 0; +#X connect 114 0 104 0; diff --git a/rs-disto~.pd b/rs-disto~.pd new file mode 100644 index 0000000..981d235 --- /dev/null +++ b/rs-disto~.pd @@ -0,0 +1,349 @@ +#N canvas 97 16 837 658 10; +#X obj 87 469 outlet~; +#X msg 149 9 preset 1; +#X msg 149 31 preset 2; +#X msg 149 56 preset 3; +#X msg 149 80 preset 4; +#X msg 149 103 preset 5; +#X obj 53 307 inlet~; +#X obj 177 468 tabwrite~ odisto; +#N canvas 0 0 450 300 graph1 0; +#X array odisto 2000 float 1; +#A 0 -0.26708 -0.267659 -0.267773 -0.267663 -0.268063 -0.268941 -0.269679 +-0.269954 -0.270085 -0.270558 -0.27125 -0.271575 -0.271187 -0.270388 +-0.269913 -0.269957 -0.270104 -0.269923 -0.269085 -0.267836 -0.266711 +-0.265669 -0.264553 -0.263606 -0.263061 -0.262861 -0.262675 -0.262145 +-0.261336 -0.260573 -0.26004 -0.25979 -0.259776 -0.260007 -0.260453 +-0.260904 -0.261228 -0.261418 -0.261567 -0.261693 -0.261452 -0.260715 +-0.259912 -0.259345 -0.258913 -0.258407 -0.257621 -0.256502 -0.255412 +-0.255096 -0.255742 -0.256443 -0.256694 -0.257092 -0.257969 -0.259069 +-0.260196 -0.26123 -0.262196 -0.263298 -0.264522 -0.265454 -0.265789 +-0.265929 -0.266428 -0.26689 -0.266694 -0.266317 -0.266395 -0.266645 +-0.266675 -0.266611 -0.266736 -0.266962 -0.267 -0.266981 -0.267214 +-0.267815 -0.268747 -0.2696 -0.269911 -0.269677 -0.269176 -0.268851 +-0.268912 -0.268914 -0.268561 -0.26814 -0.267891 -0.267844 -0.267773 +-0.267341 -0.266582 -0.265804 -0.265366 -0.265358 -0.265496 -0.265834 +-0.26651 -0.267089 -0.267197 -0.266909 -0.266797 -0.267527 -0.268878 +-0.270185 -0.27116 -0.271915 -0.272759 -0.273667 -0.274412 -0.275001 +-0.27547 -0.275987 -0.276591 -0.276781 -0.276323 -0.275748 -0.275574 +-0.275727 -0.275897 -0.275912 -0.275895 -0.276327 -0.277313 -0.277979 +-0.277727 -0.277282 -0.277164 -0.276969 -0.276543 -0.276015 -0.2754 +-0.274914 -0.274748 -0.274519 -0.273811 -0.2729 -0.272283 -0.272013 +-0.271746 -0.271213 -0.270507 -0.269961 -0.269673 -0.269341 -0.268877 +-0.268414 -0.267891 -0.267352 -0.266763 -0.266064 -0.265647 -0.265566 +-0.265281 -0.264396 -0.262932 -0.261595 -0.260885 -0.260293 -0.25929 +-0.257585 -0.255305 -0.253139 -0.251284 -0.249837 -0.249084 -0.248607 +-0.247805 -0.246543 -0.245069 -0.243764 -0.242475 -0.240633 -0.237989 +-0.234818 -0.231719 -0.229045 -0.226673 -0.224494 -0.222467 -0.220525 +-0.218764 -0.217348 -0.216235 -0.214923 -0.212796 -0.209895 -0.206839 +-0.204027 -0.201527 -0.199378 -0.197445 -0.19561 -0.193997 -0.192592 +-0.191229 -0.189718 -0.187899 -0.185764 -0.183251 -0.180503 -0.177968 +-0.175848 -0.173948 -0.171912 -0.16965 -0.167457 -0.165405 -0.163236 +-0.160912 -0.158465 -0.155786 -0.153114 -0.150846 -0.148812 -0.146713 +-0.144673 -0.142764 -0.140666 -0.13805 -0.135212 -0.132744 -0.130552 +-0.128217 -0.1258 -0.123439 -0.120903 -0.117935 -0.114675 -0.111333 +-0.107887 -0.10454 -0.101492 -0.0985705 -0.0956639 -0.092911 -0.0906006 +-0.0887248 -0.0867019 -0.0840825 -0.0809534 -0.0775766 -0.0740247 -0.070271 +-0.0665755 -0.0632598 -0.0602591 -0.0572601 -0.0539264 -0.0501022 -0.0462753 +-0.0432218 -0.0408681 -0.0384562 -0.0356554 -0.0326975 -0.0297458 -0.0264714 +-0.0226953 -0.0189905 -0.0158314 -0.0129583 -0.00992077 -0.006587 -0.00317483 +-0.000170271 0.00229779 0.00464803 0.00721599 0.0100859 0.0130355 0.0159059 +0.0189153 0.022138 0.0254052 0.028593 0.0318781 0.0354225 0.0388125 +0.041718 0.0444737 0.0475818 0.0510936 0.054507 0.057465 0.0602617 +0.0631991 0.0661021 0.0689534 0.0719189 0.0750332 0.0784235 0.0819329 +0.0854564 0.0890724 0.0924396 0.0954562 0.098226 0.100836 0.103648 +0.106636 0.109676 0.112982 0.116417 0.119893 0.123406 0.126536 0.129097 +0.131271 0.133429 0.135833 0.138202 0.140347 0.14245 0.144688 0.147011 +0.149205 0.15138 0.153773 0.156286 0.158841 0.161446 0.164034 0.166742 +0.169614 0.172283 0.174349 0.17591 0.177754 0.180279 0.182867 0.185162 +0.187412 0.189872 0.192601 0.195232 0.197485 0.199546 0.201768 0.204144 +0.206174 0.207815 0.209428 0.211006 0.212441 0.213705 0.214928 0.216237 +0.217766 0.219741 0.221722 0.223089 0.224116 0.225337 0.226729 0.227758 +0.228216 0.228675 0.22939 0.230035 0.230542 0.231047 0.231827 0.233027 +0.234295 0.235417 0.236317 0.23679 0.236896 0.23694 0.237237 0.237881 +0.238629 0.239307 0.239995 0.240721 0.24144 0.242192 0.243171 0.244484 +0.245695 0.24654 0.247529 0.248852 0.250142 0.251325 0.252652 0.254384 +0.256341 0.25797 0.259165 0.260237 0.261247 0.262037 0.262577 0.263105 +0.263864 0.264588 0.264886 0.265002 0.265396 0.266151 0.267097 0.268057 +0.268906 0.269509 0.269879 0.270139 0.270324 0.270709 0.271559 0.272587 +0.273495 0.274237 0.274801 0.275454 0.276392 0.277454 0.278621 0.279744 +0.280669 0.281482 0.281956 0.282112 0.282319 0.28269 0.283387 0.28435 +0.285342 0.286491 0.287864 0.289279 0.290437 0.291215 0.291987 0.292999 +0.294054 0.29496 0.295644 0.296266 0.297002 0.297657 0.298119 0.298521 +0.299077 0.300061 0.301543 0.303172 0.304387 0.30505 0.305493 0.305954 +0.306373 0.306843 0.307805 0.309191 0.310435 0.311297 0.31185 0.312321 +0.312821 0.313274 0.313723 0.31416 0.314671 0.315332 0.315916 0.316495 +0.317263 0.318092 0.318635 0.318368 0.31737 0.316202 0.31487 0.313304 +0.311569 0.309675 0.307999 0.306836 0.306097 0.30543 0.304414 0.303255 +0.302409 0.301928 0.301785 0.301895 0.302158 0.30259 0.302976 0.302958 +0.302395 0.301419 0.300219 0.298894 0.297635 0.296575 0.29564 0.294797 +0.294115 0.293699 0.293627 0.293838 0.294015 0.293818 0.293335 0.292805 +0.292195 0.291567 0.290985 0.290239 0.289184 0.287888 0.286705 0.285863 +0.285138 0.28429 0.283133 0.281738 0.280465 0.279229 0.277755 0.276089 +0.274151 0.271899 0.269585 0.267458 0.265824 0.264746 0.263793 0.262516 +0.260886 0.259367 0.258111 0.256866 0.255784 0.25474 0.253198 0.251293 +0.249632 0.248461 0.247448 0.246263 0.244935 0.243536 0.242133 0.240709 +0.239106 0.237425 0.23605 0.235135 0.23424 0.232885 0.231229 0.229657 +0.228392 0.227415 0.226439 0.225406 0.224468 0.223602 0.222691 0.221352 +0.219332 0.216988 0.214684 0.212667 0.210812 0.208681 0.206372 0.203835 +0.200758 0.197397 0.194213 0.191612 0.189638 0.187898 0.186069 0.183983 +0.182057 0.180838 0.180003 0.179099 0.17805 0.176769 0.175117 0.172857 +0.169997 0.167006 0.164326 0.162073 0.160094 0.158136 0.156023 0.153598 +0.150921 0.148421 0.146236 0.144047 0.142044 0.140806 0.140162 0.139427 +0.138327 0.136841 0.134884 0.132719 0.130705 0.128635 0.126181 0.123419 +0.12071 0.11838 0.11634 0.114367 0.112656 0.111487 0.110742 0.109904 +0.108587 0.107225 0.106379 0.1059 0.10524 0.104039 0.102601 0.101234 +0.0994895 0.0971318 0.0944816 0.0916963 0.0888986 0.0859872 0.0826179 +0.0789733 0.0755323 0.072549 0.069849 0.0669985 0.0642158 0.062126 +0.0608327 0.0598513 0.0585596 0.0569368 0.0554447 0.0543066 0.0532107 +0.0514894 0.0489487 0.0463233 0.044406 0.0430643 0.0415634 0.0397923 +0.038182 0.0364309 0.0341317 0.0317625 0.0296438 0.027509 0.025305 +0.0233969 0.0219949 0.0207145 0.0191473 0.0172301 0.0151133 0.013269 +0.0119967 0.0109929 0.00987112 0.00847854 0.00662015 0.00422399 0.00178499 +-4.51909e-05 -0.00127923 -0.00244447 -0.00409475 -0.00660254 -0.00976168 +-0.0128603 -0.015249 -0.0169854 -0.0187953 -0.021044 -0.0235007 -0.0259382 +-0.028343 -0.0309557 -0.0339662 -0.0371732 -0.0403194 -0.0434447 -0.0467169 +-0.04999 -0.0529932 -0.055748 -0.0583544 -0.0609852 -0.0637931 -0.0666124 +-0.0692497 -0.0717844 -0.0745041 -0.0774464 -0.0801579 -0.0823805 -0.0843732 +-0.0864587 -0.0887887 -0.0912798 -0.0939585 -0.0971554 -0.100665 -0.103826 +-0.106431 -0.108576 -0.110698 -0.113375 -0.1165 -0.119544 -0.122029 +-0.124057 -0.126174 -0.128125 -0.12965 -0.13144 -0.133778 -0.136296 +-0.138863 -0.141337 -0.143518 -0.14551 -0.14751 -0.149549 -0.151428 +-0.153072 -0.15461 -0.155989 -0.157365 -0.159025 -0.160831 -0.162686 +-0.164618 -0.166511 -0.168361 -0.170065 -0.171328 -0.172153 -0.172704 +-0.173265 -0.174136 -0.175203 -0.176386 -0.177682 -0.178703 -0.179222 +-0.179609 -0.180324 -0.181603 -0.183362 -0.185256 -0.187043 -0.188578 +-0.189993 -0.191608 -0.193295 -0.19481 -0.196331 -0.198017 -0.199753 +-0.20136 -0.202718 -0.203864 -0.204768 -0.205365 -0.205876 -0.206719 +-0.20814 -0.209633 -0.210398 -0.210418 -0.210391 -0.211039 -0.212329 +-0.213633 -0.214896 -0.21649 -0.21832 -0.220031 -0.221472 -0.222763 +-0.224144 -0.225502 -0.226554 -0.227404 -0.228308 -0.229294 -0.230278 +-0.231077 -0.23163 -0.232241 -0.232997 -0.233798 -0.234634 -0.23527 +-0.235657 -0.236139 -0.236958 -0.238334 -0.240207 -0.241985 -0.243241 +-0.243839 -0.244195 -0.244781 -0.245094 -0.245249 -0.245878 -0.24671 +-0.247417 -0.247736 -0.247701 -0.247682 -0.247737 -0.248194 -0.249232 +-0.250298 -0.251199 -0.252196 -0.25324 -0.253831 -0.253895 -0.254209 +-0.254853 -0.255181 -0.255042 -0.254884 -0.254926 -0.254162 -0.252799 +-0.252477 -0.252702 -0.252552 -0.25226 -0.251876 -0.25148 -0.251157 +-0.251159 -0.25156 -0.251571 -0.251431 -0.252436 -0.253917 -0.254709 +-0.255157 -0.25613 -0.25763 -0.258282 -0.258523 -0.259267 -0.259174 +-0.258407 -0.257889 -0.257675 -0.257922 -0.257931 -0.257996 -0.258264 +-0.25892 -0.261883 -0.26463 -0.264138 -0.26376 -0.264575 -0.265184 +-0.266336 -0.267409 -0.267822 -0.266942 -0.266393 -0.267595 -0.266748 +-0.264757 -0.263944 -0.263262 -0.265041 -0.268545 -0.269239 -0.266784 +-0.264549 -0.264479 -0.263802 -0.26211 -0.263582 -0.267065 -0.269475 +-0.270978 -0.270394 -0.269201 -0.270115 -0.271682 -0.272462 -0.270975 +-0.268228 -0.267972 -0.268954 -0.269215 -0.267879 -0.265538 -0.265747 +-0.26695 -0.265722 -0.262704 -0.261184 -0.262661 -0.263738 -0.262378 +-0.261077 -0.261745 -0.26286 -0.262206 -0.260193 -0.256853 -0.253664 +-0.254292 -0.254887 -0.253113 -0.252455 -0.252185 -0.252083 -0.251636 +-0.250378 -0.250429 -0.251083 -0.251245 -0.250197 -0.248311 -0.248316 +-0.250481 -0.25172 -0.25036 -0.248913 -0.24947 -0.250491 -0.249688 +-0.247323 -0.246362 -0.246909 -0.247081 -0.247627 -0.248639 -0.249174 +-0.248585 -0.246874 -0.245746 -0.246146 -0.247087 -0.247831 -0.247248 +-0.244618 -0.242451 -0.24337 -0.24585 -0.246548 -0.24485 -0.242945 +-0.242916 -0.244928 -0.246121 -0.243898 -0.241685 -0.241076 -0.239409 +-0.238542 -0.239267 -0.23968 -0.239633 -0.238391 -0.238028 -0.239167 +-0.238772 -0.239485 -0.241619 -0.240941 -0.239006 -0.23768 -0.237419 +-0.238752 -0.23857 -0.236359 -0.234628 -0.234589 -0.236239 -0.236151 +-0.234007; +#A 1000 -0.233151 -0.232566 -0.231177 -0.229258 -0.227183 -0.227228 +-0.227617 -0.225116 -0.222538 -0.222347 -0.223857 -0.223895 -0.219827 +-0.216547 -0.216368 -0.216054 -0.215722 -0.214559 -0.212003 -0.20963 +-0.207424 -0.206119 -0.204874 -0.202757 -0.202116 -0.201593 -0.197969 +-0.194809 -0.195558 -0.196154 -0.194239 -0.191265 -0.187853 -0.185618 +-0.184496 -0.183492 -0.182305 -0.179041 -0.174603 -0.17044 -0.166358 +-0.163546 -0.161854 -0.160624 -0.158786 -0.155308 -0.152192 -0.151414 +-0.15124 -0.148396 -0.142697 -0.137792 -0.137038 -0.137641 -0.135005 +-0.130929 -0.128258 -0.126764 -0.12501 -0.121357 -0.117967 -0.117197 +-0.116285 -0.11336 -0.109174 -0.10519 -0.102996 -0.101146 -0.0986079 +-0.096028 -0.0935584 -0.092103 -0.0909516 -0.0880864 -0.083206 -0.0781496 +-0.0753894 -0.0735017 -0.0700775 -0.0666747 -0.06456 -0.0628634 -0.0596906 +-0.05453 -0.0506355 -0.049393 -0.0486083 -0.0470291 -0.04386 -0.0400564 +-0.0375559 -0.0354427 -0.0326462 -0.0284579 -0.0241831 -0.0231869 -0.0228954 +-0.0193918 -0.0151974 -0.0131444 -0.0120789 -0.00885181 -0.00334882 +-0.000488049 -0.00124724 -0.000826269 0.00269577 0.00816899 0.0125972 +0.0139505 0.015662 0.0197424 0.0238507 0.0261824 0.0274073 0.0296689 +0.0327018 0.0354039 0.0381678 0.0418735 0.0471356 0.0513068 0.0524804 +0.052739 0.0542056 0.0578076 0.0615656 0.0639498 0.0670369 0.0705633 +0.0735998 0.0770429 0.0802246 0.0831852 0.0858242 0.0876192 0.0902116 +0.0936297 0.0971528 0.10107 0.103717 0.104464 0.104406 0.10519 0.108577 +0.11268 0.11614 0.119239 0.121048 0.122739 0.124522 0.125989 0.128996 +0.133007 0.136894 0.140435 0.143467 0.146747 0.149152 0.150424 0.152439 +0.155326 0.158756 0.162286 0.165548 0.168342 0.169027 0.168369 0.169249 +0.171925 0.175741 0.180513 0.184524 0.186305 0.187594 0.191185 0.195745 +0.197635 0.198124 0.200597 0.204669 0.208345 0.211098 0.213641 0.216164 +0.217733 0.218783 0.220983 0.224042 0.227037 0.230287 0.233653 0.235084 +0.234313 0.235109 0.239012 0.242701 0.244361 0.246525 0.250272 0.25411 +0.255897 0.25524 0.255541 0.258263 0.262457 0.266652 0.269534 0.272847 +0.277157 0.279705 0.279503 0.278611 0.279129 0.281444 0.284939 0.288047 +0.289756 0.291121 0.292858 0.294858 0.297389 0.300696 0.304043 0.306559 +0.309312 0.313112 0.316137 0.317521 0.318532 0.319404 0.320956 0.323932 +0.326422 0.327967 0.328359 0.328234 0.330002 0.331075 0.330502 0.331551 +0.334164 0.336528 0.337502 0.339519 0.343138 0.343385 0.341942 0.345137 +0.350613 0.353263 0.355074 0.357987 0.360278 0.361003 0.360899 0.359697 +0.357073 0.357094 0.3612 0.364872 0.366239 0.367065 0.367359 0.367487 +0.370281 0.374995 0.377113 0.375402 0.373893 0.375784 0.378692 0.379707 +0.378632 0.376485 0.376255 0.378171 0.379984 0.381831 0.382382 0.38122 +0.380453 0.380165 0.38094 0.382664 0.382666 0.380171 0.377955 0.378977 +0.381425 0.382074 0.381313 0.380389 0.380109 0.380732 0.381984 0.383034 +0.382157 0.380766 0.380922 0.379459 0.375111 0.371841 0.370545 0.36898 +0.367916 0.369126 0.37053 0.36945 0.366917 0.364824 0.362867 0.361097 +0.360896 0.361417 0.360585 0.358882 0.357184 0.353876 0.348368 0.344413 +0.345112 0.345563 0.341402 0.337921 0.337485 0.336197 0.334123 0.332985 +0.331907 0.32895 0.325206 0.324924 0.326902 0.325753 0.321737 0.317587 +0.313514 0.310824 0.311441 0.31337 0.312221 0.308256 0.30576 0.305427 +0.304981 0.303626 0.300351 0.295198 0.291245 0.290881 0.293548 0.295234 +0.292051 0.285143 0.278155 0.273595 0.27235 0.273075 0.273481 0.27107 +0.26558 0.260761 0.258523 0.258636 0.259687 0.258633 0.255704 0.253178 +0.251565 0.250427 0.248592 0.244545 0.240821 0.238358 0.234409 0.232209 +0.232456 0.23026 0.225788 0.221606 0.218641 0.216768 0.216123 0.217035 +0.21832 0.217213 0.212238 0.206817 0.203371 0.201033 0.199994 0.199282 +0.197333 0.194419 0.191874 0.189577 0.186936 0.184725 0.182973 0.180792 +0.178151 0.176717 0.176135 0.173983 0.169511 0.163987 0.16068 0.161077 +0.162289 0.161645 0.159045 0.155913 0.153192 0.149358 0.144425 0.140544 +0.13728 0.13542 0.135981 0.13323 0.125881 0.122486 0.124123 0.12313 +0.118366 0.115432 0.115196 0.113423 0.109305 0.105931 0.104971 0.102352 +0.0964158 0.0939342 0.0956731 0.0938349 0.0886857 0.086643 0.0860824 +0.0835724 0.0809018 0.0784262 0.074743 0.0699358 0.0654743 0.0644693 +0.0670738 0.0667907 0.0608345 0.0560668 0.0550274 0.0517716 0.0470288 +0.0461094 0.0464903 0.0437995 0.0394189 0.0369743 0.035492 0.0316002 +0.0277853 0.0261807 0.0236398 0.0198325 0.0167765 0.0148441 0.0128608 +0.00970296 0.00703723 0.00583368 0.00380263 0.000473064 -0.00252255 +-0.00541019 -0.00864094 -0.0111409 -0.0125186 -0.0135007 -0.0143205 +-0.0146019 -0.0148482 -0.0171466 -0.020987 -0.0229116 -0.0231064 -0.0245996 +-0.0276884 -0.0305513 -0.0327162 -0.0351196 -0.0376646 -0.0401182 -0.0426596 +-0.0444322 -0.0457675 -0.0478584 -0.0497565 -0.0506464 -0.0513157 -0.052159 +-0.0539484 -0.0561167 -0.0568429 -0.0573337 -0.0587494 -0.0603145 -0.0619514 +-0.0639226 -0.0669022 -0.0707158 -0.0739696 -0.0772074 -0.0811309 -0.0844747 +-0.0873654 -0.0907039 -0.0933156 -0.0941001 -0.0943444 -0.095617 -0.0974344 +-0.099484 -0.1018 -0.102882 -0.103321 -0.105848 -0.110255 -0.114038 +-0.115846 -0.116748 -0.118123 -0.119961 -0.122312 -0.124746 -0.126659 +-0.128236 -0.127689 -0.125448 -0.126103 -0.12984 -0.133319 -0.134342 +-0.133867 -0.135798 -0.139161 -0.141429 -0.144191 -0.145866 -0.145907 +-0.147306 -0.149892 -0.153489 -0.155841 -0.155249 -0.15612 -0.158146 +-0.157869 -0.156883 -0.157486 -0.159411 -0.160146 -0.160931 -0.164545 +-0.167303 -0.166925 -0.167136 -0.170044 -0.17438 -0.177245 -0.177154 +-0.176848 -0.177855 -0.179501 -0.182723 -0.187023 -0.189608 -0.189674 +-0.188992 -0.189324 -0.191281 -0.193741 -0.195296 -0.195369 -0.193301 +-0.191879 -0.194567 -0.198013 -0.199268 -0.199752 -0.199488 -0.199473 +-0.201463 -0.204911 -0.208248 -0.208627 -0.205791 -0.203813 -0.205502 +-0.209768 -0.213233 -0.213537 -0.211242 -0.209762 -0.210589 -0.212065 +-0.214414 -0.217509 -0.218825 -0.21755 -0.216575 -0.218297 -0.220953 +-0.221919 -0.222 -0.222716 -0.223324 -0.224083 -0.225504 -0.225747 +-0.22421 -0.223129 -0.22334 -0.223363 -0.223819 -0.226083 -0.228188 +-0.228343 -0.227315 -0.22695 -0.228393 -0.230022 -0.230815 -0.232001 +-0.232692 -0.231958 -0.231828 -0.233017 -0.234158 -0.234324 -0.234582 +-0.236492 -0.23755 -0.236831 -0.238344 -0.24147 -0.243434 -0.244738 +-0.245636 -0.246112 -0.245377 -0.244503 -0.246052 -0.248095 -0.248097 +-0.246671 -0.245189 -0.245102 -0.246481 -0.247893 -0.248335 -0.247514 +-0.246449 -0.245922 -0.245682 -0.246598 -0.248263 -0.248967 -0.248829 +-0.24816 -0.24748 -0.246923 -0.24558 -0.245254 -0.246168 -0.245029 +-0.242549 -0.241186 -0.241762 -0.24368 -0.244018 -0.243866 -0.245271 +-0.244062 -0.239965 -0.238904 -0.241356 -0.242091 -0.239899 -0.23877 +-0.238927 -0.237334 -0.236052 -0.237747 -0.238291 -0.233767 -0.228659 +-0.227553 -0.227043 -0.225269 -0.225544 -0.227385 -0.226236 -0.22154 +-0.218968 -0.221037 -0.222556 -0.220614 -0.219152 -0.220012 -0.219519 +-0.217602 -0.218801 -0.220957 -0.218647 -0.214792 -0.214112 -0.21522 +-0.213766 -0.210293 -0.210031 -0.209338 -0.203426 -0.199947 -0.202385 +-0.204352 -0.203511 -0.20268 -0.203071 -0.201417 -0.197239 -0.196734 +-0.200169 -0.201207 -0.198635 -0.195482 -0.193122 -0.190594 -0.188472 +-0.1884 -0.189048 -0.188209 -0.186508 -0.186198 -0.186368 -0.184437 +-0.181724 -0.180083 -0.178512 -0.177677 -0.179502 -0.1818 -0.18054 +-0.176895 -0.175291 -0.175508 -0.175358 -0.175918 -0.177403 -0.177107 +-0.174243 -0.171687 -0.170536 -0.169344 -0.168906 -0.169992 -0.170334 +-0.168262 -0.165975 -0.16621 -0.166189 -0.162635 -0.158982 -0.157627 +-0.156921 -0.156462 -0.156192 -0.155766 -0.153264 -0.14937 -0.1486 +-0.149288 -0.148866 -0.149764 -0.151418 -0.150841 -0.146987 -0.143179 +-0.142844 -0.142361 -0.140405 -0.140584 -0.14176 -0.141941 -0.141421 +-0.140756 -0.140163 -0.138007 -0.136409 -0.138076 -0.139307 -0.13895 +-0.139289 -0.139026 -0.137142 -0.136061 -0.138299 -0.142194 -0.143127 +-0.14174 -0.142156 -0.143001 -0.14211 -0.141021 -0.14012 -0.13871 -0.137428 +-0.138223 -0.140831 -0.140916 -0.137712 -0.134516 -0.131997 -0.130671 +-0.13108 -0.132343 -0.133538 -0.1325 -0.129983 -0.128205 -0.126336 +-0.124934 -0.124084 -0.123517 -0.124253 -0.124134 -0.121727 -0.11916 +-0.118518 -0.119372 -0.119263 -0.11808 -0.118028 -0.118947 -0.119155 +-0.119376 -0.120386 -0.120797 -0.119504 -0.117742 -0.117604 -0.118196 +-0.117564 -0.116427 -0.115047 -0.112277 -0.109151 -0.107823 -0.108153 +-0.108001 -0.106851 -0.106133 -0.105341 -0.103449 -0.10225 -0.102543 +-0.102643 -0.101744 -0.100163 -0.0989409 -0.0985816 -0.0983467 -0.0977372 +-0.0962336 -0.0939372 -0.0920292 -0.0910775 -0.0912255 -0.0922101 -0.0922327 +-0.0905764 -0.088414 -0.0861316 -0.0849861 -0.0859358 -0.0866984 -0.085469 +-0.082363 -0.0791981 -0.0784002 -0.0789486 -0.0792314 -0.0791902 -0.0784253 +-0.0780597 -0.0787439 -0.0790283 -0.0785446 -0.0774918 -0.0761877 -0.074771 +-0.0732108 -0.0728679 -0.0734066 -0.0736221 -0.0735405 -0.0728323 -0.0720006 +-0.0711169 -0.0703422 -0.0706587 -0.0712593 -0.0715813 -0.0713705 -0.0696971 +-0.067587 -0.065892 -0.0648743 -0.0655384 -0.0659984 -0.0640801 -0.0604196 +-0.0561824 -0.0529379 -0.051625 -0.0522934 -0.0530088 -0.0504143 -0.0461285 +-0.0434267 -0.0418044 -0.0416196 -0.0432084 -0.0442318 -0.0422415 -0.0370414 +-0.0328587 -0.0324699 -0.0334087 -0.0345388 -0.035246 -0.0336549 -0.0303687 +-0.0274198 -0.0264446 -0.0272249 -0.0270482 -0.0256714 -0.0251707 -0.0246116 +-0.0231644 -0.0228445 -0.024125 -0.0244141 -0.0223641 -0.0202823 -0.0195197 +-0.0189773 -0.019408 -0.0209408 -0.0204265 -0.0171791 -0.0140059 -0.0129334 +-0.0139812 -0.0153043 -0.0155131 -0.0147108 -0.012386 -0.00872585 -0.00597713 +-0.00589554 -0.00785846 -0.00965299 -0.0102252 -0.00991027 -0.00770097 +-0.00405239 -0.00314322 -0.00636492 -0.008773 -0.00656921 -0.00314961 +-0.00142149 0.000355286 0.00157009 0.000652503 0.000665672 0.00507241 +0.0103608 0.0112021 0.00941616 0.00791777 0.00581629 0.00400531 0.00527335 +0.00874362 0.00976684 0.00734871 0.00608535; +#X coords 0 2 1999 -2 200 140 1; +#X restore 596 461 graph; +#X msg 177 446 bang; +#X obj 192 229 hsl 128 15 0 25 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 213 263 hsl 128 15 -5 5 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 256 330 hsl 128 15 -10 10 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 380 229 hsl 128 15 0 5 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 407 270 hsl 128 15 0 22500 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X text 256 168 Note : setting a parameter overrides presets; +#X msg 152 128 preset 6; +#X text 216 7 hard distortion 100-10000Hz; +#X text 217 31 hard distortion 100-6000Hz; +#X text 221 80 medium distortion 0.2; +#X text 221 104 medium distortion 0.8; +#X text 223 126 soft distortion 0.8; +#X text 208 247 Dry mix [ -5 - 5 ]; +#X obj 242 297 hsl 128 15 -5 5 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X text 237 279 Wet mix [ -5 - 5 ]; +#X text 402 253 Low pass frequency [ 0 - 22500 ]; +#X obj 441 307 hsl 128 15 0.1 1 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 482 344 hsl 128 15 0 22500 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X obj 517 379 hsl 128 15 0.1 1 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X text 477 327 High pass frequency [ 0 - 22500 ]; +#X text 133 543 Note : see file "distort3.txt" which explains parameters +; +#X text 375 212 Volume [ 0 - 5 ]; +#X text 193 208 Drive [ 0 - 25 ]; +#X text 512 362 High pass Q [ 0.1 - 1 ]; +#X text 436 290 Low pass Q [ 0.1 - 1 ]; +#X text 253 312 Feedback [ -10 - 10 ]; +#X text 218 56 very hard distortion ( default ); +#X obj 87 414 disto~ -------------------------------------------------- +; +#X connect 1 0 37 0; +#X connect 2 0 37 0; +#X connect 3 0 37 0; +#X connect 4 0 37 0; +#X connect 5 0 37 0; +#X connect 6 0 37 0; +#X connect 9 0 7 0; +#X connect 10 0 37 1; +#X connect 11 0 37 2; +#X connect 12 0 37 4; +#X connect 13 0 37 5; +#X connect 14 0 37 6; +#X connect 16 0 37 0; +#X connect 23 0 37 3; +#X connect 26 0 37 7; +#X connect 27 0 37 8; +#X connect 28 0 37 9; +#X connect 37 0 0 0; +#X connect 37 0 7 0; diff --git a/rs-scratcher~.pd b/rs-scratcher~.pd new file mode 100644 index 0000000..87b0026 --- /dev/null +++ b/rs-scratcher~.pd @@ -0,0 +1,103 @@ +#N canvas 106 13 862 585 10; +#X msg 36 550 \; pd dsp 1; +#X msg 101 551 \; pd dsp 0; +#X text 24 13 Scratcher~ : lets you record a sound; +#X text 23 24 and \, then \, scratch it !!!; +#X text 599 557 Comments and bugs @ ydegoyon@free.fr; +#X obj 313 260 scratcher~ 151290 200 200 200 2 1e-04; +#X obj 302 475 *~ 1; +#X obj 334 474 / 100; +#X floatatom 373 474 5 0 0; +#X msg 31 88 bang; +#X obj 31 108 openpanel; +#X msg 33 227 resize \$1; +#X obj 31 130 t s b; +#X obj 31 168 pack s s; +#X msg 33 189 read -resize \$1 \$2; +#X obj 77 128 float \$0; +#X obj 100 168 makefilename %d-sonosample; +#X text 32 68 Step 1 : Load a sound file; +#X obj 31 147 route float; +#X text 84 80 ( a small one ); +#X msg 524 45 play; +#X text 522 24 Step 3 : Play the sound and scratch with the mouse; +#X msg 559 45 stop; +#X msg 527 243 reset; +#X text 572 246 Reset normal reading speed; +#X obj 36 524 loadbang; +#X text 469 493 Note : the red line indicates the reading speed; +#X text 446 527 Note 2 : only vertical movement will change reading +speed; +#X obj 176 557 table \$0-sonosample; +#X msg 524 88 sensibility \$1; +#X msg 561 65 25; +#X floatatom 659 66 5 0 0; +#X msg 524 66 5; +#X text 620 88 Set mouse sensibility ( default : 25 ); +#X obj 33 206 soundfiler; +#X msg 607 223 showspeed 1; +#X msg 527 223 showspeed 0; +#X text 687 221 Toggle speed line display; +#X msg 305 119 record; +#X msg 269 119 bang; +#X text 214 98 Step 2 : Record the sound; +#X floatatom 664 120 5 0 0; +#X msg 526 141 maxspeed \$1; +#X text 603 140 Set speed limit ( default : 2 ); +#X msg 526 119 2; +#X msg 569 119 1.5; +#X msg 603 119 1; +#X msg 635 119 0.5; +#X obj 257 146 tabplay~ \$0-sonosample; +#X msg 592 65 100; +#X msg 622 65 200; +#X floatatom 645 174 5 0 0; +#X text 603 193 Set turntable inertia ( default : 0.01 ); +#X msg 525 193 inertia \$1; +#X msg 609 173 0.01; +#X msg 570 173 0.001; +#X msg 526 173 1e-04; +#X obj 289 509 outlet~; +#X connect 5 0 6 0; +#X connect 6 0 57 0; +#X connect 7 0 6 1; +#X connect 8 0 7 0; +#X connect 9 0 10 0; +#X connect 10 0 12 0; +#X connect 11 0 5 0; +#X connect 12 0 13 0; +#X connect 12 1 15 0; +#X connect 13 0 14 0; +#X connect 14 0 34 0; +#X connect 15 0 18 0; +#X connect 16 0 13 1; +#X connect 18 0 16 0; +#X connect 20 0 5 0; +#X connect 22 0 5 0; +#X connect 23 0 5 0; +#X connect 25 0 0 0; +#X connect 29 0 5 0; +#X connect 30 0 29 0; +#X connect 31 0 29 0; +#X connect 32 0 29 0; +#X connect 34 0 11 0; +#X connect 35 0 5 0; +#X connect 36 0 5 0; +#X connect 38 0 5 0; +#X connect 39 0 38 0; +#X connect 39 0 48 0; +#X connect 41 0 42 0; +#X connect 42 0 5 0; +#X connect 44 0 42 0; +#X connect 45 0 42 0; +#X connect 46 0 42 0; +#X connect 47 0 42 0; +#X connect 48 0 5 0; +#X connect 48 0 6 0; +#X connect 49 0 29 0; +#X connect 50 0 29 0; +#X connect 51 0 53 0; +#X connect 53 0 5 0; +#X connect 54 0 53 0; +#X connect 55 0 53 0; +#X connect 56 0 53 0; diff --git a/rs-sonogram~.pd b/rs-sonogram~.pd new file mode 100644 index 0000000..08274ae --- /dev/null +++ b/rs-sonogram~.pd @@ -0,0 +1,311 @@ +#N canvas 7 13 986 674 10; +#X msg 306 57 record; +#X msg 19 34 bang; +#X obj 19 54 openpanel; +#X obj 21 152 soundfiler; +#X msg 259 42 bang; +#X obj 262 101 rfft~; +#X floatatom 59 171 10 0 0 0 - - -; +#X msg 20 211 resize \$1; +#X obj 19 74 t s b; +#X obj 22 114 pack s s; +#X msg 21 135 read -resize \$1 \$2; +#X obj 68 74 float \$0; +#X text 21 9 Step 1 : Load a sound file; +#X obj 775 595 table \$0-sonosample; +#X msg 927 588 \; pd dsp 1; +#X msg 484 36 play; +#X obj 262 195 outlet~; +#X text 491 10 Step 3 : Play the recorded sonogram; +#X msg 992 589 \; pd dsp 0; +#X obj 21 171 / 256; +#X obj 486 59 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 460 59 0 %; +#X text 620 58 100 %; +#X obj 487 77 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 461 80 0 %; +#X text 622 76 100 %; +#X msg 661 74 100; +#X obj 691 74 loadbang; +#X text 640 40 Playback positions; +#X obj 783 93 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 756 94 0 %; +#X text 917 92 100 %; +#X obj 784 111 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 756 114 0 %; +#X text 919 110 100 %; +#X text 783 76 Set portion of the sonogram to modify; +#X msg 953 108 100; +#N canvas 656 8 600 544 modifications 1; +#X text 234 236 Filter a frequency; +#X text 254 190 Enhance a frequency by 10% ( might be a range of frequencies +with message 'enhance f1 f2 x' ); +#X text 180 309 Flip frequencies ( dogs love it ); +#X msg 108 265 swappoints 1000; +#X obj 181 134 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 108 153 swapfreqs \$1 \$2; +#X obj 224 152 pack f f; +#X text 220 267 Swap 1000 points ( rain effect ); +#X msg 153 131 \$1; +#X obj 108 131 change; +#X obj 181 114 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 153 111 \$1; +#X obj 108 111 change; +#X obj 180 182 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X obj 180 223 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X text 285 152 Swap two frequencies ( set 2nd \, click 1st ); +#X msg 110 308 flipfreqs; +#X msg 110 330 flipblocks; +#X text 243 286 Swap section [0% \, 20%] and [50% \, 70%] of [start +\, end]; +#X text 188 328 Flip blocks ( reverse effect ); +#X msg 110 287 swapblocks 0 50 20; +#X text 228 66 Move frequencies up or down; +#X msg 110 91 roll 2; +#X msg 112 350 zswap; +#X text 364 374 Change the phase; +#X text 180 350 Exchange real and imaginery parts ( noisy filter ) +; +#X msg 113 374 phase \$1; +#X obj 200 373 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 184 373 0; +#X text 339 374 90; +#X obj 187 415 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 113 429 add \$1 \$1 0.5; +#X text 216 429 Add a constant to a frequency; +#X obj 189 451 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 115 466 add \$1 \$1 -0.5; +#X text 218 465 Sub a constant from a frequency; +#X text 198 393 Average over 100 blocks ( smooth with some sounds ) +; +#X obj 16 454 outlet; +#X msg 109 69 goup 1; +#X msg 159 69 godown 5; +#X msg 107 198 enhance \$1 \$1 1.1 0; +#X msg 116 488 threshold \$1; +#X floatatom 208 489 5 0 0 0 - - -; +#X msg 107 239 enhance \$1 \$1 0 0; +#X text 249 488 Suppress all points below the threshold; +#X text 159 91 Roll frequencies : same as above but without loss; +#X msg 113 395 average 10; +#X connect 3 0 37 0; +#X connect 4 0 8 0; +#X connect 5 0 37 0; +#X connect 6 0 5 0; +#X connect 8 0 9 0; +#X connect 9 0 6 1; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 12 0 6 0; +#X connect 13 0 40 0; +#X connect 14 0 43 0; +#X connect 16 0 37 0; +#X connect 17 0 37 0; +#X connect 20 0 37 0; +#X connect 22 0 37 0; +#X connect 23 0 37 0; +#X connect 26 0 37 0; +#X connect 27 0 26 0; +#X connect 30 0 31 0; +#X connect 31 0 37 0; +#X connect 33 0 34 0; +#X connect 34 0 37 0; +#X connect 38 0 37 0; +#X connect 39 0 37 0; +#X connect 40 0 37 0; +#X connect 41 0 37 0; +#X connect 42 0 41 0; +#X connect 43 0 37 0; +#X connect 46 0 37 0; +#X restore 861 131 pd modifications; +#X text 513 609 Zoom factor (>1); +#X msg 418 608 zoom 2; +#X obj 256 79 tabplay~ \$0-sonosample; +#X obj 114 263 sonogram~ 2452 1 1; +#X msg 467 608 zoom 1; +#X msg 484 99 readspeed \$1; +#X floatatom 617 99 5 0 0 0 - - -; +#X text 487 121 Reading speed; +#X obj 576 99 / 100; +#X msg 661 99 100; +#X obj 692 99 loadbang; +#X msg 779 167 play; +#X msg 780 186 open /tmp/sonogram.wav; +#X obj 779 229 writesf~ 2; +#X msg 780 207 start; +#X msg 822 207 stop; +#X msg 418 652 modstep \$1; +#X floatatom 499 652 5 0 0 0 - - -; +#X obj 525 36 spigot; +#X obj 573 36 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 +; +#X text 600 37 Loop; +#X text 70 547 Mouse modifications :; +#X text 557 656 ( default = 1.1 ); +#X text 558 646 Value added or multiplied ( can be < 0 ); +#X obj 527 588 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X obj 19 93 route float; +#X msg 418 587 enhancemode \$1; +#X text 821 166 Record; +#X text 89 562 Normal mode; +#X text 30 579 click :; +#X text 128 579 add modstep to the selected data; +#X text 43 590 click :; +#X text 161 590 erase selected data; +#X text 154 645 erase selected data; +#X text 88 615 Enhanced mode; +#X text 2 600 click :; +#X text 162 601 paste selected data; +#X text 129 656 add selected data at the new location; +#X text 483 546 Graphic actions; +#X text 128 632 multiply the selected data by modstep; +#X obj 980 109 loadbang; +#X text 73 21 ( a small one ); +#X text 417 569 Activate enhance mode; +#X text 785 57 Step 4 : modify parts of the sonogram; +#X obj 260 126 rifft~; +#X msg 418 630 refresh; +#X text 239 10 Step 2 : Record the sonogram; +#X obj 927 565 loadbang; +#N canvas 0 1 682 488 envelop 0; +#X obj 33 400 outlet; +#X obj 46 327 tabread envelop; +#X msg 23 263 bang; +#X floatatom 23 299 5 0 0 0 - - -; +#X obj 71 280 + 1; +#X msg 23 281 0; +#X text 25 239 Apply envelop; +#X obj 68 300 delay 1000; +#X obj 136 300 f; +#X obj 34 354 pack f f; +#X obj 368 349 loadbang; +#X msg 425 349 bang; +#X msg 370 374 \; envelop const 1; +#X msg 203 381 refresh; +#X floatatom 160 280 5 0 0 0 - - -; +#X msg 163 300 bang; +#X obj 98 280 moses 127; +#X msg 485 347 bang; +#X msg 486 372 \; envelop const 0.001; +#X msg 33 377 enhance \$1 \$1 \$2 1; +#X obj 202 358 delay 1000; +#N canvas 0 0 450 300 graph2 0; +#X array envelop 64 float 1; +#A 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1; +#X coords 0 10 63 0 300 200 1; +#X restore 151 12 graph; +#X connect 1 0 9 1; +#X connect 2 0 5 0; +#X connect 3 0 1 0; +#X connect 3 0 8 1; +#X connect 3 0 7 0; +#X connect 3 0 9 0; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 7 0 8 0; +#X connect 8 0 16 0; +#X connect 9 0 19 0; +#X connect 10 0 12 0; +#X connect 11 0 12 0; +#X connect 13 0 0 0; +#X connect 14 0 15 0; +#X connect 15 0 20 0; +#X connect 16 0 4 0; +#X connect 16 1 14 0; +#X connect 17 0 18 0; +#X connect 19 0 0 0; +#X connect 20 0 13 0; +#X restore 780 131 pd envelop; +#X obj 310 174 / 100; +#X floatatom 309 147 5 0 0 0 - - -; +#X obj 263 174 *~ 1; +#X obj 261 149 /~ 256; +#X text 332 129 Volume; +#X text 31 631 click :; +#X text 44 642 click :; +#X text 3 652 click :; +#X msg 488 630 undo; +#X text 526 630 One level undo; +#X obj 21 192 makefilename %d-sonosample; +#X msg 23 264 undo; +#X msg 17 317 zoom 1; +#X obj 829 571 block~ 256; +#X connect 0 0 41 0; +#X connect 1 0 2 0; +#X connect 2 0 8 0; +#X connect 3 0 19 0; +#X connect 4 0 0 0; +#X connect 4 0 40 0; +#X connect 5 0 41 0; +#X connect 5 1 41 1; +#X connect 6 0 7 0; +#X connect 7 0 41 0; +#X connect 8 0 9 0; +#X connect 8 1 11 0; +#X connect 9 0 10 0; +#X connect 10 0 3 0; +#X connect 11 0 63 0; +#X connect 15 0 41 0; +#X connect 19 0 6 0; +#X connect 20 0 41 2; +#X connect 23 0 41 3; +#X connect 26 0 23 0; +#X connect 27 0 26 0; +#X connect 29 0 41 4; +#X connect 32 0 41 5; +#X connect 36 0 32 0; +#X connect 37 0 41 0; +#X connect 39 0 41 0; +#X connect 40 0 5 0; +#X connect 40 0 89 0; +#X connect 41 0 82 0; +#X connect 41 1 82 1; +#X connect 41 3 53 0; +#X connect 41 3 56 0; +#X connect 42 0 41 0; +#X connect 43 0 41 0; +#X connect 44 0 46 0; +#X connect 46 0 43 0; +#X connect 47 0 44 0; +#X connect 48 0 47 0; +#X connect 49 0 41 0; +#X connect 49 0 50 0; +#X connect 49 0 52 0; +#X connect 50 0 51 0; +#X connect 52 0 51 0; +#X connect 53 0 51 0; +#X connect 54 0 41 0; +#X connect 55 0 54 0; +#X connect 56 0 15 0; +#X connect 57 0 56 1; +#X connect 62 0 64 0; +#X connect 63 0 97 0; +#X connect 64 0 41 0; +#X connect 78 0 36 0; +#X connect 82 0 90 0; +#X connect 83 0 41 0; +#X connect 85 0 14 0; +#X connect 86 0 41 0; +#X connect 87 0 89 1; +#X connect 88 0 87 0; +#X connect 89 0 16 0; +#X connect 89 0 51 0; +#X connect 89 0 51 1; +#X connect 90 0 89 0; +#X connect 95 0 41 0; +#X connect 97 0 9 1; +#X connect 98 0 41 0; +#X connect 99 0 41 0; diff --git a/rs-sonograph~.pd b/rs-sonograph~.pd new file mode 100644 index 0000000..a8531fa --- /dev/null +++ b/rs-sonograph~.pd @@ -0,0 +1,217 @@ +#N canvas 0 1 986 654 10; +#X msg 344 51 record; +#X msg 53 30 bang; +#X obj 53 50 openpanel; +#X obj 52 167 soundfiler; +#X msg 297 36 bang; +#X obj 298 99 rfft~; +#X floatatom 90 186 10 0 0; +#X msg 168 185 resize \$1; +#X obj 53 72 t s b; +#X obj 53 129 pack s s; +#X msg 52 150 read -resize \$1 \$2; +#X obj 99 71 float \$0; +#X obj 54 95 route float; +#X obj 52 207 makefilename %d-sonosample; +#X text 57 14 Step 1 : Load a sound file; +#X obj 820 17 table \$0-sonosample; +#X msg 822 43 \; pd dsp 1; +#X obj 121 580 rifft~; +#X msg 340 158 play; +#X obj 822 82 block~ 256; +#X obj 27 607 outlet~; +#X text 346 135 Step 3 : Play the recorded sonogram; +#X msg 887 44 \; pd dsp 0; +#X obj 52 186 / 256; +#X obj 121 607 /~ 256; +#X obj 342 181 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 316 181 0 %; +#X text 476 180 100 %; +#X obj 343 199 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 317 202 0 %; +#X text 478 198 100 %; +#X msg 512 196 100; +#X obj 539 196 loadbang; +#X text 339 217 Playback positions; +#X obj 697 184 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 671 184 0 %; +#X text 831 183 100 %; +#X obj 698 202 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 672 205 0 %; +#X text 833 201 100 %; +#X text 697 167 Set portion of the sonogram to modify; +#X text 883 183 Start Point; +#X text 883 198 End Point; +#X msg 695 220 100; +#X obj 722 220 loadbang; +#X text 242 15 Step 2 : Record the sonogram; +#N canvas 309 22 600 544 modifications 1; +#X text 234 236 Filter a frequency; +#X msg 107 239 filter \$1 \$1; +#X msg 105 161 enhance \$1 \$1 1.1; +#X msg 106 198 dim \$1 \$1 1.1; +#X text 236 155 Enhance a frequency by 10% ( might be a range of frequencies +with message 'enhance f1 f2 x' ); +#X text 234 198 Dim a frequency by 10 %; +#X text 180 309 Flip frequencies ( dogs love it ); +#X msg 108 265 swappoints 1000; +#X obj 179 97 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 106 116 swapfreqs \$1 \$2; +#X obj 223 116 pack f f; +#X text 218 264 Swap 1000 points ( rain effect ); +#X msg 151 94 \$1; +#X obj 106 94 change; +#X obj 179 77 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 151 74 \$1; +#X obj 106 74 change; +#X obj 178 145 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X obj 179 183 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X obj 180 223 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X text 285 115 Swap two frequencies ( set 2nd \, click 1st ); +#X msg 110 308 flipfreqs; +#X msg 110 330 flipblocks; +#X text 244 286 Swap section [0% \, 20%] and [50% \, 70%] of [start +\, end]; +#X text 185 330 Flip blocks ( reverse effect ); +#X msg 110 287 swapblocks 0 50 20; +#X msg 152 32 godown 1; +#X msg 107 32 goup 2; +#X text 218 32 Move frequencies up or down; +#X msg 108 54 roll 2; +#X text 210 45 Roll frequencies : same as above but without loss ( +circular ); +#X msg 112 350 zswap; +#X text 364 374 Change the phase; +#X text 180 350 Exchange real and imaginery parts ( noisy filter ) +; +#X msg 113 374 phase \$1; +#X obj 200 373 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 184 373 0; +#X text 339 374 90; +#X obj 187 415 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 113 429 add \$1 \$1 0.5; +#X text 216 429 Add a constant to a frequency; +#X obj 189 451 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 +-128992 0; +#X msg 115 466 add \$1 \$1 -0.5; +#X text 218 465 Sub a constant from a frequency; +#X msg 113 395 average 100; +#X text 190 395 Average over 100 blocks ( smooth with some sounds ) +; +#X obj 16 454 outlet; +#X connect 1 0 46 0; +#X connect 2 0 46 0; +#X connect 3 0 46 0; +#X connect 7 0 46 0; +#X connect 8 0 12 0; +#X connect 9 0 46 0; +#X connect 10 0 9 0; +#X connect 12 0 13 0; +#X connect 13 0 10 1; +#X connect 14 0 15 0; +#X connect 15 0 16 0; +#X connect 16 0 10 0; +#X connect 17 0 2 0; +#X connect 18 0 3 0; +#X connect 19 0 1 0; +#X connect 21 0 46 0; +#X connect 22 0 46 0; +#X connect 25 0 46 0; +#X connect 26 0 46 0; +#X connect 27 0 46 0; +#X connect 29 0 46 0; +#X connect 31 0 46 0; +#X connect 34 0 46 0; +#X connect 35 0 34 0; +#X connect 38 0 39 0; +#X connect 39 0 46 0; +#X connect 41 0 42 0; +#X connect 42 0 46 0; +#X connect 44 0 46 0; +#X restore 694 150 pd modifications; +#X obj 298 73 tabplay~ \$0-sonosample; +#X obj 106 329 sonogram~ 256 0; +#X text 538 54 When the sonogram is RED (updating) \,; +#X text 537 43 VERY IMPORTANT NOTE :; +#X text 591 116 Step 4 : modify parts of the sonogram ... and send +a refresh message; +#X msg 337 234 readspeed \$1; +#X floatatom 468 234 5 0 0; +#X text 337 252 Reading speed; +#X obj 428 234 / 100; +#X msg 515 234 100; +#X obj 549 234 loadbang; +#X text 538 66 no update is possible; +#X msg 221 525 play; +#X msg 217 555 open /tmp/sonogram.wav; +#X obj 246 603 writesf~ 2; +#X msg 276 576 start; +#X msg 320 576 stop; +#X floatatom 172 609 5 0 0; +#X obj 436 158 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 +1; +#X text 464 160 Loop; +#X obj 381 159 spigot; +#X connect 0 0 48 0; +#X connect 1 0 2 0; +#X connect 2 0 8 0; +#X connect 3 0 23 0; +#X connect 4 0 0 0; +#X connect 4 0 47 0; +#X connect 5 0 48 0; +#X connect 5 1 48 1; +#X connect 6 0 7 0; +#X connect 7 0 48 0; +#X connect 8 0 9 0; +#X connect 8 1 11 0; +#X connect 9 0 10 0; +#X connect 10 0 3 0; +#X connect 11 0 12 0; +#X connect 12 0 13 0; +#X connect 13 0 9 1; +#X connect 17 0 24 0; +#X connect 18 0 48 0; +#X connect 23 0 6 0; +#X connect 24 0 20 0; +#X connect 24 0 61 0; +#X connect 24 0 61 1; +#X connect 25 0 48 2; +#X connect 28 0 48 3; +#X connect 31 0 28 0; +#X connect 32 0 31 0; +#X connect 34 0 48 4; +#X connect 37 0 48 5; +#X connect 43 0 37 0; +#X connect 44 0 43 0; +#X connect 46 0 48 0; +#X connect 47 0 5 0; +#X connect 47 0 20 0; +#X connect 48 0 17 0; +#X connect 48 1 17 1; +#X connect 48 3 63 0; +#X connect 48 3 67 0; +#X connect 52 0 48 0; +#X connect 53 0 55 0; +#X connect 55 0 52 0; +#X connect 56 0 53 0; +#X connect 57 0 56 0; +#X connect 59 0 48 0; +#X connect 59 0 60 0; +#X connect 59 0 62 0; +#X connect 60 0 61 0; +#X connect 62 0 61 0; +#X connect 63 0 61 0; +#X connect 64 0 24 1; +#X connect 65 0 67 1; +#X connect 67 0 18 0; diff --git a/rs-vocoder~.pd b/rs-vocoder~.pd new file mode 100644 index 0000000..65dfc0d --- /dev/null +++ b/rs-vocoder~.pd @@ -0,0 +1,13 @@ +#N canvas 0 0 450 300 10; +#X obj 39 146 block~ 512; +#X obj 89 36 inlet~; +#X obj 151 34 inlet~; +#X obj 129 77 vocoder~; +#X obj 207 33 inlet; +#X obj 261 33 inlet; +#X obj 129 108 outlet~; +#X connect 1 0 3 0; +#X connect 2 0 3 1; +#X connect 3 0 6 0; +#X connect 4 0 3 2; +#X connect 5 0 3 3; diff --git a/rs-wahwah~.pd b/rs-wahwah~.pd new file mode 100644 index 0000000..af5c256 --- /dev/null +++ b/rs-wahwah~.pd @@ -0,0 +1,348 @@ +#N canvas 97 16 837 658 10; +#X obj 87 469 outlet~; +#X msg 149 24 preset 1; +#X msg 149 46 preset 2; +#X msg 149 71 preset 3; +#X msg 149 95 preset 4; +#X msg 149 118 preset 5; +#X text 216 25 fast change medium wah-wah; +#X text 217 46 slow change medium wah-wah; +#X text 219 71 fast wah-wah; +#X text 219 94 ranged wah-wah; +#X obj 53 307 inlet~; +#X text 220 117 wah-wah 400/2000 Hz; +#X obj 177 468 tabwrite~ owahwah; +#N canvas 0 0 450 300 graph1 0; +#X array owahwah 2000 float 1; +#A 0 -0.039093 -0.0409546 -0.0498657 -0.0647583 -0.0871887 -0.115601 +-0.149658 -0.186188 -0.222839 -0.259918 -0.295898 -0.328308 -0.356567 +-0.380859 -0.399689 -0.412933 -0.419983 -0.419434 -0.410675 -0.392517 +-0.365753 -0.331726 -0.29129 -0.245361 -0.196503 -0.148499 -0.103546 +-0.0623779 -0.0287476 -0.00424194 0.00881958 0.0116577 0.00469971 -0.0116577 +-0.0361023 -0.0664978 -0.100555 -0.136414 -0.172302 -0.205841 -0.235596 +-0.261932 -0.283508 -0.299713 -0.311584 -0.318848 -0.321991 -0.322968 +-0.322998 -0.322662 -0.321503 -0.321228 -0.321503 -0.321747 -0.322876 +-0.323883 -0.324463 -0.324066 -0.320892 -0.31308 -0.299133 -0.277191 +-0.244019 -0.198334 -0.139526 -0.0670471 0.0205078 0.121002 0.230194 +0.344482 0.460846 0.573944 0.677521 0.765656 0.833282 0.876801 0.893036 +0.882629 0.846802 0.78891 0.714539 0.629425 0.539551 0.452789 0.374146 +0.307892 0.257263 0.222931 0.204132 0.19812 0.20163 0.210175 0.21933 +0.225739 0.22525 0.214874 0.194916 0.164948 0.12674 0.0838013 0.0399475 +-0.00134277 -0.0376587 -0.0657654 -0.0814819 -0.0820007 -0.0656738 +-0.0337219 0.0140381 0.0779724 0.156006 0.245911 0.346008 0.452057 +0.559235 0.663025 0.757202 0.837769 0.896179 0.925873 0.922516 0.882751 +0.806122 0.694183 0.55191 0.387329 0.210052 0.0307922 -0.138519 -0.286224 +-0.401611 -0.480316 -0.519104 -0.516846 -0.47644 -0.40213 -0.299652 +-0.175842 -0.0374451 0.108887 0.257507 0.401276 0.536102 0.658722 0.767181 +0.857239 0.927002 0.974548 0.99762 0.995697 0.969116 0.919312 0.852112 +0.772278 0.684723 0.5961 0.511749 0.437042 0.374969 0.326416 0.289948 +0.260529 0.233032 0.201965 0.157501 0.0927124 0.00149536 -0.120087 +-0.272583 -0.452911 -0.653748 -0.863739 -1 -1 -1 -1 -1 -1 -1 -1 -1 +-0.973389 -0.805054 -0.654327 -0.533722 -0.449554 -0.403442 -0.390808 +-0.404175 -0.431488 -0.458344 -0.471954 -0.461639 -0.419342 -0.340942 +-0.226868 -0.0821228 0.0829468 0.257294 0.426544 0.577087 0.695618 +0.771759 0.798157 0.771332 0.692352 0.566376 0.402252 0.209686 -0.00247192 +-0.22171 -0.43985 -0.650452 -0.847473 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.739136 +-0.431183 -0.0951538 0.245636 0.56543 0.838531 0.999969 0.999969 0.999969 +0.999969 0.999969 0.802216 0.559937 0.29715 0.0325623 -0.217773 -0.442688 +-0.636414 -0.795715 -0.92099 -1 -1 -1 -1 -1 -1 -1 -0.950989 -0.852966 +-0.744476 -0.634064 -0.530029 -0.443756 -0.384125 -0.356415 -0.362183 +-0.400238 -0.46228 -0.535309 -0.604767 -0.653046 -0.661835 -0.615387 +-0.499878 -0.308197 -0.0406799 0.294312 0.67923 0.999969 0.999969 0.999969 +0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.966919 +0.579712 0.242889 -0.0168762 -0.183319 -0.249573 -0.221954 -0.117706 +0.0397949 0.221771 0.399139 0.544708 0.6362 0.657806 0.601624 0.468964 +0.27002 0.0221863 -0.252197 -0.526459 -0.774719 -0.97522 -1 -1 -1 -1 +-0.943573 -0.758942 -0.54248 -0.306366 -0.0611267 0.189514 0.443115 +0.697449 0.950439 0.999969 0.999969 0.999969 0.999969 0.964325 0.130615 +-0.55246 -1 -1 -1 -1 -0.892181 -0.560394 -0.220734 0.0826416 0.317352 +0.468048 0.532959 0.52005 0.447357 0.337616 0.211273 0.0874939 -0.0170288 +-0.0913391 -0.131683 -0.139923 -0.121124 -0.0817871 -0.0301208 0.024353 +0.0731506 0.110504 0.135773 0.148865 0.149841 0.140442 0.124298 0.106171 +0.0886841 0.0727234 0.059021 0.0523376 0.0513 0.0559692 0.0643921 0.0751648 +0.0877991 0.100708 0.112091 0.121948 0.129303 0.135132 0.138153 0.14032 +0.140869 0.138428 0.133514 0.126801 0.11853 0.109406 0.0989685 0.0881042 +0.0773621 0.0661926 0.0561829 0.0480652 0.0427246 0.0401917 0.0408325 +0.0447388 0.0513611 0.0603638 0.0705261 0.0811157 0.0899658 0.0986023 +0.109009 0.120209 0.129822 0.13736 0.143433 0.147369 0.147949 0.144257 +0.136719 0.125061 0.11264 0.098175 0.0823669 0.0648804 0.0462036 0.0277405 +0.0106812 -0.00558472 -0.0222473 -0.0386353 -0.0551147 -0.0707397 -0.0862732 +-0.100494 -0.114716 -0.129669 -0.144409 -0.158783 -0.17392 -0.188385 +-0.202057 -0.214661 -0.228119 -0.240845 -0.252014 -0.262207 -0.269958 +-0.2742 -0.275787 -0.275604 -0.273346 -0.268707 -0.26062 -0.249481 +-0.234894 -0.216797 -0.196503 -0.174866 -0.1521 -0.129639 -0.108246 +-0.0873108 -0.0687561 -0.0557556 -0.0469055 -0.0423889 -0.0438843 -0.052002 +-0.0664673 -0.0872803 -0.114227 -0.145477 -0.179688 -0.217499 -0.255646 +-0.293396 -0.329254 -0.361755 -0.387848 -0.407257 -0.419189 -0.423859 +-0.421204 -0.410278 -0.390991 -0.363373 -0.32843 -0.288849 -0.245178 +-0.199188 -0.151886 -0.106201 -0.0655518 -0.0318909 -0.00665283 0.00817871 +0.0127258 0.00680542 -0.00918579 -0.0333862 -0.0639954 -0.0982666 -0.134338 +-0.170715 -0.205658 -0.237183 -0.263855 -0.28479 -0.300812 -0.31189 +-0.319458 -0.324249 -0.325256 -0.324219 -0.322723 -0.320953 -0.319489 +-0.319427 -0.319794 -0.32132 -0.323334 -0.325684 -0.325531 -0.321503 +-0.31308 -0.298218 -0.275696 -0.2435 -0.198578 -0.140106 -0.0680542 +0.0185242 0.117798 0.226654 0.342102 0.459686 0.574188 0.679474 0.769562 +0.838745 0.882385 0.899384 0.889221 0.853149 0.795837 0.721283 0.636169 +0.547119 0.459595 0.379211 0.31076 0.25708 0.219452 0.197266 0.188873 +0.192383 0.202209 0.213013 0.220642 0.221832 0.213165 0.19397 0.16626 +0.13089 0.088623 0.0440369 0.000915527 -0.0377197 -0.0675049 -0.0849304 +-0.0869141 -0.0715332 -0.0384521 0.0113525 0.0761108 0.153351 0.243347 +0.34433 0.450195 0.559174 0.665131 0.762085 0.843048 0.900848 0.930298 +0.927399 0.887878 0.810791 0.698273 0.555084 0.390106 0.211395 0.0317383 +-0.137634 -0.286163 -0.404236 -0.485474 -0.526031 -0.525208 -0.485352 +-0.40918 -0.304932 -0.179535 -0.0396118 0.107544 0.255615 0.399872 +0.536102 0.660431 0.770782 0.86261 0.9328 0.980865 0.999969 0.999969 +0.974121 0.92453 0.856995 0.77594 0.6875 0.598267 0.51413 0.439209 +0.374847 0.322754 0.283844 0.25415 0.227539 0.196381 0.153137 0.0905762 +0.00128174 -0.119019 -0.271637 -0.452423 -0.653564 -0.863922 -1 -1 +-1 -1 -1 -1 -1 -1 -1 -0.983398 -0.81308 -0.660461 -0.537537 -0.450836 +-0.401978 -0.387848 -0.399719 -0.425385 -0.452332 -0.466919 -0.458435 +-0.417389 -0.341614 -0.229828 -0.0864868 0.0791321 0.254517 0.425201 +0.577057 0.696777 0.775177 0.805115 0.779572 0.700653 0.57431 0.409943 +0.216797 0.00445557 -0.216492 -0.4375 -0.651215 -0.849945 -1 -1 -1 +-1 -1 -1 -1 -1 -1 -0.74588 -0.435699 -0.0969238 0.246063 0.567993 0.84314 +0.999969 0.999969 0.999969 0.999969 0.999969 0.809875 0.567505 0.303864 +0.0378418 -0.21463 -0.440674 -0.63559 -0.796692 -0.923798 -1 -1 -1 +-1 -1 -1 -1 -0.955811 -0.856628 -0.747009 -0.635651 -0.53183 -0.44516 +-0.384369 -0.356354 -0.361908 -0.400787 -0.461456 -0.533783 -0.603088 +-0.651306 -0.660767 -0.614563 -0.500214 -0.311096 -0.0456238 0.2883 +0.672974 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 +0.999969 0.999969 0.999969 0.980499 0.590179 0.248199 -0.017334 -0.188782 +-0.259674 -0.235291 -0.132233 0.0249329 0.207764 0.386719 0.536774 +0.632294 0.657349 0.604553 0.475098 0.278259 0.0308228 -0.243103 -0.517395 +-0.768127 -0.973206 -1 -1 -1 -1 -0.959106 -0.774323 -0.556854 -0.318909 +-0.0692749 0.185944 0.443298 0.699951 0.954834 0.999969 0.999969 0.999969 +0.999969 0.974457 0.143829 -0.53949 -1 -1 -1 -1 -0.903381 -0.576324 +-0.239136 0.0640564 0.302643 0.458801 0.528595 0.521362 0.454559 0.34787 +0.223083 0.100708 -0.00384521 -0.0808716 -0.125244 -0.137299 -0.120941 +-0.0837097 -0.034668 0.0179138 0.0670166 0.107178 0.134186 0.148346 +0.149567 0.141113 0.127106 0.109955 0.0914917 0.0743103 0.0613708 0.0543518 +0.0514832 0.055542 0.0632629 0.0738831 0.086853 0.099884 0.112457 0.124176 +0.133881 0.140839 0.144562 0.143829 0.141327 0.13858 0.13269 0.124756 +0.116364 0.106812 0.0970764 0.0872192 0.0769348 0.0671387 0.0580139 +0.0501099 0.0437927 0.0418701 0.042572 0.0460205 0.052002 0.0600281 +0.0696106 0.0800171 0.0906982 0.101837 0.113098 0.123444 0.132507 0.139282 +0.144073 0.146057 0.145508 0.142029 0.135498 0.126556 0.115082 0.100403 +0.0848389 0.0665894 0.0477295 0.028595 0.00961304 -0.00848389 -0.0257874 +-0.0423584 -0.0579224 -0.0725403 -0.0869141 -0.101044 -0.115021 -0.129028 +-0.143372 -0.157471 -0.171783 -0.185913 -0.200317 -0.21463 -0.227814 +-0.240723 -0.25351 -0.263885 -0.272064 -0.27774 -0.278992 -0.277557 +-0.274323 -0.269073 -0.261414 -0.250854 -0.237091 -0.220551 -0.20047 +-0.177368 -0.153992 -0.131348 -0.108795 -0.0869141 -0.0672302 -0.0518494 +-0.0414734 -0.0362549 -0.0380554 -0.0472107 -0.0631714 -0.0870361 -0.115936 +-0.148407 -0.183716 -0.220856 -0.258362 -0.294525 -0.328491 -0.360291 +-0.386597 -0.405731 -0.418732 -0.424011 -0.420502 -0.409485 -0.390564 +-0.363495 -0.329498 -0.289948 -0.245575 -0.19812 -0.151825 -0.106964 +-0.0662842 -0.0315247 -0.00631714 0.00808716 0.0121765 0.00619507 -0.00915527 +-0.0331421 -0.0646973 -0.0995178 -0.135773 -0.170959 -0.204376 -0.234741 +-0.261475 -0.283386 -0.300293 -0.312531 -0.320435 -0.325775 -0.328857 +-0.328583 -0.327423 -0.324768 -0.321655 -0.320312 -0.320129 -0.321136 +-0.323212 -0.325043 -0.325714 -0.324677 -0.317566 -0.303802 -0.280762 +-0.246704 -0.200073 -0.140594 -0.0681763 0.0187073 0.119446 0.22998 +0.346741 0.465454 0.579559 0.684998 0.774353 0.843231 0.887451 0.903961 +0.892273 0.854736 0.795959 0.72168 0.636566 0.546875 0.457825 0.378052 +0.311493 0.258972 0.22226 0.201965 0.194702 0.195862 0.202515 0.211456 +0.21814 0.218964 0.211273 0.19342 0.165619 0.129242 0.0864563 0.0415344 +-0.000946045 -0.0385132 -0.0675964; +#A 1000 -0.0828857 -0.0823669 -0.0689392 -0.0388794 0.00836182 0.0713806 +0.14975 0.241821 0.343811 0.451385 0.560455 0.666168 0.763092 0.844269 +0.90271 0.933441 0.93103 0.891785 0.815155 0.70285 0.559235 0.392944 +0.213409 0.0327759 -0.138458 -0.288544 -0.407806 -0.489197 -0.529602 +-0.528931 -0.489471 -0.415192 -0.311523 -0.184967 -0.0444336 0.103973 +0.253021 0.398804 0.536804 0.662079 0.772064 0.864349 0.936188 0.985199 +0.999969 0.999969 0.978607 0.930573 0.862488 0.779633 0.689514 0.59845 +0.512878 0.437439 0.373901 0.32309 0.284149 0.25415 0.226807 0.195282 +0.150726 0.0862732 -0.00366211 -0.123627 -0.274872 -0.454132 -0.654205 +-0.864258 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.991821 -0.820068 -0.665405 +-0.541504 -0.453644 -0.403442 -0.386169 -0.39621 -0.42099 -0.446625 +-0.461151 -0.453278 -0.413788 -0.338745 -0.227814 -0.0853882 0.0786133 +0.252533 0.423523 0.576965 0.698975 0.777679 0.805695 0.781158 0.704956 +0.580536 0.416809 0.222107 0.00863647 -0.21347 -0.435455 -0.649841 +-0.850922 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.750519 -0.43869 -0.0991211 +0.245605 0.57016 0.846985 0.999969 0.999969 0.999969 0.999969 0.999969 +0.822144 0.578339 0.312134 0.0435181 -0.211853 -0.442688 -0.641357 +-0.804596 -0.932831 -1 -1 -1 -1 -1 -1 -1 -0.957397 -0.857697 -0.746979 +-0.63446 -0.530609 -0.444061 -0.383301 -0.354889 -0.360779 -0.397675 +-0.457886 -0.530243 -0.599121 -0.648041 -0.658875 -0.614075 -0.501556 +-0.313599 -0.0487061 0.285431 0.670898 0.999969 0.999969 0.999969 0.999969 +0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.994263 0.600861 +0.254944 -0.0148621 -0.190338 -0.26413 -0.241058 -0.140289 0.015686 +0.198242 0.379211 0.530151 0.627045 0.654694 0.604462 0.477448 0.282654 +0.0371704 -0.236206 -0.513153 -0.76593 -0.973389 -1 -1 -1 -1 -0.967407 +-0.781769 -0.56424 -0.324951 -0.0736084 0.183289 0.443054 0.702942 +0.960358 0.999969 0.999969 0.999969 0.999969 0.986908 0.159088 -0.523895 +-1 -1 -1 -1 -0.918671 -0.595154 -0.258484 0.046814 0.289673 0.451355 +0.529297 0.52771 0.463898 0.358154 0.232758 0.108521 0.00115967 -0.078125 +-0.124237 -0.138458 -0.124237 -0.089386 -0.0411987 0.0108032 0.0605774 +0.101654 0.130585 0.147491 0.152008 0.145264 0.131958 0.113983 0.0951233 +0.0777283 0.0628357 0.0530701 0.0495605 0.0513916 0.0587158 0.0714722 +0.0856323 0.0986938 0.110992 0.123718 0.133789 0.141266 0.145508 0.147034 +0.145386 0.140686 0.134216 0.125916 0.115723 0.105774 0.096283 0.0852051 +0.0751038 0.0665894 0.05896 0.0525513 0.0475464 0.0441895 0.0434875 +0.0458984 0.0515747 0.0593872 0.0674438 0.0768127 0.0877991 0.0993042 +0.110229 0.121124 0.131989 0.141052 0.147308 0.14975 0.148834 0.144836 +0.138489 0.129425 0.116486 0.100189 0.0821228 0.0637207 0.0458069 0.0279846 +0.0101318 -0.0088501 -0.0272217 -0.0437927 -0.0577393 -0.071228 -0.0854492 +-0.0998535 -0.11377 -0.127319 -0.141632 -0.157898 -0.17337 -0.187744 +-0.202179 -0.21701 -0.231873 -0.245453 -0.2565 -0.265259 -0.272217 +-0.2771 -0.278839 -0.277008 -0.272583 -0.267853 -0.261444 -0.251007 +-0.236786 -0.21933 -0.19931 -0.177551 -0.154633 -0.131104 -0.107788 +-0.0860291 -0.0675659 -0.0513306 -0.0410767 -0.037262 -0.0393066 -0.0481873 +-0.0643311 -0.0869446 -0.115143 -0.148315 -0.183868 -0.221497 -0.259308 +-0.29538 -0.328888 -0.359314 -0.384674 -0.403748 -0.416901 -0.423584 +-0.421875 -0.412445 -0.394135 -0.368683 -0.335114 -0.294617 -0.248718 +-0.200012 -0.150696 -0.103271 -0.0614319 -0.0278015 -0.00195312 0.0123291 +0.0169067 0.00997925 -0.0055542 -0.0300903 -0.0625 -0.0991211 -0.136505 +-0.172913 -0.207245 -0.238586 -0.265167 -0.287231 -0.30426 -0.316223 +-0.323425 -0.326294 -0.326965 -0.326263 -0.324585 -0.323242 -0.321442 +-0.32077 -0.320282 -0.322388 -0.323883 -0.32547 -0.326569 -0.324921 +-0.31781 -0.303741 -0.281006 -0.246765 -0.201111 -0.141479 -0.0682983 +0.0192566 0.11969 0.230042 0.346985 0.466461 0.582428 0.687988 0.777466 +0.847107 0.891693 0.908142 0.895447 0.859131 0.801605 0.726562 0.639618 +0.548218 0.459473 0.378784 0.310516 0.256836 0.219971 0.200043 0.192505 +0.195129 0.203156 0.211853 0.217621 0.218018 0.210602 0.192932 0.165924 +0.130157 0.0880737 0.0436707 0.000183105 -0.0377197 -0.0673523 -0.0857544 +-0.0892944 -0.0753784 -0.0438232 0.00436401 0.0688477 0.148773 0.241241 +0.343048 0.451538 0.561401 0.667877 0.76535 0.84613 0.903748 0.934753 +0.933105 0.895264 0.82016 0.707977 0.564514 0.39798 0.217407 0.0344543 +-0.138824 -0.291412 -0.41217 -0.494598 -0.535889 -0.534729 -0.494141 +-0.418274 -0.314331 -0.188263 -0.0472717 0.101135 0.25116 0.398132 +0.53775 0.665833 0.776978 0.870361 0.94281 0.990692 0.999969 0.999969 +0.980591 0.930176 0.862274 0.780884 0.691925 0.601074 0.516296 0.440979 +0.37616 0.324341 0.284668 0.253754 0.225769 0.192902 0.148743 0.0855713 +-0.00421143 -0.124268 -0.275452 -0.454956 -0.65567 -0.866638 -1 -1 +-1 -1 -1 -1 -1 -1 -1 -1 -0.828003 -0.672089 -0.544495 -0.453064 -0.400085 +-0.382477 -0.391357 -0.4151 -0.441681 -0.458649 -0.452606 -0.414001 +-0.339233 -0.228607 -0.0864258 0.078186 0.253143 0.424225 0.577881 +0.701019 0.781769 0.811951 0.789276 0.713867 0.589264 0.423553 0.227509 +0.0120239 -0.211914 -0.435303 -0.651703 -0.853729 -1 -1 -1 -1 -1 -1 +-1 -1 -1 -0.756287 -0.444092 -0.102905 0.243561 0.569672 0.849365 0.999969 +0.999969 0.999969 0.999969 0.999969 0.833405 0.590118 0.322998 0.0515442 +-0.206573 -0.438843 -0.638672 -0.804199 -0.935913 -1 -1 -1 -1 -1 -1 +-1 -0.96283 -0.861115 -0.749207 -0.636108 -0.531036 -0.444672 0.554535 +0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.57547 0.100037 +-0.290497 -0.564453 -0.710022 -0.732971 -0.656952 -0.510254 -0.323334 +-0.128326 0.0491943 0.191101 0.28653 0.333221 0.336029 0.302673 0.245667 +0.17749 0.108307 0.0475159 0.00280762 -0.0238342 -0.0334473 -0.0276794 +-0.00997925 0.0147095 0.0418701 0.0684509 0.0918579 0.109528 0.120117 +0.124176 0.123077 0.118225 0.111725 0.105469 0.100128 0.0970154 0.0969849 +0.0992432 0.105286 0.112579 0.120056 0.12735 0.133453 0.136932 0.136902 +0.133301 0.126068 0.116638 0.105255 0.0941467 0.0830078 0.0715942 0.0602722 +0.0501099 0.0424805 0.0380859 0.0365295 0.0378418 0.0431519 0.0505371 +0.0605164 0.0729065 0.0870056 0.100586 0.114044 0.126099 0.136108 0.144623 +0.150208 0.151245 0.149628 0.145538 0.13916 0.1297 0.11673 0.101257 +0.0846252 0.0667725 0.0483398 0.0305786 0.0133057 -0.00411987 -0.0206909 +-0.0389404 -0.0566406 -0.0726929 -0.0880432 -0.102997 -0.11734 -0.131409 +-0.145782 -0.159973 -0.174347 -0.189453 -0.204712 -0.218262 -0.231842 +-0.243958 -0.254822 -0.264679 -0.272614 -0.278137 -0.280457 -0.277985 +-0.274139 -0.26651 -0.255615 -0.242767 -0.227753 -0.210876 -0.192017 +-0.171631 -0.150085 -0.12796 -0.106537 -0.0864563 -0.0697632 -0.0567932 +-0.0470886 -0.0434875 -0.0454712 -0.0533142 -0.0669861 -0.0858154 -0.109589 +-0.138916 -0.174042 -0.212128 -0.25116 -0.289917 -0.327362 -0.36142 +-0.389282 -0.410004 -0.423279 -0.428436 -0.42514 -0.413666 -0.39328 +-0.365875 -0.330109 -0.287811 -0.241241 -0.193298 -0.146057 -0.101135 +-0.0602417 -0.0259705 -0.00109863 0.0117798 0.0144653 0.00726318 -0.00985718 +-0.033844 -0.062439 -0.0951843 -0.13028 -0.165527 -0.199432 -0.230042 +-0.256622 -0.279663 -0.296783 -0.30954 -0.317444 -0.32251 -0.324615 +-0.324493 -0.323944 -0.323425 -0.322845 -0.324738 -0.325836 -0.326599 +-0.327118 -0.327057 -0.325226 -0.320679 -0.311951 -0.296753 -0.273376 +-0.240204 -0.194733 -0.136108 -0.0620117 0.0262451 0.125214 0.233795 +0.349182 0.466644 0.580963 0.68634 0.776581 0.846069 0.890045 0.907074 +0.899292 0.865997 0.809326 0.734558 0.647552 0.554962 0.463654 0.380096 +0.30957 0.255005 0.218353 0.196045 0.187775 0.189697 0.198151 0.208984 +0.216583 0.217407 0.209686 0.192047 0.165222 0.12973 0.0860291 0.0411072 +-0.00177002 -0.0402222 -0.0692444 -0.0855408 -0.087616 -0.0743713 -0.04422 +0.00427246 0.0694275 0.149475 0.241608 0.343414 0.451263 0.561371 0.667389 +0.764069 0.845642 0.905365 0.937836 0.937012 0.899841 0.82428 0.711792 +0.567657 0.39978 0.217377 0.0335083 -0.139648 -0.292023 -0.41394 -0.498688 +-0.541809 -0.54184 -0.500946 -0.424866 -0.320526 -0.195007 -0.0548401 +0.0941772 0.246277 0.395569 0.536713 0.665955 0.779266 0.873901 0.947601 +0.99646 0.999969 0.999969 0.985901 0.934845 0.865417 0.782837 0.693024 +0.601807 0.516235 0.439514 0.374481 0.323212 0.284424 0.253693 0.225494 +0.193054 0.148132 0.0826416 -0.00842285 -0.127563 -0.278015 -0.457214 +-0.657013 -0.867767 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.832947 -0.674957 +-0.546509 -0.455109 -0.401459 -0.381561 -0.38913 -0.413025 -0.43924 +-0.454773 -0.44754 -0.410187 -0.338013 -0.229919 -0.0897827 0.0737915 +0.248657 0.420746 0.575073 0.701202 0.783661 0.81601 0.795135 0.720795 +0.597382 0.432526 0.236237 0.0197754 -0.20636 -0.433411 -0.651581 -0.85675 +-1 -1 -1 -1 -1 -1 -1 -1 -1 -0.761597 -0.449127 -0.10733 0.240723 0.567749 +0.849518 0.999969 0.999969 0.999969 0.999969 0.999969 0.846893 0.602264 +0.333496 0.0600586 -0.202484 -0.440704 -0.646301 -0.815704 -0.948914 +-1 -1 -1 -1 -1 -1 -1 -0.964539 -0.862732 -0.751526 -0.638733 -0.534088 +-0.447662 -0.387573 -0.358978 -0.362793 -0.397034 -0.4552 -0.525391 +-0.592346 -0.640137 -0.651886 -0.610596 -0.502045 -0.315704 -0.0520325 +0.280945 0.666718 0.999969; +#X coords 0 2 1999 -2 200 140 1; +#X restore 596 461 graph; +#X msg 177 446 bang; +#X obj 602 315 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 1270 0; +#X text 607 295 The pedal (step); +#X obj 601 216 f; +#X obj 632 216 + 1; +#X msg 599 158 bang; +#X obj 645 242 > 100; +#X obj 688 241 route 1; +#X msg 685 215 -1; +#X msg 559 216 0; +#X obj 693 185 route 1; +#X obj 664 186 < 0; +#X msg 690 159 1; +#X msg 555 160 stop; +#X obj 161 187 hsl 128 15 0 3000 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 5600 0; +#X text 162 166 Minimum freq [ 0 - 3000 ]; +#X obj 212 221 hsl 128 15 0 3000 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 3300 0; +#X text 207 205 Maximum freq [ 0 - 3000 ]; +#X obj 237 259 hsl 128 15 0 1000 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 4200 0; +#X text 234 241 Sensibility [ 0 - 1000 ]; +#X obj 285 292 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 1100 0; +#X text 280 275 Maxstep [ 0 - 100 ]; +#X obj 340 327 hsl 128 15 -15 15 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12400 0; +#X text 335 310 Gain [ -15 - 15 ]; +#X obj 408 369 hsl 128 15 0 10 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 5000 0; +#X text 403 351 Bandwidth [ 0 - 10 ]; +#X text 597 126 Auto; +#X text 164 148 Note : setting a parameter overrides presets; +#X obj 87 414 wahwah~ -------------------------------------------------- +; +#X text 133 543 Note : interesting to set bandwith close to 10; +#X obj 600 185 metro 10; +#X obj 648 127 loadbang; +#X connect 1 0 42 0; +#X connect 2 0 42 0; +#X connect 3 0 42 0; +#X connect 4 0 42 0; +#X connect 5 0 42 0; +#X connect 10 0 42 0; +#X connect 14 0 12 0; +#X connect 15 0 42 7; +#X connect 17 0 18 0; +#X connect 17 0 20 0; +#X connect 17 0 25 0; +#X connect 17 0 15 0; +#X connect 18 0 17 1; +#X connect 19 0 44 0; +#X connect 20 0 21 0; +#X connect 21 0 22 0; +#X connect 22 0 18 1; +#X connect 23 0 17 0; +#X connect 24 0 26 0; +#X connect 25 0 24 0; +#X connect 26 0 18 1; +#X connect 27 0 44 0; +#X connect 28 0 42 1; +#X connect 30 0 42 2; +#X connect 32 0 42 3; +#X connect 34 0 42 4; +#X connect 36 0 42 5; +#X connect 38 0 42 6; +#X connect 42 0 0 0; +#X connect 42 0 12 0; +#X connect 44 0 17 0; +#X connect 45 0 19 0; diff --git a/samplebox~-help.pd b/samplebox~-help.pd new file mode 100644 index 0000000..9b5b6f5 --- /dev/null +++ b/samplebox~-help.pd @@ -0,0 +1,145 @@ +#N canvas 19 6 986 684 10; +#X obj 126 505 dac~; +#X msg 183 318 record; +#X msg 271 39 play; +#X obj 342 252 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 309 250 0 %; +#X text 476 251 100 %; +#X obj 343 270 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 310 271 0 %; +#X text 478 269 100 %; +#X msg 352 504 \; pd dsp 1; +#X msg 414 505 \; pd dsp 0; +#X text 606 251 Start Point; +#X text 608 269 End Point; +#X msg 19 21 bang; +#X obj 19 41 openpanel; +#X obj 19 187 soundfiler; +#X msg 15 306 bang; +#X msg 512 271 100; +#X obj 544 270 loadbang; +#X text 19 546 3s * samplerate / blocksize ( 3*44100/64 = 2067 ); +#X floatatom 49 207 10 0 0; +#X obj 18 207 / 64; +#X msg 122 207 resize \$1; +#X obj 19 63 t s b; +#X text 35 592 Comments and bugs @ ydegoyon@free.fr; +#X obj 65 63 float \$0; +#X obj 19 80 route float; +#X msg 339 318 flipblocks; +#X text 410 318 Flip blocks ( reverse effect ); +#X msg 338 294 swapblocks 0 50 20; +#X text 23 5 Step 1 : Load a sound file; +#X msg 274 132 phase \$1; +#X obj 365 130 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 273 62 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X text 247 63 0 %; +#X text 407 62 100 %; +#X obj 274 81 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 248 84 0 %; +#X text 409 80 100 %; +#X text 551 61 Start Point; +#X text 552 80 End Point; +#X msg 443 78 100; +#X obj 470 78 loadbang; +#X text 630 69 Playback positions; +#X msg 268 103 readspeed \$1; +#X floatatom 399 103 5 0 0; +#X text 553 101 Reading speed; +#X obj 358 103 / 100; +#X msg 448 104 100; +#X obj 477 104 loadbang; +#X obj 223 447 samplebox~ 2067; +#X text 16 282 Step 2 : Record the sound; +#X text 276 15 Step 3 : Play back recorded sound; +#X text 341 222 Step 4 : modify parts of the sound; +#X text 474 293 Swap sections [0% \, 20%] and [50% \, 70%] of [start +\, end]; +#X text 21 533 Note : initially \, this is a 3 seconds samplebox~ : +; +#X text 34 581 Samplebox records and plays back a sound; +#X text 342 235 Set portions of the sound to modify; +#X text 500 132 100%; +#X text 341 131 0%; +#X obj 44 100 makefilename %d-leftsample; +#X obj 511 512 table \$0-leftsample; +#X obj 650 511 table \$0-rightsample; +#X obj 45 123 makefilename %d-rightsample; +#X obj 20 149 pack s s s; +#X msg 19 170 read -resize \$1 \$2 \$3; +#X obj 16 343 tabplay~ \$0-leftsample; +#X obj 80 363 tabplay~ \$0-rightsample; +#X obj 278 474 print recordend; +#X obj 399 472 print playend; +#X text 552 127 Switch channels ( use as pan for mono input ); +#X msg 456 159 bang; +#X text 557 161 Ping-pong ( requires countund object ); +#X obj 305 160 countund 90; +#X obj 113 481 *~; +#X obj 144 479 / 100; +#X floatatom 74 447 5 0 0; +#X obj 184 478 *~; +#X obj 211 477 / 100; +#X obj 384 159 metro 100; +#X obj 28 423 loadbang; +#X msg 28 449 100; +#X connect 1 0 50 0; +#X connect 2 0 50 0; +#X connect 3 0 50 4; +#X connect 6 0 50 5; +#X connect 13 0 14 0; +#X connect 14 0 23 0; +#X connect 15 0 21 0; +#X connect 16 0 1 0; +#X connect 16 0 66 0; +#X connect 16 0 67 0; +#X connect 17 0 6 0; +#X connect 18 0 17 0; +#X connect 20 0 22 0; +#X connect 21 0 20 0; +#X connect 22 0 50 0; +#X connect 23 0 64 0; +#X connect 23 1 25 0; +#X connect 25 0 26 0; +#X connect 26 0 60 0; +#X connect 26 0 63 0; +#X connect 27 0 50 0; +#X connect 29 0 50 0; +#X connect 31 0 50 0; +#X connect 32 0 31 0; +#X connect 33 0 50 2; +#X connect 36 0 50 3; +#X connect 41 0 36 0; +#X connect 42 0 41 0; +#X connect 44 0 50 0; +#X connect 45 0 47 0; +#X connect 47 0 44 0; +#X connect 48 0 45 0; +#X connect 49 0 48 0; +#X connect 50 0 74 0; +#X connect 50 1 77 0; +#X connect 50 2 68 0; +#X connect 50 3 69 0; +#X connect 50 3 2 0; +#X connect 60 0 64 1; +#X connect 63 0 64 2; +#X connect 64 0 65 0; +#X connect 65 0 15 0; +#X connect 66 0 50 0; +#X connect 67 0 50 1; +#X connect 71 0 79 0; +#X connect 73 0 31 0; +#X connect 74 0 0 0; +#X connect 75 0 74 1; +#X connect 76 0 75 0; +#X connect 76 0 78 0; +#X connect 77 0 0 1; +#X connect 78 0 77 1; +#X connect 79 0 73 0; +#X connect 80 0 81 0; +#X connect 81 0 76 0; diff --git a/samplebox~.c b/samplebox~.c new file mode 100644 index 0000000..64e656c --- /dev/null +++ b/samplebox~.c @@ -0,0 +1,530 @@ +/*------------------------ samplebox~ ----------------------------------------- */ +/* */ +/* samplebox~ : records and plays back a sound */ +/* Written by Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* All i wanted is your time */ +/* All you gave me was tomorrow */ +/* But, tomorrow never comes, tomorrow never comes */ +/* Vini Reilly -- "Tomorrow" */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#ifdef UNIX +#include +#endif +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif +#include + +#include "m_pd.h" /* standard pd stuff */ + +static char *samplebox_version = "samplebox~: stores and plays back a sound version 0.3, written by Yves Degoyon (ydegoyon@free.fr)"; + + +static t_class *samplebox_class; + +typedef struct _samplebox +{ + t_object x_obj; + + t_int x_size; /* size of the stored sound ( in blocks~ ) */ + t_float x_samplerate; /* sample rate */ + t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ + t_float x_readpos; /* data's playing position */ + t_int x_writepos; /* data's recording position */ + t_int x_readstart; /* data's starting position for reading */ + t_int x_readend; /* data's ending position for reading */ + t_int x_modstart; /* data's starting position for modifications */ + t_int x_modend; /* data's ending position for modifications */ + t_int x_play; /* playing on/off flag */ + t_float x_readspeed; /* number of grouped blocks for reading */ + t_float x_record; /* flag to start recording process */ + t_float x_allocate; /* flag to avoid reading data during generation */ + t_float *x_rdata; /* table containing left channel of the sound */ + t_float *x_idata; /* table containing right channel of the sound */ + t_float *x_rootsquares; /* sum of the root squares of a block ( energy ) */ + t_float x_phase; /* phase to apply on output */ + t_outlet *x_recordend; /* outlet for end of recording */ + t_outlet *x_playend; /* outlet for end of playing back */ + t_float x_f; /* float needed for signal input */ + +} t_samplebox; + + /* clean up */ +static void samplebox_free(t_samplebox *x) +{ + if ( x->x_rdata != NULL ) { + freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_rdata = NULL; + } + if ( x->x_idata != NULL ) { + freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_idata = NULL; + } + if ( x->x_rootsquares != NULL ) { + freebytes(x->x_rootsquares, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_rootsquares = NULL; + } +} + + /* allocate tables for storing sound */ +static t_int samplebox_allocate(t_samplebox *x) +{ + if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_rootsquares = getbytes( x->x_size*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + return 0; +} + + /* reallocate tables for storing sound */ +static t_int samplebox_reallocate(t_samplebox *x, t_int ioldsize, t_int inewsize) +{ + t_float *prdata=x->x_rdata, *pidata=x->x_idata, *prootsquares=x->x_rootsquares; + + if ( !(x->x_rdata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_idata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_rootsquares = getbytes( inewsize*sizeof(float) ) ) ) { + return -1; + } else { + post( "samplebox~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( prdata != NULL ) { + freebytes(prdata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + if ( pidata != NULL ) { + freebytes(pidata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + if ( prootsquares != NULL ) { + freebytes(prootsquares, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + return 0; +} + + /* records or playback the sonogram */ +static t_int *samplebox_perform(t_int *w) +{ + t_float *rin = (t_float *)(w[1]); + t_float *iin = (t_float *)(w[2]); + t_float *rout = (t_float *)(w[3]); + t_float *iout = (t_float *)(w[4]); + t_float fspectrum = 0.0; + t_float fphase = 0.0; + t_int rpoint; + t_int n = (int)(w[5]); /* number of samples */ + t_samplebox *x = (t_samplebox *)(w[6]); + t_int bi; + t_float v[4]; + t_float z[4]; + + // reallocate tables if blocksize has been changed + if ( n != x->x_blocksize ) { + post( "samplebox~ : reallocating tables" ); + x->x_allocate = 1; + samplebox_free(x); + x->x_blocksize = n; + samplebox_allocate(x); + x->x_allocate = 0; + } + + // new block : energy is set to zero + // if ( x->x_record ) { + // *(x->x_rootsquares+x->x_writepos) = 0.0; + // } + + if ( x->x_play || x->x_record ) { + bi = 0; + while (bix_allocate && x->x_record) { + *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=*rin; + *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=*iin; + // *(x->x_rootsquares+x->x_writepos) += sqrt( pow((*rin),2) + pow((*iin),2) ); + } + // set outputs + if ( !x->x_allocate && x->x_play) { + *rout = 0.; + *iout = 0.; + // interpolates 4 points like tabread4 + rpoint = ((int)x->x_readpos*x->x_blocksize)+bi; + + if ( rpoint == 0 ) { + v[0]=0.0; + v[1]=*(x->x_rdata+rpoint); + v[2]=*(x->x_rdata+rpoint+1); + v[3]=*(x->x_rdata+rpoint+2); + z[0]=0.0; + z[1]=*(x->x_idata+rpoint); + z[2]=*(x->x_idata+rpoint+1); + z[3]=*(x->x_idata+rpoint+2); + } else if ( rpoint == (x->x_size*x->x_blocksize-1) ) { + v[0]=*(x->x_rdata+rpoint-1); + v[1]=*(x->x_rdata+rpoint); + v[2]=*(x->x_rdata+rpoint+1); + v[3]=0.0; + z[0]=*(x->x_idata+rpoint-1); + z[1]=*(x->x_idata+rpoint); + z[2]=*(x->x_idata+rpoint+1); + z[3]=0.0; + } else if ( rpoint == (x->x_size*x->x_blocksize) ) { + v[0]=*(x->x_rdata+rpoint-1); + v[1]=*(x->x_rdata+rpoint); + v[2]=0.0; + v[3]=0.0; + z[0]=*(x->x_idata+rpoint-1); + z[1]=*(x->x_idata+rpoint); + z[2]=0.0; + z[3]=0.0; + } else { + v[0]=*(x->x_rdata+rpoint-1); + v[1]=*(x->x_rdata+rpoint); + v[2]=*(x->x_rdata+rpoint+1); + v[3]=*(x->x_rdata+rpoint+2); + z[0]=*(x->x_idata+rpoint-1); + z[1]=*(x->x_idata+rpoint); + z[2]=*(x->x_idata+rpoint+1); + z[3]=*(x->x_idata+rpoint+2); + } + + { + t_float frac = rpoint-(int)rpoint; + + // taken from tabread4_tilde + *rout = v[1]+frac*((v[2]-v[1])-0.5f*(frac-1.)*((v[0]-v[3]+3.0f*(v[2]-v[1]))*frac+(2.0f*v[1]-v[0]-v[2]))); + *iout = z[1]+frac*((z[2]-z[1])-0.5f*(frac-1.)*((z[0]-z[3]+3.0f*(z[2]-z[1]))*frac+(2.0f*z[1]-z[0]-z[2]))); + } + + // add phase argument + fspectrum = sqrt( pow( *rout, 2) + pow( *iout, 2) ); + fphase = atan2( *iout, *rout ); + fphase += (x->x_phase/180.0)*(M_PI); + *rout = fspectrum*cos( fphase ); + *iout = fspectrum*sin( fphase ); + } else { + *rout=0.0; + *iout=0.0; + } + rout++;iout++; + rin++;iin++; + bi++; + } + // reset playing position until next play + if ( x->x_play ) { + x->x_readpos+=x->x_readspeed; + // post( "xreadpos : %f (added %f)", x->x_readpos, x->x_readspeed ); + if ( x->x_readpos >= (x->x_readend*x->x_size)/100 ) { + x->x_play=0; + x->x_readpos=(x->x_readstart*x->x_size)/100; + // post( "samplebox~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_playend); + } + } + // reset recording position until next record + if ( x->x_record ) { + x->x_writepos++; + if ( x->x_writepos >= x->x_size ) { + x->x_record=0; + x->x_writepos=0; + outlet_bang(x->x_recordend); + // post( "samplebox~ : stopped recording" ); + } + } + } + return (w+7); +} + +static void samplebox_dsp(t_samplebox *x, t_signal **sp) +{ + dsp_add(samplebox_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); +} + + /* record the sonogram */ +static void samplebox_record(t_samplebox *x) +{ + x->x_record=1; + x->x_writepos=0; +} + + /* play the sonogram */ +static void samplebox_play(t_samplebox *x) +{ + x->x_play=1; + // reset read position + x->x_readpos=(x->x_readstart*x->x_size)/100; +} + + /* setting the starting point for reading ( in percent ) */ +static void samplebox_readstart(t_samplebox *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + if ( startpoint > x->x_readend ) { + x->x_readstart = x->x_readend; + post( "samplebox~ : warning : range for reading is null" ); + } else { + x->x_readstart=startpoint; + } +} + + /* setting the starting point for modification ( in percent ) */ +static void samplebox_modstart(t_samplebox *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + if ( startpoint > x->x_modend ) { + x->x_modstart = x->x_modend; + post( "samplebox~ : warning : range for modifications is null" ); + } else { + x->x_modstart=startpoint; + } +} + + /* setting the ending point for reading ( in percent ) */ +static void samplebox_readend(t_samplebox *x, t_floatarg fend) +{ + t_float endpoint = fend; + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + if ( endpoint < x->x_readstart ) { + x->x_readend = x->x_readstart; + post( "samplebox~ : warning : range for reading is null" ); + } else { + x->x_readend=endpoint; + } +} + + /* setting the ending point for modification ( in percent ) */ +static void samplebox_modend(t_samplebox *x, t_floatarg fend) +{ + t_float endpoint = fend; + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + if ( endpoint < x->x_modstart ) { + x->x_modend = x->x_modstart; + post( "samplebox~ : warning : range for modifications is null" ); + } else { + x->x_modend=endpoint; + } +} + + /* sets the reading speed */ +static void samplebox_readspeed(t_samplebox *x, t_floatarg freadspeed) +{ + if ((int)freadspeed < 0 ) { + post( "samplebox~ : wrong readspeed argument" ); + } + x->x_readspeed=freadspeed; +} + + /* resize sonogram */ +static void samplebox_resize(t_samplebox *x, t_floatarg fnewsize ) +{ + if (fnewsize <= 0) { + post( "samplebox~ : error : wrong size" ); + return; + } + post( "samplebox~ : reallocating tables" ); + x->x_record = 0; + x->x_play = 0; + x->x_allocate = 1; + samplebox_reallocate(x, x->x_size, fnewsize); + x->x_size = fnewsize; + x->x_allocate = 0; +} + + /* flip blocks */ +static void samplebox_flipblocks(t_samplebox *x) +{ + t_int samplestart, sampleend, middlesample, fi, si; + t_float fvalue; + + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + middlesample = ( sampleend+samplestart+1 ) / 2; + post( "flip blocks [%d,%d] and [%d,%d]", samplestart, middlesample, middlesample, sampleend ); + + for ( si=samplestart; si<=middlesample; si++ ) { + for ( fi=0; fix_blocksize; fi++ ) { + fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); + *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); + *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; + fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); + *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); + *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; + } + } +} + + /* change the phase */ +static void samplebox_phase(t_samplebox *x, t_floatarg fincphase) +{ + if (fincphase < 0 || fincphase > 90) { + post( "samplebox~ : error : wrong phase in phase function : out of [0,90]" ); + return; + } + x->x_phase = fincphase; +} + + /* swap blocks */ +static void samplebox_swapblocks(t_samplebox *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) +{ + t_int samplestart, samplestartb, samplesize, sp, sf; + t_int iperstart, iperend, ipersize; + t_float s1, s2; + t_float fvalue; + + iperstart = fperstart; + iperend = fperend; + ipersize = fpersize; + + if (iperstart < 0 || iperstart > iperend || + iperend <= 0 || iperend+ipersize > 100 || + ipersize < 0 || fpersize > 100 ) { + post( "samplebox~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", + iperstart, iperstart+ipersize, iperend, iperend+ipersize ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + samplestartb=(x->x_modend*(x->x_size-1))/100; + samplesize=((samplestartb-samplestart)*ipersize)/100; + samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; + samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; + + // post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); + + for ( sp=samplesize; sp>=0; sp-- ) { + for ( sf=0; sfx_blocksize; sf++) { + fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); + *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); + *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; + fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); + *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); + *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; + } + } +} + +static void *samplebox_new(t_floatarg fsize) +{ + t_samplebox *x = (t_samplebox *)pd_new(samplebox_class); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_recordend = outlet_new(&x->x_obj, &s_bang ); + x->x_playend = outlet_new(&x->x_obj, &s_bang ); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); + + if ( fsize <= 0 ) { + error( "samplebox~ : missing or negative creation arguments" ); + return NULL; + } + + x->x_size = fsize; + x->x_blocksize = sys_getblksize(); + x->x_play = 0; + x->x_readspeed = 1.; + x->x_record = 0; + x->x_readpos = 0.; + x->x_writepos = 0; + x->x_modstart = 0; + x->x_readstart = 0; + x->x_modend = 100; + x->x_readend = 100; + x->x_allocate = 0; + x->x_rdata = NULL; + x->x_idata = NULL; + x->x_rootsquares = NULL; + x->x_phase = 0.0; + x->x_samplerate = sys_getsr(); + if ( samplebox_allocate(x) <0 ) { + return NULL; + } else { + return(x); + } +} + +void samplebox_tilde_setup(void) +{ + post(samplebox_version); + samplebox_class = class_new(gensym("samplebox~"), (t_newmethod)samplebox_new, (t_method)samplebox_free, + sizeof(t_samplebox), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN( samplebox_class, t_samplebox, x_f ); + class_addmethod(samplebox_class, (t_method)samplebox_dsp, gensym("dsp"), 0); + class_addmethod(samplebox_class, (t_method)samplebox_record, gensym("record"), 0); + class_addmethod(samplebox_class, (t_method)samplebox_resize, gensym("resize"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_flipblocks, gensym("flipblocks"), 0); + class_addmethod(samplebox_class, (t_method)samplebox_play, gensym("play"), 0); + class_addmethod(samplebox_class, (t_method)samplebox_phase, gensym("phase"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_modstart, gensym("modstart"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_modend, gensym("modend"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_readstart, gensym("readstart"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_readend, gensym("readend"), A_FLOAT, 0); + class_addmethod(samplebox_class, (t_method)samplebox_readspeed, gensym("readspeed"), A_FLOAT, 0); +} diff --git a/samplebox~/INSTALL b/samplebox~/INSTALL deleted file mode 100644 index c0dc546..0000000 --- a/samplebox~/INSTALL +++ /dev/null @@ -1,9 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/samplebox~ - -make - -make install - -you're set !! diff --git a/samplebox~/samplebox~-help.pd b/samplebox~/samplebox~-help.pd deleted file mode 100644 index 9b5b6f5..0000000 --- a/samplebox~/samplebox~-help.pd +++ /dev/null @@ -1,145 +0,0 @@ -#N canvas 19 6 986 684 10; -#X obj 126 505 dac~; -#X msg 183 318 record; -#X msg 271 39 play; -#X obj 342 252 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 309 250 0 %; -#X text 476 251 100 %; -#X obj 343 270 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 310 271 0 %; -#X text 478 269 100 %; -#X msg 352 504 \; pd dsp 1; -#X msg 414 505 \; pd dsp 0; -#X text 606 251 Start Point; -#X text 608 269 End Point; -#X msg 19 21 bang; -#X obj 19 41 openpanel; -#X obj 19 187 soundfiler; -#X msg 15 306 bang; -#X msg 512 271 100; -#X obj 544 270 loadbang; -#X text 19 546 3s * samplerate / blocksize ( 3*44100/64 = 2067 ); -#X floatatom 49 207 10 0 0; -#X obj 18 207 / 64; -#X msg 122 207 resize \$1; -#X obj 19 63 t s b; -#X text 35 592 Comments and bugs @ ydegoyon@free.fr; -#X obj 65 63 float \$0; -#X obj 19 80 route float; -#X msg 339 318 flipblocks; -#X text 410 318 Flip blocks ( reverse effect ); -#X msg 338 294 swapblocks 0 50 20; -#X text 23 5 Step 1 : Load a sound file; -#X msg 274 132 phase \$1; -#X obj 365 130 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 273 62 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 247 63 0 %; -#X text 407 62 100 %; -#X obj 274 81 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 248 84 0 %; -#X text 409 80 100 %; -#X text 551 61 Start Point; -#X text 552 80 End Point; -#X msg 443 78 100; -#X obj 470 78 loadbang; -#X text 630 69 Playback positions; -#X msg 268 103 readspeed \$1; -#X floatatom 399 103 5 0 0; -#X text 553 101 Reading speed; -#X obj 358 103 / 100; -#X msg 448 104 100; -#X obj 477 104 loadbang; -#X obj 223 447 samplebox~ 2067; -#X text 16 282 Step 2 : Record the sound; -#X text 276 15 Step 3 : Play back recorded sound; -#X text 341 222 Step 4 : modify parts of the sound; -#X text 474 293 Swap sections [0% \, 20%] and [50% \, 70%] of [start -\, end]; -#X text 21 533 Note : initially \, this is a 3 seconds samplebox~ : -; -#X text 34 581 Samplebox records and plays back a sound; -#X text 342 235 Set portions of the sound to modify; -#X text 500 132 100%; -#X text 341 131 0%; -#X obj 44 100 makefilename %d-leftsample; -#X obj 511 512 table \$0-leftsample; -#X obj 650 511 table \$0-rightsample; -#X obj 45 123 makefilename %d-rightsample; -#X obj 20 149 pack s s s; -#X msg 19 170 read -resize \$1 \$2 \$3; -#X obj 16 343 tabplay~ \$0-leftsample; -#X obj 80 363 tabplay~ \$0-rightsample; -#X obj 278 474 print recordend; -#X obj 399 472 print playend; -#X text 552 127 Switch channels ( use as pan for mono input ); -#X msg 456 159 bang; -#X text 557 161 Ping-pong ( requires countund object ); -#X obj 305 160 countund 90; -#X obj 113 481 *~; -#X obj 144 479 / 100; -#X floatatom 74 447 5 0 0; -#X obj 184 478 *~; -#X obj 211 477 / 100; -#X obj 384 159 metro 100; -#X obj 28 423 loadbang; -#X msg 28 449 100; -#X connect 1 0 50 0; -#X connect 2 0 50 0; -#X connect 3 0 50 4; -#X connect 6 0 50 5; -#X connect 13 0 14 0; -#X connect 14 0 23 0; -#X connect 15 0 21 0; -#X connect 16 0 1 0; -#X connect 16 0 66 0; -#X connect 16 0 67 0; -#X connect 17 0 6 0; -#X connect 18 0 17 0; -#X connect 20 0 22 0; -#X connect 21 0 20 0; -#X connect 22 0 50 0; -#X connect 23 0 64 0; -#X connect 23 1 25 0; -#X connect 25 0 26 0; -#X connect 26 0 60 0; -#X connect 26 0 63 0; -#X connect 27 0 50 0; -#X connect 29 0 50 0; -#X connect 31 0 50 0; -#X connect 32 0 31 0; -#X connect 33 0 50 2; -#X connect 36 0 50 3; -#X connect 41 0 36 0; -#X connect 42 0 41 0; -#X connect 44 0 50 0; -#X connect 45 0 47 0; -#X connect 47 0 44 0; -#X connect 48 0 45 0; -#X connect 49 0 48 0; -#X connect 50 0 74 0; -#X connect 50 1 77 0; -#X connect 50 2 68 0; -#X connect 50 3 69 0; -#X connect 50 3 2 0; -#X connect 60 0 64 1; -#X connect 63 0 64 2; -#X connect 64 0 65 0; -#X connect 65 0 15 0; -#X connect 66 0 50 0; -#X connect 67 0 50 1; -#X connect 71 0 79 0; -#X connect 73 0 31 0; -#X connect 74 0 0 0; -#X connect 75 0 74 1; -#X connect 76 0 75 0; -#X connect 76 0 78 0; -#X connect 77 0 0 1; -#X connect 78 0 77 1; -#X connect 79 0 73 0; -#X connect 80 0 81 0; -#X connect 81 0 76 0; diff --git a/samplebox~/samplebox~.c b/samplebox~/samplebox~.c deleted file mode 100644 index 64e656c..0000000 --- a/samplebox~/samplebox~.c +++ /dev/null @@ -1,530 +0,0 @@ -/*------------------------ samplebox~ ----------------------------------------- */ -/* */ -/* samplebox~ : records and plays back a sound */ -/* Written by Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* All i wanted is your time */ -/* All you gave me was tomorrow */ -/* But, tomorrow never comes, tomorrow never comes */ -/* Vini Reilly -- "Tomorrow" */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef UNIX -#include -#endif -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif -#include - -#include "m_pd.h" /* standard pd stuff */ - -static char *samplebox_version = "samplebox~: stores and plays back a sound version 0.3, written by Yves Degoyon (ydegoyon@free.fr)"; - - -static t_class *samplebox_class; - -typedef struct _samplebox -{ - t_object x_obj; - - t_int x_size; /* size of the stored sound ( in blocks~ ) */ - t_float x_samplerate; /* sample rate */ - t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ - t_float x_readpos; /* data's playing position */ - t_int x_writepos; /* data's recording position */ - t_int x_readstart; /* data's starting position for reading */ - t_int x_readend; /* data's ending position for reading */ - t_int x_modstart; /* data's starting position for modifications */ - t_int x_modend; /* data's ending position for modifications */ - t_int x_play; /* playing on/off flag */ - t_float x_readspeed; /* number of grouped blocks for reading */ - t_float x_record; /* flag to start recording process */ - t_float x_allocate; /* flag to avoid reading data during generation */ - t_float *x_rdata; /* table containing left channel of the sound */ - t_float *x_idata; /* table containing right channel of the sound */ - t_float *x_rootsquares; /* sum of the root squares of a block ( energy ) */ - t_float x_phase; /* phase to apply on output */ - t_outlet *x_recordend; /* outlet for end of recording */ - t_outlet *x_playend; /* outlet for end of playing back */ - t_float x_f; /* float needed for signal input */ - -} t_samplebox; - - /* clean up */ -static void samplebox_free(t_samplebox *x) -{ - if ( x->x_rdata != NULL ) { - freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_idata != NULL ) { - freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_rootsquares != NULL ) { - freebytes(x->x_rootsquares, x->x_size*sizeof(float) ); - post( "Freed %d bytes", x->x_size*sizeof(float) ); - x->x_rootsquares = NULL; - } -} - - /* allocate tables for storing sound */ -static t_int samplebox_allocate(t_samplebox *x) -{ - if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_rootsquares = getbytes( x->x_size*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", x->x_size*sizeof(float) ); - } - return 0; -} - - /* reallocate tables for storing sound */ -static t_int samplebox_reallocate(t_samplebox *x, t_int ioldsize, t_int inewsize) -{ - t_float *prdata=x->x_rdata, *pidata=x->x_idata, *prootsquares=x->x_rootsquares; - - if ( !(x->x_rdata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_rootsquares = getbytes( inewsize*sizeof(float) ) ) ) { - return -1; - } else { - post( "samplebox~ : allocated %d bytes", inewsize*sizeof(float) ); - } - if ( prdata != NULL ) { - freebytes(prdata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - if ( pidata != NULL ) { - freebytes(pidata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - if ( prootsquares != NULL ) { - freebytes(prootsquares, ioldsize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*sizeof(float) ); - } - return 0; -} - - /* records or playback the sonogram */ -static t_int *samplebox_perform(t_int *w) -{ - t_float *rin = (t_float *)(w[1]); - t_float *iin = (t_float *)(w[2]); - t_float *rout = (t_float *)(w[3]); - t_float *iout = (t_float *)(w[4]); - t_float fspectrum = 0.0; - t_float fphase = 0.0; - t_int rpoint; - t_int n = (int)(w[5]); /* number of samples */ - t_samplebox *x = (t_samplebox *)(w[6]); - t_int bi; - t_float v[4]; - t_float z[4]; - - // reallocate tables if blocksize has been changed - if ( n != x->x_blocksize ) { - post( "samplebox~ : reallocating tables" ); - x->x_allocate = 1; - samplebox_free(x); - x->x_blocksize = n; - samplebox_allocate(x); - x->x_allocate = 0; - } - - // new block : energy is set to zero - // if ( x->x_record ) { - // *(x->x_rootsquares+x->x_writepos) = 0.0; - // } - - if ( x->x_play || x->x_record ) { - bi = 0; - while (bix_allocate && x->x_record) { - *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=*rin; - *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=*iin; - // *(x->x_rootsquares+x->x_writepos) += sqrt( pow((*rin),2) + pow((*iin),2) ); - } - // set outputs - if ( !x->x_allocate && x->x_play) { - *rout = 0.; - *iout = 0.; - // interpolates 4 points like tabread4 - rpoint = ((int)x->x_readpos*x->x_blocksize)+bi; - - if ( rpoint == 0 ) { - v[0]=0.0; - v[1]=*(x->x_rdata+rpoint); - v[2]=*(x->x_rdata+rpoint+1); - v[3]=*(x->x_rdata+rpoint+2); - z[0]=0.0; - z[1]=*(x->x_idata+rpoint); - z[2]=*(x->x_idata+rpoint+1); - z[3]=*(x->x_idata+rpoint+2); - } else if ( rpoint == (x->x_size*x->x_blocksize-1) ) { - v[0]=*(x->x_rdata+rpoint-1); - v[1]=*(x->x_rdata+rpoint); - v[2]=*(x->x_rdata+rpoint+1); - v[3]=0.0; - z[0]=*(x->x_idata+rpoint-1); - z[1]=*(x->x_idata+rpoint); - z[2]=*(x->x_idata+rpoint+1); - z[3]=0.0; - } else if ( rpoint == (x->x_size*x->x_blocksize) ) { - v[0]=*(x->x_rdata+rpoint-1); - v[1]=*(x->x_rdata+rpoint); - v[2]=0.0; - v[3]=0.0; - z[0]=*(x->x_idata+rpoint-1); - z[1]=*(x->x_idata+rpoint); - z[2]=0.0; - z[3]=0.0; - } else { - v[0]=*(x->x_rdata+rpoint-1); - v[1]=*(x->x_rdata+rpoint); - v[2]=*(x->x_rdata+rpoint+1); - v[3]=*(x->x_rdata+rpoint+2); - z[0]=*(x->x_idata+rpoint-1); - z[1]=*(x->x_idata+rpoint); - z[2]=*(x->x_idata+rpoint+1); - z[3]=*(x->x_idata+rpoint+2); - } - - { - t_float frac = rpoint-(int)rpoint; - - // taken from tabread4_tilde - *rout = v[1]+frac*((v[2]-v[1])-0.5f*(frac-1.)*((v[0]-v[3]+3.0f*(v[2]-v[1]))*frac+(2.0f*v[1]-v[0]-v[2]))); - *iout = z[1]+frac*((z[2]-z[1])-0.5f*(frac-1.)*((z[0]-z[3]+3.0f*(z[2]-z[1]))*frac+(2.0f*z[1]-z[0]-z[2]))); - } - - // add phase argument - fspectrum = sqrt( pow( *rout, 2) + pow( *iout, 2) ); - fphase = atan2( *iout, *rout ); - fphase += (x->x_phase/180.0)*(M_PI); - *rout = fspectrum*cos( fphase ); - *iout = fspectrum*sin( fphase ); - } else { - *rout=0.0; - *iout=0.0; - } - rout++;iout++; - rin++;iin++; - bi++; - } - // reset playing position until next play - if ( x->x_play ) { - x->x_readpos+=x->x_readspeed; - // post( "xreadpos : %f (added %f)", x->x_readpos, x->x_readspeed ); - if ( x->x_readpos >= (x->x_readend*x->x_size)/100 ) { - x->x_play=0; - x->x_readpos=(x->x_readstart*x->x_size)/100; - // post( "samplebox~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_playend); - } - } - // reset recording position until next record - if ( x->x_record ) { - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - outlet_bang(x->x_recordend); - // post( "samplebox~ : stopped recording" ); - } - } - } - return (w+7); -} - -static void samplebox_dsp(t_samplebox *x, t_signal **sp) -{ - dsp_add(samplebox_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); -} - - /* record the sonogram */ -static void samplebox_record(t_samplebox *x) -{ - x->x_record=1; - x->x_writepos=0; -} - - /* play the sonogram */ -static void samplebox_play(t_samplebox *x) -{ - x->x_play=1; - // reset read position - x->x_readpos=(x->x_readstart*x->x_size)/100; -} - - /* setting the starting point for reading ( in percent ) */ -static void samplebox_readstart(t_samplebox *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_readend ) { - x->x_readstart = x->x_readend; - post( "samplebox~ : warning : range for reading is null" ); - } else { - x->x_readstart=startpoint; - } -} - - /* setting the starting point for modification ( in percent ) */ -static void samplebox_modstart(t_samplebox *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_modend ) { - x->x_modstart = x->x_modend; - post( "samplebox~ : warning : range for modifications is null" ); - } else { - x->x_modstart=startpoint; - } -} - - /* setting the ending point for reading ( in percent ) */ -static void samplebox_readend(t_samplebox *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_readstart ) { - x->x_readend = x->x_readstart; - post( "samplebox~ : warning : range for reading is null" ); - } else { - x->x_readend=endpoint; - } -} - - /* setting the ending point for modification ( in percent ) */ -static void samplebox_modend(t_samplebox *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_modstart ) { - x->x_modend = x->x_modstart; - post( "samplebox~ : warning : range for modifications is null" ); - } else { - x->x_modend=endpoint; - } -} - - /* sets the reading speed */ -static void samplebox_readspeed(t_samplebox *x, t_floatarg freadspeed) -{ - if ((int)freadspeed < 0 ) { - post( "samplebox~ : wrong readspeed argument" ); - } - x->x_readspeed=freadspeed; -} - - /* resize sonogram */ -static void samplebox_resize(t_samplebox *x, t_floatarg fnewsize ) -{ - if (fnewsize <= 0) { - post( "samplebox~ : error : wrong size" ); - return; - } - post( "samplebox~ : reallocating tables" ); - x->x_record = 0; - x->x_play = 0; - x->x_allocate = 1; - samplebox_reallocate(x, x->x_size, fnewsize); - x->x_size = fnewsize; - x->x_allocate = 0; -} - - /* flip blocks */ -static void samplebox_flipblocks(t_samplebox *x) -{ - t_int samplestart, sampleend, middlesample, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - middlesample = ( sampleend+samplestart+1 ) / 2; - post( "flip blocks [%d,%d] and [%d,%d]", samplestart, middlesample, middlesample, sampleend ); - - for ( si=samplestart; si<=middlesample; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - } - } -} - - /* change the phase */ -static void samplebox_phase(t_samplebox *x, t_floatarg fincphase) -{ - if (fincphase < 0 || fincphase > 90) { - post( "samplebox~ : error : wrong phase in phase function : out of [0,90]" ); - return; - } - x->x_phase = fincphase; -} - - /* swap blocks */ -static void samplebox_swapblocks(t_samplebox *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) -{ - t_int samplestart, samplestartb, samplesize, sp, sf; - t_int iperstart, iperend, ipersize; - t_float s1, s2; - t_float fvalue; - - iperstart = fperstart; - iperend = fperend; - ipersize = fpersize; - - if (iperstart < 0 || iperstart > iperend || - iperend <= 0 || iperend+ipersize > 100 || - ipersize < 0 || fpersize > 100 ) { - post( "samplebox~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", - iperstart, iperstart+ipersize, iperend, iperend+ipersize ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - samplestartb=(x->x_modend*(x->x_size-1))/100; - samplesize=((samplestartb-samplestart)*ipersize)/100; - samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; - samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; - - // post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); - - for ( sp=samplesize; sp>=0; sp-- ) { - for ( sf=0; sfx_blocksize; sf++) { - fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - } - } -} - -static void *samplebox_new(t_floatarg fsize) -{ - t_samplebox *x = (t_samplebox *)pd_new(samplebox_class); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_recordend = outlet_new(&x->x_obj, &s_bang ); - x->x_playend = outlet_new(&x->x_obj, &s_bang ); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); - - if ( fsize <= 0 ) { - error( "samplebox~ : missing or negative creation arguments" ); - return NULL; - } - - x->x_size = fsize; - x->x_blocksize = sys_getblksize(); - x->x_play = 0; - x->x_readspeed = 1.; - x->x_record = 0; - x->x_readpos = 0.; - x->x_writepos = 0; - x->x_modstart = 0; - x->x_readstart = 0; - x->x_modend = 100; - x->x_readend = 100; - x->x_allocate = 0; - x->x_rdata = NULL; - x->x_idata = NULL; - x->x_rootsquares = NULL; - x->x_phase = 0.0; - x->x_samplerate = sys_getsr(); - if ( samplebox_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } -} - -void samplebox_tilde_setup(void) -{ - post(samplebox_version); - samplebox_class = class_new(gensym("samplebox~"), (t_newmethod)samplebox_new, (t_method)samplebox_free, - sizeof(t_samplebox), 0, A_DEFFLOAT, 0); - CLASS_MAINSIGNALIN( samplebox_class, t_samplebox, x_f ); - class_addmethod(samplebox_class, (t_method)samplebox_dsp, gensym("dsp"), 0); - class_addmethod(samplebox_class, (t_method)samplebox_record, gensym("record"), 0); - class_addmethod(samplebox_class, (t_method)samplebox_resize, gensym("resize"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_flipblocks, gensym("flipblocks"), 0); - class_addmethod(samplebox_class, (t_method)samplebox_play, gensym("play"), 0); - class_addmethod(samplebox_class, (t_method)samplebox_phase, gensym("phase"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_modstart, gensym("modstart"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_modend, gensym("modend"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_readstart, gensym("readstart"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_readend, gensym("readend"), A_FLOAT, 0); - class_addmethod(samplebox_class, (t_method)samplebox_readspeed, gensym("readspeed"), A_FLOAT, 0); -} diff --git a/scratcher~-help.pd b/scratcher~-help.pd new file mode 100644 index 0000000..4a9149c --- /dev/null +++ b/scratcher~-help.pd @@ -0,0 +1,7 @@ +#N canvas 0 0 450 300 10; +#X obj 174 121 rs-scratcher~; +#X text 201 77 Playing with the block size \,; +#X text 201 87 so everything's in the subpatch; +#X obj 171 160 dac~; +#X connect 0 0 3 0; +#X connect 0 0 3 1; diff --git a/scratcher~.c b/scratcher~.c new file mode 100644 index 0000000..8fec927 --- /dev/null +++ b/scratcher~.c @@ -0,0 +1,820 @@ +/*------------------------ scratcher~ ------------------------------------------ */ +/* */ +/* scratcher~ : lets you record, and then, scratch a sound. */ +/* constructor : scratcher~ */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "I've lost my kids and wife" */ +/* "Because I got high da da dap da da dap" */ +/* Afro Man -- Because I Got High */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define M_PI 3.14159265358979323846 +#else +#include +#endif + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + + +static int guidebug=0; +static int ignorevisible=1; // ignore visible test + // because this seems to lead to bad refresh + // wait for a fix + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +#define DEFAULT_SCRATCHER_SIZE 88200 // 2 seconds at 44100 hertz +#define DEFAULT_SCRATCHER_WIDTH 200 +#define DEFAULT_SCRATCHER_HEIGHT 200 +#define DEFAULT_SCRATCHER_SENSIBILITY 25 +#define DEFAULT_SCRATCHER_MAX_SPEED 2.0 +#define DEFAULT_TURNTABLE_INERTIA 0.01 + +#define SCRATCHER_NB_GROOVES 20 +#define SCRATCHER_MOVE_TIMEOUT 20 + +static char *scratcher_version = "scratcher~: version 0.10, written by Yves Degoyon (ydegoyon@free.fr)"; + +static t_class *scratcher_class; +t_widgetbehavior scratcher_widgetbehavior; + +typedef struct _scratcher +{ + t_object x_obj; + + t_int x_size; /* size of the recorded sound ( in samples ) */ + t_float x_samplerate; /* sample rate */ + t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ + t_float x_readpos; /* data's playing position */ + t_int x_writepos; /* data's recording position */ + t_int x_play; /* playing on/off flag */ + t_float x_readspeed; /* number of grouped blocks for reading */ + t_float x_maxspeed; /* maximum speed limit */ + t_float x_record; /* flag to start recording process */ + t_int x_empty; /* flag to indicate it's a brand new scratcher */ + t_float x_speedinc; /* speed increment */ + long long x_lastmovetime; /* instant ( in ms ) of the last movement */ + t_float *x_sdata; /* sound data */ + t_int x_sensibility; /* sensibility ( amount of change for a dy ) */ + t_int x_motioned; /* flag to indicate the mouse motion */ + t_int x_mousemoved; /* flag to indicate the mouse movement */ + t_float x_inertia; /* turntable inertia */ + + /* graphical data block */ + t_int x_selected; /* flag to remember if we are seleted or not */ + t_int x_width; /* width of the graphical object */ + t_int x_height; /* height of the graphical object */ + t_int x_showspeed; /* toggle on/off speed line */ + t_glist *x_glist; /* keep graphic context for various operations */ + + t_float x_f; /* float needed for signal input */ + +} t_scratcher; + +/* ------------------------ drawing functions ---------------------------- */ + +static void scratcher_draw_new(t_scratcher *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int ci; + + SYS_VGUI7(".x%x.c create oval %d %d %d %d -fill #000000 -tags %xSCRATCHER\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height, + x); + for ( ci=0; cix_obj, glist) + ci*x->x_width/(2*SCRATCHER_NB_GROOVES), + text_ypix(&x->x_obj, glist) + ci*x->x_height/(2*SCRATCHER_NB_GROOVES), + text_xpix(&x->x_obj, glist) + x->x_width - ci*x->x_width/(2*SCRATCHER_NB_GROOVES), + text_ypix(&x->x_obj, glist) + x->x_height - ci*x->x_height/(2*SCRATCHER_NB_GROOVES), + x, ci); + } + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", + canvas, text_xpix(&x->x_obj, glist)+x->x_width/2, + text_ypix(&x->x_obj, glist)+x->x_height/2, + text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), + text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), + x ); + } + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xFSCRATCHER\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, + text_ypix(&x->x_obj, glist) + x->x_height, + x); + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void scratcher_draw_delete(t_scratcher *x, t_glist *glist) +{ + t_int ci; + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( glist ) ) + { + SYS_VGUI3( ".x%x.c delete %xSCRATCHER\n", canvas, x ); + SYS_VGUI3( ".x%x.c delete %xFSCRATCHER\n", canvas, x ); + SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); + for ( ci=0; cix_glist ) ) + { + SYS_VGUI7(".x%x.c coords %xSCRATCHER %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)-1, text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist)+x->x_width+1, + text_ypix(&x->x_obj, glist)+x->x_height+1); + SYS_VGUI7(".x%x.c coords %xFSCRATCHER %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)-1, text_ypix(&x->x_obj, glist)-1, + text_xpix(&x->x_obj, glist)+x->x_width+1, + text_ypix(&x->x_obj, glist)+x->x_height+1); + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)+x->x_width/2, + text_ypix(&x->x_obj, glist)+x->x_height/2, + text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), + text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) + ); + } + for ( ci=0; cix_obj, glist) + ci*x->x_width/(2*SCRATCHER_NB_GROOVES), + text_ypix(&x->x_obj, glist) + ci*x->x_height/(2*SCRATCHER_NB_GROOVES), + text_xpix(&x->x_obj, glist) + x->x_width - ci*x->x_width/(2*SCRATCHER_NB_GROOVES), + text_ypix(&x->x_obj, glist) + x->x_height - ci*x->x_height/(2*SCRATCHER_NB_GROOVES) + ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); + } +} + +static void scratcher_draw_select(t_scratcher* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( x->x_glist ) ) + { + if(x->x_selected) + { + } + else + { + } + } +} + +/* ------------------------ widget callbacks ----------------------------- */ + + +static void scratcher_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_scratcher* x = (t_scratcher*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void scratcher_save(t_gobj *z, t_binbuf *b) +{ + t_scratcher *x = (t_scratcher *)z; + + binbuf_addv(b, "ssiisiiiiff", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_size, x->x_width, x->x_height, + x->x_sensibility, x->x_maxspeed, x->x_inertia ); + binbuf_addv(b, ";"); +} + +static void scratcher_select(t_gobj *z, t_glist *glist, int selected) +{ + t_scratcher *x = (t_scratcher *)z; + + x->x_selected = selected; + scratcher_draw_select( x, glist ); +} + +static void scratcher_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_scratcher *x = (t_scratcher *)z; + t_rtext *y; + + if (vis) + { + scratcher_draw_new( x, glist ); + } + else + { + scratcher_draw_delete( x, glist ); + } +} + +static void scratcher_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void scratcher_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_scratcher *x = (t_scratcher *)z; + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + + scratcher_draw_move( x, glist ); +} + +static void scratcher_motion(t_scratcher *x, t_floatarg dx, t_floatarg dy) +{ + struct timeval tv; + struct timezone tz; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + // post( "scratcher_motion dx=%f dy=%f", dx, dy ); + + x->x_speedinc += dy / x->x_sensibility; + + x->x_mousemoved = 1; + // get current time in ms + gettimeofday( &tv, &tz ); + x->x_lastmovetime = tv.tv_sec*1000 + tv.tv_usec/1000; + // post( "scratcher~ : move time : %ld", x->x_lastmovetime ); + + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) + ); + } +} + +static void scratcher_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_scratcher *x=(t_scratcher *)z; + + sprintf(buf, "pdtk_scratcher_dialog %%s %d %d\n", + x->x_width, x->x_height ); + // post("scratcher_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void scratcher_dialog(t_scratcher *x, t_symbol *s, int argc, t_atom *argv) +{ + if ( !x ) { + post( "scratcher : error :tried to set properties on an unexisting object" ); + } + if ( argc != 2 ) + { + post( "scratcher : error in the number of arguments ( %d instead of 2 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT ) { + post( "scratcher : wrong arguments" ); + return; + } + x->x_width = (int)argv[0].a_w.w_float; + x->x_height = (int)argv[1].a_w.w_float; + scratcher_draw_delete(x, x->x_glist); + scratcher_draw_new(x, x->x_glist); +} + + /* reset reading speed */ +static void scratcher_reset(t_scratcher *x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_readspeed=1.; + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) + ); + } +} + +static int scratcher_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_scratcher* x = (t_scratcher *)z; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + // post( "scratcher_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); + if ( doit ) + { + // activate motion callback + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scratcher_motion, + 0, xpix, ypix ); + x->x_readspeed=0.; + x->x_motioned = 1; + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist)+x->x_width/2, + text_ypix(&x->x_obj, glist)+x->x_height/2, + text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), + text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) + ); + } + } + else + { + if ( x->x_play ) scratcher_reset(x); + x->x_motioned = 0; + } + return (1); +} + + /* clean up */ +static void scratcher_free(t_scratcher *x) +{ + if ( x->x_sdata != NULL ) { + freebytes(x->x_sdata, x->x_size*sizeof(t_float) ); + post( "scratcher~ : freed %d bytes", x->x_size*sizeof(t_float) ); + x->x_sdata = NULL; + } +} + + /* allocate tables for storing sample data */ +static t_int scratcher_allocate(t_scratcher *x) +{ + if ( !(x->x_sdata = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "scratcher~ : could not allocate %d bytes", x->x_size*sizeof(t_float) ); + return -1; + } else { + post( "scratcher~ : allocated %d bytes", x->x_size*sizeof(t_float) ); + } + return 0; +} + + /* reallocate tables for storing sample data */ +static t_int scratcher_reallocate(t_scratcher *x, t_int ioldsize, t_int inewsize) +{ + t_float *pdata; + + pdata = x->x_sdata; + if ( !(x->x_sdata = getbytes( inewsize*sizeof(float) ) ) ) { + post( "scratcher~ : could not allocate %d bytes", inewsize*sizeof(t_float) ); + return -1; + } else { + post( "scratcher~ : allocated %d bytes", inewsize*sizeof(t_float) ); + } + if ( pdata != NULL ) { + freebytes(pdata, ioldsize*sizeof(t_float) ); + post( "scratcher~ : freed %d bytes", ioldsize*sizeof(t_float) ); + } + return 0; +} + + /* records or playback the scratcher */ +static t_int *scratcher_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_int n = (int)(w[3]); /* number of samples */ + t_scratcher *x = (t_scratcher *)(w[4]); + struct timeval tv; + struct timezone tz; + long long perftime = 0L; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_readspeed += x->x_speedinc; + if ( x->x_readspeed > x->x_maxspeed ) + { + x->x_readspeed = x->x_maxspeed; + } + if ( x->x_readspeed < -x->x_maxspeed ) + { + x->x_readspeed = -x->x_maxspeed; + } + x->x_speedinc = 0; + + // if the mouse hasn't moved for a certain time, reset speed + + if ( x->x_mousemoved ) + { + // get current time in ms + gettimeofday( &tv, &tz ); + perftime = tv.tv_sec*1000 + tv.tv_usec/1000; + if ( perftime - x->x_lastmovetime > SCRATCHER_MOVE_TIMEOUT ) + { + // post( "scratcher~ : mouse timeout (m=%ld)", perftime ); + // post( "scratcher~ : (m=%ld)", x->x_lastmovetime ); + if ( x->x_readspeed > 0. ) + { + x->x_readspeed -= x->x_inertia; + // post( "scratcher~ : dec speed" ); + } + if ( x->x_readspeed < 0. ) + { + x->x_readspeed += x->x_inertia; + // post( "scratcher~ : inc speed" ); + } + if ( ( x->x_readspeed <= x->x_inertia && x->x_readspeed > 0 ) || + ( x->x_readspeed >= -x->x_inertia && x->x_readspeed < 0 ) ) + { + x->x_mousemoved = 0; + x->x_readspeed = 0.; + } + if ( x->x_showspeed ) + { + SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) + ); + } + } + } + + while (n--) { + // eventually records input + if ( x->x_record) { + *(x->x_sdata+x->x_writepos)=*in; + x->x_writepos++; + if ( x->x_writepos >= x->x_size ) { + x->x_record=0; + x->x_writepos=0; + if ( x->x_empty ) x->x_empty = 0; + // post( "scratcher~ : stopped recording" ); + } + } + // set outputs + if ( x->x_play) { + *out = *(x->x_sdata+(int)x->x_readpos); + x->x_readpos+=x->x_readspeed; + if ( x->x_readpos < 0 ) x->x_readpos = x->x_size-1; + if ( x->x_readpos >= x->x_size ) x->x_readpos = 0; + } else { + *out=0.0; + } + + in++;out++; + } + + return (w+5); +} + +static void scratcher_dsp(t_scratcher *x, t_signal **sp) +{ + dsp_add(scratcher_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x); +} + + /* play the sound */ +static void scratcher_play(t_scratcher *x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_play=1; + // reset read position + x->x_readpos=0; + x->x_readspeed=1.; + if ( x->x_showspeed ) + { + SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", + canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), + x ); + } +} + + /* stop playing */ +static void scratcher_stop(t_scratcher *x) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_play=0; + // reset read position + x->x_readpos=0; + x->x_readspeed=0.; + if ( x->x_showspeed ) + { + SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", + canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), + x ); + } +} + + /* record the sound */ +static void scratcher_record(t_scratcher *x) +{ + scratcher_stop(x); + x->x_record=1; + x->x_writepos=0; +} + + /* resize sound */ +static void scratcher_resize(t_scratcher *x, t_floatarg fnewsize ) +{ + t_int dspstate; + struct timespec ts; + + if (fnewsize <= 0) { + post( "scratcher~ : error : wrong size" ); + return; + } + post( "scratcher~ : reallocating tables" ); + x->x_record = 0; + x->x_play = 0; + + scratcher_reallocate(x, x->x_size, fnewsize); + x->x_size = fnewsize; +} + + /* set sensibility */ +static void scratcher_sensibility(t_scratcher *x, t_floatarg fsensibility ) +{ + if (fsensibility <= 0) { + post( "scratcher~ : error : wrong sensibility" ); + return; + } + x->x_sensibility = fsensibility; +} + + /* set maximum speed */ +static void scratcher_maxspeed(t_scratcher *x, t_floatarg fmaxspeed ) +{ + if (fmaxspeed < 0) { + post( "scratcher~ : error : wrong maximum speed" ); + return; + } + x->x_maxspeed = fmaxspeed; +} + + /* set turntable inertia */ +static void scratcher_inertia(t_scratcher *x, t_floatarg finertia ) +{ + if (finertia < 0) { + post( "scratcher~ : error : wrong inertia" ); + return; + } + x->x_inertia = finertia; +} + + /* toggle speed line */ +static void scratcher_showspeed(t_scratcher *x, t_floatarg fshowspeed ) +{ + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (fshowspeed == 0) { + x->x_showspeed = 0; + SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); + } + else + { + x->x_showspeed = 1; + SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", + canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, + text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), + text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), + x ); + } +} + +static void *scratcher_new(t_symbol *s, int argc, t_atom *argv) +{ + t_scratcher *x = (t_scratcher *)pd_new(scratcher_class); + outlet_new(&x->x_obj, &s_signal); + + // new scratcher created from the gui + if ( argc != 0 ) + { + if ( argc < 3 ) + { + post( "scratcher~ : error in the number of arguments ( < 3 )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || + argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT ) { + post( "scratcher~ : wrong arguments" ); + return NULL; + } + x->x_size = argv[0].a_w.w_float; + x->x_width = argv[1].a_w.w_float; + x->x_height = argv[2].a_w.w_float; + if ( argc >= 4 ) + { + x->x_sensibility = argv[3].a_w.w_float; + } + else + { + x->x_sensibility = DEFAULT_SCRATCHER_SENSIBILITY; + } + if ( argc >= 5 ) + { + x->x_maxspeed = argv[4].a_w.w_float; + } + else + { + x->x_maxspeed = DEFAULT_SCRATCHER_MAX_SPEED; + } + if ( argc >= 6 ) + { + x->x_inertia = argv[5].a_w.w_float; + } + else + { + x->x_inertia = DEFAULT_TURNTABLE_INERTIA; + } + } + else + { + x->x_size = DEFAULT_SCRATCHER_SIZE; + x->x_width = DEFAULT_SCRATCHER_WIDTH; + x->x_height = DEFAULT_SCRATCHER_HEIGHT; + x->x_sensibility = DEFAULT_SCRATCHER_SENSIBILITY; + x->x_maxspeed = DEFAULT_SCRATCHER_MAX_SPEED; + x->x_inertia = DEFAULT_TURNTABLE_INERTIA; + } + + x->x_play = 0; + x->x_record = 0; + x->x_readspeed = 1.; + x->x_readpos = 0.; + x->x_speedinc = 0.; + x->x_writepos = 0; + x->x_sdata = NULL; + x->x_empty = 1; + x->x_showspeed = 1; + x->x_mousemoved = 0; + x->x_lastmovetime = 0L; + x->x_selected = 0; + x->x_glist = (t_glist*)canvas_getcurrent(); + + // activate graphical callbacks + class_setwidget(scratcher_class, &scratcher_widgetbehavior); + + // post( "scratcher~ : new scratcher : size = %d", x->x_size ); + if ( scratcher_allocate(x) <0 ) { + return NULL; + } else { + return(x); + } + +} + +void scratcher_tilde_setup(void) +{ + post(scratcher_version); + scratcher_class = class_new(gensym("scratcher~"), (t_newmethod)scratcher_new, (t_method)scratcher_free, + sizeof(t_scratcher), 0, A_GIMME, 0); + + + // set callbacks + scratcher_widgetbehavior.w_getrectfn = scratcher_getrect; + scratcher_widgetbehavior.w_displacefn = scratcher_displace; + scratcher_widgetbehavior.w_selectfn = scratcher_select; + scratcher_widgetbehavior.w_activatefn = NULL; + scratcher_widgetbehavior.w_deletefn = scratcher_delete; + scratcher_widgetbehavior.w_visfn = scratcher_vis; + scratcher_widgetbehavior.w_clickfn = scratcher_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(scratcher_class, scratcher_properties); + class_setsavefn(scratcher_class, scratcher_save); +#else + scratcher_widgetbehavior.w_propertiesfn = scratcher_properties; + scratcher_widgetbehavior.w_savefn = scratcher_save; +#endif + + CLASS_MAINSIGNALIN( scratcher_class, t_scratcher, x_f ); + class_addmethod(scratcher_class, (t_method)scratcher_dsp, gensym("dsp"), A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_record, gensym("record"), A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_resize, gensym("resize"), A_FLOAT, A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_sensibility, gensym("sensibility"), A_FLOAT, A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_maxspeed, gensym("maxspeed"), A_FLOAT, A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_inertia, gensym("inertia"), A_FLOAT, A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_showspeed, gensym("showspeed"), A_FLOAT, A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_play, gensym("play"), A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_stop, gensym("stop"), A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_reset, gensym("reset"), A_NULL); + class_addmethod(scratcher_class, (t_method)scratcher_dialog, gensym("dialog"), A_GIMME, A_NULL); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + scratcher_class->c_externdir->s_name, + scratcher_class->c_name->s_name); +} diff --git a/scratcher~.tcl b/scratcher~.tcl new file mode 100644 index 0000000..bc8ad6f --- /dev/null +++ b/scratcher~.tcl @@ -0,0 +1,77 @@ +############ scratcher procedures -- ydegoyon@free.fr ######### + +proc scratcher_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc scratcher_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc scratcher_ok {id} { + scratcher_apply $id + scratcher_cancel $id +} + +proc pdtk_scratcher_dialog {id width height} { + set vid [string trimleft $id .] + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + + set $var_graph_width $width + set $var_graph_height $height + + toplevel $id + wm title $id {scratcher} + wm protocol $id WM_DELETE_WINDOW [concat scratcher_cancel $id] + + label $id.label -text {SCRATCHER PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "scratcher_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "scratcher_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "scratcher_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + bind $id.1rangef.name [concat scratcher_ok $id] + bind $id.2rangef.height [concat scratcher_ok $id] + focus $id.1rangef.name +} + +############ scratcher procedures END -- ydegoyon@free.fr ######### diff --git a/scratcher~/INSTALL b/scratcher~/INSTALL deleted file mode 100644 index a99e2c1..0000000 --- a/scratcher~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/scratcher~ - -make clean - -make - -make install - -open help-scratcher~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/scratcher~/rs-scratcher~.pd b/scratcher~/rs-scratcher~.pd deleted file mode 100644 index 87b0026..0000000 --- a/scratcher~/rs-scratcher~.pd +++ /dev/null @@ -1,103 +0,0 @@ -#N canvas 106 13 862 585 10; -#X msg 36 550 \; pd dsp 1; -#X msg 101 551 \; pd dsp 0; -#X text 24 13 Scratcher~ : lets you record a sound; -#X text 23 24 and \, then \, scratch it !!!; -#X text 599 557 Comments and bugs @ ydegoyon@free.fr; -#X obj 313 260 scratcher~ 151290 200 200 200 2 1e-04; -#X obj 302 475 *~ 1; -#X obj 334 474 / 100; -#X floatatom 373 474 5 0 0; -#X msg 31 88 bang; -#X obj 31 108 openpanel; -#X msg 33 227 resize \$1; -#X obj 31 130 t s b; -#X obj 31 168 pack s s; -#X msg 33 189 read -resize \$1 \$2; -#X obj 77 128 float \$0; -#X obj 100 168 makefilename %d-sonosample; -#X text 32 68 Step 1 : Load a sound file; -#X obj 31 147 route float; -#X text 84 80 ( a small one ); -#X msg 524 45 play; -#X text 522 24 Step 3 : Play the sound and scratch with the mouse; -#X msg 559 45 stop; -#X msg 527 243 reset; -#X text 572 246 Reset normal reading speed; -#X obj 36 524 loadbang; -#X text 469 493 Note : the red line indicates the reading speed; -#X text 446 527 Note 2 : only vertical movement will change reading -speed; -#X obj 176 557 table \$0-sonosample; -#X msg 524 88 sensibility \$1; -#X msg 561 65 25; -#X floatatom 659 66 5 0 0; -#X msg 524 66 5; -#X text 620 88 Set mouse sensibility ( default : 25 ); -#X obj 33 206 soundfiler; -#X msg 607 223 showspeed 1; -#X msg 527 223 showspeed 0; -#X text 687 221 Toggle speed line display; -#X msg 305 119 record; -#X msg 269 119 bang; -#X text 214 98 Step 2 : Record the sound; -#X floatatom 664 120 5 0 0; -#X msg 526 141 maxspeed \$1; -#X text 603 140 Set speed limit ( default : 2 ); -#X msg 526 119 2; -#X msg 569 119 1.5; -#X msg 603 119 1; -#X msg 635 119 0.5; -#X obj 257 146 tabplay~ \$0-sonosample; -#X msg 592 65 100; -#X msg 622 65 200; -#X floatatom 645 174 5 0 0; -#X text 603 193 Set turntable inertia ( default : 0.01 ); -#X msg 525 193 inertia \$1; -#X msg 609 173 0.01; -#X msg 570 173 0.001; -#X msg 526 173 1e-04; -#X obj 289 509 outlet~; -#X connect 5 0 6 0; -#X connect 6 0 57 0; -#X connect 7 0 6 1; -#X connect 8 0 7 0; -#X connect 9 0 10 0; -#X connect 10 0 12 0; -#X connect 11 0 5 0; -#X connect 12 0 13 0; -#X connect 12 1 15 0; -#X connect 13 0 14 0; -#X connect 14 0 34 0; -#X connect 15 0 18 0; -#X connect 16 0 13 1; -#X connect 18 0 16 0; -#X connect 20 0 5 0; -#X connect 22 0 5 0; -#X connect 23 0 5 0; -#X connect 25 0 0 0; -#X connect 29 0 5 0; -#X connect 30 0 29 0; -#X connect 31 0 29 0; -#X connect 32 0 29 0; -#X connect 34 0 11 0; -#X connect 35 0 5 0; -#X connect 36 0 5 0; -#X connect 38 0 5 0; -#X connect 39 0 38 0; -#X connect 39 0 48 0; -#X connect 41 0 42 0; -#X connect 42 0 5 0; -#X connect 44 0 42 0; -#X connect 45 0 42 0; -#X connect 46 0 42 0; -#X connect 47 0 42 0; -#X connect 48 0 5 0; -#X connect 48 0 6 0; -#X connect 49 0 29 0; -#X connect 50 0 29 0; -#X connect 51 0 53 0; -#X connect 53 0 5 0; -#X connect 54 0 53 0; -#X connect 55 0 53 0; -#X connect 56 0 53 0; diff --git a/scratcher~/scratcher~-help.pd b/scratcher~/scratcher~-help.pd deleted file mode 100644 index 4a9149c..0000000 --- a/scratcher~/scratcher~-help.pd +++ /dev/null @@ -1,7 +0,0 @@ -#N canvas 0 0 450 300 10; -#X obj 174 121 rs-scratcher~; -#X text 201 77 Playing with the block size \,; -#X text 201 87 so everything's in the subpatch; -#X obj 171 160 dac~; -#X connect 0 0 3 0; -#X connect 0 0 3 1; diff --git a/scratcher~/scratcher~.c b/scratcher~/scratcher~.c deleted file mode 100644 index 6adba91..0000000 --- a/scratcher~/scratcher~.c +++ /dev/null @@ -1,817 +0,0 @@ -/*------------------------ scratcher~ ------------------------------------------ */ -/* */ -/* scratcher~ : lets you record, and then, scratch a sound. */ -/* constructor : scratcher~ */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "I've lost my kids and wife" */ -/* "Because I got high da da dap da da dap" */ -/* Afro Man -- Because I Got High */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -#else -#include -#endif -#include -#include -#include -#include -#ifdef UNIX -#include -#endif -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif -#include - -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - - -static int guidebug=0; -static int ignorevisible=1; // ignore visible test - // because this seems to lead to bad refresh - // wait for a fix - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define DEFAULT_SCRATCHER_SIZE 88200 // 2 seconds at 44100 hertz -#define DEFAULT_SCRATCHER_WIDTH 200 -#define DEFAULT_SCRATCHER_HEIGHT 200 -#define DEFAULT_SCRATCHER_SENSIBILITY 25 -#define DEFAULT_SCRATCHER_MAX_SPEED 2.0 -#define DEFAULT_TURNTABLE_INERTIA 0.01 - -#define SCRATCHER_NB_GROOVES 20 -#define SCRATCHER_MOVE_TIMEOUT 20 - -static char *scratcher_version = "scratcher~: version 0.10, written by Yves Degoyon (ydegoyon@free.fr)"; - -static t_class *scratcher_class; -t_widgetbehavior scratcher_widgetbehavior; - -typedef struct _scratcher -{ - t_object x_obj; - - t_int x_size; /* size of the recorded sound ( in samples ) */ - t_float x_samplerate; /* sample rate */ - t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ - t_float x_readpos; /* data's playing position */ - t_int x_writepos; /* data's recording position */ - t_int x_play; /* playing on/off flag */ - t_float x_readspeed; /* number of grouped blocks for reading */ - t_float x_maxspeed; /* maximum speed limit */ - t_float x_record; /* flag to start recording process */ - t_int x_empty; /* flag to indicate it's a brand new scratcher */ - t_float x_speedinc; /* speed increment */ - long long x_lastmovetime; /* instant ( in ms ) of the last movement */ - t_float *x_sdata; /* sound data */ - t_int x_sensibility; /* sensibility ( amount of change for a dy ) */ - t_int x_motioned; /* flag to indicate the mouse motion */ - t_int x_mousemoved; /* flag to indicate the mouse movement */ - t_float x_inertia; /* turntable inertia */ - - /* graphical data block */ - t_int x_selected; /* flag to remember if we are seleted or not */ - t_int x_width; /* width of the graphical object */ - t_int x_height; /* height of the graphical object */ - t_int x_showspeed; /* toggle on/off speed line */ - t_glist *x_glist; /* keep graphic context for various operations */ - - t_float x_f; /* float needed for signal input */ - -} t_scratcher; - -/* ------------------------ drawing functions ---------------------------- */ - -static void scratcher_draw_new(t_scratcher *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int ci; - - SYS_VGUI7(".x%x.c create oval %d %d %d %d -fill #000000 -tags %xSCRATCHER\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height, - x); - for ( ci=0; cix_obj, glist) + ci*x->x_width/(2*SCRATCHER_NB_GROOVES), - text_ypix(&x->x_obj, glist) + ci*x->x_height/(2*SCRATCHER_NB_GROOVES), - text_xpix(&x->x_obj, glist) + x->x_width - ci*x->x_width/(2*SCRATCHER_NB_GROOVES), - text_ypix(&x->x_obj, glist) + x->x_height - ci*x->x_height/(2*SCRATCHER_NB_GROOVES), - x, ci); - } - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", - canvas, text_xpix(&x->x_obj, glist)+x->x_width/2, - text_ypix(&x->x_obj, glist)+x->x_height/2, - text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), - text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), - x ); - } - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -tags %xFSCRATCHER\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, - text_ypix(&x->x_obj, glist) + x->x_height, - x); - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void scratcher_draw_delete(t_scratcher *x, t_glist *glist) -{ - t_int ci; - t_canvas *canvas=glist_getcanvas(glist); - - if ( glist_isvisible( glist ) ) - { - SYS_VGUI3( ".x%x.c delete %xSCRATCHER\n", canvas, x ); - SYS_VGUI3( ".x%x.c delete %xFSCRATCHER\n", canvas, x ); - SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); - for ( ci=0; cix_glist ) ) - { - SYS_VGUI7(".x%x.c coords %xSCRATCHER %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)-1, text_ypix(&x->x_obj, glist)-1, - text_xpix(&x->x_obj, glist)+x->x_width+1, - text_ypix(&x->x_obj, glist)+x->x_height+1); - SYS_VGUI7(".x%x.c coords %xFSCRATCHER %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)-1, text_ypix(&x->x_obj, glist)-1, - text_xpix(&x->x_obj, glist)+x->x_width+1, - text_ypix(&x->x_obj, glist)+x->x_height+1); - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)+x->x_width/2, - text_ypix(&x->x_obj, glist)+x->x_height/2, - text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), - text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) - ); - } - for ( ci=0; cix_obj, glist) + ci*x->x_width/(2*SCRATCHER_NB_GROOVES), - text_ypix(&x->x_obj, glist) + ci*x->x_height/(2*SCRATCHER_NB_GROOVES), - text_xpix(&x->x_obj, glist) + x->x_width - ci*x->x_width/(2*SCRATCHER_NB_GROOVES), - text_ypix(&x->x_obj, glist) + x->x_height - ci*x->x_height/(2*SCRATCHER_NB_GROOVES) - ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void scratcher_draw_select(t_scratcher* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( glist_isvisible( x->x_glist ) ) - { - if(x->x_selected) - { - } - else - { - } - } -} - -/* ------------------------ widget callbacks ----------------------------- */ - - -static void scratcher_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_scratcher* x = (t_scratcher*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void scratcher_save(t_gobj *z, t_binbuf *b) -{ - t_scratcher *x = (t_scratcher *)z; - - binbuf_addv(b, "ssiisiiiiff", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_size, x->x_width, x->x_height, - x->x_sensibility, x->x_maxspeed, x->x_inertia ); - binbuf_addv(b, ";"); -} - -static void scratcher_select(t_gobj *z, t_glist *glist, int selected) -{ - t_scratcher *x = (t_scratcher *)z; - - x->x_selected = selected; - scratcher_draw_select( x, glist ); -} - -static void scratcher_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_scratcher *x = (t_scratcher *)z; - t_rtext *y; - - if (vis) - { - scratcher_draw_new( x, glist ); - } - else - { - scratcher_draw_delete( x, glist ); - } -} - -static void scratcher_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void scratcher_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_scratcher *x = (t_scratcher *)z; - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - - scratcher_draw_move( x, glist ); -} - -static void scratcher_motion(t_scratcher *x, t_floatarg dx, t_floatarg dy) -{ - struct timeval tv; - struct timezone tz; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - // post( "scratcher_motion dx=%f dy=%f", dx, dy ); - - x->x_speedinc += dy / x->x_sensibility; - - x->x_mousemoved = 1; - // get current time in ms - gettimeofday( &tv, &tz ); - x->x_lastmovetime = tv.tv_sec*1000 + tv.tv_usec/1000; - // post( "scratcher~ : move time : %ld", x->x_lastmovetime ); - - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) - ); - } -} - -static void scratcher_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_scratcher *x=(t_scratcher *)z; - - sprintf(buf, "pdtk_scratcher_dialog %%s %d %d\n", - x->x_width, x->x_height ); - // post("scratcher_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void scratcher_dialog(t_scratcher *x, t_symbol *s, int argc, t_atom *argv) -{ - if ( !x ) { - post( "scratcher : error :tried to set properties on an unexisting object" ); - } - if ( argc != 2 ) - { - post( "scratcher : error in the number of arguments ( %d instead of 2 )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT ) { - post( "scratcher : wrong arguments" ); - return; - } - x->x_width = (int)argv[0].a_w.w_float; - x->x_height = (int)argv[1].a_w.w_float; - scratcher_draw_delete(x, x->x_glist); - scratcher_draw_new(x, x->x_glist); -} - - /* reset reading speed */ -static void scratcher_reset(t_scratcher *x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_readspeed=1.; - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) - ); - } -} - -static int scratcher_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_scratcher* x = (t_scratcher *)z; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - // post( "scratcher_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); - if ( doit ) - { - // activate motion callback - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scratcher_motion, - 0, xpix, ypix ); - x->x_readspeed=0.; - x->x_motioned = 1; - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist)+x->x_width/2, - text_ypix(&x->x_obj, glist)+x->x_height/2, - text_xpix(&x->x_obj, glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), - text_ypix(&x->x_obj, glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) - ); - } - } - else - { - if ( x->x_play ) scratcher_reset(x); - x->x_motioned = 0; - } - return (1); -} - - /* clean up */ -static void scratcher_free(t_scratcher *x) -{ - if ( x->x_sdata != NULL ) { - freebytes(x->x_sdata, x->x_size*sizeof(t_float) ); - post( "scratcher~ : freed %d bytes", x->x_size*sizeof(t_float) ); - x->x_sdata = NULL; - } -} - - /* allocate tables for storing sample data */ -static t_int scratcher_allocate(t_scratcher *x) -{ - if ( !(x->x_sdata = getbytes( x->x_size*sizeof(float) ) ) ) { - post( "scratcher~ : could not allocate %d bytes", x->x_size*sizeof(t_float) ); - return -1; - } else { - post( "scratcher~ : allocated %d bytes", x->x_size*sizeof(t_float) ); - } - return 0; -} - - /* reallocate tables for storing sample data */ -static t_int scratcher_reallocate(t_scratcher *x, t_int ioldsize, t_int inewsize) -{ - t_float *pdata; - - pdata = x->x_sdata; - if ( !(x->x_sdata = getbytes( inewsize*sizeof(float) ) ) ) { - post( "scratcher~ : could not allocate %d bytes", inewsize*sizeof(t_float) ); - return -1; - } else { - post( "scratcher~ : allocated %d bytes", inewsize*sizeof(t_float) ); - } - if ( pdata != NULL ) { - freebytes(pdata, ioldsize*sizeof(t_float) ); - post( "scratcher~ : freed %d bytes", ioldsize*sizeof(t_float) ); - } - return 0; -} - - /* records or playback the scratcher */ -static t_int *scratcher_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *out = (t_float *)(w[2]); - t_int n = (int)(w[3]); /* number of samples */ - t_scratcher *x = (t_scratcher *)(w[4]); - struct timeval tv; - struct timezone tz; - long long perftime = 0L; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_readspeed += x->x_speedinc; - if ( x->x_readspeed > x->x_maxspeed ) - { - x->x_readspeed = x->x_maxspeed; - } - if ( x->x_readspeed < -x->x_maxspeed ) - { - x->x_readspeed = -x->x_maxspeed; - } - x->x_speedinc = 0; - - // if the mouse hasn't moved for a certain time, reset speed - - if ( x->x_mousemoved ) - { - // get current time in ms - gettimeofday( &tv, &tz ); - perftime = tv.tv_sec*1000 + tv.tv_usec/1000; - if ( perftime - x->x_lastmovetime > SCRATCHER_MOVE_TIMEOUT ) - { - // post( "scratcher~ : mouse timeout (m=%ld)", perftime ); - // post( "scratcher~ : (m=%ld)", x->x_lastmovetime ); - if ( x->x_readspeed > 0. ) - { - x->x_readspeed -= x->x_inertia; - // post( "scratcher~ : dec speed" ); - } - if ( x->x_readspeed < 0. ) - { - x->x_readspeed += x->x_inertia; - // post( "scratcher~ : inc speed" ); - } - if ( ( x->x_readspeed <= x->x_inertia && x->x_readspeed > 0 ) || - ( x->x_readspeed >= -x->x_inertia && x->x_readspeed < 0 ) ) - { - x->x_mousemoved = 0; - x->x_readspeed = 0.; - } - if ( x->x_showspeed ) - { - SYS_VGUI7( ".x%x.c coords %xSPEEDBAR %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1 )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1 )) - ); - } - } - } - - while (n--) { - // eventually records input - if ( x->x_record) { - *(x->x_sdata+x->x_writepos)=*in; - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - if ( x->x_empty ) x->x_empty = 0; - // post( "scratcher~ : stopped recording" ); - } - } - // set outputs - if ( x->x_play) { - *out = *(x->x_sdata+(int)x->x_readpos); - x->x_readpos+=x->x_readspeed; - if ( x->x_readpos < 0 ) x->x_readpos = x->x_size-1; - if ( x->x_readpos >= x->x_size ) x->x_readpos = 0; - } else { - *out=0.0; - } - - in++;out++; - } - - return (w+5); -} - -static void scratcher_dsp(t_scratcher *x, t_signal **sp) -{ - dsp_add(scratcher_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x); -} - - /* play the sound */ -static void scratcher_play(t_scratcher *x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_play=1; - // reset read position - x->x_readpos=0; - x->x_readspeed=1.; - if ( x->x_showspeed ) - { - SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", - canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), - x ); - } -} - - /* stop playing */ -static void scratcher_stop(t_scratcher *x) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_play=0; - // reset read position - x->x_readpos=0; - x->x_readspeed=0.; - if ( x->x_showspeed ) - { - SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", - canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), - x ); - } -} - - /* record the sound */ -static void scratcher_record(t_scratcher *x) -{ - scratcher_stop(x); - x->x_record=1; - x->x_writepos=0; -} - - /* resize sound */ -static void scratcher_resize(t_scratcher *x, t_floatarg fnewsize ) -{ - t_int dspstate; - struct timespec ts; - - if (fnewsize <= 0) { - post( "scratcher~ : error : wrong size" ); - return; - } - post( "scratcher~ : reallocating tables" ); - x->x_record = 0; - x->x_play = 0; - - scratcher_reallocate(x, x->x_size, fnewsize); - x->x_size = fnewsize; -} - - /* set sensibility */ -static void scratcher_sensibility(t_scratcher *x, t_floatarg fsensibility ) -{ - if (fsensibility <= 0) { - post( "scratcher~ : error : wrong sensibility" ); - return; - } - x->x_sensibility = fsensibility; -} - - /* set maximum speed */ -static void scratcher_maxspeed(t_scratcher *x, t_floatarg fmaxspeed ) -{ - if (fmaxspeed < 0) { - post( "scratcher~ : error : wrong maximum speed" ); - return; - } - x->x_maxspeed = fmaxspeed; -} - - /* set turntable inertia */ -static void scratcher_inertia(t_scratcher *x, t_floatarg finertia ) -{ - if (finertia < 0) { - post( "scratcher~ : error : wrong inertia" ); - return; - } - x->x_inertia = finertia; -} - - /* toggle speed line */ -static void scratcher_showspeed(t_scratcher *x, t_floatarg fshowspeed ) -{ - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (fshowspeed == 0) { - x->x_showspeed = 0; - SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); - } - else - { - x->x_showspeed = 1; - SYS_VGUI3( ".x%x.c delete %xSPEEDBAR\n", canvas, x ); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xSPEEDBAR -width 3\n", - canvas, text_xpix(&x->x_obj, x->x_glist)+x->x_width/2, - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2, - text_xpix(&x->x_obj, x->x_glist)+x->x_width/2 + (int)(x->x_width/2*cos( x->x_readspeed - 1. )), - text_ypix(&x->x_obj, x->x_glist)+x->x_height/2 - (int)(x->x_width/2*sin( x->x_readspeed - 1. )), - x ); - } -} - -static void *scratcher_new(t_symbol *s, int argc, t_atom *argv) -{ - t_scratcher *x = (t_scratcher *)pd_new(scratcher_class); - outlet_new(&x->x_obj, &s_signal); - - // new scratcher created from the gui - if ( argc != 0 ) - { - if ( argc < 3 ) - { - post( "scratcher~ : error in the number of arguments ( < 3 )", argc ); - return NULL; - } - if ( argv[0].a_type != A_FLOAT || - argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT ) { - post( "scratcher~ : wrong arguments" ); - return NULL; - } - x->x_size = argv[0].a_w.w_float; - x->x_width = argv[1].a_w.w_float; - x->x_height = argv[2].a_w.w_float; - if ( argc >= 4 ) - { - x->x_sensibility = argv[3].a_w.w_float; - } - else - { - x->x_sensibility = DEFAULT_SCRATCHER_SENSIBILITY; - } - if ( argc >= 5 ) - { - x->x_maxspeed = argv[4].a_w.w_float; - } - else - { - x->x_maxspeed = DEFAULT_SCRATCHER_MAX_SPEED; - } - if ( argc >= 6 ) - { - x->x_inertia = argv[5].a_w.w_float; - } - else - { - x->x_inertia = DEFAULT_TURNTABLE_INERTIA; - } - } - else - { - x->x_size = DEFAULT_SCRATCHER_SIZE; - x->x_width = DEFAULT_SCRATCHER_WIDTH; - x->x_height = DEFAULT_SCRATCHER_HEIGHT; - x->x_sensibility = DEFAULT_SCRATCHER_SENSIBILITY; - x->x_maxspeed = DEFAULT_SCRATCHER_MAX_SPEED; - x->x_inertia = DEFAULT_TURNTABLE_INERTIA; - } - - x->x_play = 0; - x->x_record = 0; - x->x_readspeed = 1.; - x->x_readpos = 0.; - x->x_speedinc = 0.; - x->x_writepos = 0; - x->x_sdata = NULL; - x->x_empty = 1; - x->x_showspeed = 1; - x->x_mousemoved = 0; - x->x_lastmovetime = 0L; - x->x_selected = 0; - x->x_glist = (t_glist*)canvas_getcurrent(); - - // activate graphical callbacks - class_setwidget(scratcher_class, &scratcher_widgetbehavior); - - // post( "scratcher~ : new scratcher : size = %d", x->x_size ); - if ( scratcher_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } - -} - -void scratcher_tilde_setup(void) -{ - post(scratcher_version); -#include "scratcher~.tk2c" - scratcher_class = class_new(gensym("scratcher~"), (t_newmethod)scratcher_new, (t_method)scratcher_free, - sizeof(t_scratcher), 0, A_GIMME, 0); - - - // set callbacks - scratcher_widgetbehavior.w_getrectfn = scratcher_getrect; - scratcher_widgetbehavior.w_displacefn = scratcher_displace; - scratcher_widgetbehavior.w_selectfn = scratcher_select; - scratcher_widgetbehavior.w_activatefn = NULL; - scratcher_widgetbehavior.w_deletefn = scratcher_delete; - scratcher_widgetbehavior.w_visfn = scratcher_vis; - scratcher_widgetbehavior.w_clickfn = scratcher_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(scratcher_class, scratcher_properties); - class_setsavefn(scratcher_class, scratcher_save); -#else - scratcher_widgetbehavior.w_propertiesfn = scratcher_properties; - scratcher_widgetbehavior.w_savefn = scratcher_save; -#endif - - CLASS_MAINSIGNALIN( scratcher_class, t_scratcher, x_f ); - class_addmethod(scratcher_class, (t_method)scratcher_dsp, gensym("dsp"), A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_record, gensym("record"), A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_resize, gensym("resize"), A_FLOAT, A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_sensibility, gensym("sensibility"), A_FLOAT, A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_maxspeed, gensym("maxspeed"), A_FLOAT, A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_inertia, gensym("inertia"), A_FLOAT, A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_showspeed, gensym("showspeed"), A_FLOAT, A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_play, gensym("play"), A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_stop, gensym("stop"), A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_reset, gensym("reset"), A_NULL); - class_addmethod(scratcher_class, (t_method)scratcher_dialog, gensym("dialog"), A_GIMME, A_NULL); -} diff --git a/scratcher~/scratcher~.tk b/scratcher~/scratcher~.tk deleted file mode 100644 index bc8ad6f..0000000 --- a/scratcher~/scratcher~.tk +++ /dev/null @@ -1,77 +0,0 @@ -############ scratcher procedures -- ydegoyon@free.fr ######### - -proc scratcher_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - - set cmd [concat $id dialog \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc scratcher_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc scratcher_ok {id} { - scratcher_apply $id - scratcher_cancel $id -} - -proc pdtk_scratcher_dialog {id width height} { - set vid [string trimleft $id .] - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height_$vid] - global $var_graph_height - - set $var_graph_width $width - set $var_graph_height $height - - toplevel $id - wm title $id {scratcher} - wm protocol $id WM_DELETE_WINDOW [concat scratcher_cancel $id] - - label $id.label -text {SCRATCHER PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "scratcher_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "scratcher_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "scratcher_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lwidth -text "Width :" - entry $id.1rangef.width -textvariable $var_graph_width -width 7 - pack $id.1rangef.lwidth $id.1rangef.width -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lheight -text "Height :" - entry $id.2rangef.height -textvariable $var_graph_height -width 7 - pack $id.2rangef.lheight $id.2rangef.height -side left - - bind $id.1rangef.name [concat scratcher_ok $id] - bind $id.2rangef.height [concat scratcher_ok $id] - focus $id.1rangef.name -} - -############ scratcher procedures END -- ydegoyon@free.fr ######### diff --git a/scratcher~/scratcher~.tk2c b/scratcher~/scratcher~.tk2c deleted file mode 100755 index 8c07523..0000000 --- a/scratcher~/scratcher~.tk2c +++ /dev/null @@ -1,58 +0,0 @@ -// ########### scratcher procedures -- ydegoyon@free.fr ######### -sys_gui("proc scratcher_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_width] [eval concat $$var_graph_height] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc scratcher_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc scratcher_ok {id} {\n"); -sys_gui("scratcher_apply $id\n"); -sys_gui("scratcher_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_scratcher_dialog {id width height} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height_$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {scratcher}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat scratcher_cancel $id]\n"); -sys_gui("label $id.label -text {SCRATCHER PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"scratcher_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"scratcher_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"scratcher_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.1rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.1rangef.lwidth $id.1rangef.width -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.2rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.2rangef.lheight $id.2rangef.height -side left\n"); -sys_gui("bind $id.1rangef.name [concat scratcher_ok $id]\n"); -sys_gui("bind $id.2rangef.height [concat scratcher_ok $id]\n"); -sys_gui("focus $id.1rangef.name\n"); -sys_gui("}\n"); -// ########### scratcher procedures END -- ydegoyon@free.fr ######### diff --git a/scratcher~/timeval.h b/scratcher~/timeval.h deleted file mode 100644 index ff04962..0000000 --- a/scratcher~/timeval.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * timeval.h 1.0 01/12/19 - * - * Defines gettimeofday, timeval, etc. for Win32 - * - * By Wu Yongwei - * - */ - -#ifndef _TIMEVAL_H -#define _TIMEVAL_H - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#ifndef __GNUC__ -#define EPOCHFILETIME (116444736000000000i64) -#else -#define EPOCHFILETIME (116444736000000000LL) -#endif /* not __GNUC__ */ - -#if 0 -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* microseconds */ -}; -#endif /* 0 */ - -struct timezone { - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -__inline int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - LARGE_INTEGER li; - __int64 t; - static int tzflag; - - if (tv) - { - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - } - - if (tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} - -#else /* _WIN32 */ - -#include - -#endif /* _WIN32 */ - -#endif /* _TIMEVAL_H */ diff --git a/scratcher~/tk2c.bash b/scratcher~/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/scratcher~/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/scrolllist-help.pd b/scrolllist-help.pd new file mode 100755 index 0000000..b9b99a9 --- /dev/null +++ b/scrolllist-help.pd @@ -0,0 +1,123 @@ +#N canvas 38 85 936 562 10; +#X text 574 514 scrolllist 100 200 200; +#X text 576 527 scrolllist; +#X text 500 515 Examples :; +#X text 75 533 Comments and bugs @ ydegoyon@free.fr; +#X symbolatom 29 507 30 0 0 0 - - -; +#X text 472 332 Note : you can scroll the list by dragging; +#X msg 67 79 seek \$1; +#X floatatom 127 81 5 0 0 0 - - -; +#X text 444 129 Change the font; +#X msg 116 129 font Helvetica normal 14; +#X msg 297 129 font Courier bold 24; +#X msg 128 157 scroll 200; +#X msg 209 157 scroll -200; +#X text 300 156 Scrolling by numbers for the laziest; +#X obj 254 183 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 +1; +#X msg 164 183 graphics \$1; +#X text 383 183 Show or hide graphics; +#X msg 277 182 1; +#X obj 310 183 loadbang; +#X text 498 469 Scrollist lets you display text items in a patch window +; +#X text 498 486 Constructor : scrolllist +| scrolllist ( defaults 100 400 200 ); +#X text 168 73 You can seek in the text list; +#X text 168 86 It behaves as a circular list; +#X text 142 104 Sort the text items; +#X text 251 507 Selected text item; +#X text 470 397 with the "Properties" dialog; +#X text 470 383 You can change all the properties of the object; +#X msg 612 57 add \$1; +#X text 666 58 add a text; +#X obj 612 32 zexy/list2symbol; +#X text 808 90 insert a text; +#X msg 742 89 dystopia; +#X msg 612 7 the aesthetics of our anger; +#X msg 734 115 atacama; +#X text 797 115 replace a text; +#X text 828 149 delete a text; +#X msg 611 89 insert \$1 3; +#X obj 709 89 zexy/list2symbol; +#X obj 705 115 zexy/list2symbol; +#X msg 610 115 replace \$1 3; +#X msg 612 149 delete \$1; +#X obj 692 149 hradio 15 1 0 8 empty empty empty 0 -6 0 8 -262144 -1 +-1 0; +#X obj 555 269 textfile; +#X msg 585 236 read examples/yesterday.txt cr; +#X msg 620 270 rewind; +#X obj 527 269 zexy/list2symbol; +#X msg 525 236 add \$1; +#X obj 748 216 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 747 237 metro 1000; +#X obj 40 273 scrolllist 25 400 200 {Courier 12 bold} blue white #567823 +; +#X text 470 343 the mouse in the text area; +#X msg 33 57 clear; +#X text 79 57 clear all; +#X obj 482 270 t b; +#X text 746 270 read a full text; +#X msg 481 295 scroll 12; +#X obj 585 213 loadbang; +#X obj 57 275 r smsg; +#X obj 62 383 s somsg; +#X obj 29 481 r somsg; +#X obj 14 176 s smsg; +#X obj 557 295 s smsg; +#X obj 573 176 s smsg; +#X msg 95 105 sort; +#X msg 96 211 bgcolor blue; +#X msg 196 212 fgcolor white; +#X msg 304 211 secolor #567823; +#X text 421 212 change colors; +#X msg 97 234 bgcolor black; +#X msg 197 235 fgcolor green; +#X msg 304 234 secolor red; +#X connect 6 0 60 0; +#X connect 7 0 6 0; +#X connect 9 0 60 0; +#X connect 10 0 60 0; +#X connect 11 0 60 0; +#X connect 12 0 60 0; +#X connect 14 0 15 0; +#X connect 15 0 60 0; +#X connect 17 0 14 0; +#X connect 18 0 17 0; +#X connect 27 0 62 0; +#X connect 29 0 27 0; +#X connect 31 0 37 0; +#X connect 32 0 29 0; +#X connect 33 0 38 0; +#X connect 36 0 62 0; +#X connect 37 0 36 0; +#X connect 38 0 39 0; +#X connect 39 0 62 0; +#X connect 40 0 62 0; +#X connect 41 0 40 0; +#X connect 42 0 45 0; +#X connect 42 1 44 0; +#X connect 43 0 42 0; +#X connect 44 0 42 0; +#X connect 45 0 46 0; +#X connect 46 0 53 0; +#X connect 46 0 61 0; +#X connect 47 0 48 0; +#X connect 48 0 42 0; +#X connect 49 0 58 0; +#X connect 51 0 60 0; +#X connect 53 0 55 0; +#X connect 55 0 61 0; +#X connect 56 0 43 0; +#X connect 57 0 49 0; +#X connect 59 0 4 0; +#X connect 63 0 60 0; +#X connect 64 0 42 0; +#X connect 65 0 60 0; +#X connect 66 0 60 0; +#X connect 67 0 60 0; +#X connect 69 0 60 0; +#X connect 70 0 60 0; +#X connect 71 0 60 0; diff --git a/scrolllist.c b/scrolllist.c new file mode 100644 index 0000000..b897145 --- /dev/null +++ b/scrolllist.c @@ -0,0 +1,1041 @@ +/*---------------------- scrolllist~ ------------------------------------------ */ +/* */ +/* scrolllist~ : scrolling list of text items */ +/* constructor : scrolllist | scrolllist */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "I tried your cat's name, it tried your favorite band" */ +/* "I have the password to your ... shell account" */ +/* Barcelona - Shell Account */ +/* ---------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif + +t_widgetbehavior scrolllist_widgetbehavior; +static t_class *scrolllist_class; + +static int guidebug=0; + +static char *scrolllist_version = "scrolllist: scrolling list of text items : version 0.3, written by Yves Degoyon (ydegoyon@free.fr)"; + +#define MIN(a,b) (a>b?b:a) + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g);\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h);\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +#define MAX_STRING_LENGTH 256 + +typedef struct _scrolllist +{ + t_object x_obj; + t_glist *x_glist; + t_outlet *x_item; /* outlet to output current selected item */ + t_int x_capacity; /* number of text items */ + t_int x_height; /* height of the scrolllist */ + t_int x_width; /* width of the scrolllist */ + t_int x_itemselected; /* index of the selected item */ + t_int x_selected; /* stores selected state */ + t_int x_graphics; /* flag to draw graphics or not */ + char **x_items; /* text items */ + t_int x_nitems; /* number of current items */ + t_int x_ndisplayed; /* number of displayed items */ + t_int x_firstseen; /* first displayed item */ + t_int x_lastseen; /* last displayed item */ + t_int x_cdy; /* cumulated y drag */ + char *x_font; /* font used for entries */ + t_int x_charheight; /* height of characters */ + t_int x_charwidth; /* width of characters */ + char *x_bgcolor; /* background color */ + char *x_fgcolor; /* foreground color */ + char *x_secolor; /* selection color */ +} t_scrolllist; + +static void scrolllist_erase(t_scrolllist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + + // just in case we got confused + if ( x->x_firstseen < 0 ) x->x_firstseen=0; + if ( x->x_lastseen > x->x_capacity-1 ) x->x_lastseen=x->x_capacity-1; + + // delete previous entries + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xITEM%d\n", canvas, x, i); + } +} + +static void scrolllist_update(t_scrolllist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + + // just in case we got confused + if ( x->x_firstseen < 0 ) x->x_firstseen=0; + if ( x->x_lastseen > x->x_capacity-1 ) x->x_lastseen=x->x_capacity-1; + + // display the content of text items + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + // display the entry if displayable + if ( ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) && ( x->x_items[i] != NULL ) ) + { + SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xITEM%d\n", + canvas, + text_xpix(&x->x_obj, glist)+5, + text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight, + x->x_fgcolor, + x->x_secolor, + x->x_width, + x->x_items[i], + x->x_font, + x, i ); + } + if ( ( x->x_itemselected >= x->x_firstseen ) && ( x->x_itemselected <= x->x_lastseen ) ) + { + SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_secolor); + } + } +} + +static void scrolllist_output_current(t_scrolllist* x) +{ + if ( x->x_items && x->x_itemselected < x->x_nitems && x->x_itemselected >= 0 ) + { + outlet_symbol( x->x_item, gensym( x->x_items[x->x_itemselected] ) ); + } +} + +static void scrolllist_draw_new(t_scrolllist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + x->x_glist = glist; + if ( x->x_graphics ) + { + SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xTEXTLIST\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x->x_bgcolor, x); + } + else + { + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline white -fill white -tags %xTEXTLIST\n", + canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, x); + } + scrolllist_erase( x, glist ); + scrolllist_update( x, glist ); +} + +static void scrolllist_draw_move(t_scrolllist *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + struct timespec tv; + + tv.tv_sec = 0; + tv.tv_nsec = 10000000; + + SYS_VGUI7(".x%x.c coords %xTEXTLIST %d %d %d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist)+x->x_width, + text_ypix(&x->x_obj, glist)+x->x_height); + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + // nanosleep( &tv, NULL ); + SYS_VGUI6(".x%x.c coords %xITEM%d %d %d\n", + canvas, x, i, + text_xpix(&x->x_obj, glist)+5, + text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight); + } + + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void scrolllist_draw_erase(t_scrolllist* x, t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int i; + + SYS_VGUI3(".x%x.c delete %xTEXTLIST\n", canvas, x); + for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) + { + SYS_VGUI4(".x%x.c delete %xITEM%d\n", canvas, x, i); + } +} + +static void scrolllist_draw_select(t_scrolllist* x, t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + // post( "scrolllist : select" ); + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xTEXTLIST -outline #0000FF\n", canvas, x); + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xTEXTLIST -outline #000000\n", canvas, x); + } +} + +/* ------------------------ scrolllist widgetbehaviour----------------------------- */ + + +static void scrolllist_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_scrolllist* x = (t_scrolllist*)z; + + *xp1 = text_xpix(&x->x_obj, owner); + *yp1 = text_ypix(&x->x_obj, owner); + *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; + *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; +} + +static void scrolllist_save(t_gobj *z, t_binbuf *b) +{ + t_scrolllist *x = (t_scrolllist *)z; + + // post( "saving scrolllist : %d", x->x_capacity ); + binbuf_addv(b, "ssiisiiissss", gensym("#X"), gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_capacity, x->x_width, x->x_height, + gensym(x->x_font), gensym(x->x_bgcolor), + gensym(x->x_fgcolor), gensym(x->x_secolor) ); + binbuf_addv(b, ";"); +} + +static void scrolllist_select(t_gobj *z, t_glist *glist, int selected) +{ + t_scrolllist *x = (t_scrolllist *)z; + + x->x_selected = selected; + + scrolllist_draw_select( x, glist ); +} + +static void scrolllist_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_scrolllist *x = (t_scrolllist *)z; + t_rtext *y; + + // post( "scrolllist : vis (%d)", vis ); + x->x_glist = glist; + if (vis) + { + scrolllist_draw_erase(x, x->x_glist); + scrolllist_draw_new( x, glist ); + } + else + { + scrolllist_draw_erase( x, glist ); + } +} + +static void scrolllist_deleteobj(t_gobj *z, t_glist *glist) +{ + t_scrolllist *x = (t_scrolllist *)z; + + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void scrolllist_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_scrolllist *x = (t_scrolllist *)z; + t_int xold = text_xpix(&x->x_obj, glist); + t_int yold = text_ypix(&x->x_obj, glist); + + // post( "scrolllist_displace dx=%d dy=%d", dx, dy ); + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) + { + scrolllist_draw_move(x, glist); + } +} + +static void scrolllist_motion(t_scrolllist *x, t_floatarg dx, t_floatarg dy) +{ + t_int i; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + x->x_cdy+=dy; + scrolllist_erase( x, x->x_glist ); + + // check if we need to scroll + // eventually, move down + if ( x->x_cdy >= x->x_charheight ) + { + if ( x->x_firstseen < x->x_nitems - x->x_ndisplayed ) + { + x->x_firstseen++; + x->x_lastseen++; + // post( "scrolllist : moved down first=%d last=%d", x->x_firstseen, x->x_lastseen ); + } + } + // eventually, move up + if ( x->x_cdy <= -x->x_charheight ) + { + if ( x->x_firstseen-1 >= 0 ) + { + x->x_firstseen--; + x->x_lastseen--; + // post( "scrolllist : moved up first=%d last=%d", x->x_firstseen, x->x_lastseen ); + } + } + scrolllist_update(x, x->x_glist); + if ( ( x->x_cdy >= x->x_charheight ) || ( x->x_cdy <= -x->x_charheight ) ) x->x_cdy = 0; +} + +static void scrolllist_scroll(t_scrolllist *x, t_floatarg fdy) +{ + t_int nbsteps, si; + + x->x_cdy += (t_int)fdy; + nbsteps = (t_int)abs(x->x_cdy/x->x_charheight); + // post( "scrolllist : iterations %d", nbsteps ); + for (si=0; six_charheight); + } +} + +static void scrolllist_graphics(t_scrolllist *x, t_floatarg fgraphics) +{ + if ( ( (t_int)fgraphics == 0 ) || ( (t_int)fgraphics == 1 ) ) + { + scrolllist_draw_erase(x, x->x_glist); + x->x_graphics = (t_int) fgraphics; + scrolllist_draw_new(x, x->x_glist); + } +} + +static int scrolllist_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_scrolllist* x = (t_scrolllist *)z; + t_canvas *canvas=glist_getcanvas(x->x_glist); + t_int xoffset; + + if (doit) + { + // deselect previously selected item + SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_fgcolor); + x->x_itemselected = x->x_firstseen + (ypix-text_ypix(&x->x_obj, glist))/x->x_charheight; + SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", + canvas, x, x->x_itemselected, x->x_secolor); + // post( "scrolllist : selected item : %d", x->x_itemselected ); + if ( x->x_items && ( x->x_itemselected < x->x_nitems ) ) + { + xoffset=(xpix-text_xpix(&x->x_obj, glist)); + if ( xoffset <= (t_int)( x->x_width*4/5 ) ) + { + scrolllist_output_current(x); + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, glist ); + } + else + { + x->x_itemselected=-1; + } + } + x->x_glist = glist; + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scrolllist_motion, + NULL, xpix, ypix ); + } + return (1); +} + +static void scrolllist_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_scrolllist *x=(t_scrolllist *)z; + + sprintf(buf, "pdtk_scrolllist_dialog %%s %d %d %d %s %s %s %s\n", + (int)x->x_capacity, (int)x->x_width, (int)x->x_height, + x->x_font, x->x_bgcolor, + x->x_fgcolor, x->x_secolor ); + // post("scrolllist_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + +static void scrolllist_dialog(t_scrolllist *x, t_symbol *s, int argc, t_atom *argv) +{ + char **titems; + t_int ncapacity, i, ccapacity; + + scrolllist_erase( x, x->x_glist ); + scrolllist_draw_erase(x, x->x_glist); + + if ( !x ) { + post( "scrolllist : error :tried to set properties on an unexisting object" ); + } + if ( argc != 9 ) + { + post( "scrolllist : error in the number of arguments ( %d instead of 10 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT || argv[3].a_type != A_SYMBOL || + argv[4].a_type != A_FLOAT || argv[5].a_type != A_SYMBOL || + argv[6].a_type != A_SYMBOL || argv[7].a_type != A_SYMBOL || + argv[8].a_type != A_SYMBOL ) { + post( "scrolllist : wrong arguments" ); + return; + } + + ncapacity = (t_int)argv[0].a_w.w_float; + titems = (char**) malloc( ncapacity*sizeof(char*) ); + + if ( ncapacity < x->x_nitems ) + { + post( "scrolllist : new size is too small : texts lost !!" ); + ccapacity = ncapacity; + } + else + { + ccapacity = x->x_nitems; + } + for ( i=0; ix_items[i] != NULL ) + { + titems[i] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); + memcpy( titems[i], x->x_items[i], strlen( x->x_items[i] ) ); + titems[i][strlen( x->x_items[i] )]='\0'; + free( x->x_items[i] ); + x->x_items[i] = NULL; + } + } + if ( x->x_items ) + { + free( x->x_items ); + x->x_items = NULL; + } + x->x_items = titems; + x->x_nitems = ccapacity; + x->x_capacity = ncapacity; + + x->x_width = (int)argv[1].a_w.w_float; + x->x_height = (int)argv[2].a_w.w_float; + sprintf( x->x_font, "{%s %d %s}", argv[3].a_w.w_symbol->s_name, + (int)argv[4].a_w.w_float, argv[5].a_w.w_symbol->s_name ); + x->x_charheight = (t_int)argv[4].a_w.w_float; + strcpy( x->x_bgcolor, argv[6].a_w.w_symbol->s_name ); + strcpy( x->x_fgcolor, argv[7].a_w.w_symbol->s_name ); + strcpy( x->x_secolor, argv[8].a_w.w_symbol->s_name ); + + x->x_firstseen = 0; + x->x_ndisplayed = (t_int)(x->x_height/x->x_charheight ); + if ( x->x_nitems >= x->x_ndisplayed ) + { + x->x_lastseen = x->x_ndisplayed-1; + } + else + { + x->x_lastseen = x->x_nitems-1; + } + + scrolllist_draw_new(x, x->x_glist); + scrolllist_update(x, x->x_glist); +} + +static void scrolllist_bgcolor(t_scrolllist *x, t_symbol *s) +{ + scrolllist_erase( x, x->x_glist ); + scrolllist_draw_erase(x, x->x_glist); + + strcpy( x->x_bgcolor, s->s_name ); + + scrolllist_draw_new(x, x->x_glist); + scrolllist_update(x, x->x_glist); +} + +static void scrolllist_fgcolor(t_scrolllist *x, t_symbol *s) +{ + scrolllist_erase( x, x->x_glist ); + scrolllist_draw_erase(x, x->x_glist); + + strcpy( x->x_fgcolor, s->s_name ); + + scrolllist_draw_new(x, x->x_glist); + scrolllist_update(x, x->x_glist); +} + +static void scrolllist_secolor(t_scrolllist *x, t_symbol *s) +{ + scrolllist_erase( x, x->x_glist ); + scrolllist_draw_erase(x, x->x_glist); + + strcpy( x->x_secolor, s->s_name ); + + scrolllist_draw_new(x, x->x_glist); + scrolllist_update(x, x->x_glist); +} + +static void scrolllist_sort(t_scrolllist* x) +{ + char **titems; + t_int i, j, k, irank, indest; + + scrolllist_erase( x, x->x_glist ); + + // sort text items + titems = (char**) malloc( x->x_capacity*sizeof(char*) ); + for ( i=0; ix_capacity; i++ ) + { + titems[i]=NULL; + } + indest=0; + for ( i=0; ix_nitems; i++ ) + { + if ( x->x_items[i] != NULL ) + { + irank=0; + for ( j=0; jx_capacity; j++ ) + { + if ( titems[j] != NULL ) + { + // post( "scrollist : comparing >%s< to >%s<", titems[j], x->x_items[i] ); + if ( strcasecmp( titems[j], x->x_items[i] ) > 0 ) + { + irank=j; + break; + } + irank=j+1; + } + } + // insert in irank + // post( "scrollist : inserting %s at %d", x->x_items[i], irank ); + for ( k=indest-1; k>=irank; k-- ) + { + if ( (k+1) < x->x_capacity ) + { + if ( titems[k+1] != NULL ) + { + free( titems[k+1] ); + titems[k+1] = NULL; + } + titems[k+1] = (char*) malloc( strlen( titems[k] ) + 1 ); + memcpy( titems[k+1], titems[k], strlen( titems[k] ) ); + titems[k+1][strlen( titems[k] )]='\0'; + // post( "scrollist : copying %d to %d", k, k+1 ); + } + } + titems[irank] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); + memcpy( titems[irank], x->x_items[i], strlen( x->x_items[i] ) ); + titems[irank][strlen( x->x_items[i] )]='\0'; + free( x->x_items[i] ); + x->x_items[i]=NULL; + indest++; + } + } + if ( x->x_items ) + { + free( x->x_items ); + x->x_items = NULL; + } + x->x_items = titems; + + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_font(t_scrolllist* x, t_symbol *fname, t_symbol *fcase, t_floatarg fsize) +{ + if ( (t_int)fsize <= 4 ) + { + post( "scrolllist : wrong font size in font message : %d", (t_int)fsize ); + return; + } + sprintf( x->x_font, "{%s %d %s}", fname->s_name, (int)fsize, fcase->s_name ); + x->x_charheight = (t_int)fsize; + x->x_charwidth = (2*x->x_charheight)/3; + // post( "scrolllist : setting font to : %s", x->x_font ); + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_add(t_scrolllist* x, t_symbol *fnewtext) +{ + t_int i; + + // post( "scrollist : add : nitems = %d", x->x_nitems ); + if ( x->x_nitems >= x->x_capacity ) + { + // post( "scrolllist : warning : list is full, erasing first line" ); + for ( i=0; i<(x->x_nitems-1); i++ ) + { + if ( x->x_items[i] != NULL ) + { + free( x->x_items[i] ); + x->x_items[i] = NULL; + } + x->x_items[i] = (char*) malloc( strlen( x->x_items[i+1] ) + 1 ); + memcpy( x->x_items[i], x->x_items[i+1], strlen( x->x_items[i+1] ) ); + x->x_items[i][strlen( x->x_items[i+1] )]='\0'; + // post( "scrollist : copying %d to %d", i+1, i ); + } + x->x_items[x->x_nitems-1] = (char*) malloc( strlen( fnewtext->s_name ) + 1 ); + memcpy( x->x_items[x->x_nitems-1], fnewtext->s_name, strlen( fnewtext->s_name ) ); + x->x_items[x->x_nitems-1][strlen( fnewtext->s_name )]='\0'; + } + else + { + // post( "scrolllist : item #%d : %x", x->x_nitems, &x->x_items[x->x_nitems] ); + // post( "scrolllist : allocating : %d", strlen( fnewtext->s_name ) + 1 ); + x->x_items[x->x_nitems] = (char*) malloc( strlen( fnewtext->s_name ) + 1 ); + memcpy( x->x_items[x->x_nitems], fnewtext->s_name, strlen( fnewtext->s_name ) ); + x->x_items[x->x_nitems][strlen( fnewtext->s_name )]='\0'; + x->x_nitems++; + if ( (x->x_nitems-x->x_firstseen)*x->x_charheight+5 < x->x_height ) + { + x->x_lastseen = x->x_nitems-1; + } + } + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_insert(t_scrolllist* x, t_symbol *ftext, t_floatarg frank) +{ + t_int rank, i; + + if ( (t_int)frank > x->x_capacity ) + { + post( "scrolllist : error : incorrect rank in insert message (%d), over capacity", (t_int)frank ); + return; + } + rank = (t_int)frank-1; + if ( rank < 0 ) + { + rank=0; + } + if ( rank > x->x_nitems-1 ) + { + rank=x->x_nitems-1; + } + for ( i=x->x_nitems-1; i>=rank; i-- ) + { + if ( (i+1) < x->x_capacity ) + { + if ( x->x_items[i+1] != NULL ) + { + free( x->x_items[i+1] ); + x->x_items[i+1] = NULL; + } + x->x_items[i+1] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); + memcpy( x->x_items[i+1], x->x_items[i], strlen( x->x_items[i] ) ); + x->x_items[i+1][strlen( x->x_items[i] )]='\0'; + // post( "scrollist : copying %d to %d", i, i+1 ); + } + } + // post( "scrollist : inserting at %d", rank ); + x->x_items[rank] = (char*) malloc( strlen( ftext->s_name ) + 1 ); + memcpy( x->x_items[rank], ftext->s_name, strlen( ftext->s_name ) ); + x->x_items[rank][strlen( ftext->s_name )]='\0'; + if ( x->x_nitems < x->x_capacity ) x->x_nitems++; + if ( (x->x_nitems-x->x_firstseen)*x->x_charheight+5 < x->x_height ) + { + x->x_lastseen = x->x_nitems-1; + } + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_replace(t_scrolllist* x, t_symbol *ftext, t_floatarg frank) +{ + t_int rank; + + if ( ( (t_int)frank <= 0 ) || ( (t_int)frank > x->x_nitems ) ) + { + post( "scrolllist : error : incorrect rank in replace message (%d), no such text", (t_int)frank ); + return; + } + + rank = (t_int) frank-1; + if ( x->x_items[rank] != NULL ) + { + free( x->x_items[rank] ); + x->x_items[rank] = NULL; + } + x->x_items[rank] = (char*) malloc( strlen( ftext->s_name ) + 1 ); + memcpy( x->x_items[rank], ftext->s_name, strlen( ftext->s_name ) ); + x->x_items[rank][strlen( ftext->s_name )]='\0'; + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_delete(t_scrolllist* x, t_floatarg frank) +{ + t_int rank, i; + + if ( ( (t_int)frank <= 0 ) || ( (t_int)frank > x->x_nitems ) ) + { + post( "scrolllist : error : incorrect rank in delete message (%d), no such text (%d)", (t_int)frank, x->x_nitems ); + return; + } + + rank = (t_int) frank-1; + for ( i=rank; ix_nitems-1; i++ ) + { + if ( x->x_items[i] != NULL ) + { + free( x->x_items[i] ); + x->x_items[i] = NULL; + } + x->x_items[i] = (char*) malloc( strlen( x->x_items[i+1] ) + 1 ); + memcpy( x->x_items[i], x->x_items[i+1], strlen( x->x_items[i+1] ) ); + x->x_items[i][strlen( x->x_items[i+1] )]='\0'; + // post( "scrollist : copying %d to %d", i+1, i ); + } + free( x->x_items[x->x_nitems-1] ); + x->x_items[x->x_nitems-1] = NULL; + if ( x->x_lastseen == x->x_nitems-2 ) x->x_lastseen--; + x->x_nitems--; + scrolllist_erase( x, x->x_glist ); + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_clear(t_scrolllist* x) +{ + t_int i; + + scrolllist_erase( x, x->x_glist ); + for ( i=0; ix_capacity; i++ ) + { + x->x_items[i]=NULL; + } + x->x_nitems = 0; + x->x_selected = 0; + x->x_itemselected = -1; + x->x_firstseen = 0; + x->x_lastseen = -1; + scrolllist_update( x, x->x_glist ); +} + +static void scrolllist_seek(t_scrolllist *x, t_floatarg fseeked) +{ + t_int iout=0; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( fseeked < 0 ) + { + post( "scrolllist : wrong searched file : %f", fseeked ); + return; + } + if ( x->x_nitems == 0 ) return; + + iout = (t_int)fseeked % (x->x_nitems); + SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", canvas, x, x->x_itemselected, x->x_fgcolor); + x->x_itemselected = iout; + SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", canvas, x, x->x_itemselected, x->x_secolor); + scrolllist_output_current(x); +} + +static t_scrolllist *scrolllist_new(t_symbol *s, int argc, t_atom *argv ) +{ + t_int i, argoffset=0; + t_scrolllist *x; + + x = (t_scrolllist *)pd_new(scrolllist_class); + + x->x_capacity = 100; + x->x_width = 400; + x->x_height = 200; + x->x_font = ( char * ) malloc( MAX_STRING_LENGTH ); + sprintf( x->x_font, "{Helvetica 10 bold}" ); + x->x_charheight = 10; + x->x_charwidth = (2*10)/3; + x->x_bgcolor = ( char * ) malloc( MAX_STRING_LENGTH ); + sprintf( x->x_bgcolor, "#457782" ); + x->x_fgcolor = ( char * ) malloc( MAX_STRING_LENGTH ); + sprintf( x->x_fgcolor, "black" ); + x->x_secolor = ( char * ) malloc( MAX_STRING_LENGTH ); + sprintf( x->x_secolor, "red" ); + + if ( argc >= 1 ) + { + if ( argv[0].a_type != A_FLOAT ) + { + error( "scrolllist : wrong argument (capacity : 1)" ); + return NULL; + } + x->x_capacity = (int)argv[0].a_w.w_float; + } + if ( argc >= 2 ) + { + if ( argv[1].a_type != A_FLOAT ) + { + error( "scrolllist : wrong argument (width : 2)" ); + return NULL; + } + if ( (int)argv[1].a_w.w_float <= 0 ) + { + error( "scrolllist : wrong width (%d)", (t_int)(int)argv[1].a_w.w_float ); + error( "scrolllist : usage : scrolllist " ); + return NULL; + } + x->x_width = (int)argv[1].a_w.w_float; + } + if ( argc >= 3 ) + { + if ( argv[2].a_type != A_FLOAT ) + { + error( "scrolllist : wrong argument (height : 3)" ); + return NULL; + } + if ( (int)argv[2].a_w.w_float <= 0 ) + { + error( "scrolllist : wrong height (%d)", (t_int)(int)argv[2].a_w.w_float ); + error( "scrolllist : usage : scrolllist " ); + return NULL; + } + x->x_height = (int)argv[2].a_w.w_float; + } + if ( argc >= 6 ) + { + if ( argv[3].a_type != A_SYMBOL || + argv[5].a_type != A_SYMBOL ) + { + error( "scrolllist : wrong arguments (font : 4,6)" ); + error( "argument types : %d %d", argv[3].a_type, argv[5].a_type ); + return NULL; + } + if ( argv[4].a_type != A_SYMBOL && + argv[4].a_type != A_FLOAT ) + { + error( "scrolllist : wrong arguments (font size : 5)" ); + error( "argument types : %d", argv[4].a_type ); + return NULL; + } + if ( argv[4].a_type == A_SYMBOL ) + { + sprintf( x->x_font, "%s", argv[3].a_w.w_symbol->s_name ); + x->x_charheight = (t_int)atoi( strstr( argv[3].a_w.w_symbol->s_name, " ") ); + argoffset=2; + } + if ( argv[4].a_type == A_FLOAT ) + { + x->x_charheight = (t_int)argv[4].a_w.w_float; + sprintf( x->x_font, "%s %d %s", argv[3].a_w.w_symbol->s_name, + (int)x->x_charheight, argv[5].a_w.w_symbol->s_name ); + argoffset=0; + } + post( "scrolllist : font : %s, size : %d", x->x_font, x->x_charheight ); + } + if ( argc >= 7-argoffset ) + { + if ( argv[6-argoffset].a_type != A_SYMBOL ) + { + error( "scrolllist : wrong arguments (background color : %d)", 7-argoffset ); + return NULL; + } + strcpy( x->x_bgcolor, argv[6-argoffset].a_w.w_symbol->s_name ); + } + if ( argc >= 8-argoffset ) + { + if ( argv[7-argoffset].a_type != A_SYMBOL ) + { + error( "scrolllist : wrong arguments (foreground color : %d)", 8-argoffset ); + return NULL; + } + strcpy( x->x_fgcolor, argv[7-argoffset].a_w.w_symbol->s_name ); + } + if ( argc >= 9-argoffset ) + { + if ( argv[8-argoffset].a_type != A_SYMBOL ) + { + error( "scrolllist : wrong arguments (selection color : %d)", 9-argoffset ); + return NULL; + } + strcpy( x->x_secolor, argv[8-argoffset].a_w.w_symbol->s_name ); + } + + x->x_item = outlet_new(&x->x_obj, &s_symbol ); + + x->x_glist = (t_glist *) canvas_getcurrent(); + x->x_nitems = 0; + x->x_items = (char **) malloc( x->x_capacity*sizeof(char*) ); + for ( i=0; ix_capacity; i++ ) + { + x->x_items[i]=NULL; + } + + x->x_selected = 0; + x->x_itemselected = -1; + x->x_firstseen = 0; + x->x_lastseen = -1; + x->x_ndisplayed = (t_int)(x->x_height/x->x_charheight ); + + x->x_graphics = 1; + + post( "scrolllist : capacity=%d width=%d height=%d", x->x_capacity, x->x_width, x->x_height ); + + return (x); +} + +static void scrolllist_free(t_scrolllist *x) +{ + t_int i; + + // post( "scrolllist : scrolllist_free" ); + + // free text items list + if ( x->x_nitems ) + { + for ( i=0; ix_nitems; i++ ) + { + if ( x->x_items[i] != NULL ) + { + // post( "scrolllist : freeing entry %d size=%d : %s", i, strlen( x->x_items[i] ) + 1, x->x_items[i] ); + free( x->x_items[i] ); + } + } + } + free( x->x_items ); + if ( x->x_font ) + { + free( x->x_font ); + } + if ( x->x_bgcolor ) + { + free( x->x_bgcolor ); + } + if ( x->x_fgcolor ) + { + free( x->x_fgcolor ); + } + if ( x->x_secolor ) + { + free( x->x_secolor ); + } +} + +void scrolllist_setup(void) +{ + post( scrolllist_version ); + scrolllist_class = class_new(gensym("scrolllist"), (t_newmethod)scrolllist_new, + (t_method)scrolllist_free, sizeof(t_scrolllist), + CLASS_DEFAULT, A_GIMME, 0); + class_addmethod(scrolllist_class, (t_method)scrolllist_seek, gensym("seek"), A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_dialog, gensym("dialog"), A_GIMME, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_sort, gensym("sort"), A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_graphics, gensym("graphics"), A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_scroll, gensym("scroll"), A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_font, gensym("font"), A_SYMBOL, A_SYMBOL, A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_insert, gensym("insert"), A_SYMBOL, A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_replace, gensym("replace"), A_SYMBOL, A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_add, gensym("add"), A_SYMBOL, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_bgcolor, gensym("bgcolor"), A_SYMBOL, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_fgcolor, gensym("fgcolor"), A_SYMBOL, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_secolor, gensym("secolor"), A_SYMBOL, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_delete, gensym("delete"), A_DEFFLOAT, A_NULL ); + class_addmethod(scrolllist_class, (t_method)scrolllist_clear, gensym("clear"), A_NULL ); + + scrolllist_widgetbehavior.w_getrectfn = scrolllist_getrect; + scrolllist_widgetbehavior.w_displacefn = scrolllist_displace; + scrolllist_widgetbehavior.w_selectfn = scrolllist_select; + scrolllist_widgetbehavior.w_activatefn = NULL; + scrolllist_widgetbehavior.w_deletefn = scrolllist_deleteobj; + scrolllist_widgetbehavior.w_visfn = scrolllist_vis; + scrolllist_widgetbehavior.w_clickfn = scrolllist_click; + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(scrolllist_class, scrolllist_properties); + class_setsavefn(scrolllist_class, scrolllist_save); +#else + scrolllist_widgetbehavior.w_propertiesfn = scrolllist_properties; + scrolllist_widgetbehavior.w_savefn = scrolllist_save; +#endif + + class_setwidget(scrolllist_class, &scrolllist_widgetbehavior); + + sys_vgui("eval [read [open %s/%s.tcl]]\n", + scrolllist_class->c_externdir->s_name, + scrolllist_class->c_name->s_name); +} diff --git a/scrolllist.tcl b/scrolllist.tcl new file mode 100755 index 0000000..79ca61c --- /dev/null +++ b/scrolllist.tcl @@ -0,0 +1,141 @@ +############ scrolllist procedures -- ydegoyon@free.fr ######### + +proc scrolllist_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_capacity [concat graph_capacity_$vid] + global $var_graph_capacity + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height$vid] + global $var_graph_height + set var_graph_font [concat graph_font$vid] + global $var_graph_font + set var_graph_bgcolor [concat graph_bgcolor$vid] + global $var_graph_bgcolor + set var_graph_fgcolor [concat graph_fgcolor$vid] + global $var_graph_fgcolor + set var_graph_secolor [concat graph_secolor$vid] + global $var_graph_secolor + + set cmd [concat $id dialog \ + [eval concat $$var_graph_capacity] \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_font] \ + [eval concat $$var_graph_bgcolor] \ + [eval concat $$var_graph_fgcolor] \ + [eval concat $$var_graph_secolor] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc scrolllist_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc scrolllist_ok {id} { + scrolllist_apply $id + scrolllist_cancel $id +} + +proc pdtk_scrolllist_dialog {id capacity width height font bgcolor fgcolor secolor} { + set vid [string trimleft $id .] + set var_graph_capacity [concat graph_capacity_$vid] + global $var_graph_capacity + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height$vid] + global $var_graph_height + set var_graph_font [concat graph_font$vid] + global $var_graph_font + set var_graph_bgcolor [concat graph_bgcolor$vid] + global $var_graph_bgcolor + set var_graph_fgcolor [concat graph_fgcolor$vid] + global $var_graph_fgcolor + set var_graph_secolor [concat graph_secolor$vid] + global $var_graph_secolor + + set $var_graph_capacity $capacity + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_font $font + set $var_graph_bgcolor $bgcolor + set $var_graph_fgcolor $fgcolor + set $var_graph_secolor $secolor + + toplevel $id + wm title $id {scrolllist} + wm protocol $id WM_DELETE_WINDOW [concat scrolllist_cancel $id] + + label $id.label -text {SCROLLLIST PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "scrolllist_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "scrolllist_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "scrolllist_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lcapacity -text "Capacity :" + entry $id.1rangef.capacity -textvariable $var_graph_capacity -width 7 + pack $id.1rangef.lcapacity $id.1rangef.capacity -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lwidth -text "Width :" + entry $id.2rangef.width -textvariable $var_graph_width -width 7 + pack $id.2rangef.lwidth $id.2rangef.width -side left + + frame $id.3rangef + pack $id.3rangef -side top + label $id.3rangef.lheight -text "Height :" + entry $id.3rangef.height -textvariable $var_graph_height -width 7 + pack $id.3rangef.lheight $id.3rangef.height -side left + + frame $id.3_5rangef + pack $id.3_5rangef -side top + label $id.3_5rangef.lfont -text "Font :" + entry $id.3_5rangef.font -textvariable $var_graph_font -width 30 + pack $id.3_5rangef.lfont $id.3_5rangef.font -side left + + frame $id.4rangef + pack $id.4rangef -side top + label $id.4rangef.lbgcolor -text "Background Color :" + entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7 + pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left + + frame $id.5rangef + pack $id.5rangef -side top + label $id.5rangef.lfgcolor -text "Foreground Color :" + entry $id.5rangef.fgcolor -textvariable $var_graph_fgcolor -width 7 + pack $id.5rangef.lfgcolor $id.5rangef.fgcolor -side left + + frame $id.6rangef + pack $id.6rangef -side top + label $id.6rangef.lsecolor -text "Selection Color :" + entry $id.6rangef.secolor -textvariable $var_graph_secolor -width 7 + pack $id.6rangef.lsecolor $id.6rangef.secolor -side left + + bind $id.1rangef.capacity [concat scrolllist_ok $id] + bind $id.2rangef.width [concat scrolllist_ok $id] + bind $id.3rangef.height [concat scrolllist_ok $id] + bind $id.3_5rangef.font [concat scrolllist_ok $id] + bind $id.4rangef.bgcolor [concat scrolllist_ok $id] + bind $id.5rangef.fgcolor [concat scrolllist_ok $id] + bind $id.6rangef.secolor [concat scrolllist_ok $id] +} + +############ scrolllist procedures END -- ydegoyon@free.fr ######### diff --git a/scrolllist/INSTALL b/scrolllist/INSTALL deleted file mode 100755 index 9b308b4..0000000 --- a/scrolllist/INSTALL +++ /dev/null @@ -1,14 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/scrolllist - -make clean - -make - -make install - -open help-scrolllist.pd - -Thanx for getting here. -Yves/ diff --git a/scrolllist/ave-lucifer.txt b/scrolllist/ave-lucifer.txt deleted file mode 100644 index 8aca29e..0000000 --- a/scrolllist/ave-lucifer.txt +++ /dev/null @@ -1,35 +0,0 @@ -Ave, Lúcifer -(Arnaldo Baptista/ Rita Lee/ Élcio Decário) - -As maçãs -Envolvem os corpos nus -Nesse rio que corre -Em veias mansas dentro de mim - -Anjos e arcanjos -Não pousam neste éden infernal -E a flecha do selvagem -Matou mil aves no ar - -Quieta, a serpente se enrola -Nos seus pés -É Lúcifer da floresta -Que tenta me abraçar - -Vem amor -Que um paraíso -Num abraço amigo -Sorrira pra nós sem ninguém nos ver - -Prometa -Meu amor macio -Como uma flor cheia de mel -Pra te embriagar, sem ninguém nos ver - -Tragam uvas negras -Tragam festas e flores -Tragam copos e dores -Tragam incensos odores - -Mas, tragam Lúcifer pra mim -Em uma bandeja pra mim diff --git a/scrolllist/scrolllist-help.pd b/scrolllist/scrolllist-help.pd deleted file mode 100755 index b16fee2..0000000 --- a/scrolllist/scrolllist-help.pd +++ /dev/null @@ -1,124 +0,0 @@ -#N canvas 38 85 936 562 10; -#X text 574 514 scrolllist 100 200 200; -#X text 576 527 scrolllist; -#X text 500 515 Examples :; -#X text 75 533 Comments and bugs @ ydegoyon@free.fr; -#X symbolatom 29 507 30 0 0 0 - - -; -#X text 472 332 Note : you can scroll the list by dragging; -#X msg 67 79 seek \$1; -#X floatatom 127 81 5 0 0 0 - - -; -#X text 444 129 Change the font; -#X msg 116 129 font Helvetica normal 14; -#X msg 297 129 font Courier bold 24; -#X msg 128 157 scroll 200; -#X msg 209 157 scroll -200; -#X text 300 156 Scrolling by numbers for the laziest; -#X obj 254 183 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 -1; -#X msg 164 183 graphics \$1; -#X text 383 183 Show or hide graphics; -#X msg 277 182 1; -#X obj 310 183 loadbang; -#X text 498 469 Scrollist lets you display text items in a patch window -; -#X text 498 486 Constructor : scrolllist -| scrolllist ( defaults 100 400 200 ); -#X text 168 73 You can seek in the text list; -#X text 168 86 It behaves as a circular list; -#X text 142 104 Sort the text items; -#X text 251 507 Selected text item; -#X text 470 397 with the "Properties" dialog; -#X text 470 383 You can change all the properties of the object; -#X msg 612 57 add \$1; -#X text 666 58 add a text; -#X obj 612 32 l2s; -#X text 808 90 insert a text; -#X msg 742 89 dystopia; -#X msg 612 7 the aesthetics of our anger; -#X msg 734 115 atacama; -#X text 797 115 replace a text; -#X text 828 149 delete a text; -#X msg 611 89 insert \$1 3; -#X obj 709 89 l2s; -#X obj 705 115 l2s; -#X msg 610 115 replace \$1 3; -#X msg 612 149 delete \$1; -#X obj 692 149 hradio 15 1 0 8 empty empty empty 0 -6 0 8 -262144 -1 --1 0; -#X obj 555 269 textfile; -#X msg 585 236 read yesterday.txt cr; -#X msg 620 270 rewind; -#X obj 527 269 l2s; -#X msg 525 236 add \$1; -#X obj 748 216 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X obj 747 237 metro 1000; -#X obj 40 273 scrolllist 25 400 200 {Courier 12 bold} blue white #567823 -; -#X text 470 343 the mouse in the text area; -#X msg 33 57 clear; -#X text 79 57 clear all; -#X obj 482 270 t b; -#X text 746 270 read a full text; -#X msg 481 295 scroll 12; -#X obj 585 213 loadbang; -#X obj 57 275 r smsg; -#X obj 62 383 s somsg; -#X obj 29 481 r somsg; -#X obj 14 176 s smsg; -#X obj 557 295 s smsg; -#X obj 573 176 s smsg; -#X msg 95 105 sort; -#X msg 617 295 read ave-lucifer.txt cr; -#X msg 96 211 bgcolor blue; -#X msg 196 212 fgcolor white; -#X msg 304 211 secolor #567823; -#X text 421 212 change colors; -#X msg 97 234 bgcolor black; -#X msg 197 235 fgcolor green; -#X msg 304 234 secolor red; -#X connect 6 0 60 0; -#X connect 7 0 6 0; -#X connect 9 0 60 0; -#X connect 10 0 60 0; -#X connect 11 0 60 0; -#X connect 12 0 60 0; -#X connect 14 0 15 0; -#X connect 15 0 60 0; -#X connect 17 0 14 0; -#X connect 18 0 17 0; -#X connect 27 0 62 0; -#X connect 29 0 27 0; -#X connect 31 0 37 0; -#X connect 32 0 29 0; -#X connect 33 0 38 0; -#X connect 36 0 62 0; -#X connect 37 0 36 0; -#X connect 38 0 39 0; -#X connect 39 0 62 0; -#X connect 40 0 62 0; -#X connect 41 0 40 0; -#X connect 42 0 45 0; -#X connect 42 1 44 0; -#X connect 43 0 42 0; -#X connect 44 0 42 0; -#X connect 45 0 46 0; -#X connect 46 0 53 0; -#X connect 46 0 61 0; -#X connect 47 0 48 0; -#X connect 48 0 42 0; -#X connect 49 0 58 0; -#X connect 51 0 60 0; -#X connect 53 0 55 0; -#X connect 55 0 61 0; -#X connect 56 0 43 0; -#X connect 57 0 49 0; -#X connect 59 0 4 0; -#X connect 63 0 60 0; -#X connect 64 0 42 0; -#X connect 65 0 60 0; -#X connect 66 0 60 0; -#X connect 67 0 60 0; -#X connect 69 0 60 0; -#X connect 70 0 60 0; -#X connect 71 0 60 0; diff --git a/scrolllist/scrolllist.c b/scrolllist/scrolllist.c deleted file mode 100644 index 9348895..0000000 --- a/scrolllist/scrolllist.c +++ /dev/null @@ -1,1039 +0,0 @@ -/*---------------------- scrolllist~ ------------------------------------------ */ -/* */ -/* scrolllist~ : scrolling list of text items */ -/* constructor : scrolllist | scrolllist */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "I tried your cat's name, it tried your favorite band" */ -/* "I have the password to your ... shell account" */ -/* Barcelona - Shell Account */ -/* ---------------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - - -#ifdef NT -#include -#include -#else -#include -#include -#include -#endif - -t_widgetbehavior scrolllist_widgetbehavior; -static t_class *scrolllist_class; - -static int guidebug=0; - -static char *scrolllist_version = "scrolllist: scrolling list of text items : version 0.3, written by Yves Degoyon (ydegoyon@free.fr)"; - -#define MIN(a,b) (a>b?b:a) - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g);\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ - post(a,b,c,d,e,f,g,h);\ - sys_vgui(a,b,c,d,e,f,g,h) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define MAX_STRING_LENGTH 256 - -typedef struct _scrolllist -{ - t_object x_obj; - t_glist *x_glist; - t_outlet *x_item; /* outlet to output current selected item */ - t_int x_capacity; /* number of text items */ - t_int x_height; /* height of the scrolllist */ - t_int x_width; /* width of the scrolllist */ - t_int x_itemselected; /* index of the selected item */ - t_int x_selected; /* stores selected state */ - t_int x_graphics; /* flag to draw graphics or not */ - char **x_items; /* text items */ - t_int x_nitems; /* number of current items */ - t_int x_ndisplayed; /* number of displayed items */ - t_int x_firstseen; /* first displayed item */ - t_int x_lastseen; /* last displayed item */ - t_int x_cdy; /* cumulated y drag */ - char *x_font; /* font used for entries */ - t_int x_charheight; /* height of characters */ - t_int x_charwidth; /* width of characters */ - char *x_bgcolor; /* background color */ - char *x_fgcolor; /* foreground color */ - char *x_secolor; /* selection color */ -} t_scrolllist; - -static void scrolllist_erase(t_scrolllist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - - // just in case we got confused - if ( x->x_firstseen < 0 ) x->x_firstseen=0; - if ( x->x_lastseen > x->x_capacity-1 ) x->x_lastseen=x->x_capacity-1; - - // delete previous entries - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xITEM%d\n", canvas, x, i); - } -} - -static void scrolllist_update(t_scrolllist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - - // just in case we got confused - if ( x->x_firstseen < 0 ) x->x_firstseen=0; - if ( x->x_lastseen > x->x_capacity-1 ) x->x_lastseen=x->x_capacity-1; - - // display the content of text items - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - // display the entry if displayable - if ( ( (i-x->x_firstseen)*x->x_charheight < x->x_height ) && ( x->x_items[i] != NULL ) ) - { - SYS_VGUI11(".x%x.c create text %d %d -fill %s -activefill %s -width %d -text \"%s\" -anchor w -font %s -tags %xITEM%d\n", - canvas, - text_xpix(&x->x_obj, glist)+5, - text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight, - x->x_fgcolor, - x->x_secolor, - x->x_width, - x->x_items[i], - x->x_font, - x, i ); - } - if ( ( x->x_itemselected >= x->x_firstseen ) && ( x->x_itemselected <= x->x_lastseen ) ) - { - SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_secolor); - } - } -} - -static void scrolllist_output_current(t_scrolllist* x) -{ - if ( x->x_items && x->x_itemselected < x->x_nitems && x->x_itemselected >= 0 ) - { - outlet_symbol( x->x_item, gensym( x->x_items[x->x_itemselected] ) ); - } -} - -static void scrolllist_draw_new(t_scrolllist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - x->x_glist = glist; - if ( x->x_graphics ) - { - SYS_VGUI8(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xTEXTLIST\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, - x->x_bgcolor, x); - } - else - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -outline white -fill white -tags %xTEXTLIST\n", - canvas, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, x); - } - scrolllist_erase( x, glist ); - scrolllist_update( x, glist ); -} - -static void scrolllist_draw_move(t_scrolllist *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - struct timespec tv; - - tv.tv_sec = 0; - tv.tv_nsec = 10000000; - - SYS_VGUI7(".x%x.c coords %xTEXTLIST %d %d %d %d\n", - canvas, x, - text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), - text_xpix(&x->x_obj, glist)+x->x_width, - text_ypix(&x->x_obj, glist)+x->x_height); - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - // nanosleep( &tv, NULL ); - SYS_VGUI6(".x%x.c coords %xITEM%d %d %d\n", - canvas, x, i, - text_xpix(&x->x_obj, glist)+5, - text_ypix(&x->x_obj, glist)+5+(i-x->x_firstseen)*x->x_charheight); - } - - canvas_fixlinesfor( canvas, (t_text*)x ); -} - -static void scrolllist_draw_erase(t_scrolllist* x, t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int i; - - SYS_VGUI3(".x%x.c delete %xTEXTLIST\n", canvas, x); - for ( i=x->x_firstseen; i<=x->x_lastseen; i++ ) - { - SYS_VGUI4(".x%x.c delete %xITEM%d\n", canvas, x, i); - } -} - -static void scrolllist_draw_select(t_scrolllist* x, t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - // post( "scrolllist : select" ); - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xTEXTLIST -outline #0000FF\n", canvas, x); - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xTEXTLIST -outline #000000\n", canvas, x); - } -} - -/* ------------------------ scrolllist widgetbehaviour----------------------------- */ - - -static void scrolllist_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_scrolllist* x = (t_scrolllist*)z; - - *xp1 = text_xpix(&x->x_obj, owner); - *yp1 = text_ypix(&x->x_obj, owner); - *xp2 = text_xpix(&x->x_obj, owner)+x->x_width; - *yp2 = text_ypix(&x->x_obj, owner)+x->x_height; -} - -static void scrolllist_save(t_gobj *z, t_binbuf *b) -{ - t_scrolllist *x = (t_scrolllist *)z; - - // post( "saving scrolllist : %d", x->x_capacity ); - binbuf_addv(b, "ssiisiiissss", gensym("#X"), gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_capacity, x->x_width, x->x_height, - gensym(x->x_font), gensym(x->x_bgcolor), - gensym(x->x_fgcolor), gensym(x->x_secolor) ); - binbuf_addv(b, ";"); -} - -static void scrolllist_select(t_gobj *z, t_glist *glist, int selected) -{ - t_scrolllist *x = (t_scrolllist *)z; - - x->x_selected = selected; - - scrolllist_draw_select( x, glist ); -} - -static void scrolllist_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_scrolllist *x = (t_scrolllist *)z; - t_rtext *y; - - // post( "scrolllist : vis (%d)", vis ); - x->x_glist = glist; - if (vis) - { - scrolllist_draw_erase(x, x->x_glist); - scrolllist_draw_new( x, glist ); - } - else - { - scrolllist_draw_erase( x, glist ); - } -} - -static void scrolllist_deleteobj(t_gobj *z, t_glist *glist) -{ - t_scrolllist *x = (t_scrolllist *)z; - - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void scrolllist_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_scrolllist *x = (t_scrolllist *)z; - t_int xold = text_xpix(&x->x_obj, glist); - t_int yold = text_ypix(&x->x_obj, glist); - - // post( "scrolllist_displace dx=%d dy=%d", dx, dy ); - - x->x_obj.te_xpix += dx; - x->x_obj.te_ypix += dy; - if(xold != text_xpix(&x->x_obj, glist) || yold != text_ypix(&x->x_obj, glist)) - { - scrolllist_draw_move(x, glist); - } -} - -static void scrolllist_motion(t_scrolllist *x, t_floatarg dx, t_floatarg dy) -{ - t_int i; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - x->x_cdy+=dy; - scrolllist_erase( x, x->x_glist ); - - // check if we need to scroll - // eventually, move down - if ( x->x_cdy >= x->x_charheight ) - { - if ( x->x_firstseen < x->x_nitems - x->x_ndisplayed ) - { - x->x_firstseen++; - x->x_lastseen++; - // post( "scrolllist : moved down first=%d last=%d", x->x_firstseen, x->x_lastseen ); - } - } - // eventually, move up - if ( x->x_cdy <= -x->x_charheight ) - { - if ( x->x_firstseen-1 >= 0 ) - { - x->x_firstseen--; - x->x_lastseen--; - // post( "scrolllist : moved up first=%d last=%d", x->x_firstseen, x->x_lastseen ); - } - } - scrolllist_update(x, x->x_glist); - if ( ( x->x_cdy >= x->x_charheight ) || ( x->x_cdy <= -x->x_charheight ) ) x->x_cdy = 0; -} - -static void scrolllist_scroll(t_scrolllist *x, t_floatarg fdy) -{ - t_int nbsteps, si; - - x->x_cdy += (t_int)fdy; - nbsteps = (t_int)abs(x->x_cdy/x->x_charheight); - // post( "scrolllist : iterations %d", nbsteps ); - for (si=0; six_charheight); - } -} - -static void scrolllist_graphics(t_scrolllist *x, t_floatarg fgraphics) -{ - if ( ( (t_int)fgraphics == 0 ) || ( (t_int)fgraphics == 1 ) ) - { - scrolllist_draw_erase(x, x->x_glist); - x->x_graphics = (t_int) fgraphics; - scrolllist_draw_new(x, x->x_glist); - } -} - -static int scrolllist_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_scrolllist* x = (t_scrolllist *)z; - t_canvas *canvas=glist_getcanvas(x->x_glist); - t_int xoffset; - - if (doit) - { - // deselect previously selected item - SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_fgcolor); - x->x_itemselected = x->x_firstseen + (ypix-text_ypix(&x->x_obj, glist))/x->x_charheight; - SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", - canvas, x, x->x_itemselected, x->x_secolor); - // post( "scrolllist : selected item : %d", x->x_itemselected ); - if ( x->x_items && ( x->x_itemselected < x->x_nitems ) ) - { - xoffset=(xpix-text_xpix(&x->x_obj, glist)); - if ( xoffset <= (t_int)( x->x_width*4/5 ) ) - { - scrolllist_output_current(x); - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, glist ); - } - else - { - x->x_itemselected=-1; - } - } - x->x_glist = glist; - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scrolllist_motion, - NULL, xpix, ypix ); - } - return (1); -} - -static void scrolllist_properties(t_gobj *z, t_glist *owner) -{ - char buf[800]; - t_scrolllist *x=(t_scrolllist *)z; - - sprintf(buf, "pdtk_scrolllist_dialog %%s %d %d %d %s %s %s %s\n", - (int)x->x_capacity, (int)x->x_width, (int)x->x_height, - x->x_font, x->x_bgcolor, - x->x_fgcolor, x->x_secolor ); - // post("scrolllist_properties : %s", buf ); - gfxstub_new(&x->x_obj.ob_pd, x, buf); -} - -static void scrolllist_dialog(t_scrolllist *x, t_symbol *s, int argc, t_atom *argv) -{ - char **titems; - t_int ncapacity, i, ccapacity; - - scrolllist_erase( x, x->x_glist ); - scrolllist_draw_erase(x, x->x_glist); - - if ( !x ) { - post( "scrolllist : error :tried to set properties on an unexisting object" ); - } - if ( argc != 9 ) - { - post( "scrolllist : error in the number of arguments ( %d instead of 10 )", argc ); - return; - } - if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || - argv[2].a_type != A_FLOAT || argv[3].a_type != A_SYMBOL || - argv[4].a_type != A_FLOAT || argv[5].a_type != A_SYMBOL || - argv[6].a_type != A_SYMBOL || argv[7].a_type != A_SYMBOL || - argv[8].a_type != A_SYMBOL ) { - post( "scrolllist : wrong arguments" ); - return; - } - - ncapacity = (t_int)argv[0].a_w.w_float; - titems = (char**) malloc( ncapacity*sizeof(char*) ); - - if ( ncapacity < x->x_nitems ) - { - post( "scrolllist : new size is too small : texts lost !!" ); - ccapacity = ncapacity; - } - else - { - ccapacity = x->x_nitems; - } - for ( i=0; ix_items[i] != NULL ) - { - titems[i] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); - memcpy( titems[i], x->x_items[i], strlen( x->x_items[i] ) ); - titems[i][strlen( x->x_items[i] )]='\0'; - free( x->x_items[i] ); - x->x_items[i] = NULL; - } - } - if ( x->x_items ) - { - free( x->x_items ); - x->x_items = NULL; - } - x->x_items = titems; - x->x_nitems = ccapacity; - x->x_capacity = ncapacity; - - x->x_width = (int)argv[1].a_w.w_float; - x->x_height = (int)argv[2].a_w.w_float; - sprintf( x->x_font, "{%s %d %s}", argv[3].a_w.w_symbol->s_name, - (int)argv[4].a_w.w_float, argv[5].a_w.w_symbol->s_name ); - x->x_charheight = (t_int)argv[4].a_w.w_float; - strcpy( x->x_bgcolor, argv[6].a_w.w_symbol->s_name ); - strcpy( x->x_fgcolor, argv[7].a_w.w_symbol->s_name ); - strcpy( x->x_secolor, argv[8].a_w.w_symbol->s_name ); - - x->x_firstseen = 0; - x->x_ndisplayed = (t_int)(x->x_height/x->x_charheight ); - if ( x->x_nitems >= x->x_ndisplayed ) - { - x->x_lastseen = x->x_ndisplayed-1; - } - else - { - x->x_lastseen = x->x_nitems-1; - } - - scrolllist_draw_new(x, x->x_glist); - scrolllist_update(x, x->x_glist); -} - -static void scrolllist_bgcolor(t_scrolllist *x, t_symbol *s) -{ - scrolllist_erase( x, x->x_glist ); - scrolllist_draw_erase(x, x->x_glist); - - strcpy( x->x_bgcolor, s->s_name ); - - scrolllist_draw_new(x, x->x_glist); - scrolllist_update(x, x->x_glist); -} - -static void scrolllist_fgcolor(t_scrolllist *x, t_symbol *s) -{ - scrolllist_erase( x, x->x_glist ); - scrolllist_draw_erase(x, x->x_glist); - - strcpy( x->x_fgcolor, s->s_name ); - - scrolllist_draw_new(x, x->x_glist); - scrolllist_update(x, x->x_glist); -} - -static void scrolllist_secolor(t_scrolllist *x, t_symbol *s) -{ - scrolllist_erase( x, x->x_glist ); - scrolllist_draw_erase(x, x->x_glist); - - strcpy( x->x_secolor, s->s_name ); - - scrolllist_draw_new(x, x->x_glist); - scrolllist_update(x, x->x_glist); -} - -static void scrolllist_sort(t_scrolllist* x) -{ - char **titems; - t_int i, j, k, irank, indest; - - scrolllist_erase( x, x->x_glist ); - - // sort text items - titems = (char**) malloc( x->x_capacity*sizeof(char*) ); - for ( i=0; ix_capacity; i++ ) - { - titems[i]=NULL; - } - indest=0; - for ( i=0; ix_nitems; i++ ) - { - if ( x->x_items[i] != NULL ) - { - irank=0; - for ( j=0; jx_capacity; j++ ) - { - if ( titems[j] != NULL ) - { - // post( "scrollist : comparing >%s< to >%s<", titems[j], x->x_items[i] ); - if ( strcasecmp( titems[j], x->x_items[i] ) > 0 ) - { - irank=j; - break; - } - irank=j+1; - } - } - // insert in irank - // post( "scrollist : inserting %s at %d", x->x_items[i], irank ); - for ( k=indest-1; k>=irank; k-- ) - { - if ( (k+1) < x->x_capacity ) - { - if ( titems[k+1] != NULL ) - { - free( titems[k+1] ); - titems[k+1] = NULL; - } - titems[k+1] = (char*) malloc( strlen( titems[k] ) + 1 ); - memcpy( titems[k+1], titems[k], strlen( titems[k] ) ); - titems[k+1][strlen( titems[k] )]='\0'; - // post( "scrollist : copying %d to %d", k, k+1 ); - } - } - titems[irank] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); - memcpy( titems[irank], x->x_items[i], strlen( x->x_items[i] ) ); - titems[irank][strlen( x->x_items[i] )]='\0'; - free( x->x_items[i] ); - x->x_items[i]=NULL; - indest++; - } - } - if ( x->x_items ) - { - free( x->x_items ); - x->x_items = NULL; - } - x->x_items = titems; - - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_font(t_scrolllist* x, t_symbol *fname, t_symbol *fcase, t_floatarg fsize) -{ - if ( (t_int)fsize <= 4 ) - { - post( "scrolllist : wrong font size in font message : %d", (t_int)fsize ); - return; - } - sprintf( x->x_font, "{%s %d %s}", fname->s_name, (int)fsize, fcase->s_name ); - x->x_charheight = (t_int)fsize; - x->x_charwidth = (2*x->x_charheight)/3; - // post( "scrolllist : setting font to : %s", x->x_font ); - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_add(t_scrolllist* x, t_symbol *fnewtext) -{ - t_int i; - - // post( "scrollist : add : nitems = %d", x->x_nitems ); - if ( x->x_nitems >= x->x_capacity ) - { - // post( "scrolllist : warning : list is full, erasing first line" ); - for ( i=0; i<(x->x_nitems-1); i++ ) - { - if ( x->x_items[i] != NULL ) - { - free( x->x_items[i] ); - x->x_items[i] = NULL; - } - x->x_items[i] = (char*) malloc( strlen( x->x_items[i+1] ) + 1 ); - memcpy( x->x_items[i], x->x_items[i+1], strlen( x->x_items[i+1] ) ); - x->x_items[i][strlen( x->x_items[i+1] )]='\0'; - // post( "scrollist : copying %d to %d", i+1, i ); - } - x->x_items[x->x_nitems-1] = (char*) malloc( strlen( fnewtext->s_name ) + 1 ); - memcpy( x->x_items[x->x_nitems-1], fnewtext->s_name, strlen( fnewtext->s_name ) ); - x->x_items[x->x_nitems-1][strlen( fnewtext->s_name )]='\0'; - } - else - { - // post( "scrolllist : item #%d : %x", x->x_nitems, &x->x_items[x->x_nitems] ); - // post( "scrolllist : allocating : %d", strlen( fnewtext->s_name ) + 1 ); - x->x_items[x->x_nitems] = (char*) malloc( strlen( fnewtext->s_name ) + 1 ); - memcpy( x->x_items[x->x_nitems], fnewtext->s_name, strlen( fnewtext->s_name ) ); - x->x_items[x->x_nitems][strlen( fnewtext->s_name )]='\0'; - x->x_nitems++; - if ( (x->x_nitems-x->x_firstseen)*x->x_charheight+5 < x->x_height ) - { - x->x_lastseen = x->x_nitems-1; - } - } - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_insert(t_scrolllist* x, t_symbol *ftext, t_floatarg frank) -{ - t_int rank, i; - - if ( (t_int)frank > x->x_capacity ) - { - post( "scrolllist : error : incorrect rank in insert message (%d), over capacity", (t_int)frank ); - return; - } - rank = (t_int)frank-1; - if ( rank < 0 ) - { - rank=0; - } - if ( rank > x->x_nitems-1 ) - { - rank=x->x_nitems-1; - } - for ( i=x->x_nitems-1; i>=rank; i-- ) - { - if ( (i+1) < x->x_capacity ) - { - if ( x->x_items[i+1] != NULL ) - { - free( x->x_items[i+1] ); - x->x_items[i+1] = NULL; - } - x->x_items[i+1] = (char*) malloc( strlen( x->x_items[i] ) + 1 ); - memcpy( x->x_items[i+1], x->x_items[i], strlen( x->x_items[i] ) ); - x->x_items[i+1][strlen( x->x_items[i] )]='\0'; - // post( "scrollist : copying %d to %d", i, i+1 ); - } - } - // post( "scrollist : inserting at %d", rank ); - x->x_items[rank] = (char*) malloc( strlen( ftext->s_name ) + 1 ); - memcpy( x->x_items[rank], ftext->s_name, strlen( ftext->s_name ) ); - x->x_items[rank][strlen( ftext->s_name )]='\0'; - if ( x->x_nitems < x->x_capacity ) x->x_nitems++; - if ( (x->x_nitems-x->x_firstseen)*x->x_charheight+5 < x->x_height ) - { - x->x_lastseen = x->x_nitems-1; - } - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_replace(t_scrolllist* x, t_symbol *ftext, t_floatarg frank) -{ - t_int rank; - - if ( ( (t_int)frank <= 0 ) || ( (t_int)frank > x->x_nitems ) ) - { - post( "scrolllist : error : incorrect rank in replace message (%d), no such text", (t_int)frank ); - return; - } - - rank = (t_int) frank-1; - if ( x->x_items[rank] != NULL ) - { - free( x->x_items[rank] ); - x->x_items[rank] = NULL; - } - x->x_items[rank] = (char*) malloc( strlen( ftext->s_name ) + 1 ); - memcpy( x->x_items[rank], ftext->s_name, strlen( ftext->s_name ) ); - x->x_items[rank][strlen( ftext->s_name )]='\0'; - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_delete(t_scrolllist* x, t_floatarg frank) -{ - t_int rank, i; - - if ( ( (t_int)frank <= 0 ) || ( (t_int)frank > x->x_nitems ) ) - { - post( "scrolllist : error : incorrect rank in delete message (%d), no such text (%d)", (t_int)frank, x->x_nitems ); - return; - } - - rank = (t_int) frank-1; - for ( i=rank; ix_nitems-1; i++ ) - { - if ( x->x_items[i] != NULL ) - { - free( x->x_items[i] ); - x->x_items[i] = NULL; - } - x->x_items[i] = (char*) malloc( strlen( x->x_items[i+1] ) + 1 ); - memcpy( x->x_items[i], x->x_items[i+1], strlen( x->x_items[i+1] ) ); - x->x_items[i][strlen( x->x_items[i+1] )]='\0'; - // post( "scrollist : copying %d to %d", i+1, i ); - } - free( x->x_items[x->x_nitems-1] ); - x->x_items[x->x_nitems-1] = NULL; - if ( x->x_lastseen == x->x_nitems-2 ) x->x_lastseen--; - x->x_nitems--; - scrolllist_erase( x, x->x_glist ); - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_clear(t_scrolllist* x) -{ - t_int i; - - scrolllist_erase( x, x->x_glist ); - for ( i=0; ix_capacity; i++ ) - { - x->x_items[i]=NULL; - } - x->x_nitems = 0; - x->x_selected = 0; - x->x_itemselected = -1; - x->x_firstseen = 0; - x->x_lastseen = -1; - scrolllist_update( x, x->x_glist ); -} - -static void scrolllist_seek(t_scrolllist *x, t_floatarg fseeked) -{ - t_int iout=0; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if ( fseeked < 0 ) - { - post( "scrolllist : wrong searched file : %f", fseeked ); - return; - } - if ( x->x_nitems == 0 ) return; - - iout = (t_int)fseeked % (x->x_nitems); - SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", canvas, x, x->x_itemselected, x->x_fgcolor); - x->x_itemselected = iout; - SYS_VGUI5(".x%x.c itemconfigure %xITEM%d -fill %s\n", canvas, x, x->x_itemselected, x->x_secolor); - scrolllist_output_current(x); -} - -static t_scrolllist *scrolllist_new(t_symbol *s, int argc, t_atom *argv ) -{ - t_int i, argoffset=0; - t_scrolllist *x; - - x = (t_scrolllist *)pd_new(scrolllist_class); - - x->x_capacity = 100; - x->x_width = 400; - x->x_height = 200; - x->x_font = ( char * ) malloc( MAX_STRING_LENGTH ); - sprintf( x->x_font, "{Helvetica 10 bold}" ); - x->x_charheight = 10; - x->x_charwidth = (2*10)/3; - x->x_bgcolor = ( char * ) malloc( MAX_STRING_LENGTH ); - sprintf( x->x_bgcolor, "#457782" ); - x->x_fgcolor = ( char * ) malloc( MAX_STRING_LENGTH ); - sprintf( x->x_fgcolor, "black" ); - x->x_secolor = ( char * ) malloc( MAX_STRING_LENGTH ); - sprintf( x->x_secolor, "red" ); - - if ( argc >= 1 ) - { - if ( argv[0].a_type != A_FLOAT ) - { - error( "scrolllist : wrong argument (capacity : 1)" ); - return NULL; - } - x->x_capacity = (int)argv[0].a_w.w_float; - } - if ( argc >= 2 ) - { - if ( argv[1].a_type != A_FLOAT ) - { - error( "scrolllist : wrong argument (width : 2)" ); - return NULL; - } - if ( (int)argv[1].a_w.w_float <= 0 ) - { - error( "scrolllist : wrong width (%d)", (t_int)(int)argv[1].a_w.w_float ); - error( "scrolllist : usage : scrolllist " ); - return NULL; - } - x->x_width = (int)argv[1].a_w.w_float; - } - if ( argc >= 3 ) - { - if ( argv[2].a_type != A_FLOAT ) - { - error( "scrolllist : wrong argument (height : 3)" ); - return NULL; - } - if ( (int)argv[2].a_w.w_float <= 0 ) - { - error( "scrolllist : wrong height (%d)", (t_int)(int)argv[2].a_w.w_float ); - error( "scrolllist : usage : scrolllist " ); - return NULL; - } - x->x_height = (int)argv[2].a_w.w_float; - } - if ( argc >= 6 ) - { - if ( argv[3].a_type != A_SYMBOL || - argv[5].a_type != A_SYMBOL ) - { - error( "scrolllist : wrong arguments (font : 4,6)" ); - error( "argument types : %d %d", argv[3].a_type, argv[5].a_type ); - return NULL; - } - if ( argv[4].a_type != A_SYMBOL && - argv[4].a_type != A_FLOAT ) - { - error( "scrolllist : wrong arguments (font size : 5)" ); - error( "argument types : %d", argv[4].a_type ); - return NULL; - } - if ( argv[4].a_type == A_SYMBOL ) - { - sprintf( x->x_font, "%s", argv[3].a_w.w_symbol->s_name ); - x->x_charheight = (t_int)atoi( strstr( argv[3].a_w.w_symbol->s_name, " ") ); - argoffset=2; - } - if ( argv[4].a_type == A_FLOAT ) - { - x->x_charheight = (t_int)argv[4].a_w.w_float; - sprintf( x->x_font, "%s %d %s", argv[3].a_w.w_symbol->s_name, - (int)x->x_charheight, argv[5].a_w.w_symbol->s_name ); - argoffset=0; - } - post( "scrolllist : font : %s, size : %d", x->x_font, x->x_charheight ); - } - if ( argc >= 7-argoffset ) - { - if ( argv[6-argoffset].a_type != A_SYMBOL ) - { - error( "scrolllist : wrong arguments (background color : %d)", 7-argoffset ); - return NULL; - } - strcpy( x->x_bgcolor, argv[6-argoffset].a_w.w_symbol->s_name ); - } - if ( argc >= 8-argoffset ) - { - if ( argv[7-argoffset].a_type != A_SYMBOL ) - { - error( "scrolllist : wrong arguments (foreground color : %d)", 8-argoffset ); - return NULL; - } - strcpy( x->x_fgcolor, argv[7-argoffset].a_w.w_symbol->s_name ); - } - if ( argc >= 9-argoffset ) - { - if ( argv[8-argoffset].a_type != A_SYMBOL ) - { - error( "scrolllist : wrong arguments (selection color : %d)", 9-argoffset ); - return NULL; - } - strcpy( x->x_secolor, argv[8-argoffset].a_w.w_symbol->s_name ); - } - - x->x_item = outlet_new(&x->x_obj, &s_symbol ); - - x->x_glist = (t_glist *) canvas_getcurrent(); - x->x_nitems = 0; - x->x_items = (char **) malloc( x->x_capacity*sizeof(char*) ); - for ( i=0; ix_capacity; i++ ) - { - x->x_items[i]=NULL; - } - - x->x_selected = 0; - x->x_itemselected = -1; - x->x_firstseen = 0; - x->x_lastseen = -1; - x->x_ndisplayed = (t_int)(x->x_height/x->x_charheight ); - - x->x_graphics = 1; - - post( "scrolllist : capacity=%d width=%d height=%d", x->x_capacity, x->x_width, x->x_height ); - - return (x); -} - -static void scrolllist_free(t_scrolllist *x) -{ - t_int i; - - // post( "scrolllist : scrolllist_free" ); - - // free text items list - if ( x->x_nitems ) - { - for ( i=0; ix_nitems; i++ ) - { - if ( x->x_items[i] != NULL ) - { - // post( "scrolllist : freeing entry %d size=%d : %s", i, strlen( x->x_items[i] ) + 1, x->x_items[i] ); - free( x->x_items[i] ); - } - } - } - free( x->x_items ); - if ( x->x_font ) - { - free( x->x_font ); - } - if ( x->x_bgcolor ) - { - free( x->x_bgcolor ); - } - if ( x->x_fgcolor ) - { - free( x->x_fgcolor ); - } - if ( x->x_secolor ) - { - free( x->x_secolor ); - } -} - -void scrolllist_setup(void) -{ - post( scrolllist_version ); -#include "scrolllist.tk2c" - scrolllist_class = class_new(gensym("scrolllist"), (t_newmethod)scrolllist_new, - (t_method)scrolllist_free, sizeof(t_scrolllist), - CLASS_DEFAULT, A_GIMME, 0); - class_addmethod(scrolllist_class, (t_method)scrolllist_seek, gensym("seek"), A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_dialog, gensym("dialog"), A_GIMME, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_sort, gensym("sort"), A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_graphics, gensym("graphics"), A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_scroll, gensym("scroll"), A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_font, gensym("font"), A_SYMBOL, A_SYMBOL, A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_insert, gensym("insert"), A_SYMBOL, A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_replace, gensym("replace"), A_SYMBOL, A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_add, gensym("add"), A_SYMBOL, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_bgcolor, gensym("bgcolor"), A_SYMBOL, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_fgcolor, gensym("fgcolor"), A_SYMBOL, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_secolor, gensym("secolor"), A_SYMBOL, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_delete, gensym("delete"), A_DEFFLOAT, A_NULL ); - class_addmethod(scrolllist_class, (t_method)scrolllist_clear, gensym("clear"), A_NULL ); - - scrolllist_widgetbehavior.w_getrectfn = scrolllist_getrect; - scrolllist_widgetbehavior.w_displacefn = scrolllist_displace; - scrolllist_widgetbehavior.w_selectfn = scrolllist_select; - scrolllist_widgetbehavior.w_activatefn = NULL; - scrolllist_widgetbehavior.w_deletefn = scrolllist_deleteobj; - scrolllist_widgetbehavior.w_visfn = scrolllist_vis; - scrolllist_widgetbehavior.w_clickfn = scrolllist_click; - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(scrolllist_class, scrolllist_properties); - class_setsavefn(scrolllist_class, scrolllist_save); -#else - scrolllist_widgetbehavior.w_propertiesfn = scrolllist_properties; - scrolllist_widgetbehavior.w_savefn = scrolllist_save; -#endif - - class_setwidget(scrolllist_class, &scrolllist_widgetbehavior); - -} diff --git a/scrolllist/scrolllist.tk b/scrolllist/scrolllist.tk deleted file mode 100755 index 79ca61c..0000000 --- a/scrolllist/scrolllist.tk +++ /dev/null @@ -1,141 +0,0 @@ -############ scrolllist procedures -- ydegoyon@free.fr ######### - -proc scrolllist_apply {id} { -# strip "." from the TK id to make a variable name suffix - set vid [string trimleft $id .] -# for each variable, make a local variable to hold its name... - set var_graph_capacity [concat graph_capacity_$vid] - global $var_graph_capacity - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height$vid] - global $var_graph_height - set var_graph_font [concat graph_font$vid] - global $var_graph_font - set var_graph_bgcolor [concat graph_bgcolor$vid] - global $var_graph_bgcolor - set var_graph_fgcolor [concat graph_fgcolor$vid] - global $var_graph_fgcolor - set var_graph_secolor [concat graph_secolor$vid] - global $var_graph_secolor - - set cmd [concat $id dialog \ - [eval concat $$var_graph_capacity] \ - [eval concat $$var_graph_width] \ - [eval concat $$var_graph_height] \ - [eval concat $$var_graph_font] \ - [eval concat $$var_graph_bgcolor] \ - [eval concat $$var_graph_fgcolor] \ - [eval concat $$var_graph_secolor] \ - \;] - #puts stderr $cmd - pd $cmd -} - -proc scrolllist_cancel {id} { - set cmd [concat $id cancel \;] - #puts stderr $cmd - pd $cmd -} - -proc scrolllist_ok {id} { - scrolllist_apply $id - scrolllist_cancel $id -} - -proc pdtk_scrolllist_dialog {id capacity width height font bgcolor fgcolor secolor} { - set vid [string trimleft $id .] - set var_graph_capacity [concat graph_capacity_$vid] - global $var_graph_capacity - set var_graph_width [concat graph_width_$vid] - global $var_graph_width - set var_graph_height [concat graph_height$vid] - global $var_graph_height - set var_graph_font [concat graph_font$vid] - global $var_graph_font - set var_graph_bgcolor [concat graph_bgcolor$vid] - global $var_graph_bgcolor - set var_graph_fgcolor [concat graph_fgcolor$vid] - global $var_graph_fgcolor - set var_graph_secolor [concat graph_secolor$vid] - global $var_graph_secolor - - set $var_graph_capacity $capacity - set $var_graph_width $width - set $var_graph_height $height - set $var_graph_font $font - set $var_graph_bgcolor $bgcolor - set $var_graph_fgcolor $fgcolor - set $var_graph_secolor $secolor - - toplevel $id - wm title $id {scrolllist} - wm protocol $id WM_DELETE_WINDOW [concat scrolllist_cancel $id] - - label $id.label -text {SCROLLLIST PROPERTIES} - pack $id.label -side top - - frame $id.buttonframe - pack $id.buttonframe -side bottom -fill x -pady 2m - button $id.buttonframe.cancel -text {Cancel}\ - -command "scrolllist_cancel $id" - button $id.buttonframe.apply -text {Apply}\ - -command "scrolllist_apply $id" - button $id.buttonframe.ok -text {OK}\ - -command "scrolllist_ok $id" - pack $id.buttonframe.cancel -side left -expand 1 - pack $id.buttonframe.apply -side left -expand 1 - pack $id.buttonframe.ok -side left -expand 1 - - frame $id.1rangef - pack $id.1rangef -side top - label $id.1rangef.lcapacity -text "Capacity :" - entry $id.1rangef.capacity -textvariable $var_graph_capacity -width 7 - pack $id.1rangef.lcapacity $id.1rangef.capacity -side left - - frame $id.2rangef - pack $id.2rangef -side top - label $id.2rangef.lwidth -text "Width :" - entry $id.2rangef.width -textvariable $var_graph_width -width 7 - pack $id.2rangef.lwidth $id.2rangef.width -side left - - frame $id.3rangef - pack $id.3rangef -side top - label $id.3rangef.lheight -text "Height :" - entry $id.3rangef.height -textvariable $var_graph_height -width 7 - pack $id.3rangef.lheight $id.3rangef.height -side left - - frame $id.3_5rangef - pack $id.3_5rangef -side top - label $id.3_5rangef.lfont -text "Font :" - entry $id.3_5rangef.font -textvariable $var_graph_font -width 30 - pack $id.3_5rangef.lfont $id.3_5rangef.font -side left - - frame $id.4rangef - pack $id.4rangef -side top - label $id.4rangef.lbgcolor -text "Background Color :" - entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7 - pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left - - frame $id.5rangef - pack $id.5rangef -side top - label $id.5rangef.lfgcolor -text "Foreground Color :" - entry $id.5rangef.fgcolor -textvariable $var_graph_fgcolor -width 7 - pack $id.5rangef.lfgcolor $id.5rangef.fgcolor -side left - - frame $id.6rangef - pack $id.6rangef -side top - label $id.6rangef.lsecolor -text "Selection Color :" - entry $id.6rangef.secolor -textvariable $var_graph_secolor -width 7 - pack $id.6rangef.lsecolor $id.6rangef.secolor -side left - - bind $id.1rangef.capacity [concat scrolllist_ok $id] - bind $id.2rangef.width [concat scrolllist_ok $id] - bind $id.3rangef.height [concat scrolllist_ok $id] - bind $id.3_5rangef.font [concat scrolllist_ok $id] - bind $id.4rangef.bgcolor [concat scrolllist_ok $id] - bind $id.5rangef.fgcolor [concat scrolllist_ok $id] - bind $id.6rangef.secolor [concat scrolllist_ok $id] -} - -############ scrolllist procedures END -- ydegoyon@free.fr ######### diff --git a/scrolllist/scrolllist.tk2c b/scrolllist/scrolllist.tk2c deleted file mode 100644 index 97129fb..0000000 --- a/scrolllist/scrolllist.tk2c +++ /dev/null @@ -1,112 +0,0 @@ -// ########### scrolllist procedures -- ydegoyon@free.fr ######### -sys_gui("proc scrolllist_apply {id} {\n"); -// strip "." from the TK id to make a variable name suffix -sys_gui("set vid [string trimleft $id .]\n"); -// for each variable, make a local variable to hold its name... -sys_gui("set var_graph_capacity [concat graph_capacity_$vid]\n"); -sys_gui("global $var_graph_capacity\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_font [concat graph_font$vid]\n"); -sys_gui("global $var_graph_font\n"); -sys_gui("set var_graph_bgcolor [concat graph_bgcolor$vid]\n"); -sys_gui("global $var_graph_bgcolor\n"); -sys_gui("set var_graph_fgcolor [concat graph_fgcolor$vid]\n"); -sys_gui("global $var_graph_fgcolor\n"); -sys_gui("set var_graph_secolor [concat graph_secolor$vid]\n"); -sys_gui("global $var_graph_secolor\n"); -sys_gui("set cmd [concat $id dialog [eval concat $$var_graph_capacity] [eval concat $$var_graph_width] [eval concat $$var_graph_height] [eval concat $$var_graph_font] [eval concat $$var_graph_bgcolor] [eval concat $$var_graph_fgcolor] [eval concat $$var_graph_secolor] \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc scrolllist_cancel {id} {\n"); -sys_gui("set cmd [concat $id cancel \\;]\n"); -// puts stderr $cmd -sys_gui("pd $cmd\n"); -sys_gui("}\n"); -sys_gui("proc scrolllist_ok {id} {\n"); -sys_gui("scrolllist_apply $id\n"); -sys_gui("scrolllist_cancel $id\n"); -sys_gui("}\n"); -sys_gui("proc pdtk_scrolllist_dialog {id capacity width height font bgcolor fgcolor secolor} {\n"); -sys_gui("set vid [string trimleft $id .]\n"); -sys_gui("set var_graph_capacity [concat graph_capacity_$vid]\n"); -sys_gui("global $var_graph_capacity\n"); -sys_gui("set var_graph_width [concat graph_width_$vid]\n"); -sys_gui("global $var_graph_width\n"); -sys_gui("set var_graph_height [concat graph_height$vid]\n"); -sys_gui("global $var_graph_height\n"); -sys_gui("set var_graph_font [concat graph_font$vid]\n"); -sys_gui("global $var_graph_font\n"); -sys_gui("set var_graph_bgcolor [concat graph_bgcolor$vid]\n"); -sys_gui("global $var_graph_bgcolor\n"); -sys_gui("set var_graph_fgcolor [concat graph_fgcolor$vid]\n"); -sys_gui("global $var_graph_fgcolor\n"); -sys_gui("set var_graph_secolor [concat graph_secolor$vid]\n"); -sys_gui("global $var_graph_secolor\n"); -sys_gui("set $var_graph_capacity $capacity\n"); -sys_gui("set $var_graph_width $width\n"); -sys_gui("set $var_graph_height $height\n"); -sys_gui("set $var_graph_font $font\n"); -sys_gui("set $var_graph_bgcolor $bgcolor\n"); -sys_gui("set $var_graph_fgcolor $fgcolor\n"); -sys_gui("set $var_graph_secolor $secolor\n"); -sys_gui("toplevel $id\n"); -sys_gui("wm title $id {scrolllist}\n"); -sys_gui("wm protocol $id WM_DELETE_WINDOW [concat scrolllist_cancel $id]\n"); -sys_gui("label $id.label -text {SCROLLLIST PROPERTIES}\n"); -sys_gui("pack $id.label -side top\n"); -sys_gui("frame $id.buttonframe\n"); -sys_gui("pack $id.buttonframe -side bottom -fill x -pady 2m\n"); -sys_gui("button $id.buttonframe.cancel -text {Cancel} -command \"scrolllist_cancel $id\"\n"); -sys_gui("button $id.buttonframe.apply -text {Apply} -command \"scrolllist_apply $id\"\n"); -sys_gui("button $id.buttonframe.ok -text {OK} -command \"scrolllist_ok $id\"\n"); -sys_gui("pack $id.buttonframe.cancel -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.apply -side left -expand 1\n"); -sys_gui("pack $id.buttonframe.ok -side left -expand 1\n"); -sys_gui("frame $id.1rangef\n"); -sys_gui("pack $id.1rangef -side top\n"); -sys_gui("label $id.1rangef.lcapacity -text \"Capacity :\"\n"); -sys_gui("entry $id.1rangef.capacity -textvariable $var_graph_capacity -width 7\n"); -sys_gui("pack $id.1rangef.lcapacity $id.1rangef.capacity -side left\n"); -sys_gui("frame $id.2rangef\n"); -sys_gui("pack $id.2rangef -side top\n"); -sys_gui("label $id.2rangef.lwidth -text \"Width :\"\n"); -sys_gui("entry $id.2rangef.width -textvariable $var_graph_width -width 7\n"); -sys_gui("pack $id.2rangef.lwidth $id.2rangef.width -side left\n"); -sys_gui("frame $id.3rangef\n"); -sys_gui("pack $id.3rangef -side top\n"); -sys_gui("label $id.3rangef.lheight -text \"Height :\"\n"); -sys_gui("entry $id.3rangef.height -textvariable $var_graph_height -width 7\n"); -sys_gui("pack $id.3rangef.lheight $id.3rangef.height -side left\n"); -sys_gui("frame $id.3_5rangef\n"); -sys_gui("pack $id.3_5rangef -side top\n"); -sys_gui("label $id.3_5rangef.lfont -text \"Font :\"\n"); -sys_gui("entry $id.3_5rangef.font -textvariable $var_graph_font -width 30\n"); -sys_gui("pack $id.3_5rangef.lfont $id.3_5rangef.font -side left\n"); -sys_gui("frame $id.4rangef\n"); -sys_gui("pack $id.4rangef -side top\n"); -sys_gui("label $id.4rangef.lbgcolor -text \"Background Color :\"\n"); -sys_gui("entry $id.4rangef.bgcolor -textvariable $var_graph_bgcolor -width 7\n"); -sys_gui("pack $id.4rangef.lbgcolor $id.4rangef.bgcolor -side left\n"); -sys_gui("frame $id.5rangef\n"); -sys_gui("pack $id.5rangef -side top\n"); -sys_gui("label $id.5rangef.lfgcolor -text \"Foreground Color :\"\n"); -sys_gui("entry $id.5rangef.fgcolor -textvariable $var_graph_fgcolor -width 7\n"); -sys_gui("pack $id.5rangef.lfgcolor $id.5rangef.fgcolor -side left\n"); -sys_gui("frame $id.6rangef\n"); -sys_gui("pack $id.6rangef -side top\n"); -sys_gui("label $id.6rangef.lsecolor -text \"Selection Color :\"\n"); -sys_gui("entry $id.6rangef.secolor -textvariable $var_graph_secolor -width 7\n"); -sys_gui("pack $id.6rangef.lsecolor $id.6rangef.secolor -side left\n"); -sys_gui("bind $id.1rangef.capacity [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.2rangef.width [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.3rangef.height [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.3_5rangef.font [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.4rangef.bgcolor [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.5rangef.fgcolor [concat scrolllist_ok $id]\n"); -sys_gui("bind $id.6rangef.secolor [concat scrolllist_ok $id]\n"); -sys_gui("}\n"); -// ########### scrolllist procedures END -- ydegoyon@free.fr ######### diff --git a/scrolllist/tk2c.bash b/scrolllist/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/scrolllist/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/scrolllist/yesterday.txt b/scrolllist/yesterday.txt deleted file mode 100644 index acbd1ed..0000000 --- a/scrolllist/yesterday.txt +++ /dev/null @@ -1,34 +0,0 @@ -Yesterday -All those backups seemed a waste of pay. -Now my database has gone away. -Oh I believe in yesterday. -Suddenly, -There's not half the files there used to be, -And there's a milestone -hanging over me -The system crashed so suddenly. -I pushed something wrong -What it was I could not say. -Now all my data's gone -and I long for yesterday-ay-ay-ay. -Yesterday, -The need for back-ups seemed so far away. -I knew my data was all here to stay, -Now I believe in yesterday. -Yesterday -All those backups seemed a waste of pay. -Now my database has gone away. -Oh I believe in yesterday. -Suddenly, -There's not half the files there used to be, -And there's a milestone -hanging over me -The system crashed so suddenly. -I pushed something wrong -What it was I could not say. -Now all my data's gone -and I long for yesterday-ay-ay-ay. -Yesterday, -The need for back-ups seemed so far away. -I knew my data was all here to stay, -Now I believe in yesterday. diff --git a/setosc.pd b/setosc.pd new file mode 100644 index 0000000..6cb4ff0 --- /dev/null +++ b/setosc.pd @@ -0,0 +1,21 @@ +#N canvas 242 244 450 300 10; +#X obj 191 209 osc~; +#X obj 140 247 *~; +#X obj 140 277 outlet~; +#X obj 83 112 inlet~; +#X floatatom 236 186 5 0 0; +#X msg 274 87 bang; +#X obj 335 64 r fbstep; +#X obj 145 55 r firstfreq; +#X obj 217 138 expr $f1 + $f2 * \$1; +#X obj 341 100 t b f; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 3 0 1 1; +#X connect 5 0 8 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 4 0; +#X connect 8 0 0 0; +#X connect 9 0 8 0; +#X connect 9 1 8 1; diff --git a/sonogram~-help.pd b/sonogram~-help.pd new file mode 100644 index 0000000..ab00898 --- /dev/null +++ b/sonogram~-help.pd @@ -0,0 +1,10 @@ +#N canvas 0 1 450 300 10; +#X obj 134 93 rs-sonogram~; +#X text 193 27 To work properly \, the block size; +#X text 193 39 has to be redefined.; +#X msg 291 89 \; pd dsp 1; +#X msg 356 90 \; pd dsp 0; +#X text 193 51 that's why everything is in the subpatch.; +#X obj 132 130 dac~; +#X connect 0 0 6 0; +#X connect 0 0 6 1; diff --git a/sonogram~.c b/sonogram~.c new file mode 100644 index 0000000..4085b34 --- /dev/null +++ b/sonogram~.c @@ -0,0 +1,2088 @@ +/*------------------------ sonogram~ ------------------------------------------ */ +/* */ +/* sonogram~ : lets you record, play back and modify a sonogram */ +/* constructor : sonogram */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "Living at night" */ +/* "Doesn't help for my complexion" */ +/* David Thomas - Final Solution */ +/* ---------------------------------------------------------------------------- */ + + + +#include +#include +#include +#include +#include +#include +#include +#ifdef __APPLE__ +#include +#else +#include +#endif +#include +#include +#ifdef UNIX +#include +#endif +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif +#include + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" + + +static int guidebug=0; +static int ignorevisible=1; // ignore visible test + // because this seems to lead to bad refresh + // wait for a fix + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +#define THREAD_SLEEP_TIME 100000 // 100000 us = 100 ms + +static char *sonogram_version = "sonogram~: version 0.14, written by Yves Degoyon (ydegoyon@free.fr)"; + +static t_class *sonogram_class; +t_widgetbehavior sonogram_widgetbehavior; + + +typedef struct _sonogram +{ + t_object x_obj; + + t_int x_size; /* size of the stored fft ( in blocks~ ) */ + t_float x_samplerate; /* sample rate */ + t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ + t_float x_readpos; /* data's playing position */ + t_int x_writepos; /* data's recording position */ + t_int x_readstart; /* data's starting position for reading */ + t_int x_readend; /* data's ending position for reading */ + t_int x_modstart; /* data's starting position for modifications */ + t_int x_modend; /* data's ending position for modifications */ + t_int x_play; /* playing on/off flag */ + t_float x_readspeed; /* number of grouped blocks for reading */ + t_float x_record; /* flag to start recording process */ + t_float x_empty; /* flag to indicate it's a brand new sonogram */ + t_float *x_rdata; /* table containing real part of the fft */ + t_float *x_rudata; /* undo real data */ + t_float *x_idata; /* table containing imaginery part of the fft */ + t_float *x_iudata; /* undo imaginery data */ + t_float x_phase; /* phase to apply on output */ + t_outlet *x_end; /* outlet for end of restitution */ + t_outlet *x_recend; /* outlet for end of recording */ + t_int *x_multfreq; /* array of multiplicative factor */ + char *x_gifdata; /* buffer for graphical data */ + char *x_guicommand; /* buffer for graphical command */ + t_int x_uxs; /* starting x position for undo */ + t_int x_uxe; /* ending x position for undo */ + t_int x_uys; /* starting y position for undo */ + t_int x_uye; /* ending y position for undo */ + + /* graphical data block */ + t_int x_enhancemode; /* flag to set enhance mode */ + t_int x_graphic; /* flag to set graphic mode */ + t_int x_phaso; /* flag to indicate if phasogram is shown */ + t_int x_selected; /* flag to remember if we are seleted or not */ + t_int x_erase; /* flag used when an erase is needed */ + t_int x_redraw; /* flag used when drawing is needed */ + t_int x_nbupdated; /* number of points updated */ + t_glist *x_glist; /* keep graphic context for various operations */ + t_int x_zoom; /* zoom factor */ + #ifndef _WIN32 + pthread_t x_updatechild; /* thread id for the update child */ + #else + int x_updatechild; + #endif + t_int x_updatestart; /* starting position for update */ + t_int x_updateend; /* ending position for update */ + t_int x_xpos; /* stuck x position */ + t_int x_ypos; /* stuck y position */ + t_int x_shifted; /* remember shift state from last click */ + t_int x_alted; /* remember alt state from last click */ + t_int x_aftermousedown; /* indicates the mousedown event */ + t_int x_xstartcapture; /* x of the start of the capture */ + t_int x_ystartcapture; /* y of the start of the capture */ + t_int x_xendcapture; /* x of the start of the capture */ + t_int x_yendcapture; /* y of the start of the capture */ + t_int x_xdraw; /* x drawing position */ + t_int x_ydraw; /* y drawing position */ + t_float x_modstep; /* step for graphical modifications */ + + t_float x_f; /* float needed for signal input */ + +} t_sonogram; + +/* ------------------------ drawing functions ---------------------------- */ +static char* sonogram_get_fill_color( t_float fspectrum ) +{ + if ( fspectrum < 0.01 ) { + return "#EEEEEE "; + } else if ( fspectrum < 0.1 ) { + return "#DDDDDD "; + } else if ( fspectrum < 0.5 ) { + return "#CCCCCC "; + } else if ( fspectrum < 1 ) { + return "#BBBBBB "; + } else if ( fspectrum < 2 ) { + return "#AAAAAA "; + } else if ( fspectrum < 5 ) { + return "#999999 "; + } else if ( fspectrum < 10 ) { + return "#888888 "; + } else if ( fspectrum < 20 ) { + return "#777777 "; + } else if ( fspectrum < 30 ) { + return "#666666 "; + } else if ( fspectrum < 40 ) { + return "#555555 "; + } else if ( fspectrum < 50 ) { + return "#444444 "; + } else if ( fspectrum < 60 ) { + return "#333333 "; + } else if ( fspectrum < 80 ) { + return "#222222 "; + } else if ( fspectrum < 100 ) { + return "#111111 "; + } else { + return "#000000 "; + } +} + +static char* phasogram_get_fill_color( t_int phase ) +{ + if ( phase < 0 ) + { + if ( phase > -10 ) { + return "#111111 "; + } else if ( phase > -20 ) { + return "#222222 "; + } else if ( phase > -30 ) { + return "#333333 "; + } else if ( phase > -40 ) { + return "#444444 "; + } else if ( phase > -50 ) { + return "#555555 "; + } else if ( phase > -60 ) { + return "#666666 "; + } else if ( phase > -70 ) { + return "#777777 "; + } else if ( phase > -80 ) { + return "#888888 "; + } else { + return "#999999 "; + } + } + else + { + if ( phase == 0 ) { + return "#FFFFFF "; + } else if ( phase < 10 ) { + return "#111111 "; + } else if ( phase < 20 ) { + return "#222222 "; + } else if ( phase < 30 ) { + return "#333333 "; + } else if ( phase < 40 ) { + return "#444444 "; + } else if ( phase < 50 ) { + return "#555555 "; + } else if ( phase < 60 ) { + return "#666666 "; + } else if ( phase < 70 ) { + return "#777777 "; + } else if ( phase < 80 ) { + return "#888888 "; + } else { + return "#999999 "; + } + } + // normally never reached + return ""; +} + +static void sonogram_update_point(t_sonogram *x, t_glist *glist, t_int sample, t_int frequency) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_float fspectrum=0.0; + t_int phase=0.0; + char newColor[ 8 ], olColor[8]; + int i; + + fspectrum = + sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + + pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); + phase = (int) ( atan2( *(x->x_idata+(sample*x->x_blocksize)+frequency), + *(x->x_rdata+(sample*x->x_blocksize)+frequency) )*180/M_PI ); + if ( x->x_empty && ( fspectrum != 0 )) + { + x->x_empty = 0; + } + strncpy( newColor, sonogram_get_fill_color( fspectrum ), 8 ); + + for ( i=0; ix_zoom; i++ ) + { + sprintf( x->x_gifdata, "%s", newColor ); + } + for ( i=0; ix_zoom; i++ ) + { + SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, + sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); + } + + if ( x->x_phaso ) + { + strncpy( newColor, phasogram_get_fill_color( phase ), 8 ); + strcpy( x->x_gifdata, "" ); + for ( i=0; ix_zoom; i++ ) + { + sprintf( x->x_gifdata, "%s", newColor ); + } + for ( i=0; ix_zoom; i++ ) + { + SYS_VGUI5("FAZIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, + sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); + } + } + + x->x_nbupdated++; +} + +static void sonogram_update_block(t_sonogram *x, t_glist *glist, t_int bnumber) +{ + t_int fi, i=0; + t_float fspectrum=0.0; + t_int phase=0; + char color[8]; + + // update sonogram + for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) + { + fspectrum = + sqrt( pow( *(x->x_rdata+bnumber*x->x_blocksize+fi), 2) + + pow( *(x->x_idata+bnumber*x->x_blocksize+fi), 2) ); + strncpy( color, sonogram_get_fill_color( fspectrum ), 8 ); + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, color, 8 ); + } + } + for ( i=0; ix_zoom; i++ ) + { + sprintf( x->x_guicommand, "SONIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); + sys_gui( x->x_guicommand ); + } + + // update phasogram + if ( x->x_phaso ) + { + strcpy( x->x_gifdata, "" ); + for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) + { + phase = (int) ( atan2( *(x->x_idata+bnumber*x->x_blocksize+fi), + *(x->x_rdata+bnumber*x->x_blocksize+fi) )*180/M_PI ); + strncpy( color, phasogram_get_fill_color( phase ), 8 ); + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, color, 8 ); + } + } + for ( i=0; ix_zoom; i++ ) + { + sprintf( x->x_guicommand, "FAZIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); + sys_gui( x->x_guicommand ); + } + } + +} + +static void sonogram_erase_block(t_sonogram *x, t_glist *glist, t_int bnumber ) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int fi; + t_float fspectrum=0.0; + char fillColor[ 16 ]; + + for ( fi=0; fix_blocksize/2; fi++) + { + { + int i; + + for ( i=0; ix_zoom; i++ ) + { + strncpy( x->x_gifdata+i*sizeof("#FFFFFF "), "#FFFFFF ", 8 ); + } + SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, + bnumber*x->x_zoom, (x->x_blocksize/2-fi)*x->x_zoom ); + } + } +} + +static void *sonogram_do_update_part(void *tdata) +{ + t_sonogram *x = (t_sonogram*) tdata; + t_int si; + t_int nbpoints = 0; + t_float percentage = 0, opercentage = 0; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + + // loose synchro + usleep( THREAD_SLEEP_TIME ); + + // check boundaries + if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; + if ( x->x_updatestart < 0 ) x->x_updatestart = 0; + + // post("sonogram~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); + + if ( x->x_erase ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + sonogram_erase_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "sonogram~ : erase part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + percentage = opercentage = nbpoints = 0; + + if ( x->x_redraw ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + sonogram_update_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "sonogram~ : update part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + // set borders in black + SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); + } + + // post("sonogram~ : child thread %d ended (nb_updated=%d)", (int)x->x_updatechild, x->x_nbupdated ); + x->x_updatechild = 0; + return NULL; +} + +static void sonogram_update_part(t_sonogram *x, t_glist *glist, t_int bstart, t_int bend, + t_int erase, t_int redraw, t_int keepframe) +{ + pthread_attr_t update_child_attr; + pthread_t update_child; + t_canvas *canvas=glist_getcanvas(glist); + + if ( x->x_graphic ) + { + if ( x->x_updatechild != 0 ) + { + // post( "sonogram~ : error : no update is possible for now" ); + return; + } + x->x_updatestart = bstart; + x->x_updateend = bend; + if ( !keepframe ) + { + x->x_erase = 0; + } + else + { + x->x_erase = erase; + } + x->x_redraw = redraw; + x->x_nbupdated = 0; + // recreate the square if needed + if ( ( bstart == 0 ) && ( bend == x->x_size-1 ) && !keepframe ) + { + SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", canvas, x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", + glist_getcanvas(glist), x->x_xpos-1, x->x_ypos-1, + x->x_xpos + x->x_size*x->x_zoom+1, + x->x_ypos + x->x_blocksize/2*x->x_zoom+1, + x); + SYS_VGUI2("image delete SONIMAGE%x\n", x ); + SYS_VGUI3(".x%x.c delete ISONIMAGE%x\n", canvas, x ); + SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", + x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); + SYS_VGUI2("SONIMAGE%x blank\n", x); + SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", + canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), + (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", canvas, x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", + canvas, x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, + x->x_xpos + x->x_size*x->x_zoom +1, + x->x_ypos + x->x_blocksize*x->x_zoom + 3, + x); + SYS_VGUI2("image delete FAZIMAGE%x\n", x ); + SYS_VGUI3(".x%x.c delete IFAZIMAGE%x\n", canvas, x ); + SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", + x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); + SYS_VGUI2("FAZIMAGE%x blank\n", x); + SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", + canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), + x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); + } + // set borders in red + SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #FF0000\n", canvas, x); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #FF0000\n", canvas, x); + } + + // launch update thread + if ( pthread_attr_init( &update_child_attr ) < 0 ) { + post( "sonogram~ : could not launch update thread" ); + perror( "pthread_attr_init" ); + return; + } + if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { + post( "sonogram~ : could not launch update thread" ); + perror( "pthread_attr_setdetachstate" ); + return; + } + if ( pthread_create( &x->x_updatechild, &update_child_attr, sonogram_do_update_part, x ) < 0 ) { + post( "sonogram~ : could not launch update thread" ); + perror( "pthread_create" ); + return; + } + else + { + // post( "sonogram~ : drawing thread %d launched", (int)x->x_updatechild ); + } + } +} + + /* paste selection at the drawing point */ +static void sonogram_paste( t_sonogram* x) +{ + t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; + t_int pystart = (x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; + t_int cxs,cxe,cys,cye,si=0,fi=0; + t_float *icopy; + t_float *rcopy; + t_int copynd; + + if ( x->x_xstartcapture > x->x_xendcapture ) { + fi = x->x_xstartcapture; + x->x_xstartcapture = x->x_xendcapture; + x->x_xendcapture = fi; + } + if ( x->x_ystartcapture > x->x_yendcapture ) { + fi = x->x_ystartcapture; + x->x_ystartcapture = x->x_yendcapture; + x->x_yendcapture = fi; + } + cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; + cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; + cys=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + cye=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; + if ( cye < 0 ) cye=0; + if ( cys < 0 ) cys=0; + if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; + if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; + if ( cxe >= x->x_size ) cxe=x->x_size-1; + if ( cxs >= x->x_size ) cxs=x->x_size-1; + + // make a copy first + icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + if ( !icopy || !rcopy ) + { + post( "sonogram~ : cannot allocate buffers for pasting" ); + return; + } + // copy initial data + copynd = 0; + for ( si=cxs; si<=cxe; si++) { + for ( fi=cys; fi<=cye; fi++) { + *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); + *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); + copynd++; + } + } + + post( "sonogram~ : paste from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); + + for ( si=cxs; si<=cxe; si++) { + if ( pxstart+si-cxs >= x->x_size ) break; + copynd = (si-cxs)*(cye-cys+1); + for ( fi=cys; fi<=cye; fi++) { + // post ( "sonogram~ : si : %d : fi : %d : copynd : %d", si, fi, copynd ); + if ( pystart+fi-cys >= x->x_blocksize/2 ) break; + *(x->x_rudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); + *(x->x_iudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); + if ( x->x_enhancemode ) + { + // save data for undo + *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(rcopy+copynd); + *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(icopy+copynd); + } + else + { + *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(rcopy+copynd); + *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(icopy+copynd); + } + copynd++; + } + } + + x->x_uxs = pxstart; + x->x_uxe = pxstart+(si-1)-cxs; + x->x_uys = pystart; + x->x_uye = pystart+(fi-1)-cys;; + + freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); +} + + /* paste phase at the drawing point */ +static void sonogram_paste_phase( t_sonogram* x) +{ + t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; + t_int pystart = (x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; + t_int cxs,cxe,cys,cye,si,fi; + t_float fspectrum, fdestspectrum; + t_float fphase, fdestphase; + t_float *icopy; + t_float *rcopy; + t_int copynd; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + + if ( x->x_xstartcapture > x->x_xendcapture ) { + fi = x->x_xstartcapture; + x->x_xstartcapture = x->x_xendcapture; + x->x_xendcapture = fi; + } + if ( x->x_ystartcapture > x->x_yendcapture ) { + fi = x->x_ystartcapture; + x->x_ystartcapture = x->x_yendcapture; + x->x_yendcapture = fi; + } + cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; + cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; + cys=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + cye=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; + if ( cye < 0 ) cye=0; + if ( cys < 0 ) cys=0; + if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; + if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; + if ( cxe >= x->x_size ) cxe=x->x_size-1; + if ( cxs >= x->x_size ) cxs=x->x_size-1; + + // make a copy first + icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + if ( !icopy || !rcopy ) + { + post( "sonogram~ : cannot allocate buffers for pasting" ); + return; + } + // copy initial data + copynd = 0; + for ( si=cxs; si<=cxe; si++) { + for ( fi=cys; fi<=cye; fi++) { + *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); + *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); + copynd++; + } + } + + post( "sonogram~ : paste phase from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); + + for ( si=cxs; si<=cxe; si++) { + if ( pxstart+si-cxs >= x->x_size ) break; + copynd = (si-cxs)*(cye-cys+1); + for ( fi=cys; fi<=cye; fi++) { + if ( pystart+fi-cys > x->x_blocksize+1 ) break; + fphase = atan2( *(icopy+copynd), *(rcopy+copynd) ); + fdestspectrum = + sqrt( pow( *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) + + pow( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) ); + fdestphase = atan2( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), + *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)) ); + if ( x->x_enhancemode ) + { + *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += + fdestspectrum*cos( fdestphase + fphase ); + *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += + fdestspectrum*sin( fdestphase + fphase ); + } + else + { + *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = + fdestspectrum*cos( fphase ); + *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = + fdestspectrum*sin( fphase ); + } + copynd++; + } + } + + freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); + + sonogram_update_part(x, x->x_glist, pxstart, pxstart+(si-1)-cxs, 0, 1, 1); + // start a new capture + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); + x->x_xstartcapture = x->x_xdraw; + x->x_ystartcapture = x->x_ydraw; + x->x_xendcapture = x->x_xdraw; + x->x_yendcapture = x->x_ydraw; + +} + +static void sonogram_draw_new(t_sonogram *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + x->x_xpos=text_xpix(&x->x_obj, glist); + x->x_ypos=text_ypix(&x->x_obj, glist); + if ( x->x_graphic ) + { + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", + canvas, x->x_xpos-1, x->x_ypos-1, + x->x_xpos + x->x_size*x->x_zoom+1, + x->x_ypos + x->x_blocksize/2*x->x_zoom+1, + x); + SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", + x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); + SYS_VGUI2("SONIMAGE%x blank\n", x); + SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", + canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), + (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); + if ( x->x_phaso ) + { + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", + canvas, x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, + x->x_xpos + x->x_size*x->x_zoom +1, + x->x_ypos + x->x_blocksize*x->x_zoom + 3, + x); + SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", + x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); + SYS_VGUI2("FAZIMAGE%x blank\n", x); + SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", + canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), + x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); + } +} + +static void sonogram_draw_delete(t_sonogram *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( x->x_graphic && glist_isvisible( glist ) ) + { + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); + SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", canvas, x); + SYS_VGUI3( ".x%x.c delete line %xREADEND\n", canvas, x); + SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", canvas, x); + SYS_VGUI3( ".x%x.c delete line %xMODEND\n", canvas, x); + SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", canvas, x ); + SYS_VGUI3(".x%x.c delete %xISONIMAGE\n", canvas, x ); + SYS_VGUI2("image delete SONIMAGE%x\n", x ); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c delete %xIFAZIMAGE\n", canvas, x ); + SYS_VGUI2("image delete FAZIMAGE%x\n", x ); + } + } +} + +static void sonogram_draw_move(t_sonogram *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + SYS_VGUI7(".x%x.c coords %xSONOGRAM %d %d %d %d\n", + canvas, x, + x->x_xpos-1, x->x_ypos-1, + x->x_xpos+x->x_size*x->x_zoom+1, + x->x_ypos+x->x_blocksize/2*x->x_zoom+1); + SYS_VGUI5(".x%x.c coords ISONIMAGE%x %d %d\n", + canvas, x, + x->x_xpos+((x->x_size*x->x_zoom)/2), + (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)) ); + if ( x->x_phaso ) + { + SYS_VGUI7(".x%x.c coords %xPHASOGRAM %d %d %d %d\n", + canvas, x, + x->x_xpos-1, x->x_ypos+(x->x_blocksize/2*x->x_zoom)+1, + x->x_xpos+x->x_size*x->x_zoom+1, + x->x_ypos+x->x_blocksize*x->x_zoom+3); + SYS_VGUI5(".x%x.c coords IFAZIMAGE%x %d %d\n", + canvas, x, + x->x_xpos+((x->x_size*x->x_zoom)/2), + x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2 ); + } + canvas_fixlinesfor( canvas, (t_text*)x ); + } +} + +static void sonogram_draw_select(t_sonogram* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #0000FF\n", canvas, x); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #0000FF\n", canvas, x); + } + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); + if ( x->x_phaso ) + { + SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); + } + } + } +} + +/* ------------------------ widget callbacks ----------------------------- */ + + +static void sonogram_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_sonogram* x = (t_sonogram*)z; + + *xp1 = x->x_xpos; + *yp1 = x->x_ypos; + if ( !x->x_phaso ) + { + *xp2 = x->x_xpos+x->x_size*x->x_zoom; + *yp2 = x->x_ypos+x->x_blocksize/2*x->x_zoom+1; + } + else + { + *xp2 = x->x_xpos+x->x_size*x->x_zoom; + *yp2 = x->x_ypos+x->x_blocksize*x->x_zoom+3; + } +} + +static void sonogram_save(t_gobj *z, t_binbuf *b) +{ + t_sonogram *x = (t_sonogram *)z; + + binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), + x->x_size, x->x_graphic, x->x_phaso ); + binbuf_addv(b, ";"); +} + +static void sonogram_select(t_gobj *z, t_glist *glist, int selected) +{ + t_sonogram *x = (t_sonogram *)z; + + x->x_selected = selected; + sonogram_draw_select( x, glist ); +} + +static void sonogram_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_sonogram *x = (t_sonogram *)z; + t_rtext *y; + + if (vis) + { + sonogram_draw_new( x, glist ); + } + else + { + // erase all points + sonogram_draw_delete( x, glist ); + } +} + +static void sonogram_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void sonogram_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_sonogram *x = (t_sonogram *)z; + int xold = x->x_xpos; + int yold = x->x_ypos; + + x->x_xpos += dx; + x->x_ypos += dy; + + if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) + { + sonogram_draw_move( x, glist ); + } + +} + +static void sonogram_modify_point( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) +{ + if ( alted ) + { + *(x->x_rdata+(sample*x->x_blocksize)+frequency) = 0; + *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; + } + else + { + if ( x->x_enhancemode ) + { + *(x->x_rdata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; + *(x->x_idata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; + } + else + { + *(x->x_rdata+(sample*x->x_blocksize)+frequency) += x->x_modstep; + *(x->x_idata+(sample*x->x_blocksize)+frequency) += x->x_modstep; + } + } +} + +static void sonogram_modify_point_phase( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) +{ + t_float fspectrum; + t_float fphase; + + fspectrum = + sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + + pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); + fphase = atan2( *(x->x_idata+sample*x->x_blocksize+frequency), + *(x->x_rdata+sample*x->x_blocksize+frequency) ); + if ( alted==4 ) + { + // setting phase to 0 + *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum; + *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; + } + else + { + if ( x->x_enhancemode ) + { + *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase*x->x_modstep ); + *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase*x->x_modstep ); + } + else + { + *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase+x->x_modstep ); + *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase+x->x_modstep ); + } + } +} + +static void sonogram_motion(t_sonogram *x, t_floatarg dx, t_floatarg dy) +{ + t_int fdraw=0, sdraw=0; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + // post( "sonogram_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); + if ( ( x->x_shifted || (x->x_alted==4) ) ) + { + if ( (x->x_xdraw+dx) >= x->x_xpos && + (x->x_xdraw+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { + x->x_xdraw += dx; + } + if ( (x->x_ydraw+dy) >= x->x_ypos && + (x->x_ydraw+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { + x->x_ydraw += dy; + } + sdraw=(x->x_xdraw-x->x_xpos)/x->x_zoom; + if ( x->x_ydraw <= x->x_ypos+x->x_blocksize/2*x->x_zoom ) + { + fdraw=(x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; + // post( "modify point @ [%d, %d] alted=%d", sdraw, fdraw, x->x_alted ); + sonogram_modify_point( x, sdraw, fdraw, x->x_alted ); + } + if ( x->x_ydraw >= x->x_ypos+x->x_blocksize/2*x->x_zoom+1 ) + { + fdraw=(x->x_ypos+x->x_blocksize*x->x_zoom/2+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; + // post( "modify phase @ [%d, %d]", sdraw, fdraw ); + sonogram_modify_point_phase( x, sdraw, fdraw, x->x_alted ); + } + sonogram_update_point( x, x->x_glist, sdraw, fdraw ); + } + else + { + if ( (x->x_xendcapture+dx) >= x->x_xpos && + (x->x_xendcapture+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { + x->x_xendcapture += dx; + } + if ( (x->x_yendcapture+dy) >= x->x_ypos && + (x->x_yendcapture+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { + x->x_yendcapture += dy; + } + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #0000FF -tags %xCAPTURE\n", + canvas, x->x_xstartcapture, x->x_ystartcapture, x->x_xendcapture, x->x_yendcapture, x ); + } +} + +static int sonogram_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_sonogram* x = (t_sonogram *)z; + t_int si,fi; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + + // post( "sonogram_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); + if ( x->x_aftermousedown == 1 && doit == 0) + { + x->x_aftermousedown = 1; + } + else + { + x->x_aftermousedown = 0; + } + if ( doit ) + { + x->x_xdraw = xpix; + x->x_ydraw = ypix; + x->x_shifted = shift; + x->x_alted = alt; + // activate motion callback + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)sonogram_motion, + 0, xpix, ypix ); + + if ( shift && alt && (x->x_xstartcapture != x->x_xendcapture ) ) + { + sonogram_paste(x); + sonogram_paste_phase(x); + } + else if ( shift && (x->x_xstartcapture != x->x_xendcapture ) ) + { + // add or multiply modstep + if ( x->x_xstartcapture > x->x_xendcapture ) { + fi = x->x_xstartcapture; + x->x_xstartcapture = x->x_xendcapture; + x->x_xendcapture = fi; + } + if ( x->x_ystartcapture > x->x_yendcapture ) { + fi = x->x_ystartcapture; + x->x_ystartcapture = x->x_yendcapture; + x->x_yendcapture = fi; + } + for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; + si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { + for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { + sonogram_modify_point( x, si, fi, alt ); + } + for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { + sonogram_modify_point_phase( x, si, fi, alt ); + } + } + // post( "modified y from %d to %d", (x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2, + // (x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2 ); + sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, + (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); + } + else if ( (alt==4) && (x->x_xstartcapture != x->x_xendcapture ) ) + { + // clean up area + if ( x->x_xstartcapture > x->x_xendcapture ) { + fi = x->x_xstartcapture; + x->x_xstartcapture = x->x_xendcapture; + x->x_xendcapture = fi; + } + if ( x->x_ystartcapture > x->x_yendcapture ) { + fi = x->x_ystartcapture; + x->x_ystartcapture = x->x_yendcapture; + x->x_yendcapture = fi; + } + for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; + si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { + for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { + sonogram_modify_point( x, si, fi, alt ); + } + for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; + fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { + sonogram_modify_point_phase( x, si, fi, alt ); + } + } + sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, + (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); + } + // start a new capture + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); + x->x_xstartcapture = xpix; + x->x_ystartcapture = ypix; + x->x_xendcapture = xpix; + x->x_yendcapture = ypix; + } + else + { + // nothing + } + x->x_aftermousedown = doit; + return (1); +} + + /* clean up */ +static void sonogram_free(t_sonogram *x) +{ + if ( x->x_rdata != NULL ) { + freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_rdata = NULL; + } + if ( x->x_idata != NULL ) { + freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_idata = NULL; + } + if ( x->x_rudata != NULL ) { + freebytes(x->x_rudata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_rdata = NULL; + } + if ( x->x_iudata != NULL ) { + freebytes(x->x_iudata, x->x_size*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + x->x_idata = NULL; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } +} + + /* allocate tables for storing ffts */ +static t_int sonogram_allocate(t_sonogram *x) +{ + t_int fi; + + if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_multfreq = getbytes( x->x_blocksize*sizeof(t_int) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", x->x_blocksize*sizeof(t_int) ); + } + for ( fi=0; fix_blocksize; fi++ ) + { + *(x->x_multfreq+fi)=1; + } + // no undo is available + x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; + if ( !(x->x_rudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_iudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); + } + if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + } + + return 0; +} + + /* reallocate tables for storing ffts */ +static t_int sonogram_reallocate(t_sonogram *x, t_int ioldsize, t_int inewsize) +{ + t_int fi; + t_float *prdata=x->x_rdata, *pidata=x->x_idata; + t_float *prudata=x->x_rudata, *piudata=x->x_iudata; + + if ( !(x->x_rdata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_idata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + // no undo is available + x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; + if ( !(x->x_rudata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + if ( !(x->x_iudata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return -1; + } else { + post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); + } + if ( prdata != NULL ) { + freebytes(prdata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + if ( pidata != NULL ) { + freebytes(pidata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + if ( prudata != NULL ) { + freebytes(prudata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + if ( piudata != NULL ) { + freebytes(piudata, ioldsize*x->x_blocksize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); + } + + return 0; +} + /* records or playback the sonogram */ +static t_int *sonogram_perform(t_int *w) +{ + t_float *rin = (t_float *)(w[1]); + t_float *iin = (t_float *)(w[2]); + t_float *rout = (t_float *)(w[3]); + t_float *iout = (t_float *)(w[4]); + t_float fspectrum = 0.0; + t_float fphase = 0.0; + t_int is; + t_int n = (int)(w[5]); /* number of samples */ + t_sonogram *x = (t_sonogram *)(w[6]); + t_int bi; + t_int startsamp, endsamp; + + if ( x->x_readstart <= x->x_readend ) + { + startsamp = (x->x_readstart*x->x_size)/100; + endsamp = (x->x_readend*x->x_size)/100; + } + else + { + startsamp = (x->x_readend*x->x_size)/100; + endsamp = (x->x_readstart*x->x_size)/100; + } + + // reallocate tables if blocksize has been changed + if ( n != x->x_blocksize && x->x_updatechild == 0 ) { + post( "sonogram~ : reallocating tables" ); + // erase all points + sonogram_free(x); + x->x_blocksize = n; + sonogram_allocate(x); + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, 0, 0); + canvas_fixlinesfor(x->x_glist, (t_text*)x ); + } + + bi = 0; + while (bix_record) { + *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=(*(rin))*(*(x->x_multfreq+bi)); + *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=(*(iin))*(*(x->x_multfreq+bi)); + } + // set outputs + *rout = 0.0; + *iout = 0.0; + if ( x->x_play) { + is=0; + fspectrum = + sqrt( pow( *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) + + pow( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) ); + fphase = atan2( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), + *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi) ); + fphase += (x->x_phase/180.0)*(M_PI); + *rout += fspectrum*cos( fphase ); + *iout += fspectrum*sin( fphase ); + } + rout++;iout++; + rin++;iin++; + bi++; + + } + // reset playing position until next play + if ( x->x_play ) { + x->x_readpos+=x->x_readspeed; + // post( "xreadpos : %f (added %f) %d", x->x_readpos, x->x_readspeed, x->x_readend ); + if ( ( x->x_readspeed >= 0 ) && ( x->x_readpos >= endsamp ) ) { + x->x_play=0; + x->x_readpos=(float)(startsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + if ( ( x->x_readspeed < 0 ) && ( x->x_readpos <= startsamp ) ) { + x->x_play=0; + x->x_readpos = (float)(endsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + } + // reset recording position until next record + if ( x->x_record ) { + x->x_writepos++; + if ( x->x_writepos >= x->x_size ) { + x->x_record=0; + x->x_writepos=0; + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 0); + outlet_bang(x->x_recend); + if ( x->x_empty ) x->x_empty = 0; + // post( "sonogram~ : stopped recording" ); + } + } + // post( "sonogram~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); + return (w+7); +} + +static void sonogram_dsp(t_sonogram *x, t_signal **sp) +{ + dsp_add(sonogram_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); +} + + /* record the sonogram */ +static void sonogram_record(t_sonogram *x) +{ + x->x_record=1; + x->x_writepos=0; + // post( "sonogram~ : recording on" ); +} + + /* play the sonogram */ +static void sonogram_play(t_sonogram *x) +{ + x->x_play=1; + x->x_readpos=(x->x_readstart*x->x_size)/100; + // post( "sonogram~ : playing on" ); +} + + /* setting the starting point for reading ( in percent ) */ +static void sonogram_readstart(t_sonogram *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + x->x_readstart=startpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", + canvas, x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADSTART -width 3\n", + canvas, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), + x->x_ypos, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), + x->x_ypos+x->x_blocksize*x->x_zoom, x ); + } +} + + /* setting the starting point for modification ( in percent ) */ +static void sonogram_modstart(t_sonogram *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + if ( startpoint > x->x_modend ) { + x->x_modstart = x->x_modend; + post( "sonogram~ : warning : range for modifications is null" ); + } else { + x->x_modstart=startpoint; + } + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", + canvas, x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODSTART -width 3\n", + canvas, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), + x->x_ypos, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), + x->x_ypos+x->x_blocksize*x->x_zoom, x ); + } +} + + /* setting the modification step for graphical mode */ +static void sonogram_modstep(t_sonogram *x, t_floatarg fmodstep) +{ + if ( x->x_graphic ) + { + x->x_modstep = fmodstep; + } +} + + /* setting enhance mode */ +static void sonogram_enhancemode(t_sonogram *x, t_floatarg fenhancemode) +{ + if ( x->x_graphic ) + { + x->x_enhancemode = fenhancemode; + } +} + + /* setting the ending point for reading ( in percent ) */ +static void sonogram_readend(t_sonogram *x, t_floatarg fend) +{ + t_float endpoint = fend; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + x->x_readend=endpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xREADEND\n", + canvas, x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADEND -width 3\n", + canvas, x->x_xpos+(x->x_readend*(x->x_size)/100 ), + x->x_ypos, x->x_xpos+(x->x_readend*(x->x_size)/100 ), + x->x_ypos+x->x_blocksize*x->x_zoom, x ); + } +} + + /* setting the ending point for modification ( in percent ) */ +static void sonogram_modend(t_sonogram *x, t_floatarg fend) +{ + t_float endpoint = fend; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + if ( endpoint < x->x_modstart ) { + x->x_modend = x->x_modstart; + post( "sonogram~ : warning : range for modifications is null" ); + } else { + x->x_modend=endpoint; + } + if ( x->x_graphic && glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xMODEND\n", + canvas, x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODEND -width 3\n", + canvas, x->x_xpos+(x->x_modend*(x->x_size)/100 ), + x->x_ypos, x->x_xpos+(x->x_modend*(x->x_size)/100 ), + x->x_ypos+x->x_blocksize*x->x_zoom, x ); + } +} + + /* sets the reading speed */ +static void sonogram_readspeed(t_sonogram *x, t_floatarg freadspeed) +{ + if (freadspeed <= 0 ) { + post( "sonogram~ : wrong readspeed argument" ); + return; + } + x->x_readspeed=freadspeed; +} + + /* enhance frequencies */ +static void sonogram_enhance(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fenhance, t_floatarg fnoupdate ) +{ + t_int samplestart, sampleend, si, fi=0, ffi=0; + t_float oldenergy; + + if (fstartfreq < 0 || fendfreq < 0 || + fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || + fstartfreq > fendfreq ) { + post( "sonogram~ : error : wrong frequencies range" ); + return; + } + if ( fenhance < 0 ) { + post( "sonogram~ : error : wrong multiplicating factor" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + // post("enhancing portion [%d,%d]", samplestart, sampleend ); + for ( si=samplestart; si<=sampleend; si++ ) { + for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { + *(x->x_multfreq+fi) = fenhance; + if ( (fi != 0) && (fi != x->x_blocksize/2-1) ) + { + /* multiply both r*sin(a) and r*cos(a) to mutiply r */ + *(x->x_rdata+(si*x->x_blocksize)+fi) *= fenhance; + *(x->x_idata+(si*x->x_blocksize)+fi) *= fenhance; + } + } + } + // post( "sonogram~ : enhanced %d,%d", fi, ffi ); + if ( !(int)fnoupdate ) + { + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); + } +} + + /* add a constant to frequencies */ +static void sonogram_add(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fadd) +{ + t_int samplestart, sampleend, si, fi; + t_float oldenergy; + + if (fstartfreq < 0 || fendfreq < 0 || + fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || + fstartfreq > fendfreq ) { + post( "sonogram~ : error : wrong frequencies range" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + // post("enhancing portion [%d,%d]", samplestart, sampleend ); + for ( si=samplestart; si<=sampleend; si++ ) { + for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { + /* multiply both r*sin(a) and r*cos(a) to mutiply r */ + *(x->x_rdata+(si*x->x_blocksize)+fi) += fadd; + *(x->x_idata+(si*x->x_blocksize)+fi) += fadd; + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* resize sonogram */ +static void sonogram_resize(t_sonogram *x, t_floatarg fnewsize ) +{ + if (fnewsize <= 0) { + post( "sonogram~ : error : wrong size" ); + return; + } + if (x->x_updatechild > 0) { + post( "sonogram~ : can't resize now, an update is pending." ); + return; + } + post( "sonogram~ : reallocating tables" ); + x->x_record=0; + x->x_play=0; + sonogram_reallocate(x, x->x_size, fnewsize); + x->x_size = fnewsize; + // erase all points, as data is zero no drawing is needed + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 0, 0); +} + + /* set zoom factor */ +static void sonogram_zoom(t_sonogram *x, t_floatarg fzoom ) +{ + post( "sonogram~: warning : zoom and big block factors might lead to a crash" ); + if (fzoom < 1) { + post( "sonogram~ : error : wrong zoom factor" ); + return; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } + x->x_zoom = (int)fzoom; + if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return; + } else { + post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "sonogram~ : error : could not allocate buffers" ); + return; + } else { + post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); + } + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, !x->x_empty, 0); + canvas_fixlinesfor(x->x_glist, (t_text*)x ); +} + + /* refresh data */ +static void sonogram_refresh(t_sonogram *x) +{ + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); +} + + /* flip frequencies */ +static void sonogram_flipfreqs(t_sonogram *x) +{ + t_int samplestart, sampleend, si, fi; + t_float fvalue; + t_int ioperon; + + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + ioperon=x->x_blocksize/2; + for ( si=samplestart; si<=sampleend; si++ ) { + for ( fi=0; fi<=ioperon/2; fi++ ) { + fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); + *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)); + *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; + fvalue = *(x->x_idata+(si*x->x_blocksize)+fi); + *(x->x_idata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)); + *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* flip blocks */ +static void sonogram_flipblocks(t_sonogram *x) +{ + t_int samplestart, sampleend, middlesample, fi, si; + t_float fvalue; + + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + middlesample = ( sampleend+samplestart+1 ) / 2; + for ( si=samplestart; si<=middlesample; si++ ) { + for ( fi=0; fix_blocksize; fi++ ) { + fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); + *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); + *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; + fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); + *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); + *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* undo if available */ +static void sonogram_undo(t_sonogram *x) +{ + t_int si,fi; + + if ( x->x_uxs == -1 ) + { + post( "sonogram~ : nothing to undo, man" ); + return; + } + + post( "sonogram~ : restoring region [%d,%d,%d,%d]", x->x_uxs, x->x_uys, x->x_uxe, x->x_uye ); + for ( si=x->x_uxs; si<=x->x_uxe; si++ ) { + for ( fi=x->x_uys; fi<=x->x_uye; fi++ ) { + *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); + *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_iudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); + } + } + sonogram_update_part(x, x->x_glist, x->x_uxs, x->x_uxe, 0, 1, 1); +} + + /* zswap exchanges real and imaginery part */ +static void sonogram_zswap(t_sonogram *x) +{ + t_int samplestart, sampleend, fi, si; + t_float fvalue; + + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + for ( si=samplestart; si<=sampleend; si++ ) { + for ( fi=0; fix_blocksize; fi++ ) { + fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); + *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+fi); + *(x->x_idata+(si*x->x_blocksize)+fi) = fvalue; + } + } +} + + /* swap points */ +static void sonogram_swappoints(t_sonogram *x, t_floatarg fnbpoints) +{ + t_int samplestart, sampleend, sp; + t_float s1, s2, f1, f2; + t_float fvalue; + + if (fnbpoints <= 0) { + post( "sonogram~ : error : bad number of points" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=0; spx_blocksize/2-1 ); + f2 = random()%( x->x_blocksize/2-1 ); + fvalue = *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1); + *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2); + *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; + fvalue = *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1); + *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2); + *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* average blocks according to a factor */ +static void sonogram_average(t_sonogram *x, t_floatarg fnbblocks) +{ + t_int samplestart, sampleend, fi, si, ssi; + t_float fraverage, fiaverage; + + if (fnbblocks < 1) { + post( "sonogram~ : error : bad average factor" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + fraverage=fiaverage=0.0; + for ( fi=0; fix_blocksize; fi++ ) { + for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) { + fraverage=fiaverage=0.0; + for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi); + fiaverage += *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi); + } + fraverage /= fnbblocks; + fiaverage /= fnbblocks; + for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi)=fraverage; + *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi)=fiaverage; + } + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* go up by the given number */ +static void sonogram_goup(t_sonogram *x, t_floatarg fgoup) +{ + t_int samplestart, sampleend, sp, sf; + + if (fgoup <= 0 || fgoup > x->x_blocksize/2) { + post( "sonogram~ : error : wrong offset in goup function" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=samplestart; sp<=sampleend; sp++ ) { + for (sf=(x->x_blocksize/2)-fgoup-1; sf>=0; sf-- ) { + *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = + *(x->x_rdata+((int)sp*x->x_blocksize)+sf); + *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = + *(x->x_idata+((int)sp*x->x_blocksize)+sf); + + } + for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; + *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* roll up by the given number */ +static void sonogram_roll(t_sonogram *x, t_floatarg froll) +{ + t_int samplestart, sampleend, sp, sf; + t_float *fprvalues; + t_float *fpivalues; + + if (froll <= 0 || froll > x->x_blocksize/2) { + post( "sonogram~ : error : wrong offset in roll function" ); + return; + } + fprvalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); + if ( !fprvalues ) { + post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); + return; + } + fpivalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); + if ( !fpivalues ) { + post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); + return; + } + + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=samplestart; sp<=sampleend; sp++ ) { + + // saving values + for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); + *(fpivalues+sf) = + *(x->x_idata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); + } + for (sf=(x->x_blocksize/2)-froll-1; sf>=0; sf-- ) { + *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = + *(x->x_rdata+((int)sp*x->x_blocksize)+sf); + *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = + *(x->x_idata+((int)sp*x->x_blocksize)+sf); + } + for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = *(fprvalues+sf); + *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = *(fpivalues+sf); + } + } + freebytes( fprvalues, (int)froll*sizeof(float) ); + freebytes( fpivalues, (int)froll*sizeof(float) ); + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* suppress point below the threshold */ +static void sonogram_threshold(t_sonogram *x, t_floatarg fthreshold) +{ + t_int samplestart, sampleend, sp, sf; + t_float fspectrum; + + if (fthreshold <= 0) { + post( "sonogram~ : error : wrong threshold" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=samplestart; sp<=sampleend; sp++ ) { + for (sf=0; sf<=(x->x_blocksize/2)-1; sf++ ) { + fspectrum = sqrt( pow( *(x->x_rdata+sp*x->x_blocksize+sf), 2) + + pow( *(x->x_idata+sp*x->x_blocksize+sf), 2) ); + if ( fspectrum < fthreshold ) + { + *(x->x_rdata+sp*x->x_blocksize+sf) = 0.0; + *(x->x_idata+sp*x->x_blocksize+sf) = 0.0; + } + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* change the phase */ +static void sonogram_phase(t_sonogram *x, t_floatarg fincphase) +{ + if (fincphase < 0 || fincphase > 90) { + post( "sonogram~ : error : wrong phase in phase function : out of [0,90]" ); + return; + } + x->x_phase = fincphase; +} + + /* go down by the given number */ +static void sonogram_godown(t_sonogram *x, t_floatarg fgodown) +{ + t_int samplestart, sampleend, sp, sf; + + if (fgodown <= 0 || fgodown > x->x_blocksize/2) { + post( "sonogram~ : error : wrong offset in godown function" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=samplestart; sp<=sampleend; sp++ ) { + for (sf=0; sf<=(x->x_blocksize/2)-fgodown-1; sf++ ) { + *(x->x_rdata+((int)sp*x->x_blocksize)+sf) = + *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); + *(x->x_idata+((int)sp*x->x_blocksize)+sf) = + *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); + } + for (sf=(x->x_blocksize/2)-fgodown; sf<(x->x_blocksize/2); sf++ ) { + *(x->x_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; + *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; + } + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + + /* swap blocks */ +static void sonogram_swapblocks(t_sonogram *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) +{ + t_int samplestart, samplestartb, samplesize, sp, sf; + t_int iperstart, iperend, ipersize; + t_float s1, s2; + t_float fvalue; + + iperstart = fperstart; + iperend = fperend; + ipersize = fpersize; + + if (iperstart < 0 || iperstart > iperend || + iperend <= 0 || iperend+ipersize > 100 || + ipersize < 0 || fpersize > 100 ) { + post( "sonogram~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", + iperstart, iperstart+ipersize, iperend, iperend+ipersize ); + return; + } + + samplestart=(x->x_modstart*(x->x_size-1))/100; + samplestartb=(x->x_modend*(x->x_size-1))/100; + samplesize=((samplestartb-samplestart)*ipersize)/100; + samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; + samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; + + post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); + + for ( sp=samplesize; sp>=0; sp-- ) { + for ( sf=0; sfx_blocksize; sf++) { + fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); + *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); + *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; + fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); + *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); + *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; + } + } + sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); +} + + /* swap frequencies */ +static void sonogram_swapfreqs(t_sonogram *x, t_floatarg ffirstfreq, t_floatarg fsecondfreq) +{ + t_int samplestart, sampleend, sp; + t_float fvalue; + + if (ffirstfreq < 0 || fsecondfreq <0) { + post( "sonogram~ : error : wrong frequencies" ); + return; + } + samplestart=(x->x_modstart*(x->x_size-1))/100; + sampleend=(x->x_modend*(x->x_size-1))/100; + + for ( sp=samplestart; sp<=sampleend; sp++ ) { + fvalue = *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq); + *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = + *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq); + *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; + fvalue = *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq); + *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = + *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq); + *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; + } + sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); +} + +static void *sonogram_new(t_floatarg fsize, t_floatarg fgraphic, t_floatarg fphaso) +{ + t_sonogram *x = (t_sonogram *)pd_new(sonogram_class); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_recend = outlet_new(&x->x_obj, &s_bang ); + x->x_end = outlet_new(&x->x_obj, &s_bang ); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); + + if ( fsize <= 0 || ( fgraphic != 0 && fgraphic != 1 ) || ( fphaso != 0 && fphaso != 1 ) ) { + error( "sonogram~ : missing or negative creation arguments" ); + return NULL; + } + + // activate graphical callbacks + if ( fgraphic != 0 ) + { + class_setwidget(sonogram_class, &sonogram_widgetbehavior); + } + x->x_graphic = (int) fgraphic; + x->x_phaso = (int) fphaso; + + x->x_size = fsize; + x->x_blocksize = sys_getblksize(); + x->x_play = 0; + x->x_readspeed = 1.; + x->x_record = 0; + x->x_readpos = 0.; + x->x_writepos = 0; + x->x_modstart = 0; + x->x_readstart = 0; + x->x_modend = 100; + x->x_readend = 100; + x->x_rdata = NULL; + x->x_idata = NULL; + x->x_phase = 0.0; + x->x_empty = 1; + x->x_xpos = -1; + x->x_ypos = -1; + x->x_samplerate = sys_getsr(); + /* graphic data */ + x->x_selected = 0; + x->x_zoom = 1; + x->x_updatechild = 0; + x->x_modstep = 1.1; + x->x_enhancemode = 0; + x->x_glist = (t_glist*)canvas_getcurrent(); + + if ( sonogram_allocate(x) <0 ) { + return NULL; + } else { + return(x); + } + +} + +void sonogram_tilde_setup(void) +{ + post(sonogram_version); + sonogram_class = class_new(gensym("sonogram~"), (t_newmethod)sonogram_new, (t_method)sonogram_free, + sizeof(t_sonogram), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + + + // set callbacks + sonogram_widgetbehavior.w_getrectfn = sonogram_getrect; + sonogram_widgetbehavior.w_displacefn = sonogram_displace; + sonogram_widgetbehavior.w_selectfn = sonogram_select; + sonogram_widgetbehavior.w_activatefn = NULL; + sonogram_widgetbehavior.w_deletefn = sonogram_delete; + sonogram_widgetbehavior.w_visfn = sonogram_vis; + sonogram_widgetbehavior.w_clickfn = sonogram_click; + + +#if PD_MINOR_VERSION >= 37 + class_setpropertiesfn(sonogram_class, NULL); + class_setsavefn(sonogram_class, sonogram_save); +#else + sonogram_widgetbehavior.w_propertiesfn = NULL; + sonogram_widgetbehavior.w_savefn = sonogram_save; +#endif + + CLASS_MAINSIGNALIN( sonogram_class, t_sonogram, x_f ); + class_addmethod(sonogram_class, (t_method)sonogram_dsp, gensym("dsp"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_record, gensym("record"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_enhance, gensym("enhance"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_add, gensym("add"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_resize, gensym("resize"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_zoom, gensym("zoom"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_swappoints, gensym("swappoints"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_average, gensym("average"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_swapfreqs, gensym("swapfreqs"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_flipfreqs, gensym("flipfreqs"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_flipblocks, gensym("flipblocks"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_play, gensym("play"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_refresh, gensym("refresh"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_enhancemode, gensym("enhancemode"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_goup, gensym("goup"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_godown, gensym("godown"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_roll, gensym("roll"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_threshold, gensym("threshold"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_phase, gensym("phase"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_zswap, gensym("zswap"), A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_modstep, gensym("modstep"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_modstart, gensym("modstart"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_modend, gensym("modend"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_readstart, gensym("readstart"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_readend, gensym("readend"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); + class_addmethod(sonogram_class, (t_method)sonogram_undo, gensym("undo"), A_NULL); +} diff --git a/sonogram~/INSTALL b/sonogram~/INSTALL deleted file mode 100644 index d69da45..0000000 --- a/sonogram~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/sonogram~ - -make clean - -make - -make install - -open help-sonogram~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/sonogram~/rs-sonogram~.pd b/sonogram~/rs-sonogram~.pd deleted file mode 100644 index 08274ae..0000000 --- a/sonogram~/rs-sonogram~.pd +++ /dev/null @@ -1,311 +0,0 @@ -#N canvas 7 13 986 674 10; -#X msg 306 57 record; -#X msg 19 34 bang; -#X obj 19 54 openpanel; -#X obj 21 152 soundfiler; -#X msg 259 42 bang; -#X obj 262 101 rfft~; -#X floatatom 59 171 10 0 0 0 - - -; -#X msg 20 211 resize \$1; -#X obj 19 74 t s b; -#X obj 22 114 pack s s; -#X msg 21 135 read -resize \$1 \$2; -#X obj 68 74 float \$0; -#X text 21 9 Step 1 : Load a sound file; -#X obj 775 595 table \$0-sonosample; -#X msg 927 588 \; pd dsp 1; -#X msg 484 36 play; -#X obj 262 195 outlet~; -#X text 491 10 Step 3 : Play the recorded sonogram; -#X msg 992 589 \; pd dsp 0; -#X obj 21 171 / 256; -#X obj 486 59 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 460 59 0 %; -#X text 620 58 100 %; -#X obj 487 77 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 461 80 0 %; -#X text 622 76 100 %; -#X msg 661 74 100; -#X obj 691 74 loadbang; -#X text 640 40 Playback positions; -#X obj 783 93 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 756 94 0 %; -#X text 917 92 100 %; -#X obj 784 111 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 756 114 0 %; -#X text 919 110 100 %; -#X text 783 76 Set portion of the sonogram to modify; -#X msg 953 108 100; -#N canvas 656 8 600 544 modifications 1; -#X text 234 236 Filter a frequency; -#X text 254 190 Enhance a frequency by 10% ( might be a range of frequencies -with message 'enhance f1 f2 x' ); -#X text 180 309 Flip frequencies ( dogs love it ); -#X msg 108 265 swappoints 1000; -#X obj 181 134 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 108 153 swapfreqs \$1 \$2; -#X obj 224 152 pack f f; -#X text 220 267 Swap 1000 points ( rain effect ); -#X msg 153 131 \$1; -#X obj 108 131 change; -#X obj 181 114 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 153 111 \$1; -#X obj 108 111 change; -#X obj 180 182 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X obj 180 223 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X text 285 152 Swap two frequencies ( set 2nd \, click 1st ); -#X msg 110 308 flipfreqs; -#X msg 110 330 flipblocks; -#X text 243 286 Swap section [0% \, 20%] and [50% \, 70%] of [start -\, end]; -#X text 188 328 Flip blocks ( reverse effect ); -#X msg 110 287 swapblocks 0 50 20; -#X text 228 66 Move frequencies up or down; -#X msg 110 91 roll 2; -#X msg 112 350 zswap; -#X text 364 374 Change the phase; -#X text 180 350 Exchange real and imaginery parts ( noisy filter ) -; -#X msg 113 374 phase \$1; -#X obj 200 373 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 184 373 0; -#X text 339 374 90; -#X obj 187 415 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 113 429 add \$1 \$1 0.5; -#X text 216 429 Add a constant to a frequency; -#X obj 189 451 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 115 466 add \$1 \$1 -0.5; -#X text 218 465 Sub a constant from a frequency; -#X text 198 393 Average over 100 blocks ( smooth with some sounds ) -; -#X obj 16 454 outlet; -#X msg 109 69 goup 1; -#X msg 159 69 godown 5; -#X msg 107 198 enhance \$1 \$1 1.1 0; -#X msg 116 488 threshold \$1; -#X floatatom 208 489 5 0 0 0 - - -; -#X msg 107 239 enhance \$1 \$1 0 0; -#X text 249 488 Suppress all points below the threshold; -#X text 159 91 Roll frequencies : same as above but without loss; -#X msg 113 395 average 10; -#X connect 3 0 37 0; -#X connect 4 0 8 0; -#X connect 5 0 37 0; -#X connect 6 0 5 0; -#X connect 8 0 9 0; -#X connect 9 0 6 1; -#X connect 10 0 11 0; -#X connect 11 0 12 0; -#X connect 12 0 6 0; -#X connect 13 0 40 0; -#X connect 14 0 43 0; -#X connect 16 0 37 0; -#X connect 17 0 37 0; -#X connect 20 0 37 0; -#X connect 22 0 37 0; -#X connect 23 0 37 0; -#X connect 26 0 37 0; -#X connect 27 0 26 0; -#X connect 30 0 31 0; -#X connect 31 0 37 0; -#X connect 33 0 34 0; -#X connect 34 0 37 0; -#X connect 38 0 37 0; -#X connect 39 0 37 0; -#X connect 40 0 37 0; -#X connect 41 0 37 0; -#X connect 42 0 41 0; -#X connect 43 0 37 0; -#X connect 46 0 37 0; -#X restore 861 131 pd modifications; -#X text 513 609 Zoom factor (>1); -#X msg 418 608 zoom 2; -#X obj 256 79 tabplay~ \$0-sonosample; -#X obj 114 263 sonogram~ 2452 1 1; -#X msg 467 608 zoom 1; -#X msg 484 99 readspeed \$1; -#X floatatom 617 99 5 0 0 0 - - -; -#X text 487 121 Reading speed; -#X obj 576 99 / 100; -#X msg 661 99 100; -#X obj 692 99 loadbang; -#X msg 779 167 play; -#X msg 780 186 open /tmp/sonogram.wav; -#X obj 779 229 writesf~ 2; -#X msg 780 207 start; -#X msg 822 207 stop; -#X msg 418 652 modstep \$1; -#X floatatom 499 652 5 0 0 0 - - -; -#X obj 525 36 spigot; -#X obj 573 36 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 -; -#X text 600 37 Loop; -#X text 70 547 Mouse modifications :; -#X text 557 656 ( default = 1.1 ); -#X text 558 646 Value added or multiplied ( can be < 0 ); -#X obj 527 588 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 -1; -#X obj 19 93 route float; -#X msg 418 587 enhancemode \$1; -#X text 821 166 Record; -#X text 89 562 Normal mode; -#X text 30 579 click :; -#X text 128 579 add modstep to the selected data; -#X text 43 590 click :; -#X text 161 590 erase selected data; -#X text 154 645 erase selected data; -#X text 88 615 Enhanced mode; -#X text 2 600 click :; -#X text 162 601 paste selected data; -#X text 129 656 add selected data at the new location; -#X text 483 546 Graphic actions; -#X text 128 632 multiply the selected data by modstep; -#X obj 980 109 loadbang; -#X text 73 21 ( a small one ); -#X text 417 569 Activate enhance mode; -#X text 785 57 Step 4 : modify parts of the sonogram; -#X obj 260 126 rifft~; -#X msg 418 630 refresh; -#X text 239 10 Step 2 : Record the sonogram; -#X obj 927 565 loadbang; -#N canvas 0 1 682 488 envelop 0; -#X obj 33 400 outlet; -#X obj 46 327 tabread envelop; -#X msg 23 263 bang; -#X floatatom 23 299 5 0 0 0 - - -; -#X obj 71 280 + 1; -#X msg 23 281 0; -#X text 25 239 Apply envelop; -#X obj 68 300 delay 1000; -#X obj 136 300 f; -#X obj 34 354 pack f f; -#X obj 368 349 loadbang; -#X msg 425 349 bang; -#X msg 370 374 \; envelop const 1; -#X msg 203 381 refresh; -#X floatatom 160 280 5 0 0 0 - - -; -#X msg 163 300 bang; -#X obj 98 280 moses 127; -#X msg 485 347 bang; -#X msg 486 372 \; envelop const 0.001; -#X msg 33 377 enhance \$1 \$1 \$2 1; -#X obj 202 358 delay 1000; -#N canvas 0 0 450 300 graph2 0; -#X array envelop 64 float 1; -#A 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1; -#X coords 0 10 63 0 300 200 1; -#X restore 151 12 graph; -#X connect 1 0 9 1; -#X connect 2 0 5 0; -#X connect 3 0 1 0; -#X connect 3 0 8 1; -#X connect 3 0 7 0; -#X connect 3 0 9 0; -#X connect 4 0 3 0; -#X connect 5 0 3 0; -#X connect 7 0 8 0; -#X connect 8 0 16 0; -#X connect 9 0 19 0; -#X connect 10 0 12 0; -#X connect 11 0 12 0; -#X connect 13 0 0 0; -#X connect 14 0 15 0; -#X connect 15 0 20 0; -#X connect 16 0 4 0; -#X connect 16 1 14 0; -#X connect 17 0 18 0; -#X connect 19 0 0 0; -#X connect 20 0 13 0; -#X restore 780 131 pd envelop; -#X obj 310 174 / 100; -#X floatatom 309 147 5 0 0 0 - - -; -#X obj 263 174 *~ 1; -#X obj 261 149 /~ 256; -#X text 332 129 Volume; -#X text 31 631 click :; -#X text 44 642 click :; -#X text 3 652 click :; -#X msg 488 630 undo; -#X text 526 630 One level undo; -#X obj 21 192 makefilename %d-sonosample; -#X msg 23 264 undo; -#X msg 17 317 zoom 1; -#X obj 829 571 block~ 256; -#X connect 0 0 41 0; -#X connect 1 0 2 0; -#X connect 2 0 8 0; -#X connect 3 0 19 0; -#X connect 4 0 0 0; -#X connect 4 0 40 0; -#X connect 5 0 41 0; -#X connect 5 1 41 1; -#X connect 6 0 7 0; -#X connect 7 0 41 0; -#X connect 8 0 9 0; -#X connect 8 1 11 0; -#X connect 9 0 10 0; -#X connect 10 0 3 0; -#X connect 11 0 63 0; -#X connect 15 0 41 0; -#X connect 19 0 6 0; -#X connect 20 0 41 2; -#X connect 23 0 41 3; -#X connect 26 0 23 0; -#X connect 27 0 26 0; -#X connect 29 0 41 4; -#X connect 32 0 41 5; -#X connect 36 0 32 0; -#X connect 37 0 41 0; -#X connect 39 0 41 0; -#X connect 40 0 5 0; -#X connect 40 0 89 0; -#X connect 41 0 82 0; -#X connect 41 1 82 1; -#X connect 41 3 53 0; -#X connect 41 3 56 0; -#X connect 42 0 41 0; -#X connect 43 0 41 0; -#X connect 44 0 46 0; -#X connect 46 0 43 0; -#X connect 47 0 44 0; -#X connect 48 0 47 0; -#X connect 49 0 41 0; -#X connect 49 0 50 0; -#X connect 49 0 52 0; -#X connect 50 0 51 0; -#X connect 52 0 51 0; -#X connect 53 0 51 0; -#X connect 54 0 41 0; -#X connect 55 0 54 0; -#X connect 56 0 15 0; -#X connect 57 0 56 1; -#X connect 62 0 64 0; -#X connect 63 0 97 0; -#X connect 64 0 41 0; -#X connect 78 0 36 0; -#X connect 82 0 90 0; -#X connect 83 0 41 0; -#X connect 85 0 14 0; -#X connect 86 0 41 0; -#X connect 87 0 89 1; -#X connect 88 0 87 0; -#X connect 89 0 16 0; -#X connect 89 0 51 0; -#X connect 89 0 51 1; -#X connect 90 0 89 0; -#X connect 95 0 41 0; -#X connect 97 0 9 1; -#X connect 98 0 41 0; -#X connect 99 0 41 0; diff --git a/sonogram~/rs-sonograph~.pd b/sonogram~/rs-sonograph~.pd deleted file mode 100644 index a8531fa..0000000 --- a/sonogram~/rs-sonograph~.pd +++ /dev/null @@ -1,217 +0,0 @@ -#N canvas 0 1 986 654 10; -#X msg 344 51 record; -#X msg 53 30 bang; -#X obj 53 50 openpanel; -#X obj 52 167 soundfiler; -#X msg 297 36 bang; -#X obj 298 99 rfft~; -#X floatatom 90 186 10 0 0; -#X msg 168 185 resize \$1; -#X obj 53 72 t s b; -#X obj 53 129 pack s s; -#X msg 52 150 read -resize \$1 \$2; -#X obj 99 71 float \$0; -#X obj 54 95 route float; -#X obj 52 207 makefilename %d-sonosample; -#X text 57 14 Step 1 : Load a sound file; -#X obj 820 17 table \$0-sonosample; -#X msg 822 43 \; pd dsp 1; -#X obj 121 580 rifft~; -#X msg 340 158 play; -#X obj 822 82 block~ 256; -#X obj 27 607 outlet~; -#X text 346 135 Step 3 : Play the recorded sonogram; -#X msg 887 44 \; pd dsp 0; -#X obj 52 186 / 256; -#X obj 121 607 /~ 256; -#X obj 342 181 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 316 181 0 %; -#X text 476 180 100 %; -#X obj 343 199 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 317 202 0 %; -#X text 478 198 100 %; -#X msg 512 196 100; -#X obj 539 196 loadbang; -#X text 339 217 Playback positions; -#X obj 697 184 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 671 184 0 %; -#X text 831 183 100 %; -#X obj 698 202 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12700 1; -#X text 672 205 0 %; -#X text 833 201 100 %; -#X text 697 167 Set portion of the sonogram to modify; -#X text 883 183 Start Point; -#X text 883 198 End Point; -#X msg 695 220 100; -#X obj 722 220 loadbang; -#X text 242 15 Step 2 : Record the sonogram; -#N canvas 309 22 600 544 modifications 1; -#X text 234 236 Filter a frequency; -#X msg 107 239 filter \$1 \$1; -#X msg 105 161 enhance \$1 \$1 1.1; -#X msg 106 198 dim \$1 \$1 1.1; -#X text 236 155 Enhance a frequency by 10% ( might be a range of frequencies -with message 'enhance f1 f2 x' ); -#X text 234 198 Dim a frequency by 10 %; -#X text 180 309 Flip frequencies ( dogs love it ); -#X msg 108 265 swappoints 1000; -#X obj 179 97 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 106 116 swapfreqs \$1 \$2; -#X obj 223 116 pack f f; -#X text 218 264 Swap 1000 points ( rain effect ); -#X msg 151 94 \$1; -#X obj 106 94 change; -#X obj 179 77 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 151 74 \$1; -#X obj 106 74 change; -#X obj 178 145 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X obj 179 183 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X obj 180 223 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X text 285 115 Swap two frequencies ( set 2nd \, click 1st ); -#X msg 110 308 flipfreqs; -#X msg 110 330 flipblocks; -#X text 244 286 Swap section [0% \, 20%] and [50% \, 70%] of [start -\, end]; -#X text 185 330 Flip blocks ( reverse effect ); -#X msg 110 287 swapblocks 0 50 20; -#X msg 152 32 godown 1; -#X msg 107 32 goup 2; -#X text 218 32 Move frequencies up or down; -#X msg 108 54 roll 2; -#X text 210 45 Roll frequencies : same as above but without loss ( -circular ); -#X msg 112 350 zswap; -#X text 364 374 Change the phase; -#X text 180 350 Exchange real and imaginery parts ( noisy filter ) -; -#X msg 113 374 phase \$1; -#X obj 200 373 hsl 128 15 0 90 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X text 184 373 0; -#X text 339 374 90; -#X obj 187 415 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 113 429 add \$1 \$1 0.5; -#X text 216 429 Add a constant to a frequency; -#X obj 189 451 hdl 8 1 0 128 empty empty empty 20 8 0 8 -260818 -24198 --128992 0; -#X msg 115 466 add \$1 \$1 -0.5; -#X text 218 465 Sub a constant from a frequency; -#X msg 113 395 average 100; -#X text 190 395 Average over 100 blocks ( smooth with some sounds ) -; -#X obj 16 454 outlet; -#X connect 1 0 46 0; -#X connect 2 0 46 0; -#X connect 3 0 46 0; -#X connect 7 0 46 0; -#X connect 8 0 12 0; -#X connect 9 0 46 0; -#X connect 10 0 9 0; -#X connect 12 0 13 0; -#X connect 13 0 10 1; -#X connect 14 0 15 0; -#X connect 15 0 16 0; -#X connect 16 0 10 0; -#X connect 17 0 2 0; -#X connect 18 0 3 0; -#X connect 19 0 1 0; -#X connect 21 0 46 0; -#X connect 22 0 46 0; -#X connect 25 0 46 0; -#X connect 26 0 46 0; -#X connect 27 0 46 0; -#X connect 29 0 46 0; -#X connect 31 0 46 0; -#X connect 34 0 46 0; -#X connect 35 0 34 0; -#X connect 38 0 39 0; -#X connect 39 0 46 0; -#X connect 41 0 42 0; -#X connect 42 0 46 0; -#X connect 44 0 46 0; -#X restore 694 150 pd modifications; -#X obj 298 73 tabplay~ \$0-sonosample; -#X obj 106 329 sonogram~ 256 0; -#X text 538 54 When the sonogram is RED (updating) \,; -#X text 537 43 VERY IMPORTANT NOTE :; -#X text 591 116 Step 4 : modify parts of the sonogram ... and send -a refresh message; -#X msg 337 234 readspeed \$1; -#X floatatom 468 234 5 0 0; -#X text 337 252 Reading speed; -#X obj 428 234 / 100; -#X msg 515 234 100; -#X obj 549 234 loadbang; -#X text 538 66 no update is possible; -#X msg 221 525 play; -#X msg 217 555 open /tmp/sonogram.wav; -#X obj 246 603 writesf~ 2; -#X msg 276 576 start; -#X msg 320 576 stop; -#X floatatom 172 609 5 0 0; -#X obj 436 158 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 -1; -#X text 464 160 Loop; -#X obj 381 159 spigot; -#X connect 0 0 48 0; -#X connect 1 0 2 0; -#X connect 2 0 8 0; -#X connect 3 0 23 0; -#X connect 4 0 0 0; -#X connect 4 0 47 0; -#X connect 5 0 48 0; -#X connect 5 1 48 1; -#X connect 6 0 7 0; -#X connect 7 0 48 0; -#X connect 8 0 9 0; -#X connect 8 1 11 0; -#X connect 9 0 10 0; -#X connect 10 0 3 0; -#X connect 11 0 12 0; -#X connect 12 0 13 0; -#X connect 13 0 9 1; -#X connect 17 0 24 0; -#X connect 18 0 48 0; -#X connect 23 0 6 0; -#X connect 24 0 20 0; -#X connect 24 0 61 0; -#X connect 24 0 61 1; -#X connect 25 0 48 2; -#X connect 28 0 48 3; -#X connect 31 0 28 0; -#X connect 32 0 31 0; -#X connect 34 0 48 4; -#X connect 37 0 48 5; -#X connect 43 0 37 0; -#X connect 44 0 43 0; -#X connect 46 0 48 0; -#X connect 47 0 5 0; -#X connect 47 0 20 0; -#X connect 48 0 17 0; -#X connect 48 1 17 1; -#X connect 48 3 63 0; -#X connect 48 3 67 0; -#X connect 52 0 48 0; -#X connect 53 0 55 0; -#X connect 55 0 52 0; -#X connect 56 0 53 0; -#X connect 57 0 56 0; -#X connect 59 0 48 0; -#X connect 59 0 60 0; -#X connect 59 0 62 0; -#X connect 60 0 61 0; -#X connect 62 0 61 0; -#X connect 63 0 61 0; -#X connect 64 0 24 1; -#X connect 65 0 67 1; -#X connect 67 0 18 0; diff --git a/sonogram~/sonogram~-help.pd b/sonogram~/sonogram~-help.pd deleted file mode 100644 index ab00898..0000000 --- a/sonogram~/sonogram~-help.pd +++ /dev/null @@ -1,10 +0,0 @@ -#N canvas 0 1 450 300 10; -#X obj 134 93 rs-sonogram~; -#X text 193 27 To work properly \, the block size; -#X text 193 39 has to be redefined.; -#X msg 291 89 \; pd dsp 1; -#X msg 356 90 \; pd dsp 0; -#X text 193 51 that's why everything is in the subpatch.; -#X obj 132 130 dac~; -#X connect 0 0 6 0; -#X connect 0 0 6 1; diff --git a/sonogram~/sonogram~-joge.c b/sonogram~/sonogram~-joge.c deleted file mode 100644 index 8d148fa..0000000 --- a/sonogram~/sonogram~-joge.c +++ /dev/null @@ -1,2044 +0,0 @@ -/*------------------------ sonogram~ ------------------------------------------ */ -/* */ -/* sonogram~ : lets you record, play back and modify a sonogram */ -/* constructor : sonogram */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "Living at night" */ -/* "Doesn't help for my complexion" */ -/* David Thomas - Final Solution */ -/* ---------------------------------------------------------------------------- */ - -/* this doesn't compile on MinGW */ -#ifndef _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef UNIX -#include -#include -#endif -#ifdef _WIN32 -#define M_PI 3.14159265358979323846 -#include "pthread.h" -#include -#endif -#include - -#include -#include "m_imp.h" -#include "g_canvas.h" - - -static int guidebug=0; -static int ignorevisible=1; // ignore visible test - // because this seems to lead to bad refresh - // wait for a fix - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define THREAD_SLEEP_TIME 100000 // 100000 us = 100 ms - -static char *sonogram_version = "sonogram~: version 0.9, written by Yves Degoyon (ydegoyon@free.fr)"; - -static t_class *sonogram_class; -t_widgetbehavior sonogram_widgetbehavior; - - -typedef struct _sonogram -{ - t_object x_obj; - - t_int x_size; /* size of the stored fft ( in blocks~ ) */ - t_float x_samplerate; /* sample rate */ - t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ - t_float x_readpos; /* data's playing position */ - t_int x_writepos; /* data's recording position */ - t_int x_readstart; /* data's starting position for reading */ - t_int x_readend; /* data's ending position for reading */ - t_int x_modstart; /* data's starting position for modifications */ - t_int x_modend; /* data's ending position for modifications */ - t_int x_play; /* playing on/off flag */ - t_float x_readspeed; /* number of grouped blocks for reading */ - t_float x_record; /* flag to start recording process */ - t_float x_empty; /* flag to indicate it's a brand new sonogram */ - t_float *x_rdata; /* table containing real part of the fft */ - t_float *x_rudata; /* undo real data */ - t_float *x_idata; /* table containing imaginery part of the fft */ - t_float *x_iudata; /* undo imaginery data */ - t_float x_phase; /* phase to apply on output */ - t_outlet *x_end; /* outlet for end of restitution */ - t_outlet *x_recend; /* outlet for end of recording */ - t_int *x_multfreq; /* array of multiplicative factor */ - char *x_gifdata; /* buffer for graphical data */ - char *x_guicommand; /* buffer for graphical command */ - t_int x_uxs; /* starting x position for undo */ - t_int x_uxe; /* ending x position for undo */ - t_int x_uys; /* starting y position for undo */ - t_int x_uye; /* ending y position for undo */ - - /* graphical data block */ - t_int x_enhancemode; /* flag to set enhance mode */ - t_int x_graphic; /* flag to set graphic mode */ - t_int x_phaso; /* flag to indicate if phasogram is shown */ - t_int x_selected; /* flag to remember if we are seleted or not */ - t_int x_erase; /* flag used when an erase is needed */ - t_int x_redraw; /* flag used when drawing is needed */ - t_int x_nbupdated; /* number of points updated */ - t_glist *x_glist; /* keep graphic context for various operations */ - t_int x_zoom; /* zoom factor */ - pthread_t x_updatechild; /* thread id for the update child */ - t_int x_updatestart; /* starting position for update */ - t_int x_updateend; /* ending position for update */ - t_int x_xpos; /* stuck x position */ - t_int x_ypos; /* stuck y position */ - t_int x_shifted; /* remember shift state from last click */ - t_int x_alted; /* remember alt state from last click */ - t_int x_aftermousedown; /* indicates the mousedown event */ - t_int x_xstartcapture; /* x of the start of the capture */ - t_int x_ystartcapture; /* y of the start of the capture */ - t_int x_xendcapture; /* x of the start of the capture */ - t_int x_yendcapture; /* y of the start of the capture */ - t_int x_xdraw; /* x drawing position */ - t_int x_ydraw; /* y drawing position */ - t_float x_modstep; /* step for graphical modifications */ - - t_float x_f; /* float needed for signal input */ - -} t_sonogram; - -/* ------------------------ drawing functions ---------------------------- */ -static char* sonogram_get_fill_color( t_float fspectrum ) -{ - if ( fspectrum < 0.01 ) { - return "#EEEEEE"; - } else if ( fspectrum < 0.1 ) { - return "#DDDDDD"; - } else if ( fspectrum < 0.5 ) { - return "#CCCCCC"; - } else if ( fspectrum < 1 ) { - return "#BBBBBB"; - } else if ( fspectrum < 2 ) { - return "#AAAAAA"; - } else if ( fspectrum < 5 ) { - return "#999999"; - } else if ( fspectrum < 10 ) { - return "#888888"; - } else if ( fspectrum < 20 ) { - return "#777777"; - } else if ( fspectrum < 30 ) { - return "#666666"; - } else if ( fspectrum < 40 ) { - return "#555555"; - } else if ( fspectrum < 50 ) { - return "#444444"; - } else if ( fspectrum < 60 ) { - return "#333333"; - } else if ( fspectrum < 80 ) { - return "#222222"; - } else if ( fspectrum < 100 ) { - return "#111111"; - } else { - return "#000000"; - } -} - -static char* phasogram_get_fill_color( t_int phase ) -{ - if ( phase < 0 ) - { - if ( phase > -10 ) { - return "#111111"; - } else if ( phase > -20 ) { - return "#222222"; - } else if ( phase > -30 ) { - return "#333333"; - } else if ( phase > -40 ) { - return "#444444"; - } else if ( phase > -50 ) { - return "#555555"; - } else if ( phase > -60 ) { - return "#666666"; - } else if ( phase > -70 ) { - return "#777777"; - } else if ( phase > -80 ) { - return "#888888"; - } else { - return "#999999"; - } - } - else - { - if ( phase == 0 ) { - return "#FFFFFF"; - } else if ( phase < 10 ) { - return "#111111"; - } else if ( phase < 20 ) { - return "#222222"; - } else if ( phase < 30 ) { - return "#333333"; - } else if ( phase < 40 ) { - return "#444444"; - } else if ( phase < 50 ) { - return "#555555"; - } else if ( phase < 60 ) { - return "#666666"; - } else if ( phase < 70 ) { - return "#777777"; - } else if ( phase < 80 ) { - return "#888888"; - } else { - return "#999999"; - } - } - // normally never reached - return ""; -} - -static void sonogram_update_point(t_sonogram *x, t_glist *glist, t_int sample, t_int frequency) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_float fspectrum=0.0; - t_int phase=0.0; - char newColor[ 8 ], olColor[8]; - int i; - - post("sonogram~ : joge : updating a point"); - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - phase = (int) ( atan2( *(x->x_idata+(sample*x->x_blocksize)+frequency), - *(x->x_rdata+(sample*x->x_blocksize)+frequency) )*180/M_PI ); - if ( x->x_empty && ( fspectrum != 0 )) - { - x->x_empty = 0; - } - strcpy( newColor, sonogram_get_fill_color( fspectrum ) ); - - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", strcat( newColor, " ") ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - - if ( x->x_phaso ) - { - strcpy( newColor, phasogram_get_fill_color( phase ) ); - strcpy( x->x_gifdata, "" ); - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", strcat( newColor, " ") ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("FAZIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - } - - x->x_nbupdated++; -} - -static void sonogram_update_block(t_sonogram *x, t_glist *glist, t_int bnumber) -{ - t_int fi, i=0; - t_float fspectrum=0.0; - t_int phase=0; - char color[8]; - - // update sonogram - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - fspectrum = - sqrt( pow( *(x->x_rdata+bnumber*x->x_blocksize+fi), 2) + - pow( *(x->x_idata+bnumber*x->x_blocksize+fi), 2) ); - strcpy( color, sonogram_get_fill_color( fspectrum ) ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "SONIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - - // update phasogram - if ( x->x_phaso ) - { - strcpy( x->x_gifdata, "" ); - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - phase = (int) ( atan2( *(x->x_idata+bnumber*x->x_blocksize+fi), - *(x->x_rdata+bnumber*x->x_blocksize+fi) )*180/M_PI ); - strcpy( color, phasogram_get_fill_color( phase ) ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "FAZIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - } - - post("sonogram~ : joge in update_block : update phasogram"); - -} - -static void sonogram_erase_block(t_sonogram *x, t_glist *glist, t_int bnumber ) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int fi; - t_float fspectrum=0.0; - char fillColor[ 16 ]; - - for ( fi=0; fix_blocksize/2; fi++) - { - { - int i; - - for ( i=0; ix_zoom; i++ ) - { - strcpy( x->x_gifdata+i*sizeof("#FFFFFF "), "#FFFFFF " ); - } - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - bnumber*x->x_zoom, (x->x_blocksize/2-fi)*x->x_zoom ); - } - } -} - -static void *sonogram_do_update_part(void *tdata) -{ - t_sonogram *x = (t_sonogram*) tdata; - t_int si; - t_int nbpoints = 0; - t_float percentage = 0, opercentage = 0; - - // loose synchro -#ifdef NT - // usleep's argument is in microseconds while - // Sleep's argument is in miliseconds therefore - // need a convertion from micro to mili - Sleep( THREAD_SLEEP_TIME / 1000 ); - - // OR jsut use the pd defined sleep function - //sys_microsleep(THREAD_SLEEP_TIME / 1000); -#else - usleep( THREAD_SLEEP_TIME ); -#endif - - // check boundaries - if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; - if ( x->x_updatestart < 0 ) x->x_updatestart = 0; - - post("sonogram~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); - - if ( x->x_erase ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_erase_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "sonogram~ : erase part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - percentage = opercentage = nbpoints = 0; - - if ( x->x_redraw ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_update_block(x, x->x_glist, si); - - // post("sonogram~ : joge check point : after sonogram_update_block"); - - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - - post("sonogram~ : joge : percentage=%d completed", (int)percentage); - - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - post( "sonogram~ : update part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - // set borders in black - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", glist_getcanvas(x->x_glist), x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", glist_getcanvas(x->x_glist), x); - } - - post("sonogram~ : child thread %d ended (nb_updated=%d)", (int)x->x_updatechild, x->x_nbupdated ); - x->x_updatechild = 0; - return NULL; -} - -static void sonogram_update_part(t_sonogram *x, t_glist *glist, t_int bstart, t_int bend, - t_int erase, t_int redraw, t_int keepframe) -{ - pthread_attr_t update_child_attr; - - if ( x->x_graphic ) - { - if ( x->x_updatechild != 0 ) - { - post( "sonogram~ : error : no update is possible for now" ); - return; - } - x->x_updatestart = bstart; - x->x_updateend = bend; - if ( !keepframe ) - { - x->x_erase = 0; - } - else - { - x->x_erase = erase; - } - x->x_redraw = redraw; - x->x_nbupdated = 0; - // recreate the square if needed - if ( ( bstart == 0 ) && ( bend == x->x_size-1 ) && !keepframe ) - { - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", glist_getcanvas(glist), x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete ISONIMAGE%x\n", glist_getcanvas(glist), x ); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", glist_getcanvas(glist), x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete IFAZIMAGE%x\n", glist_getcanvas(glist), x ); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor(x->x_glist, (t_text*)x ); - } - // set borders in red - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #FF0000\n", glist_getcanvas(glist), x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #FF0000\n", glist_getcanvas(glist), x); - } - - // launch update thread - if ( pthread_attr_init( &update_child_attr ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_init" ); - return; - } - if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_setdetachstate" ); - return; - } - if ( pthread_create( &x->x_updatechild, &update_child_attr, sonogram_do_update_part, x ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_create" ); - return; - } - else - { - post( "sonogram~ : drawing thread %d launched", (int)x->x_updatechild ); - } - } -} - - /* paste selection at the drawing point */ -static void sonogram_paste( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si=0,fi=0; - t_float *icopy; - t_float *rcopy; - t_int copynd; - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - // post ( "sonogram~ : si : %d : fi : %d : copynd : %d", si, fi, copynd ); - if ( pystart+fi-cys >= x->x_blocksize/2 ) break; - *(x->x_rudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - *(x->x_iudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - if ( x->x_enhancemode ) - { - // save data for undo - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(icopy+copynd); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(icopy+copynd); - } - copynd++; - } - } - - x->x_uxs = pxstart; - x->x_uxe = pxstart+(si-1)-cxs; - x->x_uys = pystart; - x->x_uye = pystart+(fi-1)-cys;; - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); -} - - /* paste phase at the drawing point */ -static void sonogram_paste_phase( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si,fi; - t_float fspectrum, fdestspectrum; - t_float fphase, fdestphase; - t_float *icopy; - t_float *rcopy; - t_int copynd; - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste phase from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - if ( pystart+fi-cys > x->x_blocksize+1 ) break; - fphase = atan2( *(icopy+copynd), *(rcopy+copynd) ); - fdestspectrum = - sqrt( pow( *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) + - pow( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) ); - fdestphase = atan2( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), - *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)) ); - if ( x->x_enhancemode ) - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*cos( fdestphase + fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*sin( fdestphase + fphase ); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*cos( fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*sin( fphase ); - } - copynd++; - } - } - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - - sonogram_update_part(x, x->x_glist, pxstart, pxstart+(si-1)-cxs, 0, 1, 1); - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - x->x_xstartcapture = x->x_xdraw; - x->x_ystartcapture = x->x_ydraw; - x->x_xendcapture = x->x_xdraw; - x->x_yendcapture = x->x_ydraw; - -} - -static void sonogram_draw_new(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_xpos == -1 ) - { - x->x_xpos=x->x_obj.te_xpix; - x->x_ypos=x->x_obj.te_ypix; - } - if ( x->x_graphic ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - canvas, x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_delete(t_sonogram *x, t_glist *glist) -{ - if ( x->x_graphic && glist_isvisible( glist ) ) - { - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( glist ), x ); - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", glist_getcanvas( glist ), x); - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", glist_getcanvas( glist ), x ); - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", glist_getcanvas( glist ), x ); - SYS_VGUI3(".x%x.c delete %xISONIMAGE\n", glist_getcanvas( glist ), x ); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xIFAZIMAGE\n", glist_getcanvas( glist ), x ); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - } - } -} - -static void sonogram_draw_move(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI7(".x%x.c coords %xSONOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos-1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize/2*x->x_zoom+1); - SYS_VGUI5(".x%x.c coords ISONIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)) ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c coords %xPHASOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos+(x->x_blocksize/2*x->x_zoom)+1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize*x->x_zoom+3); - SYS_VGUI5(".x%x.c coords IFAZIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2 ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_select(t_sonogram* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #0000FF\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #0000FF\n", canvas, x); - } - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); - } - } - } -} - -/* ------------------------ widget callbacks ----------------------------- */ - - -static void sonogram_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_sonogram* x = (t_sonogram*)z; - - *xp1 = x->x_xpos; - *yp1 = x->x_ypos; - if ( !x->x_phaso ) - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize/2*x->x_zoom+1; - } - else - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize*x->x_zoom+3; - } -} - -static void sonogram_save(t_gobj *z, t_binbuf *b) -{ - t_sonogram *x = (t_sonogram *)z; - - binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), - (t_int)x->x_xpos, (t_int)x->x_ypos, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_size, x->x_graphic, x->x_phaso ); - binbuf_addv(b, ";"); -} - -static void sonogram_select(t_gobj *z, t_glist *glist, int selected) -{ - t_sonogram *x = (t_sonogram *)z; - - x->x_selected = selected; - sonogram_draw_select( x, glist ); -} - -static void sonogram_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_sonogram *x = (t_sonogram *)z; - t_rtext *y; - - if (vis) - { - sonogram_draw_new( x, glist ); - } - else - { - // erase all points - sonogram_draw_delete( x, glist ); - } -} - -static void sonogram_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void sonogram_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_sonogram *x = (t_sonogram *)z; - int xold = x->x_xpos; - int yold = x->x_ypos; - - x->x_xpos += dx; - x->x_ypos += dy; - - if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) - { - sonogram_draw_move( x, glist ); - } - -} - -static void sonogram_modify_point( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - if ( alted ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = 0; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - } - } -} - -static void sonogram_modify_point_phase( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - t_float fspectrum; - t_float fphase; - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - fphase = atan2( *(x->x_idata+sample*x->x_blocksize+frequency), - *(x->x_rdata+sample*x->x_blocksize+frequency) ); - if ( alted==4 ) - { - // setting phase to 0 - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase*x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase*x->x_modstep ); - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase+x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase+x->x_modstep ); - } - } -} - -static void sonogram_motion(t_sonogram *x, t_floatarg dx, t_floatarg dy) -{ - int fdraw=0, sdraw=0; - - // post( "sonogram_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); - if ( ( x->x_shifted || (x->x_alted==4) ) ) - { - if ( (x->x_xdraw+dx) >= x->x_xpos && - (x->x_xdraw+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xdraw += dx; - } - if ( (x->x_ydraw+dy) >= x->x_ypos && - (x->x_ydraw+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_ydraw += dy; - } - sdraw=(x->x_xdraw-x->x_xpos)/x->x_zoom; - if ( x->x_ydraw <= x->x_ypos+x->x_blocksize/2*x->x_zoom ) - { - fdraw=(x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify point @ [%d, %d] alted=%d", sdraw, fdraw, x->x_alted ); - sonogram_modify_point( x, sdraw, fdraw, x->x_alted ); - } - if ( x->x_ydraw >= x->x_ypos+x->x_blocksize/2*x->x_zoom+1 ) - { - fdraw=(x->x_ypos+x->x_blocksize*x->x_zoom/2+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify phase @ [%d, %d]", sdraw, fdraw ); - sonogram_modify_point_phase( x, sdraw, fdraw, x->x_alted ); - } - sonogram_update_point( x, x->x_glist, sdraw, fdraw ); - } - else - { - if ( (x->x_xendcapture+dx) >= x->x_xpos && - (x->x_xendcapture+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xendcapture += dx; - } - if ( (x->x_yendcapture+dy) >= x->x_ypos && - (x->x_yendcapture+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_yendcapture += dy; - } - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #0000FF -tags %xCAPTURE\n", - glist_getcanvas( x->x_glist ), x->x_xstartcapture, - x->x_ystartcapture, x->x_xendcapture, x->x_yendcapture, x ); - } -} - -static int sonogram_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_sonogram* x = (t_sonogram *)z; - int si,fi; - - // post( "sonogram_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); - if ( x->x_aftermousedown == 1 && doit == 0) - { - x->x_aftermousedown = 1; - } - else - { - x->x_aftermousedown = 0; - } - if ( doit ) - { - x->x_xdraw = xpix; - x->x_ydraw = ypix; - x->x_shifted = shift; - x->x_alted = alt; - // activate motion callback - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)sonogram_motion, - 0, xpix, ypix ); - - if ( shift && alt && (x->x_xstartcapture != x->x_xendcapture ) ) - { - sonogram_paste(x); - sonogram_paste_phase(x); - } - else if ( shift && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // add or multiply modstep - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - // post( "modified y from %d to %d", (x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2, - // (x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2 ); - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - else if ( (alt==4) && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // clean up area - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - x->x_xstartcapture = xpix; - x->x_ystartcapture = ypix; - x->x_xendcapture = xpix; - x->x_yendcapture = ypix; - } - else - { - // nothing - } - x->x_aftermousedown = doit; - return (1); -} - - /* clean up */ -static void sonogram_free(t_sonogram *x) -{ - if ( x->x_rdata != NULL ) { - freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_idata != NULL ) { - freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_rudata != NULL ) { - freebytes(x->x_rudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_iudata != NULL ) { - freebytes(x->x_iudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } -} - - /* allocate tables for storing ffts */ -static t_int sonogram_allocate(t_sonogram *x) -{ - t_int fi; - - if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_multfreq = getbytes( x->x_blocksize*sizeof(t_int) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_blocksize*sizeof(t_int) ); - } - for ( fi=0; fix_blocksize; fi++ ) - { - *(x->x_multfreq+fi)=1; - } - // no undo is available - x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; - if ( !(x->x_rudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_iudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - - return 0; -} - - /* records or playback the sonogram */ -static t_int *sonogram_perform(t_int *w) -{ - t_float *rin = (t_float *)(w[1]); - t_float *iin = (t_float *)(w[2]); - t_float *rout = (t_float *)(w[3]); - t_float *iout = (t_float *)(w[4]); - t_float fspectrum = 0.0; - t_float fphase = 0.0; - t_int is; - t_int n = (int)(w[5]); /* number of samples */ - t_sonogram *x = (t_sonogram *)(w[6]); - t_int bi; - - // reallocate tables if blocksize has been changed - if ( n != x->x_blocksize && x->x_updatechild == 0 ) { - post( "sonogram~ : reallocating tables" ); - // erase all points - sonogram_free(x); - x->x_blocksize = n; - sonogram_allocate(x); - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, 0, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); - } - - bi = 0; - while (bix_record) { - *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=(*(rin))*(*(x->x_multfreq+bi)); - *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=(*(iin))*(*(x->x_multfreq+bi)); - } - // set outputs - *rout = 0.0; - *iout = 0.0; - if ( x->x_play) { - is=0; - fspectrum = - sqrt( pow( *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) + - pow( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) ); - fphase = atan2( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), - *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi) ); - fphase += (x->x_phase/180.0)*(M_PI); - *rout += fspectrum*cos( fphase ); - *iout += fspectrum*sin( fphase ); - } - rout++;iout++; - rin++;iin++; - bi++; - - } - // reset playing position until next play - if ( x->x_play ) { - x->x_readpos+=x->x_readspeed; - // post( "xreadpos : %f (added %f)", x->x_readpos, x->x_readspeed ); - if ( x->x_readpos >= (x->x_readend*x->x_size)/100 ) { - x->x_play=0; - x->x_readpos=(x->x_readstart*x->x_size)/100; - // post( "sonogram~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - } - // reset recording position until next record - if ( x->x_record ) { - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 0); - outlet_bang(x->x_recend); - if ( x->x_empty ) x->x_empty = 0; - post( "sonogram~ : stopped recording" ); - } - } - // post( "sonogram~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); - return (w+7); -} - -static void sonogram_dsp(t_sonogram *x, t_signal **sp) -{ - dsp_add(sonogram_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); -} - - /* record the sonogram */ -static void sonogram_record(t_sonogram *x) -{ - x->x_record=1; - x->x_writepos=0; - post( "sonogram~ : recording on" ); -} - - /* play the sonogram */ -static void sonogram_play(t_sonogram *x) -{ - x->x_play=1; - x->x_readpos=(x->x_readstart*x->x_size)/100; - post( "sonogram~ : playing on" ); -} - - /* setting the starting point for reading ( in percent ) */ -static void sonogram_readstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_readend ) { - x->x_readstart = x->x_readend; - post( "sonogram~ : warning : range for reading is null" ); - } else { - x->x_readstart=startpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADSTART -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the starting point for modification ( in percent ) */ -static void sonogram_modstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_modend ) { - x->x_modstart = x->x_modend; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modstart=startpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODSTART -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the modification step for graphical mode */ -static void sonogram_modstep(t_sonogram *x, t_floatarg fmodstep) -{ - if ( x->x_graphic ) - { - x->x_modstep = fmodstep; - } -} - - /* setting enhance mode */ -static void sonogram_enhancemode(t_sonogram *x, t_floatarg fenhancemode) -{ - if ( x->x_graphic ) - { - x->x_enhancemode = fenhancemode; - } -} - - /* setting the ending point for reading ( in percent ) */ -static void sonogram_readend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_readstart ) { - x->x_readend = x->x_readstart; - post( "sonogram~ : warning : range for reading is null" ); - } else { - x->x_readend=endpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADEND -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the ending point for modification ( in percent ) */ -static void sonogram_modend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_modstart ) { - x->x_modend = x->x_modstart; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modend=endpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODEND -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* sets the reading speed */ -static void sonogram_readspeed(t_sonogram *x, t_floatarg freadspeed) -{ - if (freadspeed <= 0 ) { - post( "sonogram~ : wrong readspeed argument" ); - return; - } - x->x_readspeed=freadspeed; -} - - /* enhance frequencies */ -static void sonogram_enhance(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fenhance, t_floatarg fnoupdate ) -{ - t_int samplestart, sampleend, si, fi=0, ffi=0; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - if ( fenhance < 0 ) { - post( "sonogram~ : error : wrong multiplicating factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - *(x->x_multfreq+fi) = fenhance; - if ( (fi != 0) && (fi != x->x_blocksize/2-1) ) - { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) *= fenhance; - *(x->x_idata+(si*x->x_blocksize)+fi) *= fenhance; - } - } - } - // post( "sonogram~ : enhanced %d,%d", fi, ffi ); - if ( !(int)fnoupdate ) - { - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); - } -} - - /* add a constant to frequencies */ -static void sonogram_add(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fadd) -{ - t_int samplestart, sampleend, si, fi; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) += fadd; - *(x->x_idata+(si*x->x_blocksize)+fi) += fadd; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* resize sonogram */ -static void sonogram_resize(t_sonogram *x, t_floatarg fnewsize ) -{ - if (fnewsize <= 0) { - post( "sonogram~ : error : wrong size" ); - return; - } - if (x->x_updatechild > 0) { - post( "sonogram~ : can't resize now, an update is pending." ); - return; - } - post( "sonogram~ : reallocating tables" ); - x->x_record = 0; - x->x_play = 0; - sonogram_free(x); - x->x_size = fnewsize; - sonogram_allocate(x); - // erase all points, as data is zero no drawing is needed - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 0, 0); -} - - /* set zoom factor */ -static void sonogram_zoom(t_sonogram *x, t_floatarg fzoom ) -{ - post( "sonogram~: warning : zoom and big block factors might lead to a crash" ); - if (fzoom < 1) { - post( "sonogram~ : error : wrong zoom factor" ); - return; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } - x->x_zoom = (int)fzoom; - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, !x->x_empty, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); -} - - /* refresh data */ -static void sonogram_refresh(t_sonogram *x) -{ - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* flip frequencies */ -static void sonogram_flipfreqs(t_sonogram *x) -{ - t_int samplestart, sampleend, si, fi; - t_float fvalue; - t_int ioperon; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - ioperon=x->x_blocksize/2; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fi<=ioperon/2; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - fvalue = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* flip blocks */ -static void sonogram_flipblocks(t_sonogram *x) -{ - t_int samplestart, sampleend, middlesample, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - middlesample = ( sampleend+samplestart+1 ) / 2; - for ( si=samplestart; si<=middlesample; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* undo if available */ -static void sonogram_undo(t_sonogram *x) -{ - t_int si,fi; - - if ( x->x_uxs == -1 ) - { - post( "sonogram~ : nothing to undo, man" ); - return; - } - - post( "sonogram~ : restoring region [%d,%d,%d,%d]", x->x_uxs, x->x_uys, x->x_uxe, x->x_uye ); - for ( si=x->x_uxs; si<=x->x_uxe; si++ ) { - for ( fi=x->x_uys; fi<=x->x_uye; fi++ ) { - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_iudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - } - } - sonogram_update_part(x, x->x_glist, x->x_uxs, x->x_uxe, 0, 1, 1); -} - - /* zswap exchanges real and imaginery part */ -static void sonogram_zswap(t_sonogram *x) -{ - t_int samplestart, sampleend, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = fvalue; - } - } -} - - /* swap points */ -static void sonogram_swappoints(t_sonogram *x, t_floatarg fnbpoints) -{ - t_int samplestart, sampleend, sp; - t_float s1, s2, f1, f2; - t_float fvalue; - - if (fnbpoints <= 0) { - post( "sonogram~ : error : bad number of points" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=0; spx_blocksize/2-1 ); - f2 = rand()%( x->x_blocksize/2-1 ); -#else - s1 = samplestart + (random()%(sampleend-samplestart)); - s2 = samplestart + (random()%(sampleend-samplestart)); - f1 = random()%( x->x_blocksize/2-1 ); - f2 = random()%( x->x_blocksize/2-1 ); -#endif - fvalue = *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - fvalue = *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* average blocks according to a factor */ -static void sonogram_average(t_sonogram *x, t_floatarg fnbblocks) -{ - t_int samplestart, sampleend, fi, si, ssi; - t_float fraverage, fiaverage; - - if (fnbblocks < 1) { - post( "sonogram~ : error : bad average factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - fraverage=fiaverage=0.0; - for ( fi=0; fix_blocksize; fi++ ) { - for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) { - fraverage=fiaverage=0.0; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi); - fiaverage += *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi); - } - fraverage /= fnbblocks; - fiaverage /= fnbblocks; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi)=fraverage; - *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi)=fiaverage; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* go up by the given number */ -static void sonogram_goup(t_sonogram *x, t_floatarg fgoup) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgoup <= 0 || fgoup > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in goup function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=(x->x_blocksize/2)-fgoup-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* roll up by the given number */ -static void sonogram_roll(t_sonogram *x, t_floatarg froll) -{ - t_int samplestart, sampleend, sp, sf; - t_float *fprvalues; - t_float *fpivalues; - - if (froll <= 0 || froll > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in roll function" ); - return; - } - fprvalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fprvalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - fpivalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fpivalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - - // saving values - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - *(fpivalues+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - } - for (sf=(x->x_blocksize/2)-froll-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = *(fprvalues+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = *(fpivalues+sf); - } - } - freebytes( fprvalues, (int)froll*sizeof(float) ); - freebytes( fpivalues, (int)froll*sizeof(float) ); - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* suppress point below the threshold */ -static void sonogram_threshold(t_sonogram *x, t_floatarg fthreshold) -{ - t_int samplestart, sampleend, sp, sf; - t_float fspectrum; - - if (fthreshold <= 0) { - post( "sonogram~ : error : wrong threshold" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-1; sf++ ) { - fspectrum = sqrt( pow( *(x->x_rdata+sp*x->x_blocksize+sf), 2) + - pow( *(x->x_idata+sp*x->x_blocksize+sf), 2) ); - if ( fspectrum < fthreshold ) - { - *(x->x_rdata+sp*x->x_blocksize+sf) = 0.0; - *(x->x_idata+sp*x->x_blocksize+sf) = 0.0; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* change the phase */ -static void sonogram_phase(t_sonogram *x, t_floatarg fincphase) -{ - if (fincphase < 0 || fincphase > 90) { - post( "sonogram~ : error : wrong phase in phase function : out of [0,90]" ); - return; - } - x->x_phase = fincphase; -} - - /* go down by the given number */ -static void sonogram_godown(t_sonogram *x, t_floatarg fgodown) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgodown <= 0 || fgodown > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in godown function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-fgodown-1; sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+sf) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - *(x->x_idata+((int)sp*x->x_blocksize)+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - } - for (sf=(x->x_blocksize/2)-fgodown; sf<(x->x_blocksize/2); sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* swap blocks */ -static void sonogram_swapblocks(t_sonogram *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) -{ - t_int samplestart, samplestartb, samplesize, sp, sf; - t_int iperstart, iperend, ipersize; - t_float s1, s2; - t_float fvalue; - - iperstart = fperstart; - iperend = fperend; - ipersize = fpersize; - - if (iperstart < 0 || iperstart > iperend || - iperend <= 0 || iperend+ipersize > 100 || - ipersize < 0 || fpersize > 100 ) { - post( "sonogram~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", - iperstart, iperstart+ipersize, iperend, iperend+ipersize ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - samplestartb=(x->x_modend*(x->x_size-1))/100; - samplesize=((samplestartb-samplestart)*ipersize)/100; - samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; - samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; - - post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); - - for ( sp=samplesize; sp>=0; sp-- ) { - for ( sf=0; sfx_blocksize; sf++) { - fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* swap frequencies */ -static void sonogram_swapfreqs(t_sonogram *x, t_floatarg ffirstfreq, t_floatarg fsecondfreq) -{ - t_int samplestart, sampleend, sp; - t_float fvalue; - - if (ffirstfreq < 0 || fsecondfreq <0) { - post( "sonogram~ : error : wrong frequencies" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - fvalue = *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - fvalue = *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - -static void *sonogram_new(t_floatarg fsize, t_floatarg fgraphic, t_floatarg fphaso) -{ - t_sonogram *x = (t_sonogram *)pd_new(sonogram_class); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_recend = outlet_new(&x->x_obj, &s_bang ); - x->x_end = outlet_new(&x->x_obj, &s_bang ); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); - - if ( fsize <= 0 || ( fgraphic != 0 && fgraphic != 1 ) || ( fphaso != 0 && fphaso != 1 ) ) { - error( "sonogram~ : missing or negative creation arguments" ); - return NULL; - } - - // activate graphical callbacks - if ( fgraphic != 0 ) - { - class_setwidget(sonogram_class, &sonogram_widgetbehavior); - } - x->x_graphic = (int) fgraphic; - x->x_phaso = (int) fphaso; - - x->x_size = fsize; - x->x_blocksize = sys_getblksize(); - x->x_play = 0; - x->x_readspeed = 1.; - x->x_record = 0; - x->x_readpos = 0.; - x->x_writepos = 0; - x->x_modstart = 0; - x->x_readstart = 0; - x->x_modend = 100; - x->x_readend = 100; - x->x_rdata = NULL; - x->x_idata = NULL; - x->x_phase = 0.0; - x->x_empty = 1; - x->x_xpos = -1; - x->x_ypos = -1; - x->x_samplerate = sys_getsr(); - /* graphic data */ - x->x_selected = 0; - x->x_zoom = 1; - x->x_updatechild = 0; - x->x_modstep = 1.1; - x->x_enhancemode = 0; - x->x_glist = (t_glist*)canvas_getcurrent(); - - if ( sonogram_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } - -} - -void sonogram_tilde_setup(void) -{ - post(sonogram_version); - sonogram_class = class_new(gensym("sonogram~"), (t_newmethod)sonogram_new, (t_method)sonogram_free, - sizeof(t_sonogram), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - - // set callbacks - sonogram_widgetbehavior.w_getrectfn = sonogram_getrect; - sonogram_widgetbehavior.w_displacefn = sonogram_displace; - sonogram_widgetbehavior.w_selectfn = sonogram_select; - sonogram_widgetbehavior.w_activatefn = NULL; - sonogram_widgetbehavior.w_deletefn = sonogram_delete; - sonogram_widgetbehavior.w_visfn = sonogram_vis; - sonogram_widgetbehavior.w_clickfn = sonogram_click; - /* - * : As of 0.37, pd does not have these last - * two elements in t_widgetbehavoir anymore. - * see pd/src/notes.txt: - * savefunction and dialog into class structure - */ -#if PD_MINOR_VERSION < 37 || !defined(PD_MINOR_VERSION) - sonogram_widgetbehavior.w_propertiesfn = NULL; - sonogram_widgetbehavior.w_savefn = sonogram_save; -/* this is needed to make the help patch work on < 0.37 */ - -#else - class_setpropertiesfn(sonogram_class, NULL); - class_setsavefn(sonogram_class, &sonogram_save); -#endif - - CLASS_MAINSIGNALIN( sonogram_class, t_sonogram, x_f ); - class_addmethod(sonogram_class, (t_method)sonogram_dsp, gensym("dsp"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_record, gensym("record"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhance, gensym("enhance"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_add, gensym("add"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_resize, gensym("resize"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zoom, gensym("zoom"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swappoints, gensym("swappoints"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_average, gensym("average"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapfreqs, gensym("swapfreqs"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipfreqs, gensym("flipfreqs"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipblocks, gensym("flipblocks"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_play, gensym("play"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_refresh, gensym("refresh"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhancemode, gensym("enhancemode"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_goup, gensym("goup"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_godown, gensym("godown"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_roll, gensym("roll"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_threshold, gensym("threshold"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_phase, gensym("phase"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zswap, gensym("zswap"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstep, gensym("modstep"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstart, gensym("modstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modend, gensym("modend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readstart, gensym("readstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readend, gensym("readend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_undo, gensym("undo"), A_NULL); -} - - -#endif /* not _WIN32 */ diff --git a/sonogram~/sonogram~-yves.c b/sonogram~/sonogram~-yves.c deleted file mode 100644 index 6ff83d8..0000000 --- a/sonogram~/sonogram~-yves.c +++ /dev/null @@ -1,2017 +0,0 @@ -/*------------------------ sonogram~ ------------------------------------------ */ -/* */ -/* sonogram~ : lets you record, play back and modify a sonogram */ -/* constructor : sonogram */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "Living at night" */ -/* "Doesn't help for my complexion" */ -/* David Thomas - Final Solution */ -/* ---------------------------------------------------------------------------- */ - - -/* this doesn't compile on MinGW */ -#ifndef _WIN32 - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#include -#ifdef WIN32 -#define random rand -#define usleep(a) _sleep(a/1000) -#include -#include -#else -#include -#endif -#include - -#include -#include "m_imp.h" -#include "g_canvas.h" - - -static int guidebug=0; -static int ignorevisible=1; // ignore visible test - // because this seems to lead to bad refresh - // wait for a fix - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define THREAD_SLEEP_TIME 100000 // 100000 us = 100 ms - -static char *sonogram_version = "sonogram~: version 0.9, written by Yves Degoyon (ydegoyon@free.fr)"; - -static t_class *sonogram_class; -t_widgetbehavior sonogram_widgetbehavior; - - -typedef struct _sonogram -{ - t_object x_obj; - - t_int x_size; /* size of the stored fft ( in blocks~ ) */ - t_float x_samplerate; /* sample rate */ - t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ - t_float x_readpos; /* data's playing position */ - t_int x_writepos; /* data's recording position */ - t_int x_readstart; /* data's starting position for reading */ - t_int x_readend; /* data's ending position for reading */ - t_int x_modstart; /* data's starting position for modifications */ - t_int x_modend; /* data's ending position for modifications */ - t_int x_play; /* playing on/off flag */ - t_float x_readspeed; /* number of grouped blocks for reading */ - t_float x_record; /* flag to start recording process */ - t_float x_empty; /* flag to indicate it's a brand new sonogram */ - t_float *x_rdata; /* table containing real part of the fft */ - t_float *x_rudata; /* undo real data */ - t_float *x_idata; /* table containing imaginery part of the fft */ - t_float *x_iudata; /* undo imaginery data */ - t_float x_phase; /* phase to apply on output */ - t_outlet *x_end; /* outlet for end of restitution */ - t_outlet *x_recend; /* outlet for end of recording */ - t_int *x_multfreq; /* array of multiplicative factor */ - char *x_gifdata; /* buffer for graphical data */ - char *x_guicommand; /* buffer for graphical command */ - t_int x_uxs; /* starting x position for undo */ - t_int x_uxe; /* ending x position for undo */ - t_int x_uys; /* starting y position for undo */ - t_int x_uye; /* ending y position for undo */ - - /* graphical data block */ - t_int x_enhancemode; /* flag to set enhance mode */ - t_int x_graphic; /* flag to set graphic mode */ - t_int x_phaso; /* flag to indicate if phasogram is shown */ - t_int x_selected; /* flag to remember if we are seleted or not */ - t_int x_erase; /* flag used when an erase is needed */ - t_int x_redraw; /* flag used when drawing is needed */ - t_int x_nbupdated; /* number of points updated */ - t_glist *x_glist; /* keep graphic context for various operations */ - t_int x_zoom; /* zoom factor */ - pthread_t x_updatechild; /* thread id for the update child */ - t_int x_updatestart; /* starting position for update */ - t_int x_updateend; /* ending position for update */ - t_int x_xpos; /* stuck x position */ - t_int x_ypos; /* stuck y position */ - t_int x_shifted; /* remember shift state from last click */ - t_int x_alted; /* remember alt state from last click */ - t_int x_aftermousedown; /* indicates the mousedown event */ - t_int x_xstartcapture; /* x of the start of the capture */ - t_int x_ystartcapture; /* y of the start of the capture */ - t_int x_xendcapture; /* x of the start of the capture */ - t_int x_yendcapture; /* y of the start of the capture */ - t_int x_xdraw; /* x drawing position */ - t_int x_ydraw; /* y drawing position */ - t_float x_modstep; /* step for graphical modifications */ - - t_float x_f; /* float needed for signal input */ - -} t_sonogram; - -/* ------------------------ drawing functions ---------------------------- */ -static char* sonogram_get_fill_color( t_float fspectrum ) -{ - if ( fspectrum < 0.01 ) { - return "#EEEEEE"; - } else if ( fspectrum < 0.1 ) { - return "#DDDDDD"; - } else if ( fspectrum < 0.5 ) { - return "#CCCCCC"; - } else if ( fspectrum < 1 ) { - return "#BBBBBB"; - } else if ( fspectrum < 2 ) { - return "#AAAAAA"; - } else if ( fspectrum < 5 ) { - return "#999999"; - } else if ( fspectrum < 10 ) { - return "#888888"; - } else if ( fspectrum < 20 ) { - return "#777777"; - } else if ( fspectrum < 30 ) { - return "#666666"; - } else if ( fspectrum < 40 ) { - return "#555555"; - } else if ( fspectrum < 50 ) { - return "#444444"; - } else if ( fspectrum < 60 ) { - return "#333333"; - } else if ( fspectrum < 80 ) { - return "#222222"; - } else if ( fspectrum < 100 ) { - return "#111111"; - } else { - return "#000000"; - } -} - -static char* phasogram_get_fill_color( t_int phase ) -{ - if ( phase < 0 ) - { - if ( phase > -10 ) { - return "#111111"; - } else if ( phase > -20 ) { - return "#222222"; - } else if ( phase > -30 ) { - return "#333333"; - } else if ( phase > -40 ) { - return "#444444"; - } else if ( phase > -50 ) { - return "#555555"; - } else if ( phase > -60 ) { - return "#666666"; - } else if ( phase > -70 ) { - return "#777777"; - } else if ( phase > -80 ) { - return "#888888"; - } else { - return "#999999"; - } - } - else - { - if ( phase == 0 ) { - return "#FFFFFF"; - } else if ( phase < 10 ) { - return "#111111"; - } else if ( phase < 20 ) { - return "#222222"; - } else if ( phase < 30 ) { - return "#333333"; - } else if ( phase < 40 ) { - return "#444444"; - } else if ( phase < 50 ) { - return "#555555"; - } else if ( phase < 60 ) { - return "#666666"; - } else if ( phase < 70 ) { - return "#777777"; - } else if ( phase < 80 ) { - return "#888888"; - } else { - return "#999999"; - } - } - // normally never reached - return ""; -} - -static void sonogram_update_point(t_sonogram *x, t_glist *glist, t_int sample, t_int frequency) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_float fspectrum=0.0; - t_int phase=0.0; - char newColor[ 8 ], olColor[8]; - int i; - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - phase = (int) ( atan2( *(x->x_idata+(sample*x->x_blocksize)+frequency), - *(x->x_rdata+(sample*x->x_blocksize)+frequency) )*180/M_PI ); - if ( x->x_empty && ( fspectrum != 0 )) - { - x->x_empty = 0; - } - strcpy( newColor, sonogram_get_fill_color( fspectrum ) ); - - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", strcat( newColor, " ") ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - - if ( x->x_phaso ) - { - strcpy( newColor, phasogram_get_fill_color( phase ) ); - strcpy( x->x_gifdata, "" ); - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", strcat( newColor, " ") ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("FAZIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - } - - x->x_nbupdated++; -} - -static void sonogram_update_block(t_sonogram *x, t_glist *glist, t_int bnumber) -{ - t_int fi, i=0; - t_float fspectrum=0.0; - t_int phase=0; - char color[8]; - - // update sonogram - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - fspectrum = - sqrt( pow( *(x->x_rdata+bnumber*x->x_blocksize+fi), 2) + - pow( *(x->x_idata+bnumber*x->x_blocksize+fi), 2) ); - strcpy( color, sonogram_get_fill_color( fspectrum ) ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "SONIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - - // update phasogram - if ( x->x_phaso ) - { - strcpy( x->x_gifdata, "" ); - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - phase = (int) ( atan2( *(x->x_idata+bnumber*x->x_blocksize+fi), - *(x->x_rdata+bnumber*x->x_blocksize+fi) )*180/M_PI ); - strcpy( color, phasogram_get_fill_color( phase ) ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "FAZIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - } - -} - -static void sonogram_erase_block(t_sonogram *x, t_glist *glist, t_int bnumber ) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int fi; - t_float fspectrum=0.0; - char fillColor[ 16 ]; - - for ( fi=0; fix_blocksize/2; fi++) - { - { - int i; - - for ( i=0; ix_zoom; i++ ) - { - strcpy( x->x_gifdata+i*sizeof("#FFFFFF "), "#FFFFFF " ); - } - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - bnumber*x->x_zoom, (x->x_blocksize/2-fi)*x->x_zoom ); - } - } -} - -static void *sonogram_do_update_part(void *tdata) -{ - t_sonogram *x = (t_sonogram*) tdata; - t_int si; - t_int nbpoints = 0; - t_float percentage = 0, opercentage = 0; - - // loose synchro - usleep( THREAD_SLEEP_TIME ); - - // check boundaries - if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; - if ( x->x_updatestart < 0 ) x->x_updatestart = 0; - - // post("sonogram~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); - - if ( x->x_erase ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_erase_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "sonogram~ : erase part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - percentage = opercentage = nbpoints = 0; - - if ( x->x_redraw ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_update_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "sonogram~ : update part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - // set borders in black - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", glist_getcanvas(x->x_glist), x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", glist_getcanvas(x->x_glist), x); - } - - // post("sonogram~ : child thread %d ended (nb_updated=%d)", (int)x->x_updatechild, x->x_nbupdated ); - x->x_updatechild = 0; - return NULL; -} - -static void sonogram_update_part(t_sonogram *x, t_glist *glist, t_int bstart, t_int bend, - t_int erase, t_int redraw, t_int keepframe) -{ - pthread_attr_t update_child_attr; - - if ( x->x_graphic ) - { - if ( x->x_updatechild != 0 ) - { - // post( "sonogram~ : error : no update is possible for now" ); - return; - } - x->x_updatestart = bstart; - x->x_updateend = bend; - if ( !keepframe ) - { - x->x_erase = 0; - } - else - { - x->x_erase = erase; - } - x->x_redraw = redraw; - x->x_nbupdated = 0; - // recreate the square if needed - if ( ( bstart == 0 ) && ( bend == x->x_size-1 ) && !keepframe ) - { - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", glist_getcanvas(glist), x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete ISONIMAGE%x\n", glist_getcanvas(glist), x ); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", glist_getcanvas(glist), x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete IFAZIMAGE%x\n", glist_getcanvas(glist), x ); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor(x->x_glist, (t_text*)x ); - } - // set borders in red - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #FF0000\n", glist_getcanvas(glist), x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #FF0000\n", glist_getcanvas(glist), x); - } - - // launch update thread - if ( pthread_attr_init( &update_child_attr ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_init" ); - return; - } - if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_setdetachstate" ); - return; - } - if ( pthread_create( &x->x_updatechild, &update_child_attr, sonogram_do_update_part, x ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_create" ); - return; - } - else - { - // post( "sonogram~ : drawing thread %d launched", (int)x->x_updatechild ); - } - } -} - - /* paste selection at the drawing point */ -static void sonogram_paste( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si=0,fi=0; - t_float *icopy; - t_float *rcopy; - t_int copynd; - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - // post ( "sonogram~ : si : %d : fi : %d : copynd : %d", si, fi, copynd ); - if ( pystart+fi-cys >= x->x_blocksize/2 ) break; - *(x->x_rudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - *(x->x_iudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - if ( x->x_enhancemode ) - { - // save data for undo - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(icopy+copynd); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(icopy+copynd); - } - copynd++; - } - } - - x->x_uxs = pxstart; - x->x_uxe = pxstart+(si-1)-cxs; - x->x_uys = pystart; - x->x_uye = pystart+(fi-1)-cys;; - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); -} - - /* paste phase at the drawing point */ -static void sonogram_paste_phase( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si,fi; - t_float fspectrum, fdestspectrum; - t_float fphase, fdestphase; - t_float *icopy; - t_float *rcopy; - t_int copynd; - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste phase from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - if ( pystart+fi-cys > x->x_blocksize+1 ) break; - fphase = atan2( *(icopy+copynd), *(rcopy+copynd) ); - fdestspectrum = - sqrt( pow( *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) + - pow( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) ); - fdestphase = atan2( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), - *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)) ); - if ( x->x_enhancemode ) - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*cos( fdestphase + fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*sin( fdestphase + fphase ); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*cos( fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*sin( fphase ); - } - copynd++; - } - } - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - - sonogram_update_part(x, x->x_glist, pxstart, pxstart+(si-1)-cxs, 0, 1, 1); - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - x->x_xstartcapture = x->x_xdraw; - x->x_ystartcapture = x->x_ydraw; - x->x_xendcapture = x->x_xdraw; - x->x_yendcapture = x->x_ydraw; - -} - -static void sonogram_draw_new(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_xpos == -1 ) - { - x->x_xpos=x->x_obj.te_xpix; - x->x_ypos=x->x_obj.te_ypix; - } - if ( x->x_graphic ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - canvas, x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - glist_getcanvas( x->x_glist ), x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_delete(t_sonogram *x, t_glist *glist) -{ - if ( x->x_graphic && glist_isvisible( glist ) ) - { - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( glist ), x ); - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", glist_getcanvas( glist ), x); - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", glist_getcanvas( glist ), x); - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", glist_getcanvas( glist ), x ); - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", glist_getcanvas( glist ), x ); - SYS_VGUI3(".x%x.c delete %xISONIMAGE\n", glist_getcanvas( glist ), x ); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xIFAZIMAGE\n", glist_getcanvas( glist ), x ); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - } - } -} - -static void sonogram_draw_move(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI7(".x%x.c coords %xSONOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos-1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize/2*x->x_zoom+1); - SYS_VGUI5(".x%x.c coords ISONIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)) ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c coords %xPHASOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos+(x->x_blocksize/2*x->x_zoom)+1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize*x->x_zoom+3); - SYS_VGUI5(".x%x.c coords IFAZIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2 ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_select(t_sonogram* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #0000FF\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #0000FF\n", canvas, x); - } - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); - } - } - } -} - -/* ------------------------ widget callbacks ----------------------------- */ - - -static void sonogram_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_sonogram* x = (t_sonogram*)z; - - *xp1 = x->x_xpos; - *yp1 = x->x_ypos; - if ( !x->x_phaso ) - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize/2*x->x_zoom+1; - } - else - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize*x->x_zoom+3; - } -} - -static void sonogram_save(t_gobj *z, t_binbuf *b) -{ - t_sonogram *x = (t_sonogram *)z; - - binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), - (t_int)x->x_xpos, (t_int)x->x_ypos, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_size, x->x_graphic, x->x_phaso ); - binbuf_addv(b, ";"); -} - -static void sonogram_select(t_gobj *z, t_glist *glist, int selected) -{ - t_sonogram *x = (t_sonogram *)z; - - x->x_selected = selected; - sonogram_draw_select( x, glist ); -} - -static void sonogram_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_sonogram *x = (t_sonogram *)z; - t_rtext *y; - - if (vis) - { - sonogram_draw_new( x, glist ); - } - else - { - // erase all points - sonogram_draw_delete( x, glist ); - } -} - -static void sonogram_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void sonogram_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_sonogram *x = (t_sonogram *)z; - int xold = x->x_xpos; - int yold = x->x_ypos; - - x->x_xpos += dx; - x->x_ypos += dy; - - if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) - { - sonogram_draw_move( x, glist ); - } - -} - -static void sonogram_modify_point( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - if ( alted ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = 0; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - } - } -} - -static void sonogram_modify_point_phase( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - t_float fspectrum; - t_float fphase; - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - fphase = atan2( *(x->x_idata+sample*x->x_blocksize+frequency), - *(x->x_rdata+sample*x->x_blocksize+frequency) ); - if ( alted==4 ) - { - // setting phase to 0 - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase*x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase*x->x_modstep ); - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase+x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase+x->x_modstep ); - } - } -} - -static void sonogram_motion(t_sonogram *x, t_floatarg dx, t_floatarg dy) -{ - int fdraw=0, sdraw=0; - - // post( "sonogram_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); - if ( ( x->x_shifted || (x->x_alted==4) ) ) - { - if ( (x->x_xdraw+dx) >= x->x_xpos && - (x->x_xdraw+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xdraw += dx; - } - if ( (x->x_ydraw+dy) >= x->x_ypos && - (x->x_ydraw+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_ydraw += dy; - } - sdraw=(x->x_xdraw-x->x_xpos)/x->x_zoom; - if ( x->x_ydraw <= x->x_ypos+x->x_blocksize/2*x->x_zoom ) - { - fdraw=(x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify point @ [%d, %d] alted=%d", sdraw, fdraw, x->x_alted ); - sonogram_modify_point( x, sdraw, fdraw, x->x_alted ); - } - if ( x->x_ydraw >= x->x_ypos+x->x_blocksize/2*x->x_zoom+1 ) - { - fdraw=(x->x_ypos+x->x_blocksize*x->x_zoom/2+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify phase @ [%d, %d]", sdraw, fdraw ); - sonogram_modify_point_phase( x, sdraw, fdraw, x->x_alted ); - } - sonogram_update_point( x, x->x_glist, sdraw, fdraw ); - } - else - { - if ( (x->x_xendcapture+dx) >= x->x_xpos && - (x->x_xendcapture+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xendcapture += dx; - } - if ( (x->x_yendcapture+dy) >= x->x_ypos && - (x->x_yendcapture+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_yendcapture += dy; - } - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #0000FF -tags %xCAPTURE\n", - glist_getcanvas( x->x_glist ), x->x_xstartcapture, - x->x_ystartcapture, x->x_xendcapture, x->x_yendcapture, x ); - } -} - -static int sonogram_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_sonogram* x = (t_sonogram *)z; - int si,fi; - - // post( "sonogram_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); - if ( x->x_aftermousedown == 1 && doit == 0) - { - x->x_aftermousedown = 1; - } - else - { - x->x_aftermousedown = 0; - } - if ( doit ) - { - x->x_xdraw = xpix; - x->x_ydraw = ypix; - x->x_shifted = shift; - x->x_alted = alt; - // activate motion callback - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)sonogram_motion, - 0, xpix, ypix ); - - if ( shift && alt && (x->x_xstartcapture != x->x_xendcapture ) ) - { - sonogram_paste(x); - sonogram_paste_phase(x); - } - else if ( shift && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // add or multiply modstep - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - // post( "modified y from %d to %d", (x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2, - // (x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2 ); - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - else if ( (alt==4) && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // clean up area - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( x->x_glist ), x ); - x->x_xstartcapture = xpix; - x->x_ystartcapture = ypix; - x->x_xendcapture = xpix; - x->x_yendcapture = ypix; - } - else - { - // nothing - } - x->x_aftermousedown = doit; - return (1); -} - - /* clean up */ -static void sonogram_free(t_sonogram *x) -{ - if ( x->x_rdata != NULL ) { - freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_idata != NULL ) { - freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_rudata != NULL ) { - freebytes(x->x_rudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_iudata != NULL ) { - freebytes(x->x_iudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } -} - - /* allocate tables for storing ffts */ -static t_int sonogram_allocate(t_sonogram *x) -{ - t_int fi; - - if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_multfreq = getbytes( x->x_blocksize*sizeof(t_int) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_blocksize*sizeof(t_int) ); - } - for ( fi=0; fix_blocksize; fi++ ) - { - *(x->x_multfreq+fi)=1; - } - // no undo is available - x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; - if ( !(x->x_rudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_iudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - - return 0; -} - - /* records or playback the sonogram */ -static t_int *sonogram_perform(t_int *w) -{ - t_float *rin = (t_float *)(w[1]); - t_float *iin = (t_float *)(w[2]); - t_float *rout = (t_float *)(w[3]); - t_float *iout = (t_float *)(w[4]); - t_float fspectrum = 0.0; - t_float fphase = 0.0; - t_int is; - t_int n = (int)(w[5]); /* number of samples */ - t_sonogram *x = (t_sonogram *)(w[6]); - t_int bi; - - // reallocate tables if blocksize has been changed - if ( n != x->x_blocksize && x->x_updatechild == 0 ) { - post( "sonogram~ : reallocating tables" ); - // erase all points - sonogram_free(x); - x->x_blocksize = n; - sonogram_allocate(x); - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, 0, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); - } - - bi = 0; - while (bix_record) { - *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=(*(rin))*(*(x->x_multfreq+bi)); - *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=(*(iin))*(*(x->x_multfreq+bi)); - } - // set outputs - *rout = 0.0; - *iout = 0.0; - if ( x->x_play) { - is=0; - fspectrum = - sqrt( pow( *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) + - pow( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) ); - fphase = atan2( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), - *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi) ); - fphase += (x->x_phase/180.0)*(M_PI); - *rout += fspectrum*cos( fphase ); - *iout += fspectrum*sin( fphase ); - } - rout++;iout++; - rin++;iin++; - bi++; - - } - // reset playing position until next play - if ( x->x_play ) { - x->x_readpos+=x->x_readspeed; - // post( "xreadpos : %f (added %f)", x->x_readpos, x->x_readspeed ); - if ( x->x_readpos >= (x->x_readend*x->x_size)/100 ) { - x->x_play=0; - x->x_readpos=(x->x_readstart*x->x_size)/100; - // post( "sonogram~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - } - // reset recording position until next record - if ( x->x_record ) { - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 0); - outlet_bang(x->x_recend); - if ( x->x_empty ) x->x_empty = 0; - // post( "sonogram~ : stopped recording" ); - } - } - // post( "sonogram~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); - return (w+7); -} - -static void sonogram_dsp(t_sonogram *x, t_signal **sp) -{ - dsp_add(sonogram_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); -} - - /* record the sonogram */ -static void sonogram_record(t_sonogram *x) -{ - x->x_record=1; - x->x_writepos=0; - // post( "sonogram~ : recording on" ); -} - - /* play the sonogram */ -static void sonogram_play(t_sonogram *x) -{ - x->x_play=1; - x->x_readpos=(x->x_readstart*x->x_size)/100; - // post( "sonogram~ : playing on" ); -} - - /* setting the starting point for reading ( in percent ) */ -static void sonogram_readstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_readend ) { - x->x_readstart = x->x_readend; - post( "sonogram~ : warning : range for reading is null" ); - } else { - x->x_readstart=startpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADSTART -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the starting point for modification ( in percent ) */ -static void sonogram_modstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_modend ) { - x->x_modstart = x->x_modend; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modstart=startpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODSTART -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the modification step for graphical mode */ -static void sonogram_modstep(t_sonogram *x, t_floatarg fmodstep) -{ - if ( x->x_graphic ) - { - x->x_modstep = fmodstep; - } -} - - /* setting enhance mode */ -static void sonogram_enhancemode(t_sonogram *x, t_floatarg fenhancemode) -{ - if ( x->x_graphic ) - { - x->x_enhancemode = fenhancemode; - } -} - - /* setting the ending point for reading ( in percent ) */ -static void sonogram_readend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_readstart ) { - x->x_readend = x->x_readstart; - post( "sonogram~ : warning : range for reading is null" ); - } else { - x->x_readend=endpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADEND -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the ending point for modification ( in percent ) */ -static void sonogram_modend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_modstart ) { - x->x_modend = x->x_modstart; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modend=endpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", - glist_getcanvas( x->x_glist ), x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODEND -width 3\n", - glist_getcanvas( x->x_glist ), x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* sets the reading speed */ -static void sonogram_readspeed(t_sonogram *x, t_floatarg freadspeed) -{ - if (freadspeed <= 0 ) { - post( "sonogram~ : wrong readspeed argument" ); - return; - } - x->x_readspeed=freadspeed; -} - - /* enhance frequencies */ -static void sonogram_enhance(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fenhance, t_floatarg fnoupdate ) -{ - t_int samplestart, sampleend, si, fi=0, ffi=0; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - if ( fenhance < 0 ) { - post( "sonogram~ : error : wrong multiplicating factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - *(x->x_multfreq+fi) = fenhance; - if ( (fi != 0) && (fi != x->x_blocksize/2-1) ) - { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) *= fenhance; - *(x->x_idata+(si*x->x_blocksize)+fi) *= fenhance; - } - } - } - // post( "sonogram~ : enhanced %d,%d", fi, ffi ); - if ( !(int)fnoupdate ) - { - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); - } -} - - /* add a constant to frequencies */ -static void sonogram_add(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fadd) -{ - t_int samplestart, sampleend, si, fi; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) += fadd; - *(x->x_idata+(si*x->x_blocksize)+fi) += fadd; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* resize sonogram */ -static void sonogram_resize(t_sonogram *x, t_floatarg fnewsize ) -{ - if (fnewsize <= 0) { - post( "sonogram~ : error : wrong size" ); - return; - } - if (x->x_updatechild > 0) { - post( "sonogram~ : can't resize now, an update is pending." ); - return; - } - post( "sonogram~ : reallocating tables" ); - x->x_record = 0; - x->x_play = 0; - sonogram_free(x); - x->x_size = fnewsize; - sonogram_allocate(x); - // erase all points, as data is zero no drawing is needed - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 0, 0); -} - - /* set zoom factor */ -static void sonogram_zoom(t_sonogram *x, t_floatarg fzoom ) -{ - post( "sonogram~: warning : zoom and big block factors might lead to a crash" ); - if (fzoom < 1) { - post( "sonogram~ : error : wrong zoom factor" ); - return; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } - x->x_zoom = (int)fzoom; - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, !x->x_empty, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); -} - - /* refresh data */ -static void sonogram_refresh(t_sonogram *x) -{ - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* flip frequencies */ -static void sonogram_flipfreqs(t_sonogram *x) -{ - t_int samplestart, sampleend, si, fi; - t_float fvalue; - t_int ioperon; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - ioperon=x->x_blocksize/2; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fi<=ioperon/2; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - fvalue = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* flip blocks */ -static void sonogram_flipblocks(t_sonogram *x) -{ - t_int samplestart, sampleend, middlesample, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - middlesample = ( sampleend+samplestart+1 ) / 2; - for ( si=samplestart; si<=middlesample; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* undo if available */ -static void sonogram_undo(t_sonogram *x) -{ - t_int si,fi; - - if ( x->x_uxs == -1 ) - { - post( "sonogram~ : nothing to undo, man" ); - return; - } - - post( "sonogram~ : restoring region [%d,%d,%d,%d]", x->x_uxs, x->x_uys, x->x_uxe, x->x_uye ); - for ( si=x->x_uxs; si<=x->x_uxe; si++ ) { - for ( fi=x->x_uys; fi<=x->x_uye; fi++ ) { - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_iudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - } - } - sonogram_update_part(x, x->x_glist, x->x_uxs, x->x_uxe, 0, 1, 1); -} - - /* zswap exchanges real and imaginery part */ -static void sonogram_zswap(t_sonogram *x) -{ - t_int samplestart, sampleend, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = fvalue; - } - } -} - - /* swap points */ -static void sonogram_swappoints(t_sonogram *x, t_floatarg fnbpoints) -{ - t_int samplestart, sampleend, sp; - t_float s1, s2, f1, f2; - t_float fvalue; - - if (fnbpoints <= 0) { - post( "sonogram~ : error : bad number of points" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=0; spx_blocksize/2-1 ); - f2 = random()%( x->x_blocksize/2-1 ); - fvalue = *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - fvalue = *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* average blocks according to a factor */ -static void sonogram_average(t_sonogram *x, t_floatarg fnbblocks) -{ - t_int samplestart, sampleend, fi, si, ssi; - t_float fraverage, fiaverage; - - if (fnbblocks < 1) { - post( "sonogram~ : error : bad average factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - fraverage=fiaverage=0.0; - for ( fi=0; fix_blocksize; fi++ ) { - for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) { - fraverage=fiaverage=0.0; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi); - fiaverage += *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi); - } - fraverage /= fnbblocks; - fiaverage /= fnbblocks; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi)=fraverage; - *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi)=fiaverage; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* go up by the given number */ -static void sonogram_goup(t_sonogram *x, t_floatarg fgoup) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgoup <= 0 || fgoup > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in goup function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=(x->x_blocksize/2)-fgoup-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* roll up by the given number */ -static void sonogram_roll(t_sonogram *x, t_floatarg froll) -{ - t_int samplestart, sampleend, sp, sf; - t_float *fprvalues; - t_float *fpivalues; - - if (froll <= 0 || froll > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in roll function" ); - return; - } - fprvalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fprvalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - fpivalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fpivalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - - // saving values - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - *(fpivalues+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - } - for (sf=(x->x_blocksize/2)-froll-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = *(fprvalues+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = *(fpivalues+sf); - } - } - freebytes( fprvalues, (int)froll*sizeof(float) ); - freebytes( fpivalues, (int)froll*sizeof(float) ); - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* suppress point below the threshold */ -static void sonogram_threshold(t_sonogram *x, t_floatarg fthreshold) -{ - t_int samplestart, sampleend, sp, sf; - t_float fspectrum; - - if (fthreshold <= 0) { - post( "sonogram~ : error : wrong threshold" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-1; sf++ ) { - fspectrum = sqrt( pow( *(x->x_rdata+sp*x->x_blocksize+sf), 2) + - pow( *(x->x_idata+sp*x->x_blocksize+sf), 2) ); - if ( fspectrum < fthreshold ) - { - *(x->x_rdata+sp*x->x_blocksize+sf) = 0.0; - *(x->x_idata+sp*x->x_blocksize+sf) = 0.0; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* change the phase */ -static void sonogram_phase(t_sonogram *x, t_floatarg fincphase) -{ - if (fincphase < 0 || fincphase > 90) { - post( "sonogram~ : error : wrong phase in phase function : out of [0,90]" ); - return; - } - x->x_phase = fincphase; -} - - /* go down by the given number */ -static void sonogram_godown(t_sonogram *x, t_floatarg fgodown) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgodown <= 0 || fgodown > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in godown function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-fgodown-1; sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+sf) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - *(x->x_idata+((int)sp*x->x_blocksize)+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - } - for (sf=(x->x_blocksize/2)-fgodown; sf<(x->x_blocksize/2); sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* swap blocks */ -static void sonogram_swapblocks(t_sonogram *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) -{ - t_int samplestart, samplestartb, samplesize, sp, sf; - t_int iperstart, iperend, ipersize; - t_float s1, s2; - t_float fvalue; - - iperstart = fperstart; - iperend = fperend; - ipersize = fpersize; - - if (iperstart < 0 || iperstart > iperend || - iperend <= 0 || iperend+ipersize > 100 || - ipersize < 0 || fpersize > 100 ) { - post( "sonogram~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", - iperstart, iperstart+ipersize, iperend, iperend+ipersize ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - samplestartb=(x->x_modend*(x->x_size-1))/100; - samplesize=((samplestartb-samplestart)*ipersize)/100; - samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; - samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; - - post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); - - for ( sp=samplesize; sp>=0; sp-- ) { - for ( sf=0; sfx_blocksize; sf++) { - fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* swap frequencies */ -static void sonogram_swapfreqs(t_sonogram *x, t_floatarg ffirstfreq, t_floatarg fsecondfreq) -{ - t_int samplestart, sampleend, sp; - t_float fvalue; - - if (ffirstfreq < 0 || fsecondfreq <0) { - post( "sonogram~ : error : wrong frequencies" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - fvalue = *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - fvalue = *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - -static void *sonogram_new(t_floatarg fsize, t_floatarg fgraphic, t_floatarg fphaso) -{ - t_sonogram *x = (t_sonogram *)pd_new(sonogram_class); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_recend = outlet_new(&x->x_obj, &s_bang ); - x->x_end = outlet_new(&x->x_obj, &s_bang ); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); - - if ( fsize <= 0 || ( fgraphic != 0 && fgraphic != 1 ) || ( fphaso != 0 && fphaso != 1 ) ) { - error( "sonogram~ : missing or negative creation arguments" ); - return NULL; - } - - // activate graphical callbacks - if ( fgraphic != 0 ) - { - class_setwidget(sonogram_class, &sonogram_widgetbehavior); - } - x->x_graphic = (int) fgraphic; - x->x_phaso = (int) fphaso; - - x->x_size = fsize; - x->x_blocksize = sys_getblksize(); - x->x_play = 0; - x->x_readspeed = 1.; - x->x_record = 0; - x->x_readpos = 0.; - x->x_writepos = 0; - x->x_modstart = 0; - x->x_readstart = 0; - x->x_modend = 100; - x->x_readend = 100; - x->x_rdata = NULL; - x->x_idata = NULL; - x->x_phase = 0.0; - x->x_empty = 1; - x->x_xpos = -1; - x->x_ypos = -1; - x->x_samplerate = sys_getsr(); - /* graphic data */ - x->x_selected = 0; - x->x_zoom = 1; - x->x_updatechild = 0; - x->x_modstep = 1.1; - x->x_enhancemode = 0; - x->x_glist = (t_glist*)canvas_getcurrent(); - - if ( sonogram_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } - -} - -void sonogram_tilde_setup(void) -{ - post(sonogram_version); - sonogram_class = class_new(gensym("sonogram~"), (t_newmethod)sonogram_new, (t_method)sonogram_free, - sizeof(t_sonogram), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - - // set callbacks - sonogram_widgetbehavior.w_getrectfn = sonogram_getrect; - sonogram_widgetbehavior.w_displacefn = sonogram_displace; - sonogram_widgetbehavior.w_selectfn = sonogram_select; - sonogram_widgetbehavior.w_activatefn = NULL; - sonogram_widgetbehavior.w_deletefn = sonogram_delete; - sonogram_widgetbehavior.w_visfn = sonogram_vis; - sonogram_widgetbehavior.w_clickfn = sonogram_click; - /* - * : As of 0.37, pd does not have these last - * two elements in t_widgetbehavoir anymore. - * see pd/src/notes.txt: - * savefunction and dialog into class structure - */ -#if PD_MINOR_VERSION < 37 || !defined(PD_MINOR_VERSION) - sonogram_widgetbehavior.w_propertiesfn = NULL; - sonogram_widgetbehavior.w_savefn = sonogram_save; -/* this is needed to make the help patch work on < 0.37 */ - -#else - class_setpropertiesfn(sonogram_class, NULL); - class_setsavefn(sonogram_class, &sonogram_save); -#endif - - CLASS_MAINSIGNALIN( sonogram_class, t_sonogram, x_f ); - class_addmethod(sonogram_class, (t_method)sonogram_dsp, gensym("dsp"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_record, gensym("record"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhance, gensym("enhance"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_add, gensym("add"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_resize, gensym("resize"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zoom, gensym("zoom"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swappoints, gensym("swappoints"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_average, gensym("average"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapfreqs, gensym("swapfreqs"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipfreqs, gensym("flipfreqs"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipblocks, gensym("flipblocks"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_play, gensym("play"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_refresh, gensym("refresh"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhancemode, gensym("enhancemode"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_goup, gensym("goup"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_godown, gensym("godown"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_roll, gensym("roll"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_threshold, gensym("threshold"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_phase, gensym("phase"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zswap, gensym("zswap"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstep, gensym("modstep"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstart, gensym("modstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modend, gensym("modend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readstart, gensym("readstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readend, gensym("readend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_undo, gensym("undo"), A_NULL); -} - -#endif /* not _WIN32 */ diff --git a/sonogram~/sonogram~.c b/sonogram~/sonogram~.c deleted file mode 100644 index 4085b34..0000000 --- a/sonogram~/sonogram~.c +++ /dev/null @@ -1,2088 +0,0 @@ -/*------------------------ sonogram~ ------------------------------------------ */ -/* */ -/* sonogram~ : lets you record, play back and modify a sonogram */ -/* constructor : sonogram */ -/* */ -/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* "Living at night" */ -/* "Doesn't help for my complexion" */ -/* David Thomas - Final Solution */ -/* ---------------------------------------------------------------------------- */ - - - -#include -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -#else -#include -#endif -#include -#include -#ifdef UNIX -#include -#endif -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif -#include - -#include "m_pd.h" -#include "m_imp.h" -#include "g_canvas.h" - - -static int guidebug=0; -static int ignorevisible=1; // ignore visible test - // because this seems to lead to bad refresh - // wait for a fix - -#define SYS_VGUI2(a,b) if (guidebug) \ - post(a,b);\ - sys_vgui(a,b) - -#define SYS_VGUI3(a,b,c) if (guidebug) \ - post(a,b,c);\ - sys_vgui(a,b,c) - -#define SYS_VGUI4(a,b,c,d) if (guidebug) \ - post(a,b,c,d);\ - sys_vgui(a,b,c,d) - -#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ - post(a,b,c,d,e);\ - sys_vgui(a,b,c,d,e) - -#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ - post(a,b,c,d,e,f);\ - sys_vgui(a,b,c,d,e,f) - -#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ - post(a,b,c,d,e,f,g );\ - sys_vgui(a,b,c,d,e,f,g) - -#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i );\ - sys_vgui(a,b,c,d,e,f,g,h,i) - -#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j) - -#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ - post(a,b,c,d,e,f,g,h,i,j,k );\ - sys_vgui(a,b,c,d,e,f,g,h,i,j,k) - -#define THREAD_SLEEP_TIME 100000 // 100000 us = 100 ms - -static char *sonogram_version = "sonogram~: version 0.14, written by Yves Degoyon (ydegoyon@free.fr)"; - -static t_class *sonogram_class; -t_widgetbehavior sonogram_widgetbehavior; - - -typedef struct _sonogram -{ - t_object x_obj; - - t_int x_size; /* size of the stored fft ( in blocks~ ) */ - t_float x_samplerate; /* sample rate */ - t_int x_blocksize; /* current block size ( might be modified by block~ object ) */ - t_float x_readpos; /* data's playing position */ - t_int x_writepos; /* data's recording position */ - t_int x_readstart; /* data's starting position for reading */ - t_int x_readend; /* data's ending position for reading */ - t_int x_modstart; /* data's starting position for modifications */ - t_int x_modend; /* data's ending position for modifications */ - t_int x_play; /* playing on/off flag */ - t_float x_readspeed; /* number of grouped blocks for reading */ - t_float x_record; /* flag to start recording process */ - t_float x_empty; /* flag to indicate it's a brand new sonogram */ - t_float *x_rdata; /* table containing real part of the fft */ - t_float *x_rudata; /* undo real data */ - t_float *x_idata; /* table containing imaginery part of the fft */ - t_float *x_iudata; /* undo imaginery data */ - t_float x_phase; /* phase to apply on output */ - t_outlet *x_end; /* outlet for end of restitution */ - t_outlet *x_recend; /* outlet for end of recording */ - t_int *x_multfreq; /* array of multiplicative factor */ - char *x_gifdata; /* buffer for graphical data */ - char *x_guicommand; /* buffer for graphical command */ - t_int x_uxs; /* starting x position for undo */ - t_int x_uxe; /* ending x position for undo */ - t_int x_uys; /* starting y position for undo */ - t_int x_uye; /* ending y position for undo */ - - /* graphical data block */ - t_int x_enhancemode; /* flag to set enhance mode */ - t_int x_graphic; /* flag to set graphic mode */ - t_int x_phaso; /* flag to indicate if phasogram is shown */ - t_int x_selected; /* flag to remember if we are seleted or not */ - t_int x_erase; /* flag used when an erase is needed */ - t_int x_redraw; /* flag used when drawing is needed */ - t_int x_nbupdated; /* number of points updated */ - t_glist *x_glist; /* keep graphic context for various operations */ - t_int x_zoom; /* zoom factor */ - #ifndef _WIN32 - pthread_t x_updatechild; /* thread id for the update child */ - #else - int x_updatechild; - #endif - t_int x_updatestart; /* starting position for update */ - t_int x_updateend; /* ending position for update */ - t_int x_xpos; /* stuck x position */ - t_int x_ypos; /* stuck y position */ - t_int x_shifted; /* remember shift state from last click */ - t_int x_alted; /* remember alt state from last click */ - t_int x_aftermousedown; /* indicates the mousedown event */ - t_int x_xstartcapture; /* x of the start of the capture */ - t_int x_ystartcapture; /* y of the start of the capture */ - t_int x_xendcapture; /* x of the start of the capture */ - t_int x_yendcapture; /* y of the start of the capture */ - t_int x_xdraw; /* x drawing position */ - t_int x_ydraw; /* y drawing position */ - t_float x_modstep; /* step for graphical modifications */ - - t_float x_f; /* float needed for signal input */ - -} t_sonogram; - -/* ------------------------ drawing functions ---------------------------- */ -static char* sonogram_get_fill_color( t_float fspectrum ) -{ - if ( fspectrum < 0.01 ) { - return "#EEEEEE "; - } else if ( fspectrum < 0.1 ) { - return "#DDDDDD "; - } else if ( fspectrum < 0.5 ) { - return "#CCCCCC "; - } else if ( fspectrum < 1 ) { - return "#BBBBBB "; - } else if ( fspectrum < 2 ) { - return "#AAAAAA "; - } else if ( fspectrum < 5 ) { - return "#999999 "; - } else if ( fspectrum < 10 ) { - return "#888888 "; - } else if ( fspectrum < 20 ) { - return "#777777 "; - } else if ( fspectrum < 30 ) { - return "#666666 "; - } else if ( fspectrum < 40 ) { - return "#555555 "; - } else if ( fspectrum < 50 ) { - return "#444444 "; - } else if ( fspectrum < 60 ) { - return "#333333 "; - } else if ( fspectrum < 80 ) { - return "#222222 "; - } else if ( fspectrum < 100 ) { - return "#111111 "; - } else { - return "#000000 "; - } -} - -static char* phasogram_get_fill_color( t_int phase ) -{ - if ( phase < 0 ) - { - if ( phase > -10 ) { - return "#111111 "; - } else if ( phase > -20 ) { - return "#222222 "; - } else if ( phase > -30 ) { - return "#333333 "; - } else if ( phase > -40 ) { - return "#444444 "; - } else if ( phase > -50 ) { - return "#555555 "; - } else if ( phase > -60 ) { - return "#666666 "; - } else if ( phase > -70 ) { - return "#777777 "; - } else if ( phase > -80 ) { - return "#888888 "; - } else { - return "#999999 "; - } - } - else - { - if ( phase == 0 ) { - return "#FFFFFF "; - } else if ( phase < 10 ) { - return "#111111 "; - } else if ( phase < 20 ) { - return "#222222 "; - } else if ( phase < 30 ) { - return "#333333 "; - } else if ( phase < 40 ) { - return "#444444 "; - } else if ( phase < 50 ) { - return "#555555 "; - } else if ( phase < 60 ) { - return "#666666 "; - } else if ( phase < 70 ) { - return "#777777 "; - } else if ( phase < 80 ) { - return "#888888 "; - } else { - return "#999999 "; - } - } - // normally never reached - return ""; -} - -static void sonogram_update_point(t_sonogram *x, t_glist *glist, t_int sample, t_int frequency) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_float fspectrum=0.0; - t_int phase=0.0; - char newColor[ 8 ], olColor[8]; - int i; - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - phase = (int) ( atan2( *(x->x_idata+(sample*x->x_blocksize)+frequency), - *(x->x_rdata+(sample*x->x_blocksize)+frequency) )*180/M_PI ); - if ( x->x_empty && ( fspectrum != 0 )) - { - x->x_empty = 0; - } - strncpy( newColor, sonogram_get_fill_color( fspectrum ), 8 ); - - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", newColor ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - - if ( x->x_phaso ) - { - strncpy( newColor, phasogram_get_fill_color( phase ), 8 ); - strcpy( x->x_gifdata, "" ); - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_gifdata, "%s", newColor ); - } - for ( i=0; ix_zoom; i++ ) - { - SYS_VGUI5("FAZIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - sample*x->x_zoom+i, (x->x_blocksize/2-frequency)*x->x_zoom ); - } - } - - x->x_nbupdated++; -} - -static void sonogram_update_block(t_sonogram *x, t_glist *glist, t_int bnumber) -{ - t_int fi, i=0; - t_float fspectrum=0.0; - t_int phase=0; - char color[8]; - - // update sonogram - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - fspectrum = - sqrt( pow( *(x->x_rdata+bnumber*x->x_blocksize+fi), 2) + - pow( *(x->x_idata+bnumber*x->x_blocksize+fi), 2) ); - strncpy( color, sonogram_get_fill_color( fspectrum ), 8 ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, color, 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "SONIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - - // update phasogram - if ( x->x_phaso ) - { - strcpy( x->x_gifdata, "" ); - for ( fi=x->x_blocksize/2-1; fi>=0; fi-- ) - { - phase = (int) ( atan2( *(x->x_idata+bnumber*x->x_blocksize+fi), - *(x->x_rdata+bnumber*x->x_blocksize+fi) )*180/M_PI ); - strncpy( color, phasogram_get_fill_color( phase ), 8 ); - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, color, 8 ); - } - } - for ( i=0; ix_zoom; i++ ) - { - sprintf( x->x_guicommand, "FAZIMAGE%x put {%s} -to %d 0\n", (unsigned int)x, x->x_gifdata, (bnumber*x->x_zoom)+i ); - sys_gui( x->x_guicommand ); - } - } - -} - -static void sonogram_erase_block(t_sonogram *x, t_glist *glist, t_int bnumber ) -{ - t_canvas *canvas=glist_getcanvas(glist); - t_int fi; - t_float fspectrum=0.0; - char fillColor[ 16 ]; - - for ( fi=0; fix_blocksize/2; fi++) - { - { - int i; - - for ( i=0; ix_zoom; i++ ) - { - strncpy( x->x_gifdata+i*sizeof("#FFFFFF "), "#FFFFFF ", 8 ); - } - SYS_VGUI5("SONIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, - bnumber*x->x_zoom, (x->x_blocksize/2-fi)*x->x_zoom ); - } - } -} - -static void *sonogram_do_update_part(void *tdata) -{ - t_sonogram *x = (t_sonogram*) tdata; - t_int si; - t_int nbpoints = 0; - t_float percentage = 0, opercentage = 0; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - - // loose synchro - usleep( THREAD_SLEEP_TIME ); - - // check boundaries - if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; - if ( x->x_updatestart < 0 ) x->x_updatestart = 0; - - // post("sonogram~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); - - if ( x->x_erase ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_erase_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "sonogram~ : erase part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - percentage = opercentage = nbpoints = 0; - - if ( x->x_redraw ) - { - for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) - { - sonogram_update_block(x, x->x_glist, si); - nbpoints++; - percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); - if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) - { - // post( "sonogram~ : update part : %d %% completed", (int)percentage ); - opercentage = percentage; - } - } - } - - // set borders in black - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); - } - - // post("sonogram~ : child thread %d ended (nb_updated=%d)", (int)x->x_updatechild, x->x_nbupdated ); - x->x_updatechild = 0; - return NULL; -} - -static void sonogram_update_part(t_sonogram *x, t_glist *glist, t_int bstart, t_int bend, - t_int erase, t_int redraw, t_int keepframe) -{ - pthread_attr_t update_child_attr; - pthread_t update_child; - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic ) - { - if ( x->x_updatechild != 0 ) - { - // post( "sonogram~ : error : no update is possible for now" ); - return; - } - x->x_updatestart = bstart; - x->x_updateend = bend; - if ( !keepframe ) - { - x->x_erase = 0; - } - else - { - x->x_erase = erase; - } - x->x_redraw = redraw; - x->x_nbupdated = 0; - // recreate the square if needed - if ( ( bstart == 0 ) && ( bend == x->x_size-1 ) && !keepframe ) - { - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", canvas, x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - glist_getcanvas(glist), x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete ISONIMAGE%x\n", canvas, x ); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", canvas, x ); - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - canvas, x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - SYS_VGUI3(".x%x.c delete IFAZIMAGE%x\n", canvas, x ); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } - // set borders in red - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #FF0000\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #FF0000\n", canvas, x); - } - - // launch update thread - if ( pthread_attr_init( &update_child_attr ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_init" ); - return; - } - if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_attr_setdetachstate" ); - return; - } - if ( pthread_create( &x->x_updatechild, &update_child_attr, sonogram_do_update_part, x ) < 0 ) { - post( "sonogram~ : could not launch update thread" ); - perror( "pthread_create" ); - return; - } - else - { - // post( "sonogram~ : drawing thread %d launched", (int)x->x_updatechild ); - } - } -} - - /* paste selection at the drawing point */ -static void sonogram_paste( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si=0,fi=0; - t_float *icopy; - t_float *rcopy; - t_int copynd; - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - // post ( "sonogram~ : si : %d : fi : %d : copynd : %d", si, fi, copynd ); - if ( pystart+fi-cys >= x->x_blocksize/2 ) break; - *(x->x_rudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - *(x->x_iudata+((si-cxs)*x->x_blocksize)+(fi-cys)) = *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)); - if ( x->x_enhancemode ) - { - // save data for undo - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += *(icopy+copynd); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(rcopy+copynd); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = *(icopy+copynd); - } - copynd++; - } - } - - x->x_uxs = pxstart; - x->x_uxe = pxstart+(si-1)-cxs; - x->x_uys = pystart; - x->x_uye = pystart+(fi-1)-cys;; - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); -} - - /* paste phase at the drawing point */ -static void sonogram_paste_phase( t_sonogram* x) -{ - t_int pxstart = (x->x_xdraw-x->x_xpos)/x->x_zoom; - t_int pystart = (x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - t_int cxs,cxe,cys,cye,si,fi; - t_float fspectrum, fdestspectrum; - t_float fphase, fdestphase; - t_float *icopy; - t_float *rcopy; - t_int copynd; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - cxs=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - cxe=(x->x_xendcapture-x->x_xpos)/x->x_zoom; - cys=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - cye=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; - if ( cye < 0 ) cye=0; - if ( cys < 0 ) cys=0; - if ( cye >= x->x_blocksize/2 ) cye=x->x_blocksize/2-1; - if ( cys >= x->x_blocksize/2 ) cys=x->x_blocksize/2-1; - if ( cxe >= x->x_size ) cxe=x->x_size-1; - if ( cxs >= x->x_size ) cxs=x->x_size-1; - - // make a copy first - icopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - rcopy = ( t_float* ) getbytes( ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - if ( !icopy || !rcopy ) - { - post( "sonogram~ : cannot allocate buffers for pasting" ); - return; - } - // copy initial data - copynd = 0; - for ( si=cxs; si<=cxe; si++) { - for ( fi=cys; fi<=cye; fi++) { - *(rcopy+copynd) = *(x->x_rdata+(si)*x->x_blocksize+fi); - *(icopy+copynd) = *(x->x_idata+(si)*x->x_blocksize+fi); - copynd++; - } - } - - post( "sonogram~ : paste phase from [%d,%d,%d,%d] to [%d,%d]", cxs, cys, cxe, cye, pxstart, pystart ); - - for ( si=cxs; si<=cxe; si++) { - if ( pxstart+si-cxs >= x->x_size ) break; - copynd = (si-cxs)*(cye-cys+1); - for ( fi=cys; fi<=cye; fi++) { - if ( pystart+fi-cys > x->x_blocksize+1 ) break; - fphase = atan2( *(icopy+copynd), *(rcopy+copynd) ); - fdestspectrum = - sqrt( pow( *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) + - pow( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), 2) ); - fdestphase = atan2( *(x->x_idata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)), - *(x->x_rdata+(pxstart+si-cxs)*x->x_blocksize+(pystart+fi-cys)) ); - if ( x->x_enhancemode ) - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*cos( fdestphase + fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) += - fdestspectrum*sin( fdestphase + fphase ); - } - else - { - *(x->x_rdata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*cos( fphase ); - *(x->x_idata+((pxstart+si-cxs)*x->x_blocksize)+(pystart+fi-cys)) = - fdestspectrum*sin( fphase ); - } - copynd++; - } - } - - freebytes( rcopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - freebytes( icopy, ( cxe-cxs+1 )*( cye-cys+1 )*sizeof( t_float ) ); - - sonogram_update_part(x, x->x_glist, pxstart, pxstart+(si-1)-cxs, 0, 1, 1); - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); - x->x_xstartcapture = x->x_xdraw; - x->x_ystartcapture = x->x_ydraw; - x->x_xendcapture = x->x_xdraw; - x->x_yendcapture = x->x_ydraw; - -} - -static void sonogram_draw_new(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - x->x_xpos=text_xpix(&x->x_obj, glist); - x->x_ypos=text_ypix(&x->x_obj, glist); - if ( x->x_graphic ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xSONOGRAM\n", - canvas, x->x_xpos-1, x->x_ypos-1, - x->x_xpos + x->x_size*x->x_zoom+1, - x->x_ypos + x->x_blocksize/2*x->x_zoom+1, - x); - SYS_VGUI4("image create photo SONIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("SONIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image SONIMAGE%x -tags ISONIMAGE%x\n", - canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)), x, x ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xPHASOGRAM\n", - canvas, x->x_xpos-1, x->x_ypos+x->x_blocksize/2*x->x_zoom+2, - x->x_xpos + x->x_size*x->x_zoom +1, - x->x_ypos + x->x_blocksize*x->x_zoom + 3, - x); - SYS_VGUI4("image create photo FAZIMAGE%x -format gif -width %d -height %d\n", - x, x->x_size*x->x_zoom, x->x_blocksize/2*x->x_zoom ); - SYS_VGUI2("FAZIMAGE%x blank\n", x); - SYS_VGUI6(".x%x.c create image %d %d -image FAZIMAGE%x -tags IFAZIMAGE%x\n", - canvas, x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2, x, x ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_delete(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( glist ) ) - { - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", canvas, x); - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", canvas, x); - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", canvas, x); - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", canvas, x); - SYS_VGUI3(".x%x.c delete %xSONOGRAM\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xPHASOGRAM\n", canvas, x ); - SYS_VGUI3(".x%x.c delete %xISONIMAGE\n", canvas, x ); - SYS_VGUI2("image delete SONIMAGE%x\n", x ); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c delete %xIFAZIMAGE\n", canvas, x ); - SYS_VGUI2("image delete FAZIMAGE%x\n", x ); - } - } -} - -static void sonogram_draw_move(t_sonogram *x, t_glist *glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI7(".x%x.c coords %xSONOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos-1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize/2*x->x_zoom+1); - SYS_VGUI5(".x%x.c coords ISONIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - (x->x_ypos+((x->x_blocksize/2*x->x_zoom)/2)) ); - if ( x->x_phaso ) - { - SYS_VGUI7(".x%x.c coords %xPHASOGRAM %d %d %d %d\n", - canvas, x, - x->x_xpos-1, x->x_ypos+(x->x_blocksize/2*x->x_zoom)+1, - x->x_xpos+x->x_size*x->x_zoom+1, - x->x_ypos+x->x_blocksize*x->x_zoom+3); - SYS_VGUI5(".x%x.c coords IFAZIMAGE%x %d %d\n", - canvas, x, - x->x_xpos+((x->x_size*x->x_zoom)/2), - x->x_ypos+3*((x->x_blocksize/2*x->x_zoom)/2)+2 ); - } - canvas_fixlinesfor( canvas, (t_text*)x ); - } -} - -static void sonogram_draw_select(t_sonogram* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); - - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - if(x->x_selected) - { - /* sets the item in blue */ - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #0000FF\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #0000FF\n", canvas, x); - } - } - else - { - SYS_VGUI3(".x%x.c itemconfigure %xSONOGRAM -outline #000000\n", canvas, x); - if ( x->x_phaso ) - { - SYS_VGUI3(".x%x.c itemconfigure %xPHASOGRAM -outline #000000\n", canvas, x); - } - } - } -} - -/* ------------------------ widget callbacks ----------------------------- */ - - -static void sonogram_getrect(t_gobj *z, t_glist *owner, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_sonogram* x = (t_sonogram*)z; - - *xp1 = x->x_xpos; - *yp1 = x->x_ypos; - if ( !x->x_phaso ) - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize/2*x->x_zoom+1; - } - else - { - *xp2 = x->x_xpos+x->x_size*x->x_zoom; - *yp2 = x->x_ypos+x->x_blocksize*x->x_zoom+3; - } -} - -static void sonogram_save(t_gobj *z, t_binbuf *b) -{ - t_sonogram *x = (t_sonogram *)z; - - binbuf_addv(b, "ssiisiii", gensym("#X"),gensym("obj"), - (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, - atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), - x->x_size, x->x_graphic, x->x_phaso ); - binbuf_addv(b, ";"); -} - -static void sonogram_select(t_gobj *z, t_glist *glist, int selected) -{ - t_sonogram *x = (t_sonogram *)z; - - x->x_selected = selected; - sonogram_draw_select( x, glist ); -} - -static void sonogram_vis(t_gobj *z, t_glist *glist, int vis) -{ - t_sonogram *x = (t_sonogram *)z; - t_rtext *y; - - if (vis) - { - sonogram_draw_new( x, glist ); - } - else - { - // erase all points - sonogram_draw_delete( x, glist ); - } -} - -static void sonogram_delete(t_gobj *z, t_glist *glist) -{ - canvas_deletelinesfor(glist, (t_text *)z); -} - -static void sonogram_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_sonogram *x = (t_sonogram *)z; - int xold = x->x_xpos; - int yold = x->x_ypos; - - x->x_xpos += dx; - x->x_ypos += dy; - - if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) - { - sonogram_draw_move( x, glist ); - } - -} - -static void sonogram_modify_point( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - if ( alted ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = 0; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) *= x->x_modstep; - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - *(x->x_idata+(sample*x->x_blocksize)+frequency) += x->x_modstep; - } - } -} - -static void sonogram_modify_point_phase( t_sonogram* x, t_int sample, t_int frequency, t_int alted ) -{ - t_float fspectrum; - t_float fphase; - - fspectrum = - sqrt( pow( *(x->x_rdata+sample*x->x_blocksize+frequency), 2) + - pow( *(x->x_idata+sample*x->x_blocksize+frequency), 2) ); - fphase = atan2( *(x->x_idata+sample*x->x_blocksize+frequency), - *(x->x_rdata+sample*x->x_blocksize+frequency) ); - if ( alted==4 ) - { - // setting phase to 0 - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum; - *(x->x_idata+(sample*x->x_blocksize)+frequency) = 0; - } - else - { - if ( x->x_enhancemode ) - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase*x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase*x->x_modstep ); - } - else - { - *(x->x_rdata+(sample*x->x_blocksize)+frequency) = fspectrum*cos( fphase+x->x_modstep ); - *(x->x_idata+(sample*x->x_blocksize)+frequency) = fspectrum*sin( fphase+x->x_modstep ); - } - } -} - -static void sonogram_motion(t_sonogram *x, t_floatarg dx, t_floatarg dy) -{ - t_int fdraw=0, sdraw=0; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - // post( "sonogram_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); - if ( ( x->x_shifted || (x->x_alted==4) ) ) - { - if ( (x->x_xdraw+dx) >= x->x_xpos && - (x->x_xdraw+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xdraw += dx; - } - if ( (x->x_ydraw+dy) >= x->x_ypos && - (x->x_ydraw+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_ydraw += dy; - } - sdraw=(x->x_xdraw-x->x_xpos)/x->x_zoom; - if ( x->x_ydraw <= x->x_ypos+x->x_blocksize/2*x->x_zoom ) - { - fdraw=(x->x_ypos-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify point @ [%d, %d] alted=%d", sdraw, fdraw, x->x_alted ); - sonogram_modify_point( x, sdraw, fdraw, x->x_alted ); - } - if ( x->x_ydraw >= x->x_ypos+x->x_blocksize/2*x->x_zoom+1 ) - { - fdraw=(x->x_ypos+x->x_blocksize*x->x_zoom/2+1-x->x_ydraw)/x->x_zoom+x->x_blocksize/2; - // post( "modify phase @ [%d, %d]", sdraw, fdraw ); - sonogram_modify_point_phase( x, sdraw, fdraw, x->x_alted ); - } - sonogram_update_point( x, x->x_glist, sdraw, fdraw ); - } - else - { - if ( (x->x_xendcapture+dx) >= x->x_xpos && - (x->x_xendcapture+dx) <= x->x_xpos+x->x_size*x->x_zoom ) { - x->x_xendcapture += dx; - } - if ( (x->x_yendcapture+dy) >= x->x_ypos && - (x->x_yendcapture+dy) <= x->x_ypos+x->x_blocksize*x->x_zoom ) { - x->x_yendcapture += dy; - } - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); - SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #0000FF -tags %xCAPTURE\n", - canvas, x->x_xstartcapture, x->x_ystartcapture, x->x_xendcapture, x->x_yendcapture, x ); - } -} - -static int sonogram_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_sonogram* x = (t_sonogram *)z; - t_int si,fi; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - - // post( "sonogram_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); - if ( x->x_aftermousedown == 1 && doit == 0) - { - x->x_aftermousedown = 1; - } - else - { - x->x_aftermousedown = 0; - } - if ( doit ) - { - x->x_xdraw = xpix; - x->x_ydraw = ypix; - x->x_shifted = shift; - x->x_alted = alt; - // activate motion callback - glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)sonogram_motion, - 0, xpix, ypix ); - - if ( shift && alt && (x->x_xstartcapture != x->x_xendcapture ) ) - { - sonogram_paste(x); - sonogram_paste_phase(x); - } - else if ( shift && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // add or multiply modstep - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - // post( "modified y from %d to %d", (x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2, - // (x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2 ); - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - else if ( (alt==4) && (x->x_xstartcapture != x->x_xendcapture ) ) - { - // clean up area - if ( x->x_xstartcapture > x->x_xendcapture ) { - fi = x->x_xstartcapture; - x->x_xstartcapture = x->x_xendcapture; - x->x_xendcapture = fi; - } - if ( x->x_ystartcapture > x->x_yendcapture ) { - fi = x->x_ystartcapture; - x->x_ystartcapture = x->x_yendcapture; - x->x_yendcapture = fi; - } - for ( si=(x->x_xstartcapture-x->x_xpos)/x->x_zoom; - si<=(x->x_xendcapture-x->x_xpos)/x->x_zoom; si++) { - for ( fi=(x->x_ypos-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point( x, si, fi, alt ); - } - for ( fi=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_yendcapture)/x->x_zoom+x->x_blocksize/2; - fi<=(x->x_ypos+x->x_blocksize/2*x->x_zoom+1-x->x_ystartcapture)/x->x_zoom+x->x_blocksize/2; fi++) { - sonogram_modify_point_phase( x, si, fi, alt ); - } - } - sonogram_update_part(x, x->x_glist, (x->x_xstartcapture-x->x_xpos)/x->x_zoom, - (x->x_xendcapture-x->x_xpos)/x->x_zoom, 0, 1, 1); - } - // start a new capture - SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", canvas, x ); - x->x_xstartcapture = xpix; - x->x_ystartcapture = ypix; - x->x_xendcapture = xpix; - x->x_yendcapture = ypix; - } - else - { - // nothing - } - x->x_aftermousedown = doit; - return (1); -} - - /* clean up */ -static void sonogram_free(t_sonogram *x) -{ - if ( x->x_rdata != NULL ) { - freebytes(x->x_rdata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_idata != NULL ) { - freebytes(x->x_idata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_rudata != NULL ) { - freebytes(x->x_rudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_rdata = NULL; - } - if ( x->x_iudata != NULL ) { - freebytes(x->x_iudata, x->x_size*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - x->x_idata = NULL; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } -} - - /* allocate tables for storing ffts */ -static t_int sonogram_allocate(t_sonogram *x) -{ - t_int fi; - - if ( !(x->x_rdata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_multfreq = getbytes( x->x_blocksize*sizeof(t_int) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_blocksize*sizeof(t_int) ); - } - for ( fi=0; fix_blocksize; fi++ ) - { - *(x->x_multfreq+fi)=1; - } - // no undo is available - x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; - if ( !(x->x_rudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_iudata = getbytes( x->x_size*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", x->x_size*x->x_blocksize*sizeof(float) ); - } - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - - return 0; -} - - /* reallocate tables for storing ffts */ -static t_int sonogram_reallocate(t_sonogram *x, t_int ioldsize, t_int inewsize) -{ - t_int fi; - t_float *prdata=x->x_rdata, *pidata=x->x_idata; - t_float *prudata=x->x_rudata, *piudata=x->x_iudata; - - if ( !(x->x_rdata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_idata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - // no undo is available - x->x_uxs = x->x_uxe = x->x_uys = x->x_uye = -1; - if ( !(x->x_rudata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - if ( !(x->x_iudata = getbytes( inewsize*x->x_blocksize*sizeof(float) ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return -1; - } else { - post( "sonogram~ : allocated %d bytes", inewsize*x->x_blocksize*sizeof(float) ); - } - if ( prdata != NULL ) { - freebytes(prdata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - if ( pidata != NULL ) { - freebytes(pidata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - if ( prudata != NULL ) { - freebytes(prudata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - if ( piudata != NULL ) { - freebytes(piudata, ioldsize*x->x_blocksize*sizeof(float) ); - post( "Freed %d bytes", ioldsize*x->x_blocksize*sizeof(float) ); - } - - return 0; -} - /* records or playback the sonogram */ -static t_int *sonogram_perform(t_int *w) -{ - t_float *rin = (t_float *)(w[1]); - t_float *iin = (t_float *)(w[2]); - t_float *rout = (t_float *)(w[3]); - t_float *iout = (t_float *)(w[4]); - t_float fspectrum = 0.0; - t_float fphase = 0.0; - t_int is; - t_int n = (int)(w[5]); /* number of samples */ - t_sonogram *x = (t_sonogram *)(w[6]); - t_int bi; - t_int startsamp, endsamp; - - if ( x->x_readstart <= x->x_readend ) - { - startsamp = (x->x_readstart*x->x_size)/100; - endsamp = (x->x_readend*x->x_size)/100; - } - else - { - startsamp = (x->x_readend*x->x_size)/100; - endsamp = (x->x_readstart*x->x_size)/100; - } - - // reallocate tables if blocksize has been changed - if ( n != x->x_blocksize && x->x_updatechild == 0 ) { - post( "sonogram~ : reallocating tables" ); - // erase all points - sonogram_free(x); - x->x_blocksize = n; - sonogram_allocate(x); - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, 0, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); - } - - bi = 0; - while (bix_record) { - *(x->x_rdata+(x->x_writepos*x->x_blocksize)+bi)=(*(rin))*(*(x->x_multfreq+bi)); - *(x->x_idata+(x->x_writepos*x->x_blocksize)+bi)=(*(iin))*(*(x->x_multfreq+bi)); - } - // set outputs - *rout = 0.0; - *iout = 0.0; - if ( x->x_play) { - is=0; - fspectrum = - sqrt( pow( *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) + - pow( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), 2) ); - fphase = atan2( *(x->x_idata+(((int)x->x_readpos+is)*x->x_blocksize)+bi), - *(x->x_rdata+(((int)x->x_readpos+is)*x->x_blocksize)+bi) ); - fphase += (x->x_phase/180.0)*(M_PI); - *rout += fspectrum*cos( fphase ); - *iout += fspectrum*sin( fphase ); - } - rout++;iout++; - rin++;iin++; - bi++; - - } - // reset playing position until next play - if ( x->x_play ) { - x->x_readpos+=x->x_readspeed; - // post( "xreadpos : %f (added %f) %d", x->x_readpos, x->x_readspeed, x->x_readend ); - if ( ( x->x_readspeed >= 0 ) && ( x->x_readpos >= endsamp ) ) { - x->x_play=0; - x->x_readpos=(float)(startsamp); - // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - if ( ( x->x_readspeed < 0 ) && ( x->x_readpos <= startsamp ) ) { - x->x_play=0; - x->x_readpos = (float)(endsamp); - // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); - outlet_bang(x->x_end); - } - } - // reset recording position until next record - if ( x->x_record ) { - x->x_writepos++; - if ( x->x_writepos >= x->x_size ) { - x->x_record=0; - x->x_writepos=0; - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 0); - outlet_bang(x->x_recend); - if ( x->x_empty ) x->x_empty = 0; - // post( "sonogram~ : stopped recording" ); - } - } - // post( "sonogram~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); - return (w+7); -} - -static void sonogram_dsp(t_sonogram *x, t_signal **sp) -{ - dsp_add(sonogram_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); -} - - /* record the sonogram */ -static void sonogram_record(t_sonogram *x) -{ - x->x_record=1; - x->x_writepos=0; - // post( "sonogram~ : recording on" ); -} - - /* play the sonogram */ -static void sonogram_play(t_sonogram *x) -{ - x->x_play=1; - x->x_readpos=(x->x_readstart*x->x_size)/100; - // post( "sonogram~ : playing on" ); -} - - /* setting the starting point for reading ( in percent ) */ -static void sonogram_readstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - x->x_readstart=startpoint; - // set readspeed sign - if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADSTART\n", - canvas, x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADSTART -width 3\n", - canvas, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the starting point for modification ( in percent ) */ -static void sonogram_modstart(t_sonogram *x, t_floatarg fstart) -{ - t_float startpoint = fstart; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (startpoint < 0) startpoint = 0; - if (startpoint > 100) startpoint = 100; - if ( startpoint > x->x_modend ) { - x->x_modstart = x->x_modend; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modstart=startpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODSTART\n", - canvas, x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODSTART -width 3\n", - canvas, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modstart*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the modification step for graphical mode */ -static void sonogram_modstep(t_sonogram *x, t_floatarg fmodstep) -{ - if ( x->x_graphic ) - { - x->x_modstep = fmodstep; - } -} - - /* setting enhance mode */ -static void sonogram_enhancemode(t_sonogram *x, t_floatarg fenhancemode) -{ - if ( x->x_graphic ) - { - x->x_enhancemode = fenhancemode; - } -} - - /* setting the ending point for reading ( in percent ) */ -static void sonogram_readend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - x->x_readend=endpoint; - // set readspeed sign - if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xREADEND\n", - canvas, x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #FF0000 -tags %xREADEND -width 3\n", - canvas, x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_readend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* setting the ending point for modification ( in percent ) */ -static void sonogram_modend(t_sonogram *x, t_floatarg fend) -{ - t_float endpoint = fend; - t_canvas *canvas=glist_getcanvas(x->x_glist); - - if (endpoint < 0) endpoint = 0; - if (endpoint > 100) endpoint = 100; - if ( endpoint < x->x_modstart ) { - x->x_modend = x->x_modstart; - post( "sonogram~ : warning : range for modifications is null" ); - } else { - x->x_modend=endpoint; - } - if ( x->x_graphic && glist_isvisible( x->x_glist ) ) - { - SYS_VGUI3( ".x%x.c delete line %xMODEND\n", - canvas, x); - SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #11E834 -tags %xMODEND -width 3\n", - canvas, x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos, x->x_xpos+(x->x_modend*(x->x_size)/100 ), - x->x_ypos+x->x_blocksize*x->x_zoom, x ); - } -} - - /* sets the reading speed */ -static void sonogram_readspeed(t_sonogram *x, t_floatarg freadspeed) -{ - if (freadspeed <= 0 ) { - post( "sonogram~ : wrong readspeed argument" ); - return; - } - x->x_readspeed=freadspeed; -} - - /* enhance frequencies */ -static void sonogram_enhance(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fenhance, t_floatarg fnoupdate ) -{ - t_int samplestart, sampleend, si, fi=0, ffi=0; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - if ( fenhance < 0 ) { - post( "sonogram~ : error : wrong multiplicating factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - *(x->x_multfreq+fi) = fenhance; - if ( (fi != 0) && (fi != x->x_blocksize/2-1) ) - { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) *= fenhance; - *(x->x_idata+(si*x->x_blocksize)+fi) *= fenhance; - } - } - } - // post( "sonogram~ : enhanced %d,%d", fi, ffi ); - if ( !(int)fnoupdate ) - { - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); - } -} - - /* add a constant to frequencies */ -static void sonogram_add(t_sonogram *x, t_floatarg fstartfreq, t_floatarg fendfreq, t_floatarg fadd) -{ - t_int samplestart, sampleend, si, fi; - t_float oldenergy; - - if (fstartfreq < 0 || fendfreq < 0 || - fstartfreq > x->x_blocksize || fendfreq > x->x_blocksize || - fstartfreq > fendfreq ) { - post( "sonogram~ : error : wrong frequencies range" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - // post("enhancing portion [%d,%d]", samplestart, sampleend ); - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=(int)fstartfreq; fi<=(int)fendfreq; fi++ ) { - /* multiply both r*sin(a) and r*cos(a) to mutiply r */ - *(x->x_rdata+(si*x->x_blocksize)+fi) += fadd; - *(x->x_idata+(si*x->x_blocksize)+fi) += fadd; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* resize sonogram */ -static void sonogram_resize(t_sonogram *x, t_floatarg fnewsize ) -{ - if (fnewsize <= 0) { - post( "sonogram~ : error : wrong size" ); - return; - } - if (x->x_updatechild > 0) { - post( "sonogram~ : can't resize now, an update is pending." ); - return; - } - post( "sonogram~ : reallocating tables" ); - x->x_record=0; - x->x_play=0; - sonogram_reallocate(x, x->x_size, fnewsize); - x->x_size = fnewsize; - // erase all points, as data is zero no drawing is needed - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 0, 0); -} - - /* set zoom factor */ -static void sonogram_zoom(t_sonogram *x, t_floatarg fzoom ) -{ - post( "sonogram~: warning : zoom and big block factors might lead to a crash" ); - if (fzoom < 1) { - post( "sonogram~ : error : wrong zoom factor" ); - return; - } - if ( x->x_gifdata != NULL ) { - freebytes(x->x_gifdata, (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_gifdata = NULL; - } - if ( x->x_guicommand != NULL ) { - freebytes(x->x_guicommand, 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - post( "Freed %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - x->x_guicommand = NULL; - } - x->x_zoom = (int)fzoom; - if ( !( x->x_gifdata = ( char* ) getbytes( (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", (x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - if ( !( x->x_guicommand = ( char* ) getbytes( 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { - post( "sonogram~ : error : could not allocate buffers" ); - return; - } else { - post( "sonogram~ : allocated %d bytes", 128+(x->x_blocksize/2)*x->x_zoom*sizeof("#FFFFFF ") ); - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, !x->x_empty, !x->x_empty, 0); - canvas_fixlinesfor(x->x_glist, (t_text*)x ); -} - - /* refresh data */ -static void sonogram_refresh(t_sonogram *x) -{ - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* flip frequencies */ -static void sonogram_flipfreqs(t_sonogram *x) -{ - t_int samplestart, sampleend, si, fi; - t_float fvalue; - t_int ioperon; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - ioperon=x->x_blocksize/2; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fi<=ioperon/2; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_rdata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - fvalue = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)); - *(x->x_idata+(si*x->x_blocksize)+(ioperon-fi-1)) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* flip blocks */ -static void sonogram_flipblocks(t_sonogram *x) -{ - t_int samplestart, sampleend, middlesample, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - middlesample = ( sampleend+samplestart+1 ) / 2; - for ( si=samplestart; si<=middlesample; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+((si)*x->x_blocksize)+fi); - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_rdata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - fvalue = *(x->x_idata+((si)*x->x_blocksize)+fi); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi); - *(x->x_idata+((sampleend+samplestart-si)*x->x_blocksize)+fi) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* undo if available */ -static void sonogram_undo(t_sonogram *x) -{ - t_int si,fi; - - if ( x->x_uxs == -1 ) - { - post( "sonogram~ : nothing to undo, man" ); - return; - } - - post( "sonogram~ : restoring region [%d,%d,%d,%d]", x->x_uxs, x->x_uys, x->x_uxe, x->x_uye ); - for ( si=x->x_uxs; si<=x->x_uxe; si++ ) { - for ( fi=x->x_uys; fi<=x->x_uye; fi++ ) { - *(x->x_rdata+((si)*x->x_blocksize)+fi) = *(x->x_rudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - *(x->x_idata+((si)*x->x_blocksize)+fi) = *(x->x_iudata+(si-x->x_uxs)*x->x_blocksize+(fi-x->x_uys)); - } - } - sonogram_update_part(x, x->x_glist, x->x_uxs, x->x_uxe, 0, 1, 1); -} - - /* zswap exchanges real and imaginery part */ -static void sonogram_zswap(t_sonogram *x) -{ - t_int samplestart, sampleend, fi, si; - t_float fvalue; - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - for ( si=samplestart; si<=sampleend; si++ ) { - for ( fi=0; fix_blocksize; fi++ ) { - fvalue = *(x->x_rdata+(si*x->x_blocksize)+fi); - *(x->x_rdata+(si*x->x_blocksize)+fi) = *(x->x_idata+(si*x->x_blocksize)+fi); - *(x->x_idata+(si*x->x_blocksize)+fi) = fvalue; - } - } -} - - /* swap points */ -static void sonogram_swappoints(t_sonogram *x, t_floatarg fnbpoints) -{ - t_int samplestart, sampleend, sp; - t_float s1, s2, f1, f2; - t_float fvalue; - - if (fnbpoints <= 0) { - post( "sonogram~ : error : bad number of points" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=0; spx_blocksize/2-1 ); - f2 = random()%( x->x_blocksize/2-1 ); - fvalue = *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_rdata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_rdata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - fvalue = *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1); - *(x->x_idata+((int)s1*x->x_blocksize)+(int)f1) = *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2); - *(x->x_idata+((int)s2*x->x_blocksize)+(int)f2) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* average blocks according to a factor */ -static void sonogram_average(t_sonogram *x, t_floatarg fnbblocks) -{ - t_int samplestart, sampleend, fi, si, ssi; - t_float fraverage, fiaverage; - - if (fnbblocks < 1) { - post( "sonogram~ : error : bad average factor" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - fraverage=fiaverage=0.0; - for ( fi=0; fix_blocksize; fi++ ) { - for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) { - fraverage=fiaverage=0.0; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi); - fiaverage += *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi); - } - fraverage /= fnbblocks; - fiaverage /= fnbblocks; - for ( ssi=0; ssix_rdata+((int)(si+ssi)*x->x_blocksize)+fi)=fraverage; - *(x->x_idata+((int)(si+ssi)*x->x_blocksize)+fi)=fiaverage; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* go up by the given number */ -static void sonogram_goup(t_sonogram *x, t_floatarg fgoup) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgoup <= 0 || fgoup > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in goup function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=(x->x_blocksize/2)-fgoup-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgoup)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* roll up by the given number */ -static void sonogram_roll(t_sonogram *x, t_floatarg froll) -{ - t_int samplestart, sampleend, sp, sf; - t_float *fprvalues; - t_float *fpivalues; - - if (froll <= 0 || froll > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in roll function" ); - return; - } - fprvalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fprvalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - fpivalues = (t_float*)getbytes( ((int)froll)*sizeof( float ) ); - if ( !fpivalues ) { - post( "sonogram~ : error : could not allocate %d bytes", ((int)froll)*sizeof(float) ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - - // saving values - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - *(fpivalues+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(x->x_blocksize/2-(int)froll+sf)); - } - for (sf=(x->x_blocksize/2)-froll-1; sf>=0; sf-- ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_rdata+((int)sp*x->x_blocksize)+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)froll)) = - *(x->x_idata+((int)sp*x->x_blocksize)+sf); - } - for (sf=0; sfx_rdata+((int)sp*x->x_blocksize)+(int)sf) = *(fprvalues+sf); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = *(fpivalues+sf); - } - } - freebytes( fprvalues, (int)froll*sizeof(float) ); - freebytes( fpivalues, (int)froll*sizeof(float) ); - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* suppress point below the threshold */ -static void sonogram_threshold(t_sonogram *x, t_floatarg fthreshold) -{ - t_int samplestart, sampleend, sp, sf; - t_float fspectrum; - - if (fthreshold <= 0) { - post( "sonogram~ : error : wrong threshold" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-1; sf++ ) { - fspectrum = sqrt( pow( *(x->x_rdata+sp*x->x_blocksize+sf), 2) + - pow( *(x->x_idata+sp*x->x_blocksize+sf), 2) ); - if ( fspectrum < fthreshold ) - { - *(x->x_rdata+sp*x->x_blocksize+sf) = 0.0; - *(x->x_idata+sp*x->x_blocksize+sf) = 0.0; - } - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* change the phase */ -static void sonogram_phase(t_sonogram *x, t_floatarg fincphase) -{ - if (fincphase < 0 || fincphase > 90) { - post( "sonogram~ : error : wrong phase in phase function : out of [0,90]" ); - return; - } - x->x_phase = fincphase; -} - - /* go down by the given number */ -static void sonogram_godown(t_sonogram *x, t_floatarg fgodown) -{ - t_int samplestart, sampleend, sp, sf; - - if (fgodown <= 0 || fgodown > x->x_blocksize/2) { - post( "sonogram~ : error : wrong offset in godown function" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - for (sf=0; sf<=(x->x_blocksize/2)-fgodown-1; sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+sf) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - *(x->x_idata+((int)sp*x->x_blocksize)+sf) = - *(x->x_idata+((int)sp*x->x_blocksize)+(sf+(int)fgodown)); - } - for (sf=(x->x_blocksize/2)-fgodown; sf<(x->x_blocksize/2); sf++ ) { - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - *(x->x_idata+((int)sp*x->x_blocksize)+(int)sf) = 0.0; - } - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - - /* swap blocks */ -static void sonogram_swapblocks(t_sonogram *x, t_floatarg fperstart, t_floatarg fperend, t_floatarg fpersize) -{ - t_int samplestart, samplestartb, samplesize, sp, sf; - t_int iperstart, iperend, ipersize; - t_float s1, s2; - t_float fvalue; - - iperstart = fperstart; - iperend = fperend; - ipersize = fpersize; - - if (iperstart < 0 || iperstart > iperend || - iperend <= 0 || iperend+ipersize > 100 || - ipersize < 0 || fpersize > 100 ) { - post( "sonogram~ : error : wrong interval [%d%%, %d%%] <-> [%d%%, %d%%]", - iperstart, iperstart+ipersize, iperend, iperend+ipersize ); - return; - } - - samplestart=(x->x_modstart*(x->x_size-1))/100; - samplestartb=(x->x_modend*(x->x_size-1))/100; - samplesize=((samplestartb-samplestart)*ipersize)/100; - samplestart=samplestart+((samplestartb-samplestart)*iperstart)/100; - samplestartb=samplestart+((samplestartb-samplestart)*iperend)/100; - - post( "swap blocks [%d,%d] and [%d,%d]", samplestart, samplestart+samplesize, samplestartb, samplestartb+samplesize ); - - for ( sp=samplesize; sp>=0; sp-- ) { - for ( sf=0; sfx_blocksize; sf++) { - fvalue = *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_rdata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - fvalue = *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestart+sp)*x->x_blocksize)+sf) = *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf); - *(x->x_idata+((int)(samplestartb+sp)*x->x_blocksize)+sf) = fvalue; - } - } - sonogram_update_part(x, x->x_glist, 0, x->x_size-1, 0, 1, 1); -} - - /* swap frequencies */ -static void sonogram_swapfreqs(t_sonogram *x, t_floatarg ffirstfreq, t_floatarg fsecondfreq) -{ - t_int samplestart, sampleend, sp; - t_float fvalue; - - if (ffirstfreq < 0 || fsecondfreq <0) { - post( "sonogram~ : error : wrong frequencies" ); - return; - } - samplestart=(x->x_modstart*(x->x_size-1))/100; - sampleend=(x->x_modend*(x->x_size-1))/100; - - for ( sp=samplestart; sp<=sampleend; sp++ ) { - fvalue = *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_rdata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - fvalue = *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)ffirstfreq) = - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq); - *(x->x_idata+((int)sp*x->x_blocksize)+(int)fsecondfreq) = fvalue; - } - sonogram_update_part(x, x->x_glist, samplestart, sampleend, 0, 1, 1); -} - -static void *sonogram_new(t_floatarg fsize, t_floatarg fgraphic, t_floatarg fphaso) -{ - t_sonogram *x = (t_sonogram *)pd_new(sonogram_class); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - x->x_recend = outlet_new(&x->x_obj, &s_bang ); - x->x_end = outlet_new(&x->x_obj, &s_bang ); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modstart")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("modend")); - - if ( fsize <= 0 || ( fgraphic != 0 && fgraphic != 1 ) || ( fphaso != 0 && fphaso != 1 ) ) { - error( "sonogram~ : missing or negative creation arguments" ); - return NULL; - } - - // activate graphical callbacks - if ( fgraphic != 0 ) - { - class_setwidget(sonogram_class, &sonogram_widgetbehavior); - } - x->x_graphic = (int) fgraphic; - x->x_phaso = (int) fphaso; - - x->x_size = fsize; - x->x_blocksize = sys_getblksize(); - x->x_play = 0; - x->x_readspeed = 1.; - x->x_record = 0; - x->x_readpos = 0.; - x->x_writepos = 0; - x->x_modstart = 0; - x->x_readstart = 0; - x->x_modend = 100; - x->x_readend = 100; - x->x_rdata = NULL; - x->x_idata = NULL; - x->x_phase = 0.0; - x->x_empty = 1; - x->x_xpos = -1; - x->x_ypos = -1; - x->x_samplerate = sys_getsr(); - /* graphic data */ - x->x_selected = 0; - x->x_zoom = 1; - x->x_updatechild = 0; - x->x_modstep = 1.1; - x->x_enhancemode = 0; - x->x_glist = (t_glist*)canvas_getcurrent(); - - if ( sonogram_allocate(x) <0 ) { - return NULL; - } else { - return(x); - } - -} - -void sonogram_tilde_setup(void) -{ - post(sonogram_version); - sonogram_class = class_new(gensym("sonogram~"), (t_newmethod)sonogram_new, (t_method)sonogram_free, - sizeof(t_sonogram), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - - - // set callbacks - sonogram_widgetbehavior.w_getrectfn = sonogram_getrect; - sonogram_widgetbehavior.w_displacefn = sonogram_displace; - sonogram_widgetbehavior.w_selectfn = sonogram_select; - sonogram_widgetbehavior.w_activatefn = NULL; - sonogram_widgetbehavior.w_deletefn = sonogram_delete; - sonogram_widgetbehavior.w_visfn = sonogram_vis; - sonogram_widgetbehavior.w_clickfn = sonogram_click; - - -#if PD_MINOR_VERSION >= 37 - class_setpropertiesfn(sonogram_class, NULL); - class_setsavefn(sonogram_class, sonogram_save); -#else - sonogram_widgetbehavior.w_propertiesfn = NULL; - sonogram_widgetbehavior.w_savefn = sonogram_save; -#endif - - CLASS_MAINSIGNALIN( sonogram_class, t_sonogram, x_f ); - class_addmethod(sonogram_class, (t_method)sonogram_dsp, gensym("dsp"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_record, gensym("record"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhance, gensym("enhance"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_add, gensym("add"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_resize, gensym("resize"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zoom, gensym("zoom"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swappoints, gensym("swappoints"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_average, gensym("average"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapblocks, gensym("swapblocks"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_swapfreqs, gensym("swapfreqs"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipfreqs, gensym("flipfreqs"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_flipblocks, gensym("flipblocks"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_play, gensym("play"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_refresh, gensym("refresh"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_enhancemode, gensym("enhancemode"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_goup, gensym("goup"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_godown, gensym("godown"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_roll, gensym("roll"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_threshold, gensym("threshold"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_phase, gensym("phase"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_zswap, gensym("zswap"), A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstep, gensym("modstep"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modstart, gensym("modstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_modend, gensym("modend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readstart, gensym("readstart"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readend, gensym("readend"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); - class_addmethod(sonogram_class, (t_method)sonogram_undo, gensym("undo"), A_NULL); -} diff --git a/sonogram~/sonograph~-help.pd b/sonogram~/sonograph~-help.pd deleted file mode 100644 index 4352c3d..0000000 --- a/sonogram~/sonograph~-help.pd +++ /dev/null @@ -1,10 +0,0 @@ -#N canvas 0 0 450 300 10; -#X obj 134 93 rs-sonograph~; -#X text 193 27 To work properly \, the block size; -#X text 193 39 has to be redefined.; -#X obj 132 130 dac~; -#X msg 291 89 \; pd dsp 1; -#X msg 356 90 \; pd dsp 0; -#X text 193 51 that's why everything is in the subpatch.; -#X connect 0 0 3 0; -#X connect 0 0 3 1; diff --git a/sonograph~-help.pd b/sonograph~-help.pd new file mode 100644 index 0000000..4352c3d --- /dev/null +++ b/sonograph~-help.pd @@ -0,0 +1,10 @@ +#N canvas 0 0 450 300 10; +#X obj 134 93 rs-sonograph~; +#X text 193 27 To work properly \, the block size; +#X text 193 39 has to be redefined.; +#X obj 132 130 dac~; +#X msg 291 89 \; pd dsp 1; +#X msg 356 90 \; pd dsp 0; +#X text 193 51 that's why everything is in the subpatch.; +#X connect 0 0 3 0; +#X connect 0 0 3 1; diff --git a/speexin~.c b/speexin~.c new file mode 100644 index 0000000..eff2601 --- /dev/null +++ b/speexin~.c @@ -0,0 +1,612 @@ +/* ------------------------ speexin~ ------------------------------------------ */ +/* */ +/* Object to receive a speex encoded stream sent by a peer using speexin~. */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates @ http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the Speex voice quality encoding library which can */ +/* be found at http://speex.sourceforge.net. */ +/* */ +/* ---------------------------------------------------------------------------- */ + + +#include +#include + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +#if defined(__APPLE__) || defined(_WIN32) +#define MSG_NOSIGNAL 0 +#define SOL_TCP IPPROTO_TCP +#endif + +#include /* speex decoder stuff */ +#include /* speex decoder stuff */ + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#define MIN_AUDIO_INPUT 1024 // we must a least have 8 chunks to play a correct sound +#define INPUT_BUFFER_SIZE 32768 +#define OUTPUT_BUFFER_SIZE 32768 /* 32k */ +#define BARHEIGHT 10 + +#define SPEEX_NB_MODE 0 /* audio data must be 8kHz */ +#define SPEEX_WB_MODE 1 /* audio data must be 16kHz */ + +//#define DATADEBUG + +typedef void (*t_fdpollfn)(void *ptr, int fd); +extern void sys_rmpollfn(int fd); +extern void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); + +/* time-out used for select() call */ +static struct timeval ztout; + +static char *speexin_version = "speexin~: speex voice quality streamer version 0.2, written by ydegoyon@free.fr"; + +extern void sys_sockerror(char *s); + +void speexin_closesocket(int fd) +{ +#ifdef UNIX + if ( close(fd) < 0 ) + { + perror( "close" ); + } + else + { + post( "speexin~ : closed socket : %d", fd ); + } +#endif +#ifdef NT + closesocket(fd); +#endif + sys_rmpollfn(fd); +} + +int setsocketoptions(int sockfd) +{ + int sockopt = 1; + if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0) + { + post("speexin~ : setsockopt TCP_NODELAY failed"); + perror( "setsockopt" ); + return -1; + } + else + { + post("speexin~ : TCP_NODELAY set"); + } + +#ifdef UNIX + sockopt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) + { + post("speexin~ : setsockopt SO_REUSEADDR failed"); + perror( "setsockopt" ); + return -1; + } + else + { + post("speexin~ : setsockopt SO_REUSEADDR done."); + } +#endif + return 0; +} + + +/* ------------------------ speexin~ ----------------------------- */ + +static t_class *speexin_class; + +typedef struct _speexin +{ + t_object x_obj; + t_int x_socket; + t_outlet *x_connectionip; + t_int x_serversocket; + t_int x_samplerate; + + /* Speex stuff */ + SpeexBits x_bits; /* bits packing structure */ + void *x_decstate; /* decoder state */ + t_int x_framesize; /* frame size */ + t_int x_mode; /* Narrow or Wide Band */ + int x_quality; /* encoding quality ( 0 to 10 ) */ + + t_int x_inpackets; /* number of packets received */ + t_int x_dpacket; /* displayed packet in status bar */ + t_int x_packetsize; /* size of the packets */ + t_int x_pblocks; /* processed blocks */ + t_int x_graphic; /* indicates if we show a graphic bar */ + + void *x_inbuffer; /* accumulation buffer for incoming speex frames */ + t_int x_inwritepos; /* accumulation buffer for incoming speex frames */ + t_int x_encsize; + t_int x_inbuffersize; + + t_float *x_outbuffer; /* buffer to store audio decoded data */ + t_int x_oinp; + t_int x_ooutp; + t_int x_outunread; + t_int x_outbuffersize; + t_float *x_decchunk; + + t_canvas *x_canvas; + + t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ + t_int x_newstream; /* at first, the stream must provide enough data to start */ + +} t_speexin; + +void speexin_tilde_speex_init(t_speexin *x) +{ + int ret; + int pf=1; + + speex_bits_init(&x->x_bits); + + switch ( x->x_mode ) + { + case SPEEX_NB_MODE : + x->x_decstate = speex_decoder_init(&speex_nb_mode); + break; + + case SPEEX_WB_MODE : + x->x_decstate = speex_decoder_init(&speex_wb_mode); + break; + + default : + error( "speexin~ : severe error : decoding scheme is unknown" ); + break; + } + + speex_decoder_ctl(x->x_decstate, SPEEX_GET_FRAME_SIZE, (void*)&x->x_framesize); + + speex_decoder_ctl(x->x_decstate, SPEEX_SET_PF, &pf); + + post( "speexin~ : frame size : %d", x->x_framesize ); + +} + +static void speexin_decode_input(t_speexin *x) +{ + int i; + int alength = 0; + static char out[8192]; + signed short int *p = (signed short int *) out; + int pbytes; + int ret; + int flength = 0; + + if ( x->x_encsize > 0 ) + { + + while ( x->x_encsize > *(char *)(x->x_inbuffer) ) + { + + flength = *(char *)(x->x_inbuffer ); + + // post( "speexin~ : reading bits from 1 to : %d", flength+1 ); + speex_bits_read_from(&x->x_bits, x->x_inbuffer+1, flength); + +#ifdef DATADEBUG + { + t_int si; + + printf( "speexin~ : decoding : " ); + for ( si=0; six_inbuffer+1+si) ); + } + printf( "\n" ); + } +#endif + + { + t_int sp=0, rp=0; + + speex_decode(x->x_decstate, &x->x_bits, x->x_decchunk); + + while( sp < x->x_framesize ) + { + rp=(x->x_oinp+sp)%x->x_outbuffersize; + // if ( rp == x->x_outbuffersize - 1 ) post( "speexin~ : write at the end of audio buffer" ); + // post( "speexin~ : sp=%d : rp=%d", sp, rp ); + x->x_outbuffer[ rp ] = x->x_decchunk[sp++]; + } + x->x_oinp = rp+1; + } + x->x_outunread += x->x_framesize; + memcpy( x->x_inbuffer, x->x_inbuffer+flength+1, x->x_inbuffersize-flength-1 ); + x->x_encsize -= flength+1; + x->x_inwritepos -= flength+1; + + } + + } + + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + /* update graphical read status */ + if ( x->x_inpackets != x->x_dpacket ) + { + char color[32]; + int minpackets = ( MIN_AUDIO_INPUT/x->x_framesize)-2; // audio loop has eaten some already + + + sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); + sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); + if ( x->x_outunread > 0 ) + { + t_int width; + + if ( x->x_inpackets < (MIN_AUDIO_INPUT/x->x_framesize)/2 ) + { + strcpy( color, "red" ); + } + else + { + strcpy( color, "lightgreen" ); + } + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix+(x->x_inpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix - 1, color, x ); + sys_vgui(".x%x.c create line %d %d %d %d -fill red -tags %xTHRESHOLD\n", + x->x_canvas, x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, + x->x_obj.te_ypix-1, x ); + x->x_dpacket = x->x_inpackets; + } + } + + } + +} + +static void speexin_recv(t_speexin *x) +{ + int ret; + + if ( x->x_inwritepos > x->x_inbuffersize - 1024 ) + { + post( "speexin~ : input buffer is full" ); + return; + } + if ( ( ret = recv(x->x_socket, (void*) x->x_inbuffer + x->x_inwritepos, + (size_t)x->x_inbuffersize, + MSG_NOSIGNAL) ) < 0 ) + { + post( "speexin~ : receive error" ); + perror( "recv" ); + return; + } + else + { + // post( "speexin~ : received %d bytes at %d on %d ( up to %d)", + // ret, x->x_inwritepos, x->x_socket, + // x->x_inbuffersize ); + + if ( ret == 0 ) + { + post( "speexin~ : closing connection ( s=%d )", x->x_socket ); + speexin_closesocket(x->x_socket); + x->x_socket = -1; + sys_vgui(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); + sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); + sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); + outlet_symbol( x->x_connectionip, gensym("") ); + } + else + { + x->x_inpackets++; + } + + x->x_encsize += ret; + x->x_inwritepos += ret; + + speexin_decode_input(x); + } +} + +static void speexin_acceptconnection(t_speexin *x) +{ + struct sockaddr_in incomer_address; + int sockaddrl = (int) sizeof( struct sockaddr ); + + int fd = accept(x->x_serversocket, (struct sockaddr*)&incomer_address, &sockaddrl ); + post("speexin~: accepted incomer : %d.", fd ); + + if (fd < 0) { + post("speexin~: accept failed"); + return; + } + + if (x->x_socket > 0) { + post("speexin~: the source has changed to %s ( new socket = %d ).", + inet_ntoa( incomer_address.sin_addr ), fd ); + speexin_closesocket(x->x_socket); + } + + x->x_socket = fd; + sys_addpollfn(x->x_socket, (t_fdpollfn)speexin_recv, x); + outlet_symbol( x->x_connectionip, gensym( inet_ntoa( incomer_address.sin_addr) ) ); + + if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) + { + t_int width; + + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", + x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, + x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); + } + x->x_stream = 0; + x->x_newstream = 1; + +} + + +static int speexin_startservice(t_speexin* x, int portno) +{ + struct sockaddr_in server; + int sockfd; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + { + sys_sockerror("socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* assign server port number */ + server.sin_port = htons((u_short)portno); + post("listening to port number %d", portno); + + setsocketoptions(sockfd); + + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { + sys_sockerror("bind"); + speexin_closesocket(sockfd); + return (0); + } + + if (listen(sockfd, 5) < 0) { + sys_sockerror("listen"); + speexin_closesocket(sockfd); + } + else + { + x->x_serversocket = sockfd; + sys_addpollfn(x->x_serversocket, (t_fdpollfn)speexin_acceptconnection, x); + } + + return 1; +} + +static void speexin_free(t_speexin *x) +{ + post( "speexin~ : free %x", x ); + if (x->x_serversocket > 0) { + post( "speexin~ : closing server socket" ); + speexin_closesocket(x->x_serversocket); + x->x_serversocket = -1; + } + if (x->x_socket > 0) { + post( "speexin~ : closing socket" ); + speexin_closesocket(x->x_socket); + x->x_socket = -1; + } + if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); + if ( x->x_outbuffer ) freebytes( x->x_outbuffer, x->x_outbuffersize*sizeof(t_float) ); + if ( x->x_decchunk ) freebytes(x->x_decchunk, x->x_framesize*sizeof(t_float)); +} + +static t_int *speexin_perform(t_int *w) +{ + t_speexin *x = (t_speexin*) (w[1]); + t_float *out = (t_float *)(w[2]); + t_int n = (int)(w[3]); + t_int bsize = n; + t_int ret; + t_int i = 0; + t_int j = 0; + t_int sp = 0; + t_int sratio; + + // samplerate is supposed to be above 16kHz, thus sratio>1 + if ( x->x_mode == SPEEX_NB_MODE ) + { + sratio = x->x_samplerate / 8000; + } + else + { + sratio = x->x_samplerate / 16000; + } + // post( "speexin~ : ratio : %d", sratio ); + + memset( out, 0x0, n*sizeof(t_float ) ); + + sp = 0; + while( sp < n ) + { + if ( ( ( x->x_outunread > MIN_AUDIO_INPUT ) && x->x_newstream ) || // wait the buffer to load + ( x->x_stream ) // check that the stream provides enough data + ) + { + if ( x->x_newstream ) + { + x->x_newstream = 0; + x->x_stream = 1; + } + /* resampling */ + for ( j=0; jx_outbuffer+x->x_ooutp)/8000; // input has been scaled + //*(x->x_outbuffer+x->x_ooutp)=0.0; // data read, now zeroed + sp++; + if ( sp >= n ) break; + } + x->x_ooutp = (x->x_ooutp + 1)%x->x_outbuffersize; + // if ( x->x_ooutp == x->x_outbuffersize - 1 ) post( "speexin~ : end of audio buffer" ); + x->x_outunread-=1; + } + else + { + for ( j=0; j= n ) break; + } + } + } + x->x_pblocks++; + + if ( ( x->x_outunread <= MIN_AUDIO_INPUT/10 ) && ( x->x_stream ) ) + { + // post( "speexin~ : stream lost (too little input)" ); + x->x_stream = 0; + x->x_newstream = 1; // waiting for a new stream + } + + if ( x->x_pblocks == x->x_framesize/bsize ) + { + x->x_inpackets--; + x->x_pblocks = 0; + } + + return (w+4); +} + +static void speexin_dsp(t_speexin *x, t_signal **sp) +{ + dsp_add(speexin_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + + +static void *speexin_new(t_floatarg fportno, t_floatarg fdographics) +{ + t_speexin *x; + int i; + + if ( fportno < 0 || fportno > 65535 ) + { + post( "speexin~ : error : wrong portnumber : %d", (int)fportno ); + return NULL; + } + if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) + { + post( "speexin~ : error : constructor : speexin~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); + return NULL; + } + + x = (t_speexin *)pd_new(speexin_class); + outlet_new(&x->x_obj, &s_signal); + x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); + + x->x_serversocket = -1; + x->x_socket = -1; + x->x_inpackets = 0; + x->x_inwritepos = 0; + x->x_dpacket = -1; + x->x_mode = SPEEX_NB_MODE; + x->x_samplerate = sys_getsr(); + + x->x_canvas = canvas_getcurrent(); + + x->x_inbuffersize = INPUT_BUFFER_SIZE; + x->x_outbuffersize = OUTPUT_BUFFER_SIZE; + x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); + memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); + x->x_outbuffer = (t_float*) getbytes( x->x_outbuffersize*sizeof(t_float) ); + memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE*sizeof(t_float) ); + + if ( !x->x_inbuffer || !x->x_outbuffer ) + { + post( "speexin~ : could not allocate buffers." ); + return NULL; + } + + x->x_encsize = 0; + x->x_oinp = 0; + x->x_ooutp = 0; + + ztout.tv_sec = 0; + ztout.tv_usec = 0; + + x->x_graphic = (int)fdographics; + + post( "speexin~ : starting service on port %d", (int)fportno ); + speexin_startservice(x, (int)fportno); + + // init speex decoder + speexin_tilde_speex_init(x); + + x->x_decchunk = (t_float*)getbytes(x->x_framesize*sizeof(t_float)); + if (!x->x_decchunk) /* check allocation... */ + { + error("speexin~ : cannot allocate chunk"); + return NULL; + } + + return (x); +} + + +void speexin_tilde_setup(void) +{ + post( speexin_version ); + speexin_class = class_new(gensym("speexin~"), + (t_newmethod) speexin_new, (t_method) speexin_free, + sizeof(t_speexin), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, A_NULL); + + class_addmethod(speexin_class, nullfn, gensym("signal"), 0); + class_addmethod(speexin_class, (t_method) speexin_dsp, gensym("dsp"), 0); +} diff --git a/speexout~.c b/speexout~.c new file mode 100644 index 0000000..994ee6b --- /dev/null +++ b/speexout~.c @@ -0,0 +1,455 @@ +/* ------------------------ speexout~ ----------------------------------------- */ +/* */ +/* Tilde object to send speex encoded data to a peer using speexin~. */ +/* Written by Yves Degoyon (ydegoyon@free.fr). */ +/* Tarballs and updates @ http://ydegoyon.free.fr */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* Uses the Speex codec which can */ +/* be found at http://speex.sourceforge.net */ +/* */ +/* "Western values mean nothing to us" */ +/* "She is beyond good and evil" */ +/* Pop Group -- */ +/* ---------------------------------------------------------------------------- */ + + + +#ifdef _MSC_VER +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +#if defined(__APPLE__) || defined(_WIN32) +#define MSG_NOSIGNAL 0 +#endif + +#include /* speex codec stuff */ +#include /* speex codec stuff */ + +#include "m_pd.h" /* standard pd stuff */ + +#define IN_BUFFER_SIZE 65536 +#define OUT_BUFFER_SIZE 8192 + +// #define DATADEBUG + +#define SPEEX_NB_MODE 0 /* audio data must be 8kHz */ +#define SPEEX_WB_MODE 1 /* audio data must be 16kHz */ + +#define SPEEX_DEFAULT_QUALITY 5 /* default quality */ + +static char *speexout_version = "speexout~: speex voice quality streamer version 0.2, written by ydegoyon@free.fr"; + +static t_class *speexout_class; + +typedef struct _speexout +{ + t_object x_obj; + int x_samplerate; /* pd sampling rate */ + + /* Speex stuff */ + SpeexBits x_bits; /* bits packing structure */ + void *x_encstate; /* encoder state */ + t_int x_framesize; /* frame size */ + t_int x_mode; /* Narrow or Wide Band */ + int x_quality; /* encoding quality ( 0 to 10 ) */ + + /* buffer stuff */ + unsigned short x_inp; /* in position for buffer */ + unsigned short x_outp; /* out position for buffer */ + t_int x_encsize; /* size of encoded data */ + t_float *x_inbuf; /* data to be coded by Speex */ + char *x_outbuf; /* data returned by Speex -> our speex stream */ + int x_bytesbuffered; /* number of unprocessed bytes in buffer */ + int x_bytesemitted; /* number of encoded bytes emitted */ + int x_start; + t_float *x_encchunk; + + /* connection data */ + int x_fd; /* info about connection status */ + int x_outpackets; /* speex packets sent */ + + t_float x_f; /* float needed for signal input */ + +} t_speexout; + + + /* encode PCM data to speex frames */ +static void speexout_encode(t_speexout *x) +{ + if ( x->x_bytesbuffered > x->x_framesize ) + { + speex_bits_reset(&x->x_bits); + + { + t_int sp=0, rp=0; + + while( sp < x->x_framesize ) + { + rp=(x->x_outp+sp)%IN_BUFFER_SIZE; + // post( "speexout~ : sp=%d : rp=%d", sp, rp ); + x->x_encchunk[ sp++ ] = *(x->x_inbuf+rp); + } + speex_encode(x->x_encstate, x->x_encchunk, &x->x_bits); + } + + x->x_outp = (x->x_outp+x->x_framesize)%IN_BUFFER_SIZE; + x->x_bytesbuffered -= x->x_framesize; + x->x_encsize = speex_bits_write(&x->x_bits, x->x_outbuf+1, OUT_BUFFER_SIZE ); + if ( x->x_encsize < 127 ) + { + *(x->x_outbuf) = (char)x->x_encsize; + } + else + { + post( "speexout~ : encoding error : frame is more than 127 bytes" ); + x->x_encsize = -1; + } + x->x_bytesemitted += x->x_encsize; +#ifdef DATADEBUG + { + t_int si; + + printf( "speexout~ : encoded : " ); + for ( si=0; six_encsize; si++ ) + { + printf( "%d ", *(x->x_outbuf+si) ); + } + printf( "\n" ); + } +#endif + } + else + { + x->x_encsize = -1; + } +} + + /* stream data to the peer */ +static void speexout_stream(t_speexout *x) +{ + int count = -1, i; + + if ( x->x_encsize > 0 ) + { + count = send(x->x_fd, x->x_outbuf, x->x_encsize+1, MSG_NOSIGNAL); + if(count < 0) + { + error("speexout~: could not send encoded data to the peer (%d)", count); +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + } + else + { + x->x_outpackets++; + // post( "speexout~ : emitted %d bytes (packets = %d)", count, x->x_outpackets ); + if ( x->x_outpackets%100 == 0 ) + { + // post( "speexout~ : emitted %d bytes (packets = %d)", x->x_bytesemitted, x->x_outpackets ); + } + if(count != x->x_encsize+1) + { + error("speexout~: %d bytes skipped", x->x_encsize - count); + } + } + x->x_encsize = -1; + } +} + + + /* buffer and downsample the data */ +static t_int *speexout_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); /* audio inlet */ + t_speexout *x = (t_speexout *)(w[2]); + int n = (int)(w[3]); /* number of samples */ + unsigned short i,wp; + t_float accum = 0.; + int sratio; + + /* samplerate is supposed to be > 16kHz, thus sratio > 1 */ + if ( x->x_mode == SPEEX_NB_MODE ) + { + sratio = x->x_samplerate / 8000; + } + else + { + sratio = x->x_samplerate / 16000; + } + + /* copy the data into the buffer and resample audio data */ + + accum=0; + for(wp = 0; wp < n; wp++) + { + accum += *(in+wp); + if ( wp % sratio == sratio - 1 ) + { + x->x_inbuf[x->x_inp] = ( accum / sratio ) * 8000; // scale the input for speex best efficiency + // post( "x->x_inp : %d", x->x_inp ); + x->x_inp = (x->x_inp+1)%IN_BUFFER_SIZE; + x->x_bytesbuffered ++; + accum = 0; + } + } + + if( ( x->x_fd >= 0 ) && ( x->x_bytesbuffered > x->x_framesize ) ) + { + /* encode and send to the peer */ + speexout_encode(x); /* speex encoding */ + speexout_stream(x); /* stream mp3 to the peer */ + } + else + { + x->x_start = -1; + } + return (w+4); +} + +static void speexout_dsp(t_speexout *x, t_signal **sp) +{ + dsp_add(speexout_perform, 3, sp[0]->s_vec, x, sp[0]->s_n); +} + + /* initialize the speex library */ +static void speexout_tilde_speex_init(t_speexout *x) +{ + + speex_bits_init(&x->x_bits); + + switch ( x->x_mode ) + { + case SPEEX_NB_MODE : + x->x_encstate = speex_encoder_init(&speex_nb_mode); + break; + + case SPEEX_WB_MODE : + x->x_encstate = speex_encoder_init(&speex_wb_mode); + break; + + default : + error( "speexout~ : severe error : encoding scheme is unknown" ); + break; + } + + speex_encoder_ctl(x->x_encstate, SPEEX_GET_FRAME_SIZE, (void*)&x->x_framesize); + post( "speexout~ : frame size : %d", x->x_framesize ); + +} + + /* connect to the peer */ +static void speexout_connect(t_speexout *x, t_symbol *hostname, t_floatarg fportno) +{ + struct sockaddr_in csocket; + struct hostent *hp; + int portno = fportno; /* get port from message box */ + + /* variables used for communication with the peer */ + const char *buf = 0; + unsigned int len; + int sockfd; + +#ifdef _WIN32 + unsigned int ret; +#else + int ret; +#endif + + if (x->x_fd >= 0) + { + error("speexout~: already connected"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("speexout~: internal error while attempting to open socket"); + return; + } + + /* connect socket using hostname provided in command line */ + csocket.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("speexout~: bad host?"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + csocket.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("speexout~: connecting to port %d", portno); + if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) + { + error("speexout~: connection failed!\n"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + x->x_fd = sockfd; + x->x_outpackets = 0; + outlet_float( x->x_obj.ob_outlet, 1 ); + post( "speexout~ : connected to peer" ); + + +} + + /* close connection to the peer */ +static void speexout_disconnect(t_speexout *x) +{ + + int err = -1; + + if(x->x_fd >= 0) /* close socket */ + { +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + x->x_fd = -1; + outlet_float( x->x_obj.ob_outlet, 0 ); + post("speexout~: connection closed"); + } +} + + /* settings for encoding quality */ +static void speexout_quality(t_speexout *x, t_floatarg fquality ) +{ + if ( fquality < 0 || fquality > 10 ) { + post( "speexout~ : wrong quality." ); + return; + } + x->x_quality = fquality; + post("speexout~: setting quality to : %d", x->x_quality); + speex_encoder_ctl(x->x_encstate, SPEEX_SET_QUALITY, &x->x_quality); +} + + /* clean up */ +static void speexout_free(t_speexout *x) +{ + + speex_bits_destroy(&x->x_bits); + + speex_encoder_destroy(x->x_encstate); + + post("speexout~: encoder destroyed"); + + if(x->x_fd >= 0) +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + freebytes(x->x_inbuf, IN_BUFFER_SIZE*sizeof(t_float)); + freebytes(x->x_outbuf, OUT_BUFFER_SIZE); + freebytes(x->x_encchunk, x->x_framesize*sizeof(t_float)); +} + +static void *speexout_new(t_symbol *s, int argc, t_atom *argv) +{ + t_speexout *x = (t_speexout *)pd_new(speexout_class); + outlet_new( &x->x_obj, &s_float ); + + x->x_mode = SPEEX_NB_MODE; + x->x_quality = SPEEX_DEFAULT_QUALITY; + x->x_fd = -1; + x->x_outpackets = 0; + x->x_samplerate = sys_getsr(); + x->x_inbuf = getbytes(IN_BUFFER_SIZE*sizeof(t_float)); /* buffer for encoder input */ + x->x_outbuf = getbytes(OUT_BUFFER_SIZE); /* our mp3 stream */ + if ((!x->x_inbuf)||(!x->x_outbuf)) /* check buffers... */ + { + error("speexout~ : cannot allocate buffers"); + return NULL; + } + x->x_bytesbuffered = 0; + x->x_bytesemitted = 0; + x->x_inp = 0; + x->x_outp = 0; + x->x_encsize = 0; + x->x_start = -1; + speexout_tilde_speex_init(x); + + x->x_encchunk = (t_float*)getbytes(x->x_framesize*sizeof(t_float)); + if (!x->x_encchunk) /* check allocation... */ + { + error("speexout~ : cannot allocate chunk"); + return NULL; + } + return(x); +} + +void speexout_tilde_setup(void) +{ + post(speexout_version); + speexout_class = class_new(gensym("speexout~"), (t_newmethod)speexout_new, (t_method)speexout_free, + sizeof(t_speexout), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(speexout_class, t_speexout, x_f ); + class_addmethod(speexout_class, (t_method)speexout_dsp, gensym("dsp"), 0); + class_addmethod(speexout_class, (t_method)speexout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(speexout_class, (t_method)speexout_disconnect, gensym("disconnect"), 0); + class_addmethod(speexout_class, (t_method)speexout_quality, gensym("quality"), A_FLOAT, 0); +} + diff --git a/speex~-help.pd b/speex~-help.pd new file mode 100644 index 0000000..d1c40d4 --- /dev/null +++ b/speex~-help.pd @@ -0,0 +1,68 @@ +#N canvas 52 27 918 567 10; +#X msg 36 286 \; pd dsp 1; +#X msg 102 286 \; pd dsp 0; +#X msg 323 51 disconnect; +#X floatatom 221 227 5 0 0; +#X obj 221 199 speexout~; +#X obj 36 265 loadbang; +#X symbolatom 679 245 20 0 0; +#X text 662 261 Incomer's address; +#X text 26 8 speex~ : speexout~ / speexin~; +#X msg 343 161 quality 3; +#X msg 345 327 quality 10; +#X text 432 91 <-- settings for encoding quality; +#X obj 87 145 adc~; +#X obj 615 206 speexin~ 5000 1; +#X text 321 8 Step 1 : connect the emitter to the receiver; +#X text 30 124 Step 2 : speak in your microphone; +#X text 541 487 bugs and comments @ ydegoyon@free.fr [-_-]; +#X text 541 469 part of unauthorized PD ( http://ydegoyon.free.fr ) +; +#X msg 344 301 quality 9; +#X msg 344 276 quality 8; +#X msg 344 254 quality 7; +#X msg 344 231 quality 6; +#X msg 343 208 quality 5; +#X msg 343 185 quality 4; +#X msg 343 139 quality 2; +#X msg 343 116 quality 1; +#X msg 343 92 quality 0; +#X text 461 104 quality: lowest = 0 \, highest = 10 \, default = 5 +; +#X text 497 173 constructor : speexin~ ; +#X msg 444 356 bang; +#X obj 445 384 tabwrite~ speex-output; +#N canvas 0 0 450 300 graph2 0; +#X array speex-output 100 float 1; +#A 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0; +#X coords 0 1 99 -1 200 140 1; +#X restore 172 360 graph; +#X text 26 24 speech quality encoder/decoder/streamer; +#X obj 611 316 dac~; +#X msg 323 70 connect localhost 5000; +#X msg 323 29 connect 81.65.246.123 5000; +#X connect 2 0 4 0; +#X connect 4 0 3 0; +#X connect 5 0 0 0; +#X connect 9 0 4 0; +#X connect 10 0 4 0; +#X connect 12 0 4 0; +#X connect 13 0 30 0; +#X connect 13 0 33 0; +#X connect 13 0 33 1; +#X connect 13 1 6 0; +#X connect 18 0 4 0; +#X connect 19 0 4 0; +#X connect 20 0 4 0; +#X connect 21 0 4 0; +#X connect 22 0 4 0; +#X connect 23 0 4 0; +#X connect 24 0 4 0; +#X connect 25 0 4 0; +#X connect 26 0 4 0; +#X connect 29 0 30 0; +#X connect 34 0 4 0; +#X connect 35 0 4 0; diff --git a/speex~/INSTALL b/speex~/INSTALL deleted file mode 100644 index 852c774..0000000 --- a/speex~/INSTALL +++ /dev/null @@ -1,18 +0,0 @@ -first, you need to install Speex library, -i used v0.6.0 available from http://speex.sourceforge.net - -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/speex~ - -make clean - -make - -make install - -open help-speex~.pd - -Thanx for getting here. - -Yves/ diff --git a/speex~/speexin~.c b/speex~/speexin~.c deleted file mode 100644 index eff2601..0000000 --- a/speex~/speexin~.c +++ /dev/null @@ -1,612 +0,0 @@ -/* ------------------------ speexin~ ------------------------------------------ */ -/* */ -/* Object to receive a speex encoded stream sent by a peer using speexin~. */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates @ http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the Speex voice quality encoding library which can */ -/* be found at http://speex.sourceforge.net. */ -/* */ -/* ---------------------------------------------------------------------------- */ - - -#include -#include - -#include -#include -#include -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#define SOL_TCP IPPROTO_TCP -#endif - -#include /* speex decoder stuff */ -#include /* speex decoder stuff */ - -#ifdef _MSC_VER -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4305 ) -#endif - -#define MIN_AUDIO_INPUT 1024 // we must a least have 8 chunks to play a correct sound -#define INPUT_BUFFER_SIZE 32768 -#define OUTPUT_BUFFER_SIZE 32768 /* 32k */ -#define BARHEIGHT 10 - -#define SPEEX_NB_MODE 0 /* audio data must be 8kHz */ -#define SPEEX_WB_MODE 1 /* audio data must be 16kHz */ - -//#define DATADEBUG - -typedef void (*t_fdpollfn)(void *ptr, int fd); -extern void sys_rmpollfn(int fd); -extern void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); - -/* time-out used for select() call */ -static struct timeval ztout; - -static char *speexin_version = "speexin~: speex voice quality streamer version 0.2, written by ydegoyon@free.fr"; - -extern void sys_sockerror(char *s); - -void speexin_closesocket(int fd) -{ -#ifdef UNIX - if ( close(fd) < 0 ) - { - perror( "close" ); - } - else - { - post( "speexin~ : closed socket : %d", fd ); - } -#endif -#ifdef NT - closesocket(fd); -#endif - sys_rmpollfn(fd); -} - -int setsocketoptions(int sockfd) -{ - int sockopt = 1; - if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0) - { - post("speexin~ : setsockopt TCP_NODELAY failed"); - perror( "setsockopt" ); - return -1; - } - else - { - post("speexin~ : TCP_NODELAY set"); - } - -#ifdef UNIX - sockopt = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) - { - post("speexin~ : setsockopt SO_REUSEADDR failed"); - perror( "setsockopt" ); - return -1; - } - else - { - post("speexin~ : setsockopt SO_REUSEADDR done."); - } -#endif - return 0; -} - - -/* ------------------------ speexin~ ----------------------------- */ - -static t_class *speexin_class; - -typedef struct _speexin -{ - t_object x_obj; - t_int x_socket; - t_outlet *x_connectionip; - t_int x_serversocket; - t_int x_samplerate; - - /* Speex stuff */ - SpeexBits x_bits; /* bits packing structure */ - void *x_decstate; /* decoder state */ - t_int x_framesize; /* frame size */ - t_int x_mode; /* Narrow or Wide Band */ - int x_quality; /* encoding quality ( 0 to 10 ) */ - - t_int x_inpackets; /* number of packets received */ - t_int x_dpacket; /* displayed packet in status bar */ - t_int x_packetsize; /* size of the packets */ - t_int x_pblocks; /* processed blocks */ - t_int x_graphic; /* indicates if we show a graphic bar */ - - void *x_inbuffer; /* accumulation buffer for incoming speex frames */ - t_int x_inwritepos; /* accumulation buffer for incoming speex frames */ - t_int x_encsize; - t_int x_inbuffersize; - - t_float *x_outbuffer; /* buffer to store audio decoded data */ - t_int x_oinp; - t_int x_ooutp; - t_int x_outunread; - t_int x_outbuffersize; - t_float *x_decchunk; - - t_canvas *x_canvas; - - t_int x_stream; /* indicates if a stream is connected ( meaning correct input flow ) */ - t_int x_newstream; /* at first, the stream must provide enough data to start */ - -} t_speexin; - -void speexin_tilde_speex_init(t_speexin *x) -{ - int ret; - int pf=1; - - speex_bits_init(&x->x_bits); - - switch ( x->x_mode ) - { - case SPEEX_NB_MODE : - x->x_decstate = speex_decoder_init(&speex_nb_mode); - break; - - case SPEEX_WB_MODE : - x->x_decstate = speex_decoder_init(&speex_wb_mode); - break; - - default : - error( "speexin~ : severe error : decoding scheme is unknown" ); - break; - } - - speex_decoder_ctl(x->x_decstate, SPEEX_GET_FRAME_SIZE, (void*)&x->x_framesize); - - speex_decoder_ctl(x->x_decstate, SPEEX_SET_PF, &pf); - - post( "speexin~ : frame size : %d", x->x_framesize ); - -} - -static void speexin_decode_input(t_speexin *x) -{ - int i; - int alength = 0; - static char out[8192]; - signed short int *p = (signed short int *) out; - int pbytes; - int ret; - int flength = 0; - - if ( x->x_encsize > 0 ) - { - - while ( x->x_encsize > *(char *)(x->x_inbuffer) ) - { - - flength = *(char *)(x->x_inbuffer ); - - // post( "speexin~ : reading bits from 1 to : %d", flength+1 ); - speex_bits_read_from(&x->x_bits, x->x_inbuffer+1, flength); - -#ifdef DATADEBUG - { - t_int si; - - printf( "speexin~ : decoding : " ); - for ( si=0; six_inbuffer+1+si) ); - } - printf( "\n" ); - } -#endif - - { - t_int sp=0, rp=0; - - speex_decode(x->x_decstate, &x->x_bits, x->x_decchunk); - - while( sp < x->x_framesize ) - { - rp=(x->x_oinp+sp)%x->x_outbuffersize; - // if ( rp == x->x_outbuffersize - 1 ) post( "speexin~ : write at the end of audio buffer" ); - // post( "speexin~ : sp=%d : rp=%d", sp, rp ); - x->x_outbuffer[ rp ] = x->x_decchunk[sp++]; - } - x->x_oinp = rp+1; - } - x->x_outunread += x->x_framesize; - memcpy( x->x_inbuffer, x->x_inbuffer+flength+1, x->x_inbuffersize-flength-1 ); - x->x_encsize -= flength+1; - x->x_inwritepos -= flength+1; - - } - - } - - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - /* update graphical read status */ - if ( x->x_inpackets != x->x_dpacket ) - { - char color[32]; - int minpackets = ( MIN_AUDIO_INPUT/x->x_framesize)-2; // audio loop has eaten some already - - - sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); - sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); - if ( x->x_outunread > 0 ) - { - t_int width; - - if ( x->x_inpackets < (MIN_AUDIO_INPUT/x->x_framesize)/2 ) - { - strcpy( color, "red" ); - } - else - { - strcpy( color, "lightgreen" ); - } - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix+(x->x_inpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix - 1, color, x ); - sys_vgui(".x%x.c create line %d %d %d %d -fill red -tags %xTHRESHOLD\n", - x->x_canvas, x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, - x->x_obj.te_ypix-1, x ); - x->x_dpacket = x->x_inpackets; - } - } - - } - -} - -static void speexin_recv(t_speexin *x) -{ - int ret; - - if ( x->x_inwritepos > x->x_inbuffersize - 1024 ) - { - post( "speexin~ : input buffer is full" ); - return; - } - if ( ( ret = recv(x->x_socket, (void*) x->x_inbuffer + x->x_inwritepos, - (size_t)x->x_inbuffersize, - MSG_NOSIGNAL) ) < 0 ) - { - post( "speexin~ : receive error" ); - perror( "recv" ); - return; - } - else - { - // post( "speexin~ : received %d bytes at %d on %d ( up to %d)", - // ret, x->x_inwritepos, x->x_socket, - // x->x_inbuffersize ); - - if ( ret == 0 ) - { - post( "speexin~ : closing connection ( s=%d )", x->x_socket ); - speexin_closesocket(x->x_socket); - x->x_socket = -1; - sys_vgui(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x ); - sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x ); - sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x ); - outlet_symbol( x->x_connectionip, gensym("") ); - } - else - { - x->x_inpackets++; - } - - x->x_encsize += ret; - x->x_inwritepos += ret; - - speexin_decode_input(x); - } -} - -static void speexin_acceptconnection(t_speexin *x) -{ - struct sockaddr_in incomer_address; - int sockaddrl = (int) sizeof( struct sockaddr ); - - int fd = accept(x->x_serversocket, (struct sockaddr*)&incomer_address, &sockaddrl ); - post("speexin~: accepted incomer : %d.", fd ); - - if (fd < 0) { - post("speexin~: accept failed"); - return; - } - - if (x->x_socket > 0) { - post("speexin~: the source has changed to %s ( new socket = %d ).", - inet_ntoa( incomer_address.sin_addr ), fd ); - speexin_closesocket(x->x_socket); - } - - x->x_socket = fd; - sys_addpollfn(x->x_socket, (t_fdpollfn)speexin_recv, x); - outlet_symbol( x->x_connectionip, gensym( inet_ntoa( incomer_address.sin_addr) ) ); - - if ( x->x_graphic && glist_isvisible( x->x_canvas ) ) - { - t_int width; - - width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); - sys_vgui(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n", - x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1, - x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x ); - } - x->x_stream = 0; - x->x_newstream = 1; - -} - - -static int speexin_startservice(t_speexin* x, int portno) -{ - struct sockaddr_in server; - int sockfd; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) - { - sys_sockerror("socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - - /* assign server port number */ - server.sin_port = htons((u_short)portno); - post("listening to port number %d", portno); - - setsocketoptions(sockfd); - - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { - sys_sockerror("bind"); - speexin_closesocket(sockfd); - return (0); - } - - if (listen(sockfd, 5) < 0) { - sys_sockerror("listen"); - speexin_closesocket(sockfd); - } - else - { - x->x_serversocket = sockfd; - sys_addpollfn(x->x_serversocket, (t_fdpollfn)speexin_acceptconnection, x); - } - - return 1; -} - -static void speexin_free(t_speexin *x) -{ - post( "speexin~ : free %x", x ); - if (x->x_serversocket > 0) { - post( "speexin~ : closing server socket" ); - speexin_closesocket(x->x_serversocket); - x->x_serversocket = -1; - } - if (x->x_socket > 0) { - post( "speexin~ : closing socket" ); - speexin_closesocket(x->x_socket); - x->x_socket = -1; - } - if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize ); - if ( x->x_outbuffer ) freebytes( x->x_outbuffer, x->x_outbuffersize*sizeof(t_float) ); - if ( x->x_decchunk ) freebytes(x->x_decchunk, x->x_framesize*sizeof(t_float)); -} - -static t_int *speexin_perform(t_int *w) -{ - t_speexin *x = (t_speexin*) (w[1]); - t_float *out = (t_float *)(w[2]); - t_int n = (int)(w[3]); - t_int bsize = n; - t_int ret; - t_int i = 0; - t_int j = 0; - t_int sp = 0; - t_int sratio; - - // samplerate is supposed to be above 16kHz, thus sratio>1 - if ( x->x_mode == SPEEX_NB_MODE ) - { - sratio = x->x_samplerate / 8000; - } - else - { - sratio = x->x_samplerate / 16000; - } - // post( "speexin~ : ratio : %d", sratio ); - - memset( out, 0x0, n*sizeof(t_float ) ); - - sp = 0; - while( sp < n ) - { - if ( ( ( x->x_outunread > MIN_AUDIO_INPUT ) && x->x_newstream ) || // wait the buffer to load - ( x->x_stream ) // check that the stream provides enough data - ) - { - if ( x->x_newstream ) - { - x->x_newstream = 0; - x->x_stream = 1; - } - /* resampling */ - for ( j=0; jx_outbuffer+x->x_ooutp)/8000; // input has been scaled - //*(x->x_outbuffer+x->x_ooutp)=0.0; // data read, now zeroed - sp++; - if ( sp >= n ) break; - } - x->x_ooutp = (x->x_ooutp + 1)%x->x_outbuffersize; - // if ( x->x_ooutp == x->x_outbuffersize - 1 ) post( "speexin~ : end of audio buffer" ); - x->x_outunread-=1; - } - else - { - for ( j=0; j= n ) break; - } - } - } - x->x_pblocks++; - - if ( ( x->x_outunread <= MIN_AUDIO_INPUT/10 ) && ( x->x_stream ) ) - { - // post( "speexin~ : stream lost (too little input)" ); - x->x_stream = 0; - x->x_newstream = 1; // waiting for a new stream - } - - if ( x->x_pblocks == x->x_framesize/bsize ) - { - x->x_inpackets--; - x->x_pblocks = 0; - } - - return (w+4); -} - -static void speexin_dsp(t_speexin *x, t_signal **sp) -{ - dsp_add(speexin_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); -} - - -static void *speexin_new(t_floatarg fportno, t_floatarg fdographics) -{ - t_speexin *x; - int i; - - if ( fportno < 0 || fportno > 65535 ) - { - post( "speexin~ : error : wrong portnumber : %d", (int)fportno ); - return NULL; - } - if ( ((int)fdographics != 0) && ((int)fdographics != 1.) ) - { - post( "speexin~ : error : constructor : speexin~ [graphic flag = 0 | 1 ] ( got = %f)", fdographics ); - return NULL; - } - - x = (t_speexin *)pd_new(speexin_class); - outlet_new(&x->x_obj, &s_signal); - x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); - - x->x_serversocket = -1; - x->x_socket = -1; - x->x_inpackets = 0; - x->x_inwritepos = 0; - x->x_dpacket = -1; - x->x_mode = SPEEX_NB_MODE; - x->x_samplerate = sys_getsr(); - - x->x_canvas = canvas_getcurrent(); - - x->x_inbuffersize = INPUT_BUFFER_SIZE; - x->x_outbuffersize = OUTPUT_BUFFER_SIZE; - x->x_inbuffer = (char*) getbytes( x->x_inbuffersize ); - memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE ); - x->x_outbuffer = (t_float*) getbytes( x->x_outbuffersize*sizeof(t_float) ); - memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE*sizeof(t_float) ); - - if ( !x->x_inbuffer || !x->x_outbuffer ) - { - post( "speexin~ : could not allocate buffers." ); - return NULL; - } - - x->x_encsize = 0; - x->x_oinp = 0; - x->x_ooutp = 0; - - ztout.tv_sec = 0; - ztout.tv_usec = 0; - - x->x_graphic = (int)fdographics; - - post( "speexin~ : starting service on port %d", (int)fportno ); - speexin_startservice(x, (int)fportno); - - // init speex decoder - speexin_tilde_speex_init(x); - - x->x_decchunk = (t_float*)getbytes(x->x_framesize*sizeof(t_float)); - if (!x->x_decchunk) /* check allocation... */ - { - error("speexin~ : cannot allocate chunk"); - return NULL; - } - - return (x); -} - - -void speexin_tilde_setup(void) -{ - post( speexin_version ); - speexin_class = class_new(gensym("speexin~"), - (t_newmethod) speexin_new, (t_method) speexin_free, - sizeof(t_speexin), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, A_NULL); - - class_addmethod(speexin_class, nullfn, gensym("signal"), 0); - class_addmethod(speexin_class, (t_method) speexin_dsp, gensym("dsp"), 0); -} diff --git a/speex~/speexout~.c b/speex~/speexout~.c deleted file mode 100644 index 2391e6f..0000000 --- a/speex~/speexout~.c +++ /dev/null @@ -1,455 +0,0 @@ -/* ------------------------ speexout~ ----------------------------------------- */ -/* */ -/* Tilde object to send speex encoded data to a peer using speexin~. */ -/* Written by Yves Degoyon (ydegoyon@free.fr). */ -/* Tarballs and updates @ http://ydegoyon.free.fr */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* Uses the Speex codec which can */ -/* be found at http://speex.sourceforge.net */ -/* */ -/* "Western values mean nothing to us" */ -/* "She is beyond good and evil" */ -/* Pop Group -- */ -/* ---------------------------------------------------------------------------- */ - - - -#ifdef _MSC_VER -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4305 ) -#endif - -#include -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#ifdef _WIN32 -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#endif - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#endif - -#include /* speex codec stuff */ -#include /* speex codec stuff */ - -#include "m_pd.h" /* standard pd stuff */ - -#define IN_BUFFER_SIZE 65536 -#define OUT_BUFFER_SIZE 8192 - -// #define DATADEBUG - -#define SPEEX_NB_MODE 0 /* audio data must be 8kHz */ -#define SPEEX_WB_MODE 1 /* audio data must be 16kHz */ - -#define SPEEX_DEFAULT_QUALITY 5 /* default quality */ - -static char *speexout_version = "speexout~: speex voice quality streamer version 0.2, written by ydegoyon@free.fr"; - -static t_class *speexout_class; - -typedef struct _speexout -{ - t_object x_obj; - int x_samplerate; /* pd sampling rate */ - - /* Speex stuff */ - SpeexBits x_bits; /* bits packing structure */ - void *x_encstate; /* encoder state */ - t_int x_framesize; /* frame size */ - t_int x_mode; /* Narrow or Wide Band */ - int x_quality; /* encoding quality ( 0 to 10 ) */ - - /* buffer stuff */ - unsigned short x_inp; /* in position for buffer */ - unsigned short x_outp; /* out position for buffer */ - t_int x_encsize; /* size of encoded data */ - t_float *x_inbuf; /* data to be coded by Speex */ - char *x_outbuf; /* data returned by Speex -> our speex stream */ - int x_bytesbuffered; /* number of unprocessed bytes in buffer */ - int x_bytesemitted; /* number of encoded bytes emitted */ - int x_start; - t_float *x_encchunk; - - /* connection data */ - int x_fd; /* info about connection status */ - int x_outpackets; /* speex packets sent */ - - t_float x_f; /* float needed for signal input */ - -} t_speexout; - - - /* encode PCM data to speex frames */ -static void speexout_encode(t_speexout *x) -{ - if ( x->x_bytesbuffered > x->x_framesize ) - { - speex_bits_reset(&x->x_bits); - - { - t_int sp=0, rp=0; - - while( sp < x->x_framesize ) - { - rp=(x->x_outp+sp)%IN_BUFFER_SIZE; - // post( "speexout~ : sp=%d : rp=%d", sp, rp ); - x->x_encchunk[ sp++ ] = *(x->x_inbuf+rp); - } - speex_encode(x->x_encstate, x->x_encchunk, &x->x_bits); - } - - x->x_outp = (x->x_outp+x->x_framesize)%IN_BUFFER_SIZE; - x->x_bytesbuffered -= x->x_framesize; - x->x_encsize = speex_bits_write(&x->x_bits, x->x_outbuf+1, OUT_BUFFER_SIZE ); - if ( x->x_encsize < 127 ) - { - *(x->x_outbuf) = (char)x->x_encsize; - } - else - { - post( "speexout~ : encoding error : frame is more than 127 bytes" ); - x->x_encsize = -1; - } - x->x_bytesemitted += x->x_encsize; -#ifdef DATADEBUG - { - t_int si; - - printf( "speexout~ : encoded : " ); - for ( si=0; six_encsize; si++ ) - { - printf( "%d ", *(x->x_outbuf+si) ); - } - printf( "\n" ); - } -#endif - } - else - { - x->x_encsize = -1; - } -} - - /* stream data to the peer */ -static void speexout_stream(t_speexout *x) -{ - int count = -1, i; - - if ( x->x_encsize > 0 ) - { - count = send(x->x_fd, x->x_outbuf, x->x_encsize+1, MSG_NOSIGNAL); - if(count < 0) - { - error("speexout~: could not send encoded data to the peer (%d)", count); -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - } - else - { - x->x_outpackets++; - // post( "speexout~ : emitted %d bytes (packets = %d)", count, x->x_outpackets ); - if ( x->x_outpackets%100 == 0 ) - { - // post( "speexout~ : emitted %d bytes (packets = %d)", x->x_bytesemitted, x->x_outpackets ); - } - if(count != x->x_encsize+1) - { - error("speexout~: %d bytes skipped", x->x_encsize - count); - } - } - x->x_encsize = -1; - } -} - - - /* buffer and downsample the data */ -static t_int *speexout_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); /* audio inlet */ - t_speexout *x = (t_speexout *)(w[2]); - int n = (int)(w[3]); /* number of samples */ - unsigned short i,wp; - t_float accum = 0.; - int sratio; - - /* samplerate is supposed to be > 16kHz, thus sratio > 1 */ - if ( x->x_mode == SPEEX_NB_MODE ) - { - sratio = x->x_samplerate / 8000; - } - else - { - sratio = x->x_samplerate / 16000; - } - - /* copy the data into the buffer and resample audio data */ - - accum=0; - for(wp = 0; wp < n; wp++) - { - accum += *(in+wp); - if ( wp % sratio == sratio - 1 ) - { - x->x_inbuf[x->x_inp] = ( accum / sratio ) * 8000; // scale the input for speex best efficiency - // post( "x->x_inp : %d", x->x_inp ); - x->x_inp = (x->x_inp+1)%IN_BUFFER_SIZE; - x->x_bytesbuffered ++; - accum = 0; - } - } - - if( ( x->x_fd >= 0 ) && ( x->x_bytesbuffered > x->x_framesize ) ) - { - /* encode and send to the peer */ - speexout_encode(x); /* speex encoding */ - speexout_stream(x); /* stream mp3 to the peer */ - } - else - { - x->x_start = -1; - } - return (w+4); -} - -static void speexout_dsp(t_speexout *x, t_signal **sp) -{ - dsp_add(speexout_perform, 3, sp[0]->s_vec, x, sp[0]->s_n); -} - - /* initialize the speex library */ -static void speexout_tilde_speex_init(t_speexout *x) -{ - - speex_bits_init(&x->x_bits); - - switch ( x->x_mode ) - { - case SPEEX_NB_MODE : - x->x_encstate = speex_encoder_init(&speex_nb_mode); - break; - - case SPEEX_WB_MODE : - x->x_encstate = speex_encoder_init(&speex_wb_mode); - break; - - default : - error( "speexout~ : severe error : encoding scheme is unknown" ); - break; - } - - speex_encoder_ctl(x->x_encstate, SPEEX_GET_FRAME_SIZE, (void*)&x->x_framesize); - post( "speexout~ : frame size : %d", x->x_framesize ); - -} - - /* connect to the peer */ -static void speexout_connect(t_speexout *x, t_symbol *hostname, t_floatarg fportno) -{ - struct sockaddr_in csocket; - struct hostent *hp; - int portno = fportno; /* get port from message box */ - - /* variables used for communication with the peer */ - const char *buf = 0; - unsigned int len; - int sockfd; - -#ifndef UNIX - unsigned int ret; -#else - int ret; -#endif - - if (x->x_fd >= 0) - { - error("speexout~: already connected"); - return; - } - - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - error("speexout~: internal error while attempting to open socket"); - return; - } - - /* connect socket using hostname provided in command line */ - csocket.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) - { - post("speexout~: bad host?"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - csocket.sin_port = htons((unsigned short)portno); - - /* try to connect. */ - post("speexout~: connecting to port %d", portno); - if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0) - { - error("speexout~: connection failed!\n"); -#ifndef UNIX - closesocket(sockfd); -#else - close(sockfd); -#endif - return; - } - - x->x_fd = sockfd; - x->x_outpackets = 0; - outlet_float( x->x_obj.ob_outlet, 1 ); - post( "speexout~ : connected to peer" ); - - -} - - /* close connection to the peer */ -static void speexout_disconnect(t_speexout *x) -{ - - int err = -1; - - if(x->x_fd >= 0) /* close socket */ - { -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - x->x_fd = -1; - outlet_float( x->x_obj.ob_outlet, 0 ); - post("speexout~: connection closed"); - } -} - - /* settings for encoding quality */ -static void speexout_quality(t_speexout *x, t_floatarg fquality ) -{ - if ( fquality < 0 || fquality > 10 ) { - post( "speexout~ : wrong quality." ); - return; - } - x->x_quality = fquality; - post("speexout~: setting quality to : %d", x->x_quality); - speex_encoder_ctl(x->x_encstate, SPEEX_SET_QUALITY, &x->x_quality); -} - - /* clean up */ -static void speexout_free(t_speexout *x) -{ - - speex_bits_destroy(&x->x_bits); - - speex_encoder_destroy(x->x_encstate); - - post("speexout~: encoder destroyed"); - - if(x->x_fd >= 0) -#ifndef UNIX - closesocket(x->x_fd); -#else - close(x->x_fd); -#endif - freebytes(x->x_inbuf, IN_BUFFER_SIZE*sizeof(t_float)); - freebytes(x->x_outbuf, OUT_BUFFER_SIZE); - freebytes(x->x_encchunk, x->x_framesize*sizeof(t_float)); -} - -static void *speexout_new(t_symbol *s, int argc, t_atom *argv) -{ - t_speexout *x = (t_speexout *)pd_new(speexout_class); - outlet_new( &x->x_obj, &s_float ); - - x->x_mode = SPEEX_NB_MODE; - x->x_quality = SPEEX_DEFAULT_QUALITY; - x->x_fd = -1; - x->x_outpackets = 0; - x->x_samplerate = sys_getsr(); - x->x_inbuf = getbytes(IN_BUFFER_SIZE*sizeof(t_float)); /* buffer for encoder input */ - x->x_outbuf = getbytes(OUT_BUFFER_SIZE); /* our mp3 stream */ - if ((!x->x_inbuf)||(!x->x_outbuf)) /* check buffers... */ - { - error("speexout~ : cannot allocate buffers"); - return NULL; - } - x->x_bytesbuffered = 0; - x->x_bytesemitted = 0; - x->x_inp = 0; - x->x_outp = 0; - x->x_encsize = 0; - x->x_start = -1; - speexout_tilde_speex_init(x); - - x->x_encchunk = (t_float*)getbytes(x->x_framesize*sizeof(t_float)); - if (!x->x_encchunk) /* check allocation... */ - { - error("speexout~ : cannot allocate chunk"); - return NULL; - } - return(x); -} - -void speexout_tilde_setup(void) -{ - post(speexout_version); - speexout_class = class_new(gensym("speexout~"), (t_newmethod)speexout_new, (t_method)speexout_free, - sizeof(t_speexout), 0, A_GIMME, 0); - CLASS_MAINSIGNALIN(speexout_class, t_speexout, x_f ); - class_addmethod(speexout_class, (t_method)speexout_dsp, gensym("dsp"), 0); - class_addmethod(speexout_class, (t_method)speexout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(speexout_class, (t_method)speexout_disconnect, gensym("disconnect"), 0); - class_addmethod(speexout_class, (t_method)speexout_quality, gensym("quality"), A_FLOAT, 0); -} - diff --git a/speex~/speex~-help.pd b/speex~/speex~-help.pd deleted file mode 100644 index d1c40d4..0000000 --- a/speex~/speex~-help.pd +++ /dev/null @@ -1,68 +0,0 @@ -#N canvas 52 27 918 567 10; -#X msg 36 286 \; pd dsp 1; -#X msg 102 286 \; pd dsp 0; -#X msg 323 51 disconnect; -#X floatatom 221 227 5 0 0; -#X obj 221 199 speexout~; -#X obj 36 265 loadbang; -#X symbolatom 679 245 20 0 0; -#X text 662 261 Incomer's address; -#X text 26 8 speex~ : speexout~ / speexin~; -#X msg 343 161 quality 3; -#X msg 345 327 quality 10; -#X text 432 91 <-- settings for encoding quality; -#X obj 87 145 adc~; -#X obj 615 206 speexin~ 5000 1; -#X text 321 8 Step 1 : connect the emitter to the receiver; -#X text 30 124 Step 2 : speak in your microphone; -#X text 541 487 bugs and comments @ ydegoyon@free.fr [-_-]; -#X text 541 469 part of unauthorized PD ( http://ydegoyon.free.fr ) -; -#X msg 344 301 quality 9; -#X msg 344 276 quality 8; -#X msg 344 254 quality 7; -#X msg 344 231 quality 6; -#X msg 343 208 quality 5; -#X msg 343 185 quality 4; -#X msg 343 139 quality 2; -#X msg 343 116 quality 1; -#X msg 343 92 quality 0; -#X text 461 104 quality: lowest = 0 \, highest = 10 \, default = 5 -; -#X text 497 173 constructor : speexin~ ; -#X msg 444 356 bang; -#X obj 445 384 tabwrite~ speex-output; -#N canvas 0 0 450 300 graph2 0; -#X array speex-output 100 float 1; -#A 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0; -#X coords 0 1 99 -1 200 140 1; -#X restore 172 360 graph; -#X text 26 24 speech quality encoder/decoder/streamer; -#X obj 611 316 dac~; -#X msg 323 70 connect localhost 5000; -#X msg 323 29 connect 81.65.246.123 5000; -#X connect 2 0 4 0; -#X connect 4 0 3 0; -#X connect 5 0 0 0; -#X connect 9 0 4 0; -#X connect 10 0 4 0; -#X connect 12 0 4 0; -#X connect 13 0 30 0; -#X connect 13 0 33 0; -#X connect 13 0 33 1; -#X connect 13 1 6 0; -#X connect 18 0 4 0; -#X connect 19 0 4 0; -#X connect 20 0 4 0; -#X connect 21 0 4 0; -#X connect 22 0 4 0; -#X connect 23 0 4 0; -#X connect 24 0 4 0; -#X connect 25 0 4 0; -#X connect 26 0 4 0; -#X connect 29 0 30 0; -#X connect 34 0 4 0; -#X connect 35 0 4 0; diff --git a/spigot~-help.pd b/spigot~-help.pd new file mode 100644 index 0000000..eb7f0eb --- /dev/null +++ b/spigot~-help.pd @@ -0,0 +1,14 @@ +#N canvas 172 55 627 444 10; +#X obj 151 163 dac~; +#X obj 150 127 spigot~; +#X text 232 50 spigot~ sends its signal to its right or left outlet +; +#X text 232 65 according to the state of the toggle; +#X obj 199 101 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X obj 108 74 osc~ 233; +#X text 237 148 bugs and comments @ ydegoyon@free.fr; +#X connect 1 0 0 0; +#X connect 1 1 0 1; +#X connect 4 0 1 1; +#X connect 5 0 1 0; diff --git a/spigot~.c b/spigot~.c new file mode 100644 index 0000000..fe54152 --- /dev/null +++ b/spigot~.c @@ -0,0 +1,74 @@ +/* spigot~ -- route a signal to its right or left output */ + +/* Copyleft 2001 Yves Degoyon. +Permission is granted to use this software for any purpose provided you +keep this copyright notice intact. + +THE AUTHOR AND HIS EXPLOITERS MAKE NO WARRANTY, EXPRESS OR IMPLIED, +IN CONNECTION WITH THIS SOFTWARE. + +*/ + +#include "m_pd.h" + +typedef struct _spigot +{ + t_object x_obj; + t_int x_on; + t_float x_f; +} t_spigot; + +static t_class *spigot_class; + +static char *spigot_version = "spigot~: a signal router : version 0.1, written by Yves Degoyon (ydegoyon@free.fr)"; + +static void *spigot_new(void) +{ + t_spigot *x = (t_spigot *)pd_new(spigot_class); + x->x_on = 0; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("seton") ); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static t_int *spigot_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *outr = (t_float *)(w[2]); + t_float *outl = (t_float *)(w[3]); + int n = (int)(w[4]); + t_spigot* x = (t_spigot*)(w[5]); + while (n--) { + if ( (x->x_on)==0.0 ) { + *(outl)=0.0; + *(outr)=*(in); + } else { + *(outl)=*(in); + *(outr)=0.0; + } + in++;outl++;outr++; + } + return (w+6); +} + +static void spigot_dsp(t_spigot *x, t_signal **sp) +{ + dsp_add(spigot_perform, 5, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + sp[0]->s_n, x); +} + +static void spigot_set(t_spigot *x, t_float f) +{ + x->x_on=f; +} + +void spigot_tilde_setup(void) +{ + post ( spigot_version ); + spigot_class = class_new(gensym("spigot~"), (t_newmethod)spigot_new, 0, + sizeof(t_spigot), 0, 0); + CLASS_MAINSIGNALIN( spigot_class, t_spigot, x_f ); + class_addmethod(spigot_class, (t_method)spigot_dsp, gensym("dsp"), 0); + class_addmethod(spigot_class, (t_method)spigot_set, gensym("seton"), A_FLOAT, 0); +} diff --git a/spigot~/INSTALL b/spigot~/INSTALL deleted file mode 100644 index d8c07c9..0000000 --- a/spigot~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/spigot~ - -make clean - -make - -make install - -open help-spigot~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/spigot~/spigot~-help.pd b/spigot~/spigot~-help.pd deleted file mode 100644 index eb7f0eb..0000000 --- a/spigot~/spigot~-help.pd +++ /dev/null @@ -1,14 +0,0 @@ -#N canvas 172 55 627 444 10; -#X obj 151 163 dac~; -#X obj 150 127 spigot~; -#X text 232 50 spigot~ sends its signal to its right or left outlet -; -#X text 232 65 according to the state of the toggle; -#X obj 199 101 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 -1; -#X obj 108 74 osc~ 233; -#X text 237 148 bugs and comments @ ydegoyon@free.fr; -#X connect 1 0 0 0; -#X connect 1 1 0 1; -#X connect 4 0 1 1; -#X connect 5 0 1 0; diff --git a/spigot~/spigot~.c b/spigot~/spigot~.c deleted file mode 100644 index fe54152..0000000 --- a/spigot~/spigot~.c +++ /dev/null @@ -1,74 +0,0 @@ -/* spigot~ -- route a signal to its right or left output */ - -/* Copyleft 2001 Yves Degoyon. -Permission is granted to use this software for any purpose provided you -keep this copyright notice intact. - -THE AUTHOR AND HIS EXPLOITERS MAKE NO WARRANTY, EXPRESS OR IMPLIED, -IN CONNECTION WITH THIS SOFTWARE. - -*/ - -#include "m_pd.h" - -typedef struct _spigot -{ - t_object x_obj; - t_int x_on; - t_float x_f; -} t_spigot; - -static t_class *spigot_class; - -static char *spigot_version = "spigot~: a signal router : version 0.1, written by Yves Degoyon (ydegoyon@free.fr)"; - -static void *spigot_new(void) -{ - t_spigot *x = (t_spigot *)pd_new(spigot_class); - x->x_on = 0; - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("seton") ); - outlet_new(&x->x_obj, &s_signal); - outlet_new(&x->x_obj, &s_signal); - return (x); -} - -static t_int *spigot_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *outr = (t_float *)(w[2]); - t_float *outl = (t_float *)(w[3]); - int n = (int)(w[4]); - t_spigot* x = (t_spigot*)(w[5]); - while (n--) { - if ( (x->x_on)==0.0 ) { - *(outl)=0.0; - *(outr)=*(in); - } else { - *(outl)=*(in); - *(outr)=0.0; - } - in++;outl++;outr++; - } - return (w+6); -} - -static void spigot_dsp(t_spigot *x, t_signal **sp) -{ - dsp_add(spigot_perform, 5, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, - sp[0]->s_n, x); -} - -static void spigot_set(t_spigot *x, t_float f) -{ - x->x_on=f; -} - -void spigot_tilde_setup(void) -{ - post ( spigot_version ); - spigot_class = class_new(gensym("spigot~"), (t_newmethod)spigot_new, 0, - sizeof(t_spigot), 0, 0); - CLASS_MAINSIGNALIN( spigot_class, t_spigot, x_f ); - class_addmethod(spigot_class, (t_method)spigot_dsp, gensym("dsp"), 0); - class_addmethod(spigot_class, (t_method)spigot_set, gensym("seton"), A_FLOAT, 0); -} diff --git a/tables.c b/tables.c new file mode 100644 index 0000000..049a523 --- /dev/null +++ b/tables.c @@ -0,0 +1,311 @@ +/* +vox - a musical real-time vocoder. version 1.0 +Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +double LspDcTable[11] = { + 0, + 0.0955505 , + 0.144073 , + 0.23468 , + 0.329773 , + 0.42334 , + 0.503387 , + 0.602783 , + 0.679321 , + 0.77771 , + 0.845886 +}; + +double CosineTable[257] = { + 1 , + 0.999939 , + 0.999695 , + 0.999329 , + 0.998779 , + 0.998108 , + 0.997314 , + 0.996338 , + 0.995178 , + 0.993896 , + 0.992493 , + 0.990906 , + 0.989197 , + 0.987305 , + 0.985291 , + 0.983093 , + 0.980774 , + 0.978333 , + 0.975708 , + 0.972961 , + 0.970032 , + 0.96698 , + 0.963806 , + 0.960449 , + 0.95697 , + 0.953308 , + 0.949524 , + 0.945618 , + 0.941528 , + 0.937317 , + 0.932983 , + 0.928528 , + 0.923889 , + 0.919128 , + 0.914185 , + 0.90918 , + 0.903992 , + 0.898682 , + 0.89325 , + 0.887634 , + 0.881897 , + 0.876099 , + 0.870117 , + 0.863953 , + 0.857727 , + 0.851379 , + 0.844849 , + 0.838196 , + 0.831482 , + 0.824585 , + 0.817566 , + 0.810486 , + 0.803223 , + 0.795837 , + 0.78833 , + 0.780762 , + 0.77301 , + 0.765198 , + 0.757202 , + 0.749146 , + 0.740967 , + 0.732666 , + 0.724243 , + 0.715759 , + 0.707092 , + 0.698364 , + 0.689514 , + 0.680603 , + 0.67157 , + 0.662415 , + 0.653198 , + 0.64386 , + 0.634399 , + 0.624878 , + 0.615234 , + 0.60553 , + 0.595703 , + 0.585815 , + 0.575806 , + 0.565735 , + 0.555542 , + 0.545349 , + 0.534973 , + 0.524597 , + 0.514099 , + 0.50354 , + 0.49292 , + 0.482178 , + 0.471375 , + 0.46051 , + 0.449585 , + 0.438599 , + 0.427551 , + 0.416443 , + 0.405212 , + 0.393982 , + 0.38269 , + 0.371338 , + 0.359924 , + 0.348389 , + 0.336914 , + 0.325317 , + 0.31366 , + 0.302002 , + 0.290283 , + 0.278503 , + 0.266724 , + 0.254883 , + 0.242981 , + 0.231079 , + 0.219116 , + 0.207092 , + 0.195068 , + 0.183044 , + 0.170959 , + 0.158875 , + 0.146729 , + 0.134583 , + 0.122437 , + 0.110229 , + 0.0980225 , + 0.0858154 , + 0.0735474 , + 0.0613403 , + 0.0490723 , + 0.0368042 , + 0.0245361 , + 0.0122681 , + 0 , + -0.0122681 , + -0.0245361 , + -0.0368042 , + -0.0490723 , + -0.0613403 , + -0.0735474 , + -0.0858154 , + -0.0980225 , + -0.110229 , + -0.122437 , + -0.134583 , + -0.146729 , + -0.158875 , + -0.170959 , + -0.183044 , + -0.195068 , + -0.207092 , + -0.219116 , + -0.231079 , + -0.242981 , + -0.254883 , + -0.266724 , + -0.278503 , + -0.290283 , + -0.302002 , + -0.31366 , + -0.325317 , + -0.336914 , + -0.348389 , + -0.359924 , + -0.371338 , + -0.38269 , + -0.393982 , + -0.405212 , + -0.416443 , + -0.427551 , + -0.438599 , + -0.449585 , + -0.46051 , + -0.471375 , + -0.482178 , + -0.49292 , + -0.50354 , + -0.514099 , + -0.524597 , + -0.534973 , + -0.545349 , + -0.555542 , + -0.565735 , + -0.575806 , + -0.585815 , + -0.595703 , + -0.60553 , + -0.615234 , + -0.624878 , + -0.634399 , + -0.64386 , + -0.653198 , + -0.662415 , + -0.67157 , + -0.680603 , + -0.689514 , + -0.698364 , + -0.707092 , + -0.715759 , + -0.724243 , + -0.732666 , + -0.740967 , + -0.749146 , + -0.757202 , + -0.765198 , + -0.77301 , + -0.780762 , + -0.78833 , + -0.795837 , + -0.803223 , + -0.810486 , + -0.817566 , + -0.824585 , + -0.831482 , + -0.838196 , + -0.844849 , + -0.851379 , + -0.857727 , + -0.863953 , + -0.870117 , + -0.876099 , + -0.881897 , + -0.887634 , + -0.89325 , + -0.898682 , + -0.903992 , + -0.90918 , + -0.914185 , + -0.919128 , + -0.923889 , + -0.928528 , + -0.932983 , + -0.937317 , + -0.941528 , + -0.945618 , + -0.949524 , + -0.953308 , + -0.95697 , + -0.960449 , + -0.963806 , + -0.96698 , + -0.970032 , + -0.972961 , + -0.975708 , + -0.978333 , + -0.980774 , + -0.983093 , + -0.985291 , + -0.987305 , + -0.989197 , + -0.990906 , + -0.992493 , + -0.993896 , + -0.995178 , + -0.996338 , + -0.997314 , + -0.998108 , + -0.998779 , + -0.999329 , + -0.999695 , + -0.999939 , + -1 +}; + +double BandExpTable[11] = { + 1, + 0.993988 , + 0.988037 , + 0.982117 , + 0.976227 , + 0.970367 , + 0.964539 , + 0.95874 , + 0.953003 , + 0.947266 , + 0.941589 +}; + + +double HammingWindowTable[128*3]={ +5.38469e-16, 6.69307e-05, 0.000267706, 0.000602271, 0.00107054, 0.00167238, 0.00240763, 0.00327611, 0.00427757, 0.00541174, 0.00667833, 0.00807699, 0.00960736, 0.011269, 0.0130615, 0.0149844, 0.0170371, 0.0192191, 0.0215298, 0.0239687, 0.0265349, 0.029228, 0.032047, 0.0349914, 0.0380602, 0.0412527, 0.0445681, 0.0480053, 0.0515636, 0.055242, 0.0590394, 0.0629548, 0.0669873, 0.0711357, 0.0753989, 0.0797758, 0.0842652, 0.0888659, 0.0935766, 0.0983962, 0.103323, 0.108357, 0.113495, 0.118736, 0.12408, 0.129524, 0.135068, 0.140709, 0.146447, 0.152279, 0.158204, 0.164221, 0.170327, 0.176522, 0.182803, 0.18917, 0.195619, 0.20215, 0.208761, 0.21545, 0.222215, 0.229054, 0.235966, 0.242949, 0.25, 0.257118, 0.264302, 0.271548, 0.278856, 0.286222, 0.293646, 0.301126, 0.308658, 0.316242, 0.323875, 0.331555, 0.33928, 0.347048, 0.354858, 0.362706, 0.37059, 0.37851, 0.386462, 0.394444, 0.402455, 0.410492, 0.418552, 0.426635, 0.434737, 0.442857, 0.450991, 0.459139, 0.467298, 0.475466, 0.48364, 0.491819, 0.5, 0.508181, 0.51636, 0.524534, 0.532702, 0.540861, 0.549009, 0.557143, 0.565263, 0.573365, 0.581448, 0.589508, 0.597545, 0.605556, 0.613538, 0.62149, 0.62941, 0.637294, 0.645142, 0.652952, 0.66072, 0.668445, 0.676125, 0.683758, 0.691342, 0.698874, 0.706354, 0.713778, 0.721144, 0.728452, 0.735698, 0.742882, 0.75, 0.757051, 0.764034, 0.770946, 0.777785, 0.78455, 0.791239, 0.79785, 0.804381, 0.81083, 0.817197, 0.823478, 0.829673, 0.835779, 0.841796, 0.847721, 0.853553, 0.859291, 0.864932, 0.870476, 0.87592, 0.881264, 0.886505, 0.891643, 0.896677, 0.901604, 0.906423, 0.911134, 0.915735, 0.920224, 0.924601, 0.928864, 0.933013, 0.937045, 0.940961, 0.944758, 0.948436, 0.951995, 0.955432, 0.958747, 0.96194, 0.965009, 0.967953, 0.970772, 0.973465, 0.976031, 0.97847, 0.980781, 0.982963, 0.985016, 0.986938, 0.988731, 0.990393, 0.991923, 0.993322, 0.994588, 0.995722, 0.996724, 0.997592, 0.998328, 0.998929, 0.999398, 0.999732, 0.999933, 1, 0.999933, 0.999732, 0.999398, 0.998929, 0.998328, 0.997592, 0.996724, 0.995722, 0.994588, 0.993322, 0.991923, 0.990393, 0.988731, 0.986938, 0.985016, 0.982963, 0.980781, 0.97847, 0.976031, 0.973465, 0.970772, 0.967953, 0.965009, 0.96194, 0.958747, 0.955432, 0.951995, 0.948436, 0.944758, 0.940961, 0.937045, 0.933013, 0.928864, 0.924601, 0.920224, 0.915735, 0.911134, 0.906423, 0.901604, 0.896677, 0.891643, 0.886505, 0.881264, 0.87592, 0.870476, 0.864932, 0.859291, 0.853553, 0.847721, 0.841796, 0.835779, 0.829673, 0.823478, 0.817197, 0.81083, 0.804381, 0.79785, 0.791239, 0.78455, 0.777785, 0.770946, 0.764034, 0.757051, 0.75, 0.742882, 0.735698, 0.728452, 0.721144, 0.713778, 0.706354, 0.698874, 0.691342, 0.683758, 0.676125, 0.668445, 0.66072, 0.652952, 0.645142, 0.637294, 0.62941, 0.62149, 0.613538, 0.605556, 0.597545, 0.589508, 0.581448, 0.573365, 0.565263, 0.557143, 0.549009, 0.540861, 0.532702, 0.524534, 0.51636, 0.508181, 0.5, 0.491819, 0.48364, 0.475466, 0.467298, 0.459139, 0.450991, 0.442857, 0.434737, 0.426635, 0.418552, 0.410492, 0.402455, 0.394444, 0.386462, 0.37851, 0.37059, 0.362706, 0.354858, 0.347048, 0.33928, 0.331555, 0.323875, 0.316242, 0.308658, 0.301126, 0.293646, 0.286222, 0.278856, 0.271548, 0.264302, 0.257118, 0.25, 0.242949, 0.235966, 0.229054, 0.222215, 0.21545, 0.208761, 0.20215, 0.195619, 0.18917, 0.182803, 0.176522, 0.170327, 0.164221, 0.158204, 0.152279, 0.146447, 0.140709, 0.135068, 0.129524, 0.12408, 0.118736, 0.113495, 0.108357, 0.103323, 0.0983962, 0.0935766, 0.0888659, 0.0842652, 0.0797758, 0.0753989, 0.0711357, 0.0669873, 0.0629548, 0.0590394, 0.055242, 0.0515636, 0.0480053, 0.0445681, 0.0412527, 0.0380602, 0.0349914, 0.032047, 0.029228, 0.0265349, 0.0239687, 0.0215298, 0.0192191, 0.0170371, 0.0149844, 0.0130615, 0.011269, 0.00960736, 0.00807699, 0.00667833, 0.00541174, 0.00427757, 0.00327611, 0.00240763, 0.00167238, 0.00107054, 0.000602271, 0.000267706, 6.69307e-05, + }; diff --git a/test-streaming-mp3.pd b/test-streaming-mp3.pd new file mode 100644 index 0000000..e9e6b2e --- /dev/null +++ b/test-streaming-mp3.pd @@ -0,0 +1,96 @@ +#N canvas 15 9 986 678 10; +#X msg 63 58 bang; +#X obj 63 78 openpanel; +#X obj 63 100 t s b; +#X obj 63 137 pack s s; +#X obj 99 100 float \$0; +#X text 51 39 Step 1 : Load a sound file; +#X obj 117 137 makefilename %d-sample; +#X msg 443 280 \; pd dsp 1; +#X msg 509 280 \; pd dsp 0; +#X obj 454 254 loadbang; +#X obj 62 217 mp3streamout~; +#X floatatom 63 240 5 0 0; +#X obj 62 181 readsf~; +#X msg 62 158 open \$1 \$2; +#X msg 33 148 1; +#X msg 265 185 disconnect; +#X obj 63 117 route float; +#X msg 569 47 bang; +#X obj 569 67 openpanel; +#X obj 569 89 t s b; +#X obj 569 126 pack s s; +#X obj 605 89 float \$0; +#X text 557 28 Step 1 : Load a sound file; +#X obj 623 126 makefilename %d-sample; +#X obj 568 206 mp3streamout~; +#X floatatom 569 229 5 0 0; +#X obj 568 170 readsf~; +#X msg 568 147 open \$1 \$2; +#X msg 539 137 1; +#X msg 784 177 disconnect; +#X obj 569 106 route float; +#X obj 364 462 dac~; +#X obj 361 438 *~; +#X floatatom 416 465 5 0 0; +#X symbolatom 459 437 15 0 0; +#X obj 407 440 / 100; +#X obj 122 470 dac~; +#X obj 119 446 *~; +#X floatatom 174 473 5 0 0; +#X symbolatom 217 445 10 0 0; +#X obj 165 448 / 100; +#X obj 96 419 mp3streamin~ 5001 1; +#X obj 345 410 mp3streamin~ 5000 1; +#X msg 777 149 connect yves 5001; +#X msg 246 228 mpeg 32 2 5; +#X msg 246 228 mpeg 32 2 5; +#X msg 246 264 mpeg 224 2 5; +#X msg 258 157 connect localhost 5000; +#X msg 263 125 connect dregs 5000; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 2 0 3 0; +#X connect 2 1 4 0; +#X connect 3 0 13 0; +#X connect 4 0 16 0; +#X connect 6 0 3 1; +#X connect 9 0 7 0; +#X connect 10 0 11 0; +#X connect 12 0 10 0; +#X connect 12 0 10 1; +#X connect 13 0 12 0; +#X connect 14 0 12 0; +#X connect 15 0 10 0; +#X connect 16 0 6 0; +#X connect 17 0 18 0; +#X connect 18 0 19 0; +#X connect 19 0 20 0; +#X connect 19 1 21 0; +#X connect 20 0 27 0; +#X connect 21 0 30 0; +#X connect 23 0 20 1; +#X connect 24 0 25 0; +#X connect 26 0 24 0; +#X connect 26 0 24 1; +#X connect 27 0 26 0; +#X connect 28 0 26 0; +#X connect 29 0 24 0; +#X connect 30 0 23 0; +#X connect 32 0 31 0; +#X connect 32 0 31 1; +#X connect 33 0 35 0; +#X connect 35 0 32 1; +#X connect 37 0 36 0; +#X connect 37 0 36 1; +#X connect 38 0 40 0; +#X connect 40 0 37 1; +#X connect 41 0 37 0; +#X connect 41 2 39 0; +#X connect 42 0 32 0; +#X connect 42 2 34 0; +#X connect 43 0 24 0; +#X connect 44 0 10 0; +#X connect 46 0 10 0; +#X connect 47 0 10 0; +#X connect 48 0 10 0; diff --git a/timeval.h b/timeval.h new file mode 100644 index 0000000..ff04962 --- /dev/null +++ b/timeval.h @@ -0,0 +1,76 @@ +/* + * timeval.h 1.0 01/12/19 + * + * Defines gettimeofday, timeval, etc. for Win32 + * + * By Wu Yongwei + * + */ + +#ifndef _TIMEVAL_H +#define _TIMEVAL_H + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#ifndef __GNUC__ +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif /* not __GNUC__ */ + +#if 0 +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; +#endif /* 0 */ + +struct timezone { + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +__inline int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + static int tzflag; + + if (tv) + { + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + } + + if (tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} + +#else /* _WIN32 */ + +#include + +#endif /* _WIN32 */ + +#endif /* _TIMEVAL_H */ diff --git a/tk2c.bash b/tk2c.bash deleted file mode 100755 index 9dfeb03..0000000 --- a/tk2c.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -#set -x - -while read line -do - for word in $line - do - if [ "X"$word != "X"${word#\#} ] - then - echo // ${line#\#} - break - else - line=${line//\'/\\\'} -#useless, slashes never gets in - line=${line//\\/\\\\} -#this one's dirty, i know - line=${line//;/\\\\;} - line=${line//\"/\\\"} - echo 'sys_gui("'$line'\n");' - break - fi - done -done diff --git a/vocoder~-help.pd b/vocoder~-help.pd new file mode 100644 index 0000000..7bbf3b2 --- /dev/null +++ b/vocoder~-help.pd @@ -0,0 +1,55 @@ +#N canvas 123 129 764 525 10; +#X obj 201 393 dac~; +#X obj 153 330 adc~; +#X obj 204 355 rs-vocoder~; +#X text 356 457 vocoder~ : vocoder effect; +#X text 356 469 inspired by xvox written by; +#X text 357 483 Simon Morlat ( http://simon.morlat.free.fr ); +#X text 357 497 Part of unauthorized PD ( http://ydegoyon.free.fr ) +; +#X obj 125 406 env~; +#X floatatom 124 435 5 0 0; +#X obj 265 301 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 11500 1; +#X text 409 299 Cutoff Frequency; +#X obj 295 327 hsl 128 15 0 100 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 10500 1; +#X text 439 325 Voice Feedback [ 0 - 100 ]; +#X msg 49 39 bang; +#X obj 48 61 openpanel; +#X obj 48 81 t s b; +#X obj 105 83 float \$0; +#X text 56 16 Step 1 : Load a sound file; +#X obj 48 104 route float; +#X obj 49 196 soundfiler; +#X text 106 32 ( maybe \, a guitar sound ? ); +#X obj 48 127 makefilename %d-sample; +#X msg 49 174 read -resize \$1 \$2; +#X obj 50 153 pack s s; +#X msg 237 207 bang; +#X text 282 207 Step 2 : Start playing; +#X obj 237 254 tabplay~ \$0-sample; +#X msg 308 230 stop; +#X obj 237 230 metro 250; +#X text 49 300 Step 3 : Grab the mike !!!; +#X obj 333 90 table \$0-sample; +#X connect 1 0 2 0; +#X connect 2 0 0 0; +#X connect 2 0 0 1; +#X connect 2 0 7 0; +#X connect 7 0 8 0; +#X connect 9 0 2 2; +#X connect 11 0 2 3; +#X connect 13 0 14 0; +#X connect 14 0 15 0; +#X connect 15 0 23 0; +#X connect 15 1 16 0; +#X connect 16 0 18 0; +#X connect 18 0 21 0; +#X connect 21 0 23 1; +#X connect 22 0 19 0; +#X connect 23 0 22 0; +#X connect 24 0 28 0; +#X connect 26 0 2 1; +#X connect 27 0 28 0; +#X connect 28 0 26 0; diff --git a/vocoder~.c b/vocoder~.c new file mode 100644 index 0000000..08dbe3d --- /dev/null +++ b/vocoder~.c @@ -0,0 +1,163 @@ +/* vocoder~ -- vocoder effect inspired by xvox + * written by Simon Morlat ( http://simon.morlat.free.fr ) + * + * Copyleft 2001 Yves Degoyon. + * Permission is granted to use this software for any purpose provided you + * keep this copyright notice intact. + * + * THE AUTHOR AND HIS EXPLOITERS MAKE NO WARRANTY, EXPRESS OR IMPLIED, + * IN CONNECTION WITH THIS SOFTWARE. + * + */ + +#include "m_pd.h" +#include "filters.h" +#include "lpc.h" + +#define OUTPUT_DELAY 50 + +typedef struct _vocoder +{ + t_object x_obj; + t_float x_f; + t_float x_cutoff; + t_int x_vfeedback; + double *x_in1buf; + double *x_in2buf; + double *x_outbuf; + t_int x_blocksize; + t_int x_process; +} t_vocoder; + +static t_class *vocoder_class; + +static char *vocoder_version = "vocoder~: version 0.1, written by ydegoyon@free.fr, inspired by xvox (Simon Morlat)"; + +static void vocoder_cutoff(t_vocoder *x, t_floatarg fcutoff ) +{ + if ( fcutoff > 128.0 ) + { + fcutoff = 128.0; + } + if ( fcutoff < 0.0 ) + { + fcutoff = 0.0; + } + x->x_cutoff = fcutoff; +} + +static void vocoder_vfeedback(t_vocoder *x, t_floatarg fvfeedback ) +{ + if ( fvfeedback > 100.0 ) + { + fvfeedback = 100.0; + } + if ( fvfeedback < 0.0 ) + { + fvfeedback = 0.0; + } + x->x_vfeedback = fvfeedback; +} + +static t_int *vocoder_perform(t_int *w) +{ + t_vocoder *x = (t_vocoder *)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *fin1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out1 = (t_float *)(w[4]); + double correls[12], lpc_coef[11], f1[12], f2[12], lsp_coef[11]; + int offset=0; + int n = (int)(w[5]), i; + + if ( !x->x_process ) return (w+6); + if ( x->x_blocksize != n ) + { + if ( x->x_in1buf ) freebytes( x->x_in1buf, 3*x->x_blocksize/2*sizeof( double ) ); + if ( x->x_in2buf ) freebytes( x->x_in2buf, 3*x->x_blocksize/2*sizeof( double ) ); + if ( x->x_outbuf ) freebytes( x->x_outbuf, (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); + x->x_blocksize = n; + x->x_in1buf = (double*) getbytes( 3*x->x_blocksize/2*sizeof( double ) ); + x->x_in2buf = (double*) getbytes( 3*x->x_blocksize/2*sizeof( double ) ); + x->x_outbuf = (double*) getbytes( (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); + if ( !x->x_in1buf || !x->x_in2buf || !x->x_outbuf ) + { + post( "vocoder~ : allocations failed : stop processing" ); + x->x_process = 0; + } + } + + for(i=0;ix_blocksize/2;i++) + { + x->x_in1buf[i]=x->x_in1buf[i+x->x_blocksize]; + }; + for(i=0;ix_outbuf[i]=x->x_outbuf[i+x->x_blocksize]; + for(i=0;ix_blocksize;i++) + { + x->x_in1buf[x->x_blocksize/2+i]=(double)(*(in1++)); + x->x_in2buf[x->x_blocksize/2+i]=(double)(*(in2++)); + } + + hp_filter(x->x_in2buf,x->x_cutoff/128.,n); + for(i=0;i<4;i++) + { + comp_lpc(x->x_in1buf+offset,correls,lpc_coef,x->x_blocksize/4); + if (lpc_coef[0]!=0) + { + lpc2lsp(lpc_coef,f1,f2,lsp_coef); + lsp2lpc(lsp_coef,lpc_coef); + }; + lpc_filter(x->x_in2buf+offset,lpc_coef,x->x_outbuf+OUTPUT_DELAY+offset,x->x_blocksize/4); + offset+=x->x_blocksize/4; + }; + for(i=0;ix_blocksize;i++) + { + if ( x->x_outbuf[OUTPUT_DELAY+i] > 1.0 ) x->x_outbuf[OUTPUT_DELAY+i]=1.0; + if ( x->x_outbuf[OUTPUT_DELAY+i] < -1.0 ) x->x_outbuf[OUTPUT_DELAY+i]=-1.0; + *(out1++)=(t_float)(((100-x->x_vfeedback)*x->x_outbuf[OUTPUT_DELAY+i] + + x->x_vfeedback*(*fin1++))/100.0); + }; + + return (w+6); +} + +static void vocoder_dsp(t_vocoder *x, t_signal **sp) +{ + dsp_add(vocoder_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void *vocoder_new(void) +{ + t_vocoder *x = (t_vocoder *)pd_new(vocoder_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("cutoff")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("vfeedback")); + outlet_new(&x->x_obj, &s_signal); + x->x_cutoff = 60.; + x->x_vfeedback = 50; + x->x_blocksize=-1; + x->x_in1buf = NULL; + x->x_in2buf = NULL; + x->x_outbuf = NULL; + x->x_process = 1; + return (x); +} + + /* clean up */ +static void vocoder_free(t_vocoder *x) +{ + if ( x->x_in1buf ) freebytes( x->x_in1buf, 3*x->x_blocksize/2*sizeof( double ) ); + if ( x->x_in2buf ) freebytes( x->x_in2buf, 3*x->x_blocksize/2*sizeof( double ) ); + if ( x->x_outbuf ) freebytes( x->x_outbuf, (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); +} + +void vocoder_tilde_setup(void) +{ + post(vocoder_version); + vocoder_class = class_new(gensym("vocoder~"), (t_newmethod)vocoder_new, (t_method)vocoder_free, + sizeof(t_vocoder), 0, 0); + CLASS_MAINSIGNALIN( vocoder_class, t_vocoder, x_f ); + class_addmethod(vocoder_class, (t_method)vocoder_dsp, gensym("dsp"), 0); + class_addmethod(vocoder_class, (t_method)vocoder_cutoff, gensym("cutoff"), A_FLOAT, 0); + class_addmethod(vocoder_class, (t_method)vocoder_vfeedback, gensym("vfeedback"), A_FLOAT, 0); +} diff --git a/vocoder~/INSTALL b/vocoder~/INSTALL deleted file mode 100644 index 37c9567..0000000 --- a/vocoder~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/vocoder~ - -make clean - -make - -make install - -open help-vocoder~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/vocoder~/filters.c b/vocoder~/filters.c deleted file mode 100644 index 2bf9253..0000000 --- a/vocoder~/filters.c +++ /dev/null @@ -1,49 +0,0 @@ -/* -vox - a musical real-time vocoder. version 1.0 -Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - - - -void lpc_filter(double *buf_ppf, double *lpc_coef, double *buf_sy, int n) -{ - int i,j; - double acc; - - for(i=0;iTHRES) - { - for(i=0;i<3*n;i++) - { - buffer[i]=buf_x[i-n]*HammingWindowTable[i]; - }; - /* autocorrelation computation*/ - for(i=0;i<11;i++) - { - acc=0; - for(j=i;j0;k--) - { - b[k]=2*x*b[k+1]-b[k+2]+fonc[5-k]; - }; - res=x*b[1]-b[2]+fonc[5]/2; - return(res); -} - - - -/* converts LPC vector into LSP frequency vector */ -/* all LSP frenquencies are in [0;PI] but are normalized to be in [0;1] */ -void lpc2lsp(double lpc_coef[],double *f1,double *f2,double lsp_coef[]) -{ - - int i,k=1; - double *fonc,*prev_f,*f_exch; - double prev_sign1,sign,prev_sign2; - double *s, *prev_s,*s_exch; - double lpc_exp[11]; - - /* first computes an additional bandwidth expansion on LPC coeffs*/ - for(i=1;i<11;i++) - { - lpc_exp[i]=lpc_coef[i]*BandExpTable[i]; - }; - /* computes the F1 and F2 coeffs*/ - f1[0]=f2[0]=1; - for(i=0;i<5;i++) - { - f1[i+1]=lpc_exp[i+1]+lpc_exp[10-i]-f1[i]; - f2[i+1]=lpc_exp[i+1]-lpc_exp[10-i]+f2[i]; - }; - - /*find the roots of C(x) alternatively for F1 and F2*/ - fonc=f1; - prev_f=f2; - prev_sign1=evalc(1.0,f1); - prev_sign2=evalc(1.0,f2); - s=&prev_sign1; - prev_s=&prev_sign2; - for(i=1;i<256;i++) - { - sign=evalc(CosineTable[i],fonc); - if ((sign)*(*s)<0) - { - /* interpolate to find root*/ - lsp_coef[k]=((double)i-(*s)/(sign-(*s)))/256.0; - k++; - /* chek if all roots are found */ - if (k==11) i=257; - (*s)=sign; - /* pointers exchange */ - s_exch=s; - s=prev_s; - prev_s=s_exch; - f_exch=fonc; - fonc=prev_f; - prev_f=f_exch; - } - else (*s)=sign; - } - /* if here all roots are not found , use lspDC vector */ - if (k!=11) - { - for(i=1;i<11;i++) - { - lsp_coef[i]=LspDcTable[i]; - }; - }; -} - - -/* converts lsp frequencies to lpc coeffs */ - -void lsp2lpc(double *lsp_coef,double *lpc_coef) -{ - int i,j=0,index,ok=1; - double lspcos[11],delta,tmp,p_avg; - double F1[12],F2[12]; /* begin at indice two*/ - - F1[0]=0;F1[1]=1; - F2[0]=0;F2[1]=1; - /* stability check */ - while(ok && (j<11)) - { - ok=0; - for(i=1;i<10;i++) - { - if( (lsp_coef[i+1]-lsp_coef[i]) < Dmin) - { - ok=1; - p_avg=(lsp_coef[i]+lsp_coef[i+1])/2.0; - lsp_coef[i]=p_avg-Dmin/2.0; - lsp_coef[i+1]=p_avg+Dmin/2.0; - }; - }; - j++; - } - - /* first converts lsp frequencies to lsp coefficients */ - for (i=1;i<11;i++) - { - /* interpolation */ - tmp=lsp_coef[i]*255.0; - index=(int)tmp; - delta=CosineTable[index+1]-CosineTable[index]; - lspcos[i]=CosineTable[index]+delta*(tmp-index); - }; - - for(i=2;i<7;i++) - { - F1[i]=-2*lspcos[2*i-3]*F1[i-1]+2*F1[i-2]; - F2[i]=-2*lspcos[2*i-2]*F2[i-1]+2*F2[i-2]; - for(j=i-1;j>1;j--) - { - F1[j]=F1[j]-2*lspcos[2*i-3]*F1[j-1]+F1[j-2]; - F2[j]=F2[j]-2*lspcos[2*i-2]*F2[j-1]+F2[j-2]; - }; - }; - for(i=6;i>1;i--) - { - F1[i]=F1[i]+F1[i-1]; - F2[i]=F2[i]-F2[i-1]; - }; - for(i=2;i<7;i++) - { - lpc_coef[i-1]=(F1[i]+F2[i])*0.5; - lpc_coef[i+4]=(F1[8-i]-F2[8-i])*0.5; - }; - lpc_coef[0]=1; -} - diff --git a/vocoder~/rs-vocoder~.pd b/vocoder~/rs-vocoder~.pd deleted file mode 100644 index 65dfc0d..0000000 --- a/vocoder~/rs-vocoder~.pd +++ /dev/null @@ -1,13 +0,0 @@ -#N canvas 0 0 450 300 10; -#X obj 39 146 block~ 512; -#X obj 89 36 inlet~; -#X obj 151 34 inlet~; -#X obj 129 77 vocoder~; -#X obj 207 33 inlet; -#X obj 261 33 inlet; -#X obj 129 108 outlet~; -#X connect 1 0 3 0; -#X connect 2 0 3 1; -#X connect 3 0 6 0; -#X connect 4 0 3 2; -#X connect 5 0 3 3; diff --git a/vocoder~/tables.c b/vocoder~/tables.c deleted file mode 100644 index 049a523..0000000 --- a/vocoder~/tables.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -vox - a musical real-time vocoder. version 1.0 -Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -double LspDcTable[11] = { - 0, - 0.0955505 , - 0.144073 , - 0.23468 , - 0.329773 , - 0.42334 , - 0.503387 , - 0.602783 , - 0.679321 , - 0.77771 , - 0.845886 -}; - -double CosineTable[257] = { - 1 , - 0.999939 , - 0.999695 , - 0.999329 , - 0.998779 , - 0.998108 , - 0.997314 , - 0.996338 , - 0.995178 , - 0.993896 , - 0.992493 , - 0.990906 , - 0.989197 , - 0.987305 , - 0.985291 , - 0.983093 , - 0.980774 , - 0.978333 , - 0.975708 , - 0.972961 , - 0.970032 , - 0.96698 , - 0.963806 , - 0.960449 , - 0.95697 , - 0.953308 , - 0.949524 , - 0.945618 , - 0.941528 , - 0.937317 , - 0.932983 , - 0.928528 , - 0.923889 , - 0.919128 , - 0.914185 , - 0.90918 , - 0.903992 , - 0.898682 , - 0.89325 , - 0.887634 , - 0.881897 , - 0.876099 , - 0.870117 , - 0.863953 , - 0.857727 , - 0.851379 , - 0.844849 , - 0.838196 , - 0.831482 , - 0.824585 , - 0.817566 , - 0.810486 , - 0.803223 , - 0.795837 , - 0.78833 , - 0.780762 , - 0.77301 , - 0.765198 , - 0.757202 , - 0.749146 , - 0.740967 , - 0.732666 , - 0.724243 , - 0.715759 , - 0.707092 , - 0.698364 , - 0.689514 , - 0.680603 , - 0.67157 , - 0.662415 , - 0.653198 , - 0.64386 , - 0.634399 , - 0.624878 , - 0.615234 , - 0.60553 , - 0.595703 , - 0.585815 , - 0.575806 , - 0.565735 , - 0.555542 , - 0.545349 , - 0.534973 , - 0.524597 , - 0.514099 , - 0.50354 , - 0.49292 , - 0.482178 , - 0.471375 , - 0.46051 , - 0.449585 , - 0.438599 , - 0.427551 , - 0.416443 , - 0.405212 , - 0.393982 , - 0.38269 , - 0.371338 , - 0.359924 , - 0.348389 , - 0.336914 , - 0.325317 , - 0.31366 , - 0.302002 , - 0.290283 , - 0.278503 , - 0.266724 , - 0.254883 , - 0.242981 , - 0.231079 , - 0.219116 , - 0.207092 , - 0.195068 , - 0.183044 , - 0.170959 , - 0.158875 , - 0.146729 , - 0.134583 , - 0.122437 , - 0.110229 , - 0.0980225 , - 0.0858154 , - 0.0735474 , - 0.0613403 , - 0.0490723 , - 0.0368042 , - 0.0245361 , - 0.0122681 , - 0 , - -0.0122681 , - -0.0245361 , - -0.0368042 , - -0.0490723 , - -0.0613403 , - -0.0735474 , - -0.0858154 , - -0.0980225 , - -0.110229 , - -0.122437 , - -0.134583 , - -0.146729 , - -0.158875 , - -0.170959 , - -0.183044 , - -0.195068 , - -0.207092 , - -0.219116 , - -0.231079 , - -0.242981 , - -0.254883 , - -0.266724 , - -0.278503 , - -0.290283 , - -0.302002 , - -0.31366 , - -0.325317 , - -0.336914 , - -0.348389 , - -0.359924 , - -0.371338 , - -0.38269 , - -0.393982 , - -0.405212 , - -0.416443 , - -0.427551 , - -0.438599 , - -0.449585 , - -0.46051 , - -0.471375 , - -0.482178 , - -0.49292 , - -0.50354 , - -0.514099 , - -0.524597 , - -0.534973 , - -0.545349 , - -0.555542 , - -0.565735 , - -0.575806 , - -0.585815 , - -0.595703 , - -0.60553 , - -0.615234 , - -0.624878 , - -0.634399 , - -0.64386 , - -0.653198 , - -0.662415 , - -0.67157 , - -0.680603 , - -0.689514 , - -0.698364 , - -0.707092 , - -0.715759 , - -0.724243 , - -0.732666 , - -0.740967 , - -0.749146 , - -0.757202 , - -0.765198 , - -0.77301 , - -0.780762 , - -0.78833 , - -0.795837 , - -0.803223 , - -0.810486 , - -0.817566 , - -0.824585 , - -0.831482 , - -0.838196 , - -0.844849 , - -0.851379 , - -0.857727 , - -0.863953 , - -0.870117 , - -0.876099 , - -0.881897 , - -0.887634 , - -0.89325 , - -0.898682 , - -0.903992 , - -0.90918 , - -0.914185 , - -0.919128 , - -0.923889 , - -0.928528 , - -0.932983 , - -0.937317 , - -0.941528 , - -0.945618 , - -0.949524 , - -0.953308 , - -0.95697 , - -0.960449 , - -0.963806 , - -0.96698 , - -0.970032 , - -0.972961 , - -0.975708 , - -0.978333 , - -0.980774 , - -0.983093 , - -0.985291 , - -0.987305 , - -0.989197 , - -0.990906 , - -0.992493 , - -0.993896 , - -0.995178 , - -0.996338 , - -0.997314 , - -0.998108 , - -0.998779 , - -0.999329 , - -0.999695 , - -0.999939 , - -1 -}; - -double BandExpTable[11] = { - 1, - 0.993988 , - 0.988037 , - 0.982117 , - 0.976227 , - 0.970367 , - 0.964539 , - 0.95874 , - 0.953003 , - 0.947266 , - 0.941589 -}; - - -double HammingWindowTable[128*3]={ -5.38469e-16, 6.69307e-05, 0.000267706, 0.000602271, 0.00107054, 0.00167238, 0.00240763, 0.00327611, 0.00427757, 0.00541174, 0.00667833, 0.00807699, 0.00960736, 0.011269, 0.0130615, 0.0149844, 0.0170371, 0.0192191, 0.0215298, 0.0239687, 0.0265349, 0.029228, 0.032047, 0.0349914, 0.0380602, 0.0412527, 0.0445681, 0.0480053, 0.0515636, 0.055242, 0.0590394, 0.0629548, 0.0669873, 0.0711357, 0.0753989, 0.0797758, 0.0842652, 0.0888659, 0.0935766, 0.0983962, 0.103323, 0.108357, 0.113495, 0.118736, 0.12408, 0.129524, 0.135068, 0.140709, 0.146447, 0.152279, 0.158204, 0.164221, 0.170327, 0.176522, 0.182803, 0.18917, 0.195619, 0.20215, 0.208761, 0.21545, 0.222215, 0.229054, 0.235966, 0.242949, 0.25, 0.257118, 0.264302, 0.271548, 0.278856, 0.286222, 0.293646, 0.301126, 0.308658, 0.316242, 0.323875, 0.331555, 0.33928, 0.347048, 0.354858, 0.362706, 0.37059, 0.37851, 0.386462, 0.394444, 0.402455, 0.410492, 0.418552, 0.426635, 0.434737, 0.442857, 0.450991, 0.459139, 0.467298, 0.475466, 0.48364, 0.491819, 0.5, 0.508181, 0.51636, 0.524534, 0.532702, 0.540861, 0.549009, 0.557143, 0.565263, 0.573365, 0.581448, 0.589508, 0.597545, 0.605556, 0.613538, 0.62149, 0.62941, 0.637294, 0.645142, 0.652952, 0.66072, 0.668445, 0.676125, 0.683758, 0.691342, 0.698874, 0.706354, 0.713778, 0.721144, 0.728452, 0.735698, 0.742882, 0.75, 0.757051, 0.764034, 0.770946, 0.777785, 0.78455, 0.791239, 0.79785, 0.804381, 0.81083, 0.817197, 0.823478, 0.829673, 0.835779, 0.841796, 0.847721, 0.853553, 0.859291, 0.864932, 0.870476, 0.87592, 0.881264, 0.886505, 0.891643, 0.896677, 0.901604, 0.906423, 0.911134, 0.915735, 0.920224, 0.924601, 0.928864, 0.933013, 0.937045, 0.940961, 0.944758, 0.948436, 0.951995, 0.955432, 0.958747, 0.96194, 0.965009, 0.967953, 0.970772, 0.973465, 0.976031, 0.97847, 0.980781, 0.982963, 0.985016, 0.986938, 0.988731, 0.990393, 0.991923, 0.993322, 0.994588, 0.995722, 0.996724, 0.997592, 0.998328, 0.998929, 0.999398, 0.999732, 0.999933, 1, 0.999933, 0.999732, 0.999398, 0.998929, 0.998328, 0.997592, 0.996724, 0.995722, 0.994588, 0.993322, 0.991923, 0.990393, 0.988731, 0.986938, 0.985016, 0.982963, 0.980781, 0.97847, 0.976031, 0.973465, 0.970772, 0.967953, 0.965009, 0.96194, 0.958747, 0.955432, 0.951995, 0.948436, 0.944758, 0.940961, 0.937045, 0.933013, 0.928864, 0.924601, 0.920224, 0.915735, 0.911134, 0.906423, 0.901604, 0.896677, 0.891643, 0.886505, 0.881264, 0.87592, 0.870476, 0.864932, 0.859291, 0.853553, 0.847721, 0.841796, 0.835779, 0.829673, 0.823478, 0.817197, 0.81083, 0.804381, 0.79785, 0.791239, 0.78455, 0.777785, 0.770946, 0.764034, 0.757051, 0.75, 0.742882, 0.735698, 0.728452, 0.721144, 0.713778, 0.706354, 0.698874, 0.691342, 0.683758, 0.676125, 0.668445, 0.66072, 0.652952, 0.645142, 0.637294, 0.62941, 0.62149, 0.613538, 0.605556, 0.597545, 0.589508, 0.581448, 0.573365, 0.565263, 0.557143, 0.549009, 0.540861, 0.532702, 0.524534, 0.51636, 0.508181, 0.5, 0.491819, 0.48364, 0.475466, 0.467298, 0.459139, 0.450991, 0.442857, 0.434737, 0.426635, 0.418552, 0.410492, 0.402455, 0.394444, 0.386462, 0.37851, 0.37059, 0.362706, 0.354858, 0.347048, 0.33928, 0.331555, 0.323875, 0.316242, 0.308658, 0.301126, 0.293646, 0.286222, 0.278856, 0.271548, 0.264302, 0.257118, 0.25, 0.242949, 0.235966, 0.229054, 0.222215, 0.21545, 0.208761, 0.20215, 0.195619, 0.18917, 0.182803, 0.176522, 0.170327, 0.164221, 0.158204, 0.152279, 0.146447, 0.140709, 0.135068, 0.129524, 0.12408, 0.118736, 0.113495, 0.108357, 0.103323, 0.0983962, 0.0935766, 0.0888659, 0.0842652, 0.0797758, 0.0753989, 0.0711357, 0.0669873, 0.0629548, 0.0590394, 0.055242, 0.0515636, 0.0480053, 0.0445681, 0.0412527, 0.0380602, 0.0349914, 0.032047, 0.029228, 0.0265349, 0.0239687, 0.0215298, 0.0192191, 0.0170371, 0.0149844, 0.0130615, 0.011269, 0.00960736, 0.00807699, 0.00667833, 0.00541174, 0.00427757, 0.00327611, 0.00240763, 0.00167238, 0.00107054, 0.000602271, 0.000267706, 6.69307e-05, - }; diff --git a/vocoder~/vocoder~-help.pd b/vocoder~/vocoder~-help.pd deleted file mode 100644 index 7bbf3b2..0000000 --- a/vocoder~/vocoder~-help.pd +++ /dev/null @@ -1,55 +0,0 @@ -#N canvas 123 129 764 525 10; -#X obj 201 393 dac~; -#X obj 153 330 adc~; -#X obj 204 355 rs-vocoder~; -#X text 356 457 vocoder~ : vocoder effect; -#X text 356 469 inspired by xvox written by; -#X text 357 483 Simon Morlat ( http://simon.morlat.free.fr ); -#X text 357 497 Part of unauthorized PD ( http://ydegoyon.free.fr ) -; -#X obj 125 406 env~; -#X floatatom 124 435 5 0 0; -#X obj 265 301 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 11500 1; -#X text 409 299 Cutoff Frequency; -#X obj 295 327 hsl 128 15 0 100 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 10500 1; -#X text 439 325 Voice Feedback [ 0 - 100 ]; -#X msg 49 39 bang; -#X obj 48 61 openpanel; -#X obj 48 81 t s b; -#X obj 105 83 float \$0; -#X text 56 16 Step 1 : Load a sound file; -#X obj 48 104 route float; -#X obj 49 196 soundfiler; -#X text 106 32 ( maybe \, a guitar sound ? ); -#X obj 48 127 makefilename %d-sample; -#X msg 49 174 read -resize \$1 \$2; -#X obj 50 153 pack s s; -#X msg 237 207 bang; -#X text 282 207 Step 2 : Start playing; -#X obj 237 254 tabplay~ \$0-sample; -#X msg 308 230 stop; -#X obj 237 230 metro 250; -#X text 49 300 Step 3 : Grab the mike !!!; -#X obj 333 90 table \$0-sample; -#X connect 1 0 2 0; -#X connect 2 0 0 0; -#X connect 2 0 0 1; -#X connect 2 0 7 0; -#X connect 7 0 8 0; -#X connect 9 0 2 2; -#X connect 11 0 2 3; -#X connect 13 0 14 0; -#X connect 14 0 15 0; -#X connect 15 0 23 0; -#X connect 15 1 16 0; -#X connect 16 0 18 0; -#X connect 18 0 21 0; -#X connect 21 0 23 1; -#X connect 22 0 19 0; -#X connect 23 0 22 0; -#X connect 24 0 28 0; -#X connect 26 0 2 1; -#X connect 27 0 28 0; -#X connect 28 0 26 0; diff --git a/vocoder~/vocoder~.c b/vocoder~/vocoder~.c deleted file mode 100644 index 08dbe3d..0000000 --- a/vocoder~/vocoder~.c +++ /dev/null @@ -1,163 +0,0 @@ -/* vocoder~ -- vocoder effect inspired by xvox - * written by Simon Morlat ( http://simon.morlat.free.fr ) - * - * Copyleft 2001 Yves Degoyon. - * Permission is granted to use this software for any purpose provided you - * keep this copyright notice intact. - * - * THE AUTHOR AND HIS EXPLOITERS MAKE NO WARRANTY, EXPRESS OR IMPLIED, - * IN CONNECTION WITH THIS SOFTWARE. - * - */ - -#include "m_pd.h" -#include "filters.h" -#include "lpc.h" - -#define OUTPUT_DELAY 50 - -typedef struct _vocoder -{ - t_object x_obj; - t_float x_f; - t_float x_cutoff; - t_int x_vfeedback; - double *x_in1buf; - double *x_in2buf; - double *x_outbuf; - t_int x_blocksize; - t_int x_process; -} t_vocoder; - -static t_class *vocoder_class; - -static char *vocoder_version = "vocoder~: version 0.1, written by ydegoyon@free.fr, inspired by xvox (Simon Morlat)"; - -static void vocoder_cutoff(t_vocoder *x, t_floatarg fcutoff ) -{ - if ( fcutoff > 128.0 ) - { - fcutoff = 128.0; - } - if ( fcutoff < 0.0 ) - { - fcutoff = 0.0; - } - x->x_cutoff = fcutoff; -} - -static void vocoder_vfeedback(t_vocoder *x, t_floatarg fvfeedback ) -{ - if ( fvfeedback > 100.0 ) - { - fvfeedback = 100.0; - } - if ( fvfeedback < 0.0 ) - { - fvfeedback = 0.0; - } - x->x_vfeedback = fvfeedback; -} - -static t_int *vocoder_perform(t_int *w) -{ - t_vocoder *x = (t_vocoder *)(w[1]); - t_float *in1 = (t_float *)(w[2]); - t_float *fin1 = (t_float *)(w[2]); - t_float *in2 = (t_float *)(w[3]); - t_float *out1 = (t_float *)(w[4]); - double correls[12], lpc_coef[11], f1[12], f2[12], lsp_coef[11]; - int offset=0; - int n = (int)(w[5]), i; - - if ( !x->x_process ) return (w+6); - if ( x->x_blocksize != n ) - { - if ( x->x_in1buf ) freebytes( x->x_in1buf, 3*x->x_blocksize/2*sizeof( double ) ); - if ( x->x_in2buf ) freebytes( x->x_in2buf, 3*x->x_blocksize/2*sizeof( double ) ); - if ( x->x_outbuf ) freebytes( x->x_outbuf, (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); - x->x_blocksize = n; - x->x_in1buf = (double*) getbytes( 3*x->x_blocksize/2*sizeof( double ) ); - x->x_in2buf = (double*) getbytes( 3*x->x_blocksize/2*sizeof( double ) ); - x->x_outbuf = (double*) getbytes( (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); - if ( !x->x_in1buf || !x->x_in2buf || !x->x_outbuf ) - { - post( "vocoder~ : allocations failed : stop processing" ); - x->x_process = 0; - } - } - - for(i=0;ix_blocksize/2;i++) - { - x->x_in1buf[i]=x->x_in1buf[i+x->x_blocksize]; - }; - for(i=0;ix_outbuf[i]=x->x_outbuf[i+x->x_blocksize]; - for(i=0;ix_blocksize;i++) - { - x->x_in1buf[x->x_blocksize/2+i]=(double)(*(in1++)); - x->x_in2buf[x->x_blocksize/2+i]=(double)(*(in2++)); - } - - hp_filter(x->x_in2buf,x->x_cutoff/128.,n); - for(i=0;i<4;i++) - { - comp_lpc(x->x_in1buf+offset,correls,lpc_coef,x->x_blocksize/4); - if (lpc_coef[0]!=0) - { - lpc2lsp(lpc_coef,f1,f2,lsp_coef); - lsp2lpc(lsp_coef,lpc_coef); - }; - lpc_filter(x->x_in2buf+offset,lpc_coef,x->x_outbuf+OUTPUT_DELAY+offset,x->x_blocksize/4); - offset+=x->x_blocksize/4; - }; - for(i=0;ix_blocksize;i++) - { - if ( x->x_outbuf[OUTPUT_DELAY+i] > 1.0 ) x->x_outbuf[OUTPUT_DELAY+i]=1.0; - if ( x->x_outbuf[OUTPUT_DELAY+i] < -1.0 ) x->x_outbuf[OUTPUT_DELAY+i]=-1.0; - *(out1++)=(t_float)(((100-x->x_vfeedback)*x->x_outbuf[OUTPUT_DELAY+i] - + x->x_vfeedback*(*fin1++))/100.0); - }; - - return (w+6); -} - -static void vocoder_dsp(t_vocoder *x, t_signal **sp) -{ - dsp_add(vocoder_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} - -static void *vocoder_new(void) -{ - t_vocoder *x = (t_vocoder *)pd_new(vocoder_class); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("cutoff")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("vfeedback")); - outlet_new(&x->x_obj, &s_signal); - x->x_cutoff = 60.; - x->x_vfeedback = 50; - x->x_blocksize=-1; - x->x_in1buf = NULL; - x->x_in2buf = NULL; - x->x_outbuf = NULL; - x->x_process = 1; - return (x); -} - - /* clean up */ -static void vocoder_free(t_vocoder *x) -{ - if ( x->x_in1buf ) freebytes( x->x_in1buf, 3*x->x_blocksize/2*sizeof( double ) ); - if ( x->x_in2buf ) freebytes( x->x_in2buf, 3*x->x_blocksize/2*sizeof( double ) ); - if ( x->x_outbuf ) freebytes( x->x_outbuf, (x->x_blocksize+OUTPUT_DELAY)*sizeof( double ) ); -} - -void vocoder_tilde_setup(void) -{ - post(vocoder_version); - vocoder_class = class_new(gensym("vocoder~"), (t_newmethod)vocoder_new, (t_method)vocoder_free, - sizeof(t_vocoder), 0, 0); - CLASS_MAINSIGNALIN( vocoder_class, t_vocoder, x_f ); - class_addmethod(vocoder_class, (t_method)vocoder_dsp, gensym("dsp"), 0); - class_addmethod(vocoder_class, (t_method)vocoder_cutoff, gensym("cutoff"), A_FLOAT, 0); - class_addmethod(vocoder_class, (t_method)vocoder_vfeedback, gensym("vfeedback"), A_FLOAT, 0); -} diff --git a/wahwah~-help.pd b/wahwah~-help.pd new file mode 100644 index 0000000..8afeb3c --- /dev/null +++ b/wahwah~-help.pd @@ -0,0 +1,48 @@ +#N canvas 45 57 817 573 10; +#X text 319 534 comments & bugs @ ydegoyon.free.fr; +#X text 431 111 Wahwah~ : used in psychedelic music; +#X obj 144 411 dac~; +#X obj 148 377 rs-wahwah~; +#X msg 94 62 bang; +#X obj 93 84 openpanel; +#X obj 93 104 t s b; +#X obj 150 106 float \$0; +#X text 101 39 Step 1 : Load a sound file; +#X obj 93 127 route float; +#X obj 94 219 soundfiler; +#X text 151 55 ( maybe \, a guitar sound ? ); +#X obj 93 150 makefilename %d-sample; +#X obj 582 374 table \$0-sample; +#X msg 94 197 read -resize \$1 \$2; +#X obj 95 176 pack s s; +#X msg 146 307 bang; +#X text 191 307 Step 2 : Start playing; +#X obj 59 288 adc~; +#X text 229 379 Step 3 : Modify parameters; +#X text 487 483 ( http://st.karelia.ru/~smlalx ); +#X text 320 470 a DOS guitar effects software that rocks; +#X text 321 484 written by Alexei Smoli; +#X obj 606 263 loadbang; +#X msg 608 293 \; pd dsp 1; +#X text 319 456 the algorithm is borrowed from Digital Effects \,; +#X obj 146 354 tabplay~ \$0-sample; +#X text 35 266 Plug a guitar ??; +#X msg 228 330 stop; +#X obj 146 330 metro 250; +#X connect 3 0 2 0; +#X connect 3 0 2 1; +#X connect 4 0 5 0; +#X connect 5 0 6 0; +#X connect 6 0 15 0; +#X connect 6 1 7 0; +#X connect 7 0 9 0; +#X connect 9 0 12 0; +#X connect 12 0 15 1; +#X connect 14 0 10 0; +#X connect 15 0 14 0; +#X connect 16 0 29 0; +#X connect 18 0 3 0; +#X connect 23 0 24 0; +#X connect 26 0 3 0; +#X connect 28 0 29 0; +#X connect 29 0 26 0; diff --git a/wahwah~.c b/wahwah~.c new file mode 100644 index 0000000..7f9a9ed --- /dev/null +++ b/wahwah~.c @@ -0,0 +1,408 @@ +/* Copyright (c) 2002 Yves Degoyon. */ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ +/* WARRANTIES, see the file, "COPYING" in this distribution. */ +/* */ +/* wahwah~ -- a kind of effect used in psychedelic music */ +/* the algorithm was taken from Digital Effects, */ +/* a guitar effects software for DOS which rocks, written by Alexey Smoli */ +/* ( http://st.karelia.ru/~smlalx/ ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* Made while listening to : */ +/* */ +/* Crass -- "Shaved Women ( Collaborators )" */ +/* Zounds -- "Can't Cheat Karma" */ +/* */ +/* Special message for the french : */ +/* "Delay all your work...and go vote against national front" */ +/* ---------------------------------------------------------------------------- */ + +#include "m_pd.h" +#include +#include + +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif + +#define BFSZ 4096 /* main delay buffer */ +#define BLOCK_DELAY 10 /* number of blocks to delay */ +#define NA 0.0 /* param not applicable */ +#define COEFFSIZE 3000 /* coefficients size */ +#define NBCOEFFS 5 /* number of coefficients */ + +static char *wahwah_version = "wahwah~: an audio wahwah, version 0.1 (ydegoyon@free.fr)"; + +typedef struct _wahwah +{ + t_object x_obj; + double *x_buf; + t_int x_samplerate; + t_float *x_coeffs; + double x_minfc; /* min frequency Hz */ /* 0< <3000 */ + double x_maxfc; /* max frequency Hz */ /* 0< <3000 */ + double x_sense; /* increase/decrease frequency change by one mouse movement Hz */ /* 0< <=1000 */ + double x_maxstep; /* maximum frequency change step KHz */ /* 0< <=100 */ + double x_dbgain; /* peaking filter gain dB */ /* -15<= <=15 */ + double x_bandwidth; /* bandwidth in octaves (between midpoint (dBgain/2) + gain frequencies) or */ /* 0< <10 */ + double x_Q; /* the EE kinda definition */ /* 0< <=1 */ + + /* variables for audio computation */ + double min_coef,max_coef,cur_coef,step,maxstep; + t_int down; + /* amplitudes */ + short x0,x1,x2; + t_int y0,y1,y2; + + t_float x_f; +} t_wahwah; + +static t_class *wahwah_class; + +static void wahwah_set_coeffs (t_wahwah *x) +{ + t_int i; + double omega; + double sn,cs; + double alpha = 0.0; + /* filter coefficients */ + double a0,a1,a2,b0,b1,b2; + double A; + + A = exp(x->x_dbgain/40.0)*log(10.0); + for (i = 0; i < COEFFSIZE; i++) + { + omega = 2.0*M_PI*(double)i/(double)x->x_samplerate; + sn = sin(omega); + cs = cos(omega); + if (x->x_bandwidth) + alpha = sn*sin(log(2.0)/2.0*x->x_bandwidth*omega/sn); + else + /* if Q is specified instead of bandwidth */ + if (x->x_Q) + alpha = sn/(2.0*x->x_Q); + + /* then compute the coefs for whichever filter type you want */ + b0 = 1.0 + alpha*A; + b1 = -2.0*cs ; + b2 = 1.0 - alpha*A; + a0 = 1.0 + alpha/A; + a1 = -2.0*cs ; + a2 = 1.0 - alpha/A; + + *(x->x_coeffs+i*NBCOEFFS) = (b0/a0); + *(x->x_coeffs+i*NBCOEFFS+1) = (b1/a0); + *(x->x_coeffs+i*NBCOEFFS+2) = (b2/a0); + *(x->x_coeffs+i*NBCOEFFS+3) = (a1/a0); + *(x->x_coeffs+i*NBCOEFFS+4) = (a2/a0); + // post( "wahwah~ : coeff : %f", *(x->x_coeffs+i*NBCOEFFS+4) ); + } + x->min_coef = x->x_minfc; + x->max_coef = x->x_maxfc; + x->cur_coef = x->min_coef; + x->down = 1; + x->step = 0; + x->maxstep = x->x_maxstep/(double)x->x_samplerate*1000.0; +} + +static void wahwah_bandwidth(t_wahwah *x, t_floatarg fbandwidth ) +{ + if ( fbandwidth > 10.0 ) + { + fbandwidth = 10.0; + } + if ( fbandwidth < 0.0 ) + { + fbandwidth = 0.0; + } + x->x_bandwidth = fbandwidth; + // post( "wahwah~ : bandwidth: %f", x->x_bandwidth ); + wahwah_set_coeffs( x ); +} + +static void wahwah_dbgain(t_wahwah *x, t_floatarg fdbgain ) +{ + if ( fdbgain > 15.0 ) + { + fdbgain = 15.0; + } + if ( fdbgain < -15.0 ) + { + fdbgain = -15.0; + } + x->x_dbgain = fdbgain; + // post( "wahwah~ : dbgain: %f", x->x_dbgain ); + wahwah_set_coeffs( x ); +} + +static void wahwah_maxstep(t_wahwah *x, t_floatarg fmaxstep ) +{ + if ( fmaxstep > 100.0 ) + { + fmaxstep = 100.0; + } + if ( fmaxstep < 0.0 ) + { + fmaxstep = 0.0; + } + x->x_maxstep = fmaxstep; + // post( "wahwah~ : maxstep: %f", x->x_maxstep ); + wahwah_set_coeffs( x ); +} + +static void wahwah_sensibility(t_wahwah *x, t_floatarg fsensibility ) +{ + if ( fsensibility > 1000.0 ) + { + fsensibility = 1000.0; + } + if ( fsensibility < 0.0 ) + { + fsensibility = 0.0; + } + x->x_sense = fsensibility; + // post( "wahwah~ : sensibility: %f", x->x_sense ); + wahwah_set_coeffs( x ); +} + +static void wahwah_maxfreq(t_wahwah *x, t_floatarg fmaxfreq ) +{ + if ( fmaxfreq > 3000.0 ) + { + fmaxfreq = 3000.0; + } + if ( fmaxfreq < 0.0 ) + { + fmaxfreq = 0.0; + } + x->x_maxfc = fmaxfreq; + // post( "wahwah~ : maxfreq: %f", x->x_maxfc ); + wahwah_set_coeffs( x ); +} + +static void wahwah_minfreq(t_wahwah *x, t_floatarg fminfreq ) +{ + if ( fminfreq > 3000.0 ) + { + fminfreq = 3000.0; + } + if ( fminfreq < 0.0 ) + { + fminfreq = 0.0; + } + x->x_minfc = fminfreq; + // post( "wahwah~ : minfreq: %f", x->x_minfc ); + wahwah_set_coeffs( x ); +} + +static void wahwah_step(t_wahwah *x, t_floatarg fstep ) +{ + if ( fstep > x->x_maxstep ) + { + fstep = x->x_maxstep; + } + if ( fstep < 0 ) + { + fstep = 0; + } + x->step = fstep*x->x_sense/x->x_samplerate; +} + +static t_int *wahwah_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_int n = (int)(w[3]); + t_wahwah *x = (t_wahwah*)(w[4]); + t_int i; + + for (i=0; ix0 = (int)((*(in+i))*32768); + + x->y0 = (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS))*x->x0 + + (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+1))*x->x1 + + (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+2))*x->x2 + - (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+3))*x->y1 + - (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+4))*x->y2; + + x->y2 = x->y1; + x->y1 = x->y0; + x->x2 = x->x1; + x->x1 = x->x0; + + if(x->y0 > 32767.0) + x->y0 = 32767.0; + else if(x->y0 < -32768.0) + x->y0 = -32768.0; + + *(out+i) = (t_float)(x->y0) / 32768.0; + + x->cur_coef = x->cur_coef+x->down*x->step*(abs(x->x0)/(0.5*32768.0)); + // post ( "wahwah~ : cur coeff : %f", x->cur_coef ); + if(x->cur_coef > x->max_coef) + { + x->cur_coef = x->max_coef; + x->down = -1; + } + else if(x->cur_coef < x->min_coef) + { + x->cur_coef = x->min_coef; + x->down = 1; + } + + } + + return (w+5); +} + +static void wahwah_preset(t_wahwah *x, t_float pnumber) +{ + switch ( (int)pnumber ) + { + /* fast change medium wah wah */ + case 1: + x->x_minfc = 100.0; + x->x_maxfc = 1600.0; + x->x_sense = 100.0; + x->x_maxstep = 60.0; + x->x_dbgain = 15.0; + x->x_Q = 1.0; + break; + + /* slow change medium wah wah */ + case 2: + x->x_minfc = 100.0; + x->x_maxfc = 1600.0; + x->x_sense = 50.0; + x->x_maxstep = 36.0; + x->x_dbgain = 15.0; + x->x_Q = 1.0; + break; + + /* fast wah wah */ + case 3: + x->x_minfc = 100.0; + x->x_maxfc = 600.0; + x->x_sense = 100.0; + x->x_maxstep = 66.0; + x->x_dbgain = 15.0; + x->x_Q = 1.0; + break; + + /* ranged wah wah */ + case 4: + x->x_minfc = 10.0; + x->x_maxfc = 2900.0; + x->x_sense = 100.0; + x->x_maxstep = 66.0; + x->x_dbgain = 15.0; + x->x_Q = 1.0; + break; + + /* wah wah 400 - 2000 */ + case 5: + x->x_minfc = 400.0; + x->x_maxfc = 2000.0; + x->x_sense = 100.0; + x->x_maxstep = 66.0; + x->x_dbgain = 15.0; + x->x_Q = 1.0; + break; + + default: + post( "wahwah~ : unknown preset requested : %d", pnumber ); + return; + break; + } + wahwah_set_coeffs( x ); +} + +static void wahwah_dsp(t_wahwah *x, t_signal **sp) +{ + dsp_add(wahwah_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); +} + + /* clean up */ +static void wahwah_free(t_wahwah *x) +{ + if ( x->x_buf != NULL ) { + freebytes(x->x_buf, BFSZ*sizeof( double ) ); + post( "Freed %d bytes", BFSZ*sizeof( double ) ); + x->x_buf = NULL; + } + if ( x->x_coeffs != NULL ) { + freebytes(x->x_coeffs, COEFFSIZE*NBCOEFFS*sizeof( t_float ) ); + post( "Freed %d bytes", COEFFSIZE*NBCOEFFS*sizeof( t_float )); + x->x_coeffs = NULL; + } +} + +static void *wahwah_new(void) +{ + t_wahwah *x = (t_wahwah *)pd_new(wahwah_class); + outlet_new(&x->x_obj, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minfreq")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxfreq")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("sensibility")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxstep")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dbgain")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("bandwidth")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("step")); + + x->x_samplerate = (int)sys_getsr(); + + if ( !( x->x_buf = ( double* ) getbytes( BFSZ*sizeof( double ) ) ) ) + { + post ("wahwah~ : could not allocate buffer" ); + return NULL; + } + if ( !( x->x_coeffs = ( t_float* ) getbytes( COEFFSIZE*NBCOEFFS*sizeof( t_float ) ) ) ) + { + post ("wahwah~ : could not allocate coeffs" ); + return NULL; + } + + // set default parameters + wahwah_preset( x, 1 ); + wahwah_set_coeffs( x ); + + return (x); +} + +void wahwah_tilde_setup(void) +{ + post( wahwah_version ); + wahwah_class = class_new(gensym("wahwah~"), (t_newmethod)wahwah_new, (t_method)wahwah_free, + sizeof(t_wahwah), 0, 0); + + CLASS_MAINSIGNALIN( wahwah_class, t_wahwah, x_f ); + class_addmethod(wahwah_class, (t_method)wahwah_step, gensym("step"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_minfreq, gensym("minfreq"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_maxfreq, gensym("maxfreq"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_sensibility, gensym("sensibility"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_maxstep, gensym("maxstep"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_dbgain, gensym("dbgain"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_bandwidth, gensym("bandwidth"), A_FLOAT, 0); + class_addmethod(wahwah_class, (t_method)wahwah_dsp, gensym("dsp"), 0); + class_addmethod(wahwah_class, (t_method)wahwah_preset, gensym("preset"), A_FLOAT, 0); +} diff --git a/wahwah~/INSTALL b/wahwah~/INSTALL deleted file mode 100644 index 62ca7df..0000000 --- a/wahwah~/INSTALL +++ /dev/null @@ -1,15 +0,0 @@ -untar in /my/pd/dir/externs - -cd /my/pd/dir/externs/wahwah~ - -make clean - -make - -make install - -open help-wahwah~.pd - -Thanx for getting here. -Yves/ -comments and bugs @ ydegoyon@free.fr diff --git a/wahwah~/rs-wahwah~.pd b/wahwah~/rs-wahwah~.pd deleted file mode 100644 index af5c256..0000000 --- a/wahwah~/rs-wahwah~.pd +++ /dev/null @@ -1,348 +0,0 @@ -#N canvas 97 16 837 658 10; -#X obj 87 469 outlet~; -#X msg 149 24 preset 1; -#X msg 149 46 preset 2; -#X msg 149 71 preset 3; -#X msg 149 95 preset 4; -#X msg 149 118 preset 5; -#X text 216 25 fast change medium wah-wah; -#X text 217 46 slow change medium wah-wah; -#X text 219 71 fast wah-wah; -#X text 219 94 ranged wah-wah; -#X obj 53 307 inlet~; -#X text 220 117 wah-wah 400/2000 Hz; -#X obj 177 468 tabwrite~ owahwah; -#N canvas 0 0 450 300 graph1 0; -#X array owahwah 2000 float 1; -#A 0 -0.039093 -0.0409546 -0.0498657 -0.0647583 -0.0871887 -0.115601 --0.149658 -0.186188 -0.222839 -0.259918 -0.295898 -0.328308 -0.356567 --0.380859 -0.399689 -0.412933 -0.419983 -0.419434 -0.410675 -0.392517 --0.365753 -0.331726 -0.29129 -0.245361 -0.196503 -0.148499 -0.103546 --0.0623779 -0.0287476 -0.00424194 0.00881958 0.0116577 0.00469971 -0.0116577 --0.0361023 -0.0664978 -0.100555 -0.136414 -0.172302 -0.205841 -0.235596 --0.261932 -0.283508 -0.299713 -0.311584 -0.318848 -0.321991 -0.322968 --0.322998 -0.322662 -0.321503 -0.321228 -0.321503 -0.321747 -0.322876 --0.323883 -0.324463 -0.324066 -0.320892 -0.31308 -0.299133 -0.277191 --0.244019 -0.198334 -0.139526 -0.0670471 0.0205078 0.121002 0.230194 -0.344482 0.460846 0.573944 0.677521 0.765656 0.833282 0.876801 0.893036 -0.882629 0.846802 0.78891 0.714539 0.629425 0.539551 0.452789 0.374146 -0.307892 0.257263 0.222931 0.204132 0.19812 0.20163 0.210175 0.21933 -0.225739 0.22525 0.214874 0.194916 0.164948 0.12674 0.0838013 0.0399475 --0.00134277 -0.0376587 -0.0657654 -0.0814819 -0.0820007 -0.0656738 --0.0337219 0.0140381 0.0779724 0.156006 0.245911 0.346008 0.452057 -0.559235 0.663025 0.757202 0.837769 0.896179 0.925873 0.922516 0.882751 -0.806122 0.694183 0.55191 0.387329 0.210052 0.0307922 -0.138519 -0.286224 --0.401611 -0.480316 -0.519104 -0.516846 -0.47644 -0.40213 -0.299652 --0.175842 -0.0374451 0.108887 0.257507 0.401276 0.536102 0.658722 0.767181 -0.857239 0.927002 0.974548 0.99762 0.995697 0.969116 0.919312 0.852112 -0.772278 0.684723 0.5961 0.511749 0.437042 0.374969 0.326416 0.289948 -0.260529 0.233032 0.201965 0.157501 0.0927124 0.00149536 -0.120087 --0.272583 -0.452911 -0.653748 -0.863739 -1 -1 -1 -1 -1 -1 -1 -1 -1 --0.973389 -0.805054 -0.654327 -0.533722 -0.449554 -0.403442 -0.390808 --0.404175 -0.431488 -0.458344 -0.471954 -0.461639 -0.419342 -0.340942 --0.226868 -0.0821228 0.0829468 0.257294 0.426544 0.577087 0.695618 -0.771759 0.798157 0.771332 0.692352 0.566376 0.402252 0.209686 -0.00247192 --0.22171 -0.43985 -0.650452 -0.847473 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.739136 --0.431183 -0.0951538 0.245636 0.56543 0.838531 0.999969 0.999969 0.999969 -0.999969 0.999969 0.802216 0.559937 0.29715 0.0325623 -0.217773 -0.442688 --0.636414 -0.795715 -0.92099 -1 -1 -1 -1 -1 -1 -1 -0.950989 -0.852966 --0.744476 -0.634064 -0.530029 -0.443756 -0.384125 -0.356415 -0.362183 --0.400238 -0.46228 -0.535309 -0.604767 -0.653046 -0.661835 -0.615387 --0.499878 -0.308197 -0.0406799 0.294312 0.67923 0.999969 0.999969 0.999969 -0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.966919 -0.579712 0.242889 -0.0168762 -0.183319 -0.249573 -0.221954 -0.117706 -0.0397949 0.221771 0.399139 0.544708 0.6362 0.657806 0.601624 0.468964 -0.27002 0.0221863 -0.252197 -0.526459 -0.774719 -0.97522 -1 -1 -1 -1 --0.943573 -0.758942 -0.54248 -0.306366 -0.0611267 0.189514 0.443115 -0.697449 0.950439 0.999969 0.999969 0.999969 0.999969 0.964325 0.130615 --0.55246 -1 -1 -1 -1 -0.892181 -0.560394 -0.220734 0.0826416 0.317352 -0.468048 0.532959 0.52005 0.447357 0.337616 0.211273 0.0874939 -0.0170288 --0.0913391 -0.131683 -0.139923 -0.121124 -0.0817871 -0.0301208 0.024353 -0.0731506 0.110504 0.135773 0.148865 0.149841 0.140442 0.124298 0.106171 -0.0886841 0.0727234 0.059021 0.0523376 0.0513 0.0559692 0.0643921 0.0751648 -0.0877991 0.100708 0.112091 0.121948 0.129303 0.135132 0.138153 0.14032 -0.140869 0.138428 0.133514 0.126801 0.11853 0.109406 0.0989685 0.0881042 -0.0773621 0.0661926 0.0561829 0.0480652 0.0427246 0.0401917 0.0408325 -0.0447388 0.0513611 0.0603638 0.0705261 0.0811157 0.0899658 0.0986023 -0.109009 0.120209 0.129822 0.13736 0.143433 0.147369 0.147949 0.144257 -0.136719 0.125061 0.11264 0.098175 0.0823669 0.0648804 0.0462036 0.0277405 -0.0106812 -0.00558472 -0.0222473 -0.0386353 -0.0551147 -0.0707397 -0.0862732 --0.100494 -0.114716 -0.129669 -0.144409 -0.158783 -0.17392 -0.188385 --0.202057 -0.214661 -0.228119 -0.240845 -0.252014 -0.262207 -0.269958 --0.2742 -0.275787 -0.275604 -0.273346 -0.268707 -0.26062 -0.249481 --0.234894 -0.216797 -0.196503 -0.174866 -0.1521 -0.129639 -0.108246 --0.0873108 -0.0687561 -0.0557556 -0.0469055 -0.0423889 -0.0438843 -0.052002 --0.0664673 -0.0872803 -0.114227 -0.145477 -0.179688 -0.217499 -0.255646 --0.293396 -0.329254 -0.361755 -0.387848 -0.407257 -0.419189 -0.423859 --0.421204 -0.410278 -0.390991 -0.363373 -0.32843 -0.288849 -0.245178 --0.199188 -0.151886 -0.106201 -0.0655518 -0.0318909 -0.00665283 0.00817871 -0.0127258 0.00680542 -0.00918579 -0.0333862 -0.0639954 -0.0982666 -0.134338 --0.170715 -0.205658 -0.237183 -0.263855 -0.28479 -0.300812 -0.31189 --0.319458 -0.324249 -0.325256 -0.324219 -0.322723 -0.320953 -0.319489 --0.319427 -0.319794 -0.32132 -0.323334 -0.325684 -0.325531 -0.321503 --0.31308 -0.298218 -0.275696 -0.2435 -0.198578 -0.140106 -0.0680542 -0.0185242 0.117798 0.226654 0.342102 0.459686 0.574188 0.679474 0.769562 -0.838745 0.882385 0.899384 0.889221 0.853149 0.795837 0.721283 0.636169 -0.547119 0.459595 0.379211 0.31076 0.25708 0.219452 0.197266 0.188873 -0.192383 0.202209 0.213013 0.220642 0.221832 0.213165 0.19397 0.16626 -0.13089 0.088623 0.0440369 0.000915527 -0.0377197 -0.0675049 -0.0849304 --0.0869141 -0.0715332 -0.0384521 0.0113525 0.0761108 0.153351 0.243347 -0.34433 0.450195 0.559174 0.665131 0.762085 0.843048 0.900848 0.930298 -0.927399 0.887878 0.810791 0.698273 0.555084 0.390106 0.211395 0.0317383 --0.137634 -0.286163 -0.404236 -0.485474 -0.526031 -0.525208 -0.485352 --0.40918 -0.304932 -0.179535 -0.0396118 0.107544 0.255615 0.399872 -0.536102 0.660431 0.770782 0.86261 0.9328 0.980865 0.999969 0.999969 -0.974121 0.92453 0.856995 0.77594 0.6875 0.598267 0.51413 0.439209 -0.374847 0.322754 0.283844 0.25415 0.227539 0.196381 0.153137 0.0905762 -0.00128174 -0.119019 -0.271637 -0.452423 -0.653564 -0.863922 -1 -1 --1 -1 -1 -1 -1 -1 -1 -0.983398 -0.81308 -0.660461 -0.537537 -0.450836 --0.401978 -0.387848 -0.399719 -0.425385 -0.452332 -0.466919 -0.458435 --0.417389 -0.341614 -0.229828 -0.0864868 0.0791321 0.254517 0.425201 -0.577057 0.696777 0.775177 0.805115 0.779572 0.700653 0.57431 0.409943 -0.216797 0.00445557 -0.216492 -0.4375 -0.651215 -0.849945 -1 -1 -1 --1 -1 -1 -1 -1 -1 -0.74588 -0.435699 -0.0969238 0.246063 0.567993 0.84314 -0.999969 0.999969 0.999969 0.999969 0.999969 0.809875 0.567505 0.303864 -0.0378418 -0.21463 -0.440674 -0.63559 -0.796692 -0.923798 -1 -1 -1 --1 -1 -1 -1 -0.955811 -0.856628 -0.747009 -0.635651 -0.53183 -0.44516 --0.384369 -0.356354 -0.361908 -0.400787 -0.461456 -0.533783 -0.603088 --0.651306 -0.660767 -0.614563 -0.500214 -0.311096 -0.0456238 0.2883 -0.672974 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 -0.999969 0.999969 0.999969 0.980499 0.590179 0.248199 -0.017334 -0.188782 --0.259674 -0.235291 -0.132233 0.0249329 0.207764 0.386719 0.536774 -0.632294 0.657349 0.604553 0.475098 0.278259 0.0308228 -0.243103 -0.517395 --0.768127 -0.973206 -1 -1 -1 -1 -0.959106 -0.774323 -0.556854 -0.318909 --0.0692749 0.185944 0.443298 0.699951 0.954834 0.999969 0.999969 0.999969 -0.999969 0.974457 0.143829 -0.53949 -1 -1 -1 -1 -0.903381 -0.576324 --0.239136 0.0640564 0.302643 0.458801 0.528595 0.521362 0.454559 0.34787 -0.223083 0.100708 -0.00384521 -0.0808716 -0.125244 -0.137299 -0.120941 --0.0837097 -0.034668 0.0179138 0.0670166 0.107178 0.134186 0.148346 -0.149567 0.141113 0.127106 0.109955 0.0914917 0.0743103 0.0613708 0.0543518 -0.0514832 0.055542 0.0632629 0.0738831 0.086853 0.099884 0.112457 0.124176 -0.133881 0.140839 0.144562 0.143829 0.141327 0.13858 0.13269 0.124756 -0.116364 0.106812 0.0970764 0.0872192 0.0769348 0.0671387 0.0580139 -0.0501099 0.0437927 0.0418701 0.042572 0.0460205 0.052002 0.0600281 -0.0696106 0.0800171 0.0906982 0.101837 0.113098 0.123444 0.132507 0.139282 -0.144073 0.146057 0.145508 0.142029 0.135498 0.126556 0.115082 0.100403 -0.0848389 0.0665894 0.0477295 0.028595 0.00961304 -0.00848389 -0.0257874 --0.0423584 -0.0579224 -0.0725403 -0.0869141 -0.101044 -0.115021 -0.129028 --0.143372 -0.157471 -0.171783 -0.185913 -0.200317 -0.21463 -0.227814 --0.240723 -0.25351 -0.263885 -0.272064 -0.27774 -0.278992 -0.277557 --0.274323 -0.269073 -0.261414 -0.250854 -0.237091 -0.220551 -0.20047 --0.177368 -0.153992 -0.131348 -0.108795 -0.0869141 -0.0672302 -0.0518494 --0.0414734 -0.0362549 -0.0380554 -0.0472107 -0.0631714 -0.0870361 -0.115936 --0.148407 -0.183716 -0.220856 -0.258362 -0.294525 -0.328491 -0.360291 --0.386597 -0.405731 -0.418732 -0.424011 -0.420502 -0.409485 -0.390564 --0.363495 -0.329498 -0.289948 -0.245575 -0.19812 -0.151825 -0.106964 --0.0662842 -0.0315247 -0.00631714 0.00808716 0.0121765 0.00619507 -0.00915527 --0.0331421 -0.0646973 -0.0995178 -0.135773 -0.170959 -0.204376 -0.234741 --0.261475 -0.283386 -0.300293 -0.312531 -0.320435 -0.325775 -0.328857 --0.328583 -0.327423 -0.324768 -0.321655 -0.320312 -0.320129 -0.321136 --0.323212 -0.325043 -0.325714 -0.324677 -0.317566 -0.303802 -0.280762 --0.246704 -0.200073 -0.140594 -0.0681763 0.0187073 0.119446 0.22998 -0.346741 0.465454 0.579559 0.684998 0.774353 0.843231 0.887451 0.903961 -0.892273 0.854736 0.795959 0.72168 0.636566 0.546875 0.457825 0.378052 -0.311493 0.258972 0.22226 0.201965 0.194702 0.195862 0.202515 0.211456 -0.21814 0.218964 0.211273 0.19342 0.165619 0.129242 0.0864563 0.0415344 --0.000946045 -0.0385132 -0.0675964; -#A 1000 -0.0828857 -0.0823669 -0.0689392 -0.0388794 0.00836182 0.0713806 -0.14975 0.241821 0.343811 0.451385 0.560455 0.666168 0.763092 0.844269 -0.90271 0.933441 0.93103 0.891785 0.815155 0.70285 0.559235 0.392944 -0.213409 0.0327759 -0.138458 -0.288544 -0.407806 -0.489197 -0.529602 --0.528931 -0.489471 -0.415192 -0.311523 -0.184967 -0.0444336 0.103973 -0.253021 0.398804 0.536804 0.662079 0.772064 0.864349 0.936188 0.985199 -0.999969 0.999969 0.978607 0.930573 0.862488 0.779633 0.689514 0.59845 -0.512878 0.437439 0.373901 0.32309 0.284149 0.25415 0.226807 0.195282 -0.150726 0.0862732 -0.00366211 -0.123627 -0.274872 -0.454132 -0.654205 --0.864258 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.991821 -0.820068 -0.665405 --0.541504 -0.453644 -0.403442 -0.386169 -0.39621 -0.42099 -0.446625 --0.461151 -0.453278 -0.413788 -0.338745 -0.227814 -0.0853882 0.0786133 -0.252533 0.423523 0.576965 0.698975 0.777679 0.805695 0.781158 0.704956 -0.580536 0.416809 0.222107 0.00863647 -0.21347 -0.435455 -0.649841 --0.850922 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.750519 -0.43869 -0.0991211 -0.245605 0.57016 0.846985 0.999969 0.999969 0.999969 0.999969 0.999969 -0.822144 0.578339 0.312134 0.0435181 -0.211853 -0.442688 -0.641357 --0.804596 -0.932831 -1 -1 -1 -1 -1 -1 -1 -0.957397 -0.857697 -0.746979 --0.63446 -0.530609 -0.444061 -0.383301 -0.354889 -0.360779 -0.397675 --0.457886 -0.530243 -0.599121 -0.648041 -0.658875 -0.614075 -0.501556 --0.313599 -0.0487061 0.285431 0.670898 0.999969 0.999969 0.999969 0.999969 -0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.994263 0.600861 -0.254944 -0.0148621 -0.190338 -0.26413 -0.241058 -0.140289 0.015686 -0.198242 0.379211 0.530151 0.627045 0.654694 0.604462 0.477448 0.282654 -0.0371704 -0.236206 -0.513153 -0.76593 -0.973389 -1 -1 -1 -1 -0.967407 --0.781769 -0.56424 -0.324951 -0.0736084 0.183289 0.443054 0.702942 -0.960358 0.999969 0.999969 0.999969 0.999969 0.986908 0.159088 -0.523895 --1 -1 -1 -1 -0.918671 -0.595154 -0.258484 0.046814 0.289673 0.451355 -0.529297 0.52771 0.463898 0.358154 0.232758 0.108521 0.00115967 -0.078125 --0.124237 -0.138458 -0.124237 -0.089386 -0.0411987 0.0108032 0.0605774 -0.101654 0.130585 0.147491 0.152008 0.145264 0.131958 0.113983 0.0951233 -0.0777283 0.0628357 0.0530701 0.0495605 0.0513916 0.0587158 0.0714722 -0.0856323 0.0986938 0.110992 0.123718 0.133789 0.141266 0.145508 0.147034 -0.145386 0.140686 0.134216 0.125916 0.115723 0.105774 0.096283 0.0852051 -0.0751038 0.0665894 0.05896 0.0525513 0.0475464 0.0441895 0.0434875 -0.0458984 0.0515747 0.0593872 0.0674438 0.0768127 0.0877991 0.0993042 -0.110229 0.121124 0.131989 0.141052 0.147308 0.14975 0.148834 0.144836 -0.138489 0.129425 0.116486 0.100189 0.0821228 0.0637207 0.0458069 0.0279846 -0.0101318 -0.0088501 -0.0272217 -0.0437927 -0.0577393 -0.071228 -0.0854492 --0.0998535 -0.11377 -0.127319 -0.141632 -0.157898 -0.17337 -0.187744 --0.202179 -0.21701 -0.231873 -0.245453 -0.2565 -0.265259 -0.272217 --0.2771 -0.278839 -0.277008 -0.272583 -0.267853 -0.261444 -0.251007 --0.236786 -0.21933 -0.19931 -0.177551 -0.154633 -0.131104 -0.107788 --0.0860291 -0.0675659 -0.0513306 -0.0410767 -0.037262 -0.0393066 -0.0481873 --0.0643311 -0.0869446 -0.115143 -0.148315 -0.183868 -0.221497 -0.259308 --0.29538 -0.328888 -0.359314 -0.384674 -0.403748 -0.416901 -0.423584 --0.421875 -0.412445 -0.394135 -0.368683 -0.335114 -0.294617 -0.248718 --0.200012 -0.150696 -0.103271 -0.0614319 -0.0278015 -0.00195312 0.0123291 -0.0169067 0.00997925 -0.0055542 -0.0300903 -0.0625 -0.0991211 -0.136505 --0.172913 -0.207245 -0.238586 -0.265167 -0.287231 -0.30426 -0.316223 --0.323425 -0.326294 -0.326965 -0.326263 -0.324585 -0.323242 -0.321442 --0.32077 -0.320282 -0.322388 -0.323883 -0.32547 -0.326569 -0.324921 --0.31781 -0.303741 -0.281006 -0.246765 -0.201111 -0.141479 -0.0682983 -0.0192566 0.11969 0.230042 0.346985 0.466461 0.582428 0.687988 0.777466 -0.847107 0.891693 0.908142 0.895447 0.859131 0.801605 0.726562 0.639618 -0.548218 0.459473 0.378784 0.310516 0.256836 0.219971 0.200043 0.192505 -0.195129 0.203156 0.211853 0.217621 0.218018 0.210602 0.192932 0.165924 -0.130157 0.0880737 0.0436707 0.000183105 -0.0377197 -0.0673523 -0.0857544 --0.0892944 -0.0753784 -0.0438232 0.00436401 0.0688477 0.148773 0.241241 -0.343048 0.451538 0.561401 0.667877 0.76535 0.84613 0.903748 0.934753 -0.933105 0.895264 0.82016 0.707977 0.564514 0.39798 0.217407 0.0344543 --0.138824 -0.291412 -0.41217 -0.494598 -0.535889 -0.534729 -0.494141 --0.418274 -0.314331 -0.188263 -0.0472717 0.101135 0.25116 0.398132 -0.53775 0.665833 0.776978 0.870361 0.94281 0.990692 0.999969 0.999969 -0.980591 0.930176 0.862274 0.780884 0.691925 0.601074 0.516296 0.440979 -0.37616 0.324341 0.284668 0.253754 0.225769 0.192902 0.148743 0.0855713 --0.00421143 -0.124268 -0.275452 -0.454956 -0.65567 -0.866638 -1 -1 --1 -1 -1 -1 -1 -1 -1 -1 -0.828003 -0.672089 -0.544495 -0.453064 -0.400085 --0.382477 -0.391357 -0.4151 -0.441681 -0.458649 -0.452606 -0.414001 --0.339233 -0.228607 -0.0864258 0.078186 0.253143 0.424225 0.577881 -0.701019 0.781769 0.811951 0.789276 0.713867 0.589264 0.423553 0.227509 -0.0120239 -0.211914 -0.435303 -0.651703 -0.853729 -1 -1 -1 -1 -1 -1 --1 -1 -1 -0.756287 -0.444092 -0.102905 0.243561 0.569672 0.849365 0.999969 -0.999969 0.999969 0.999969 0.999969 0.833405 0.590118 0.322998 0.0515442 --0.206573 -0.438843 -0.638672 -0.804199 -0.935913 -1 -1 -1 -1 -1 -1 --1 -0.96283 -0.861115 -0.749207 -0.636108 -0.531036 -0.444672 0.554535 -0.999969 0.999969 0.999969 0.999969 0.999969 0.999969 0.57547 0.100037 --0.290497 -0.564453 -0.710022 -0.732971 -0.656952 -0.510254 -0.323334 --0.128326 0.0491943 0.191101 0.28653 0.333221 0.336029 0.302673 0.245667 -0.17749 0.108307 0.0475159 0.00280762 -0.0238342 -0.0334473 -0.0276794 --0.00997925 0.0147095 0.0418701 0.0684509 0.0918579 0.109528 0.120117 -0.124176 0.123077 0.118225 0.111725 0.105469 0.100128 0.0970154 0.0969849 -0.0992432 0.105286 0.112579 0.120056 0.12735 0.133453 0.136932 0.136902 -0.133301 0.126068 0.116638 0.105255 0.0941467 0.0830078 0.0715942 0.0602722 -0.0501099 0.0424805 0.0380859 0.0365295 0.0378418 0.0431519 0.0505371 -0.0605164 0.0729065 0.0870056 0.100586 0.114044 0.126099 0.136108 0.144623 -0.150208 0.151245 0.149628 0.145538 0.13916 0.1297 0.11673 0.101257 -0.0846252 0.0667725 0.0483398 0.0305786 0.0133057 -0.00411987 -0.0206909 --0.0389404 -0.0566406 -0.0726929 -0.0880432 -0.102997 -0.11734 -0.131409 --0.145782 -0.159973 -0.174347 -0.189453 -0.204712 -0.218262 -0.231842 --0.243958 -0.254822 -0.264679 -0.272614 -0.278137 -0.280457 -0.277985 --0.274139 -0.26651 -0.255615 -0.242767 -0.227753 -0.210876 -0.192017 --0.171631 -0.150085 -0.12796 -0.106537 -0.0864563 -0.0697632 -0.0567932 --0.0470886 -0.0434875 -0.0454712 -0.0533142 -0.0669861 -0.0858154 -0.109589 --0.138916 -0.174042 -0.212128 -0.25116 -0.289917 -0.327362 -0.36142 --0.389282 -0.410004 -0.423279 -0.428436 -0.42514 -0.413666 -0.39328 --0.365875 -0.330109 -0.287811 -0.241241 -0.193298 -0.146057 -0.101135 --0.0602417 -0.0259705 -0.00109863 0.0117798 0.0144653 0.00726318 -0.00985718 --0.033844 -0.062439 -0.0951843 -0.13028 -0.165527 -0.199432 -0.230042 --0.256622 -0.279663 -0.296783 -0.30954 -0.317444 -0.32251 -0.324615 --0.324493 -0.323944 -0.323425 -0.322845 -0.324738 -0.325836 -0.326599 --0.327118 -0.327057 -0.325226 -0.320679 -0.311951 -0.296753 -0.273376 --0.240204 -0.194733 -0.136108 -0.0620117 0.0262451 0.125214 0.233795 -0.349182 0.466644 0.580963 0.68634 0.776581 0.846069 0.890045 0.907074 -0.899292 0.865997 0.809326 0.734558 0.647552 0.554962 0.463654 0.380096 -0.30957 0.255005 0.218353 0.196045 0.187775 0.189697 0.198151 0.208984 -0.216583 0.217407 0.209686 0.192047 0.165222 0.12973 0.0860291 0.0411072 --0.00177002 -0.0402222 -0.0692444 -0.0855408 -0.087616 -0.0743713 -0.04422 -0.00427246 0.0694275 0.149475 0.241608 0.343414 0.451263 0.561371 0.667389 -0.764069 0.845642 0.905365 0.937836 0.937012 0.899841 0.82428 0.711792 -0.567657 0.39978 0.217377 0.0335083 -0.139648 -0.292023 -0.41394 -0.498688 --0.541809 -0.54184 -0.500946 -0.424866 -0.320526 -0.195007 -0.0548401 -0.0941772 0.246277 0.395569 0.536713 0.665955 0.779266 0.873901 0.947601 -0.99646 0.999969 0.999969 0.985901 0.934845 0.865417 0.782837 0.693024 -0.601807 0.516235 0.439514 0.374481 0.323212 0.284424 0.253693 0.225494 -0.193054 0.148132 0.0826416 -0.00842285 -0.127563 -0.278015 -0.457214 --0.657013 -0.867767 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0.832947 -0.674957 --0.546509 -0.455109 -0.401459 -0.381561 -0.38913 -0.413025 -0.43924 --0.454773 -0.44754 -0.410187 -0.338013 -0.229919 -0.0897827 0.0737915 -0.248657 0.420746 0.575073 0.701202 0.783661 0.81601 0.795135 0.720795 -0.597382 0.432526 0.236237 0.0197754 -0.20636 -0.433411 -0.651581 -0.85675 --1 -1 -1 -1 -1 -1 -1 -1 -1 -0.761597 -0.449127 -0.10733 0.240723 0.567749 -0.849518 0.999969 0.999969 0.999969 0.999969 0.999969 0.846893 0.602264 -0.333496 0.0600586 -0.202484 -0.440704 -0.646301 -0.815704 -0.948914 --1 -1 -1 -1 -1 -1 -1 -0.964539 -0.862732 -0.751526 -0.638733 -0.534088 --0.447662 -0.387573 -0.358978 -0.362793 -0.397034 -0.4552 -0.525391 --0.592346 -0.640137 -0.651886 -0.610596 -0.502045 -0.315704 -0.0520325 -0.280945 0.666718 0.999969; -#X coords 0 2 1999 -2 200 140 1; -#X restore 596 461 graph; -#X msg 177 446 bang; -#X obj 602 315 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 1270 0; -#X text 607 295 The pedal (step); -#X obj 601 216 f; -#X obj 632 216 + 1; -#X msg 599 158 bang; -#X obj 645 242 > 100; -#X obj 688 241 route 1; -#X msg 685 215 -1; -#X msg 559 216 0; -#X obj 693 185 route 1; -#X obj 664 186 < 0; -#X msg 690 159 1; -#X msg 555 160 stop; -#X obj 161 187 hsl 128 15 0 3000 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 5600 0; -#X text 162 166 Minimum freq [ 0 - 3000 ]; -#X obj 212 221 hsl 128 15 0 3000 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 3300 0; -#X text 207 205 Maximum freq [ 0 - 3000 ]; -#X obj 237 259 hsl 128 15 0 1000 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 4200 0; -#X text 234 241 Sensibility [ 0 - 1000 ]; -#X obj 285 292 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 1100 0; -#X text 280 275 Maxstep [ 0 - 100 ]; -#X obj 340 327 hsl 128 15 -15 15 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 12400 0; -#X text 335 310 Gain [ -15 - 15 ]; -#X obj 408 369 hsl 128 15 0 10 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 5000 0; -#X text 403 351 Bandwidth [ 0 - 10 ]; -#X text 597 126 Auto; -#X text 164 148 Note : setting a parameter overrides presets; -#X obj 87 414 wahwah~ -------------------------------------------------- -; -#X text 133 543 Note : interesting to set bandwith close to 10; -#X obj 600 185 metro 10; -#X obj 648 127 loadbang; -#X connect 1 0 42 0; -#X connect 2 0 42 0; -#X connect 3 0 42 0; -#X connect 4 0 42 0; -#X connect 5 0 42 0; -#X connect 10 0 42 0; -#X connect 14 0 12 0; -#X connect 15 0 42 7; -#X connect 17 0 18 0; -#X connect 17 0 20 0; -#X connect 17 0 25 0; -#X connect 17 0 15 0; -#X connect 18 0 17 1; -#X connect 19 0 44 0; -#X connect 20 0 21 0; -#X connect 21 0 22 0; -#X connect 22 0 18 1; -#X connect 23 0 17 0; -#X connect 24 0 26 0; -#X connect 25 0 24 0; -#X connect 26 0 18 1; -#X connect 27 0 44 0; -#X connect 28 0 42 1; -#X connect 30 0 42 2; -#X connect 32 0 42 3; -#X connect 34 0 42 4; -#X connect 36 0 42 5; -#X connect 38 0 42 6; -#X connect 42 0 0 0; -#X connect 42 0 12 0; -#X connect 44 0 17 0; -#X connect 45 0 19 0; diff --git a/wahwah~/wahwah~-help.pd b/wahwah~/wahwah~-help.pd deleted file mode 100644 index 8afeb3c..0000000 --- a/wahwah~/wahwah~-help.pd +++ /dev/null @@ -1,48 +0,0 @@ -#N canvas 45 57 817 573 10; -#X text 319 534 comments & bugs @ ydegoyon.free.fr; -#X text 431 111 Wahwah~ : used in psychedelic music; -#X obj 144 411 dac~; -#X obj 148 377 rs-wahwah~; -#X msg 94 62 bang; -#X obj 93 84 openpanel; -#X obj 93 104 t s b; -#X obj 150 106 float \$0; -#X text 101 39 Step 1 : Load a sound file; -#X obj 93 127 route float; -#X obj 94 219 soundfiler; -#X text 151 55 ( maybe \, a guitar sound ? ); -#X obj 93 150 makefilename %d-sample; -#X obj 582 374 table \$0-sample; -#X msg 94 197 read -resize \$1 \$2; -#X obj 95 176 pack s s; -#X msg 146 307 bang; -#X text 191 307 Step 2 : Start playing; -#X obj 59 288 adc~; -#X text 229 379 Step 3 : Modify parameters; -#X text 487 483 ( http://st.karelia.ru/~smlalx ); -#X text 320 470 a DOS guitar effects software that rocks; -#X text 321 484 written by Alexei Smoli; -#X obj 606 263 loadbang; -#X msg 608 293 \; pd dsp 1; -#X text 319 456 the algorithm is borrowed from Digital Effects \,; -#X obj 146 354 tabplay~ \$0-sample; -#X text 35 266 Plug a guitar ??; -#X msg 228 330 stop; -#X obj 146 330 metro 250; -#X connect 3 0 2 0; -#X connect 3 0 2 1; -#X connect 4 0 5 0; -#X connect 5 0 6 0; -#X connect 6 0 15 0; -#X connect 6 1 7 0; -#X connect 7 0 9 0; -#X connect 9 0 12 0; -#X connect 12 0 15 1; -#X connect 14 0 10 0; -#X connect 15 0 14 0; -#X connect 16 0 29 0; -#X connect 18 0 3 0; -#X connect 23 0 24 0; -#X connect 26 0 3 0; -#X connect 28 0 29 0; -#X connect 29 0 26 0; diff --git a/wahwah~/wahwah~.c b/wahwah~/wahwah~.c deleted file mode 100644 index 7f9a9ed..0000000 --- a/wahwah~/wahwah~.c +++ /dev/null @@ -1,408 +0,0 @@ -/* Copyright (c) 2002 Yves Degoyon. */ -/* For information on usage and redistribution, and for a DISCLAIMER OF ALL */ -/* WARRANTIES, see the file, "COPYING" in this distribution. */ -/* */ -/* wahwah~ -- a kind of effect used in psychedelic music */ -/* the algorithm was taken from Digital Effects, */ -/* a guitar effects software for DOS which rocks, written by Alexey Smoli */ -/* ( http://st.karelia.ru/~smlalx/ ) */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 2 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* See file LICENSE for further informations on licensing terms. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* Made while listening to : */ -/* */ -/* Crass -- "Shaved Women ( Collaborators )" */ -/* Zounds -- "Can't Cheat Karma" */ -/* */ -/* Special message for the french : */ -/* "Delay all your work...and go vote against national front" */ -/* ---------------------------------------------------------------------------- */ - -#include "m_pd.h" -#include -#include - -#ifdef NT -#define M_PI 3.14159265358979323846 -#endif - -#define BFSZ 4096 /* main delay buffer */ -#define BLOCK_DELAY 10 /* number of blocks to delay */ -#define NA 0.0 /* param not applicable */ -#define COEFFSIZE 3000 /* coefficients size */ -#define NBCOEFFS 5 /* number of coefficients */ - -static char *wahwah_version = "wahwah~: an audio wahwah, version 0.1 (ydegoyon@free.fr)"; - -typedef struct _wahwah -{ - t_object x_obj; - double *x_buf; - t_int x_samplerate; - t_float *x_coeffs; - double x_minfc; /* min frequency Hz */ /* 0< <3000 */ - double x_maxfc; /* max frequency Hz */ /* 0< <3000 */ - double x_sense; /* increase/decrease frequency change by one mouse movement Hz */ /* 0< <=1000 */ - double x_maxstep; /* maximum frequency change step KHz */ /* 0< <=100 */ - double x_dbgain; /* peaking filter gain dB */ /* -15<= <=15 */ - double x_bandwidth; /* bandwidth in octaves (between midpoint (dBgain/2) - gain frequencies) or */ /* 0< <10 */ - double x_Q; /* the EE kinda definition */ /* 0< <=1 */ - - /* variables for audio computation */ - double min_coef,max_coef,cur_coef,step,maxstep; - t_int down; - /* amplitudes */ - short x0,x1,x2; - t_int y0,y1,y2; - - t_float x_f; -} t_wahwah; - -static t_class *wahwah_class; - -static void wahwah_set_coeffs (t_wahwah *x) -{ - t_int i; - double omega; - double sn,cs; - double alpha = 0.0; - /* filter coefficients */ - double a0,a1,a2,b0,b1,b2; - double A; - - A = exp(x->x_dbgain/40.0)*log(10.0); - for (i = 0; i < COEFFSIZE; i++) - { - omega = 2.0*M_PI*(double)i/(double)x->x_samplerate; - sn = sin(omega); - cs = cos(omega); - if (x->x_bandwidth) - alpha = sn*sin(log(2.0)/2.0*x->x_bandwidth*omega/sn); - else - /* if Q is specified instead of bandwidth */ - if (x->x_Q) - alpha = sn/(2.0*x->x_Q); - - /* then compute the coefs for whichever filter type you want */ - b0 = 1.0 + alpha*A; - b1 = -2.0*cs ; - b2 = 1.0 - alpha*A; - a0 = 1.0 + alpha/A; - a1 = -2.0*cs ; - a2 = 1.0 - alpha/A; - - *(x->x_coeffs+i*NBCOEFFS) = (b0/a0); - *(x->x_coeffs+i*NBCOEFFS+1) = (b1/a0); - *(x->x_coeffs+i*NBCOEFFS+2) = (b2/a0); - *(x->x_coeffs+i*NBCOEFFS+3) = (a1/a0); - *(x->x_coeffs+i*NBCOEFFS+4) = (a2/a0); - // post( "wahwah~ : coeff : %f", *(x->x_coeffs+i*NBCOEFFS+4) ); - } - x->min_coef = x->x_minfc; - x->max_coef = x->x_maxfc; - x->cur_coef = x->min_coef; - x->down = 1; - x->step = 0; - x->maxstep = x->x_maxstep/(double)x->x_samplerate*1000.0; -} - -static void wahwah_bandwidth(t_wahwah *x, t_floatarg fbandwidth ) -{ - if ( fbandwidth > 10.0 ) - { - fbandwidth = 10.0; - } - if ( fbandwidth < 0.0 ) - { - fbandwidth = 0.0; - } - x->x_bandwidth = fbandwidth; - // post( "wahwah~ : bandwidth: %f", x->x_bandwidth ); - wahwah_set_coeffs( x ); -} - -static void wahwah_dbgain(t_wahwah *x, t_floatarg fdbgain ) -{ - if ( fdbgain > 15.0 ) - { - fdbgain = 15.0; - } - if ( fdbgain < -15.0 ) - { - fdbgain = -15.0; - } - x->x_dbgain = fdbgain; - // post( "wahwah~ : dbgain: %f", x->x_dbgain ); - wahwah_set_coeffs( x ); -} - -static void wahwah_maxstep(t_wahwah *x, t_floatarg fmaxstep ) -{ - if ( fmaxstep > 100.0 ) - { - fmaxstep = 100.0; - } - if ( fmaxstep < 0.0 ) - { - fmaxstep = 0.0; - } - x->x_maxstep = fmaxstep; - // post( "wahwah~ : maxstep: %f", x->x_maxstep ); - wahwah_set_coeffs( x ); -} - -static void wahwah_sensibility(t_wahwah *x, t_floatarg fsensibility ) -{ - if ( fsensibility > 1000.0 ) - { - fsensibility = 1000.0; - } - if ( fsensibility < 0.0 ) - { - fsensibility = 0.0; - } - x->x_sense = fsensibility; - // post( "wahwah~ : sensibility: %f", x->x_sense ); - wahwah_set_coeffs( x ); -} - -static void wahwah_maxfreq(t_wahwah *x, t_floatarg fmaxfreq ) -{ - if ( fmaxfreq > 3000.0 ) - { - fmaxfreq = 3000.0; - } - if ( fmaxfreq < 0.0 ) - { - fmaxfreq = 0.0; - } - x->x_maxfc = fmaxfreq; - // post( "wahwah~ : maxfreq: %f", x->x_maxfc ); - wahwah_set_coeffs( x ); -} - -static void wahwah_minfreq(t_wahwah *x, t_floatarg fminfreq ) -{ - if ( fminfreq > 3000.0 ) - { - fminfreq = 3000.0; - } - if ( fminfreq < 0.0 ) - { - fminfreq = 0.0; - } - x->x_minfc = fminfreq; - // post( "wahwah~ : minfreq: %f", x->x_minfc ); - wahwah_set_coeffs( x ); -} - -static void wahwah_step(t_wahwah *x, t_floatarg fstep ) -{ - if ( fstep > x->x_maxstep ) - { - fstep = x->x_maxstep; - } - if ( fstep < 0 ) - { - fstep = 0; - } - x->step = fstep*x->x_sense/x->x_samplerate; -} - -static t_int *wahwah_perform(t_int *w) -{ - t_float *in = (t_float *)(w[1]); - t_float *out = (t_float *)(w[2]); - t_int n = (int)(w[3]); - t_wahwah *x = (t_wahwah*)(w[4]); - t_int i; - - for (i=0; ix0 = (int)((*(in+i))*32768); - - x->y0 = (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS))*x->x0 - + (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+1))*x->x1 - + (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+2))*x->x2 - - (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+3))*x->y1 - - (*(x->x_coeffs+(int)x->cur_coef*NBCOEFFS+4))*x->y2; - - x->y2 = x->y1; - x->y1 = x->y0; - x->x2 = x->x1; - x->x1 = x->x0; - - if(x->y0 > 32767.0) - x->y0 = 32767.0; - else if(x->y0 < -32768.0) - x->y0 = -32768.0; - - *(out+i) = (t_float)(x->y0) / 32768.0; - - x->cur_coef = x->cur_coef+x->down*x->step*(abs(x->x0)/(0.5*32768.0)); - // post ( "wahwah~ : cur coeff : %f", x->cur_coef ); - if(x->cur_coef > x->max_coef) - { - x->cur_coef = x->max_coef; - x->down = -1; - } - else if(x->cur_coef < x->min_coef) - { - x->cur_coef = x->min_coef; - x->down = 1; - } - - } - - return (w+5); -} - -static void wahwah_preset(t_wahwah *x, t_float pnumber) -{ - switch ( (int)pnumber ) - { - /* fast change medium wah wah */ - case 1: - x->x_minfc = 100.0; - x->x_maxfc = 1600.0; - x->x_sense = 100.0; - x->x_maxstep = 60.0; - x->x_dbgain = 15.0; - x->x_Q = 1.0; - break; - - /* slow change medium wah wah */ - case 2: - x->x_minfc = 100.0; - x->x_maxfc = 1600.0; - x->x_sense = 50.0; - x->x_maxstep = 36.0; - x->x_dbgain = 15.0; - x->x_Q = 1.0; - break; - - /* fast wah wah */ - case 3: - x->x_minfc = 100.0; - x->x_maxfc = 600.0; - x->x_sense = 100.0; - x->x_maxstep = 66.0; - x->x_dbgain = 15.0; - x->x_Q = 1.0; - break; - - /* ranged wah wah */ - case 4: - x->x_minfc = 10.0; - x->x_maxfc = 2900.0; - x->x_sense = 100.0; - x->x_maxstep = 66.0; - x->x_dbgain = 15.0; - x->x_Q = 1.0; - break; - - /* wah wah 400 - 2000 */ - case 5: - x->x_minfc = 400.0; - x->x_maxfc = 2000.0; - x->x_sense = 100.0; - x->x_maxstep = 66.0; - x->x_dbgain = 15.0; - x->x_Q = 1.0; - break; - - default: - post( "wahwah~ : unknown preset requested : %d", pnumber ); - return; - break; - } - wahwah_set_coeffs( x ); -} - -static void wahwah_dsp(t_wahwah *x, t_signal **sp) -{ - dsp_add(wahwah_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x ); -} - - /* clean up */ -static void wahwah_free(t_wahwah *x) -{ - if ( x->x_buf != NULL ) { - freebytes(x->x_buf, BFSZ*sizeof( double ) ); - post( "Freed %d bytes", BFSZ*sizeof( double ) ); - x->x_buf = NULL; - } - if ( x->x_coeffs != NULL ) { - freebytes(x->x_coeffs, COEFFSIZE*NBCOEFFS*sizeof( t_float ) ); - post( "Freed %d bytes", COEFFSIZE*NBCOEFFS*sizeof( t_float )); - x->x_coeffs = NULL; - } -} - -static void *wahwah_new(void) -{ - t_wahwah *x = (t_wahwah *)pd_new(wahwah_class); - outlet_new(&x->x_obj, &s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("minfreq")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxfreq")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("sensibility")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("maxstep")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dbgain")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("bandwidth")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("step")); - - x->x_samplerate = (int)sys_getsr(); - - if ( !( x->x_buf = ( double* ) getbytes( BFSZ*sizeof( double ) ) ) ) - { - post ("wahwah~ : could not allocate buffer" ); - return NULL; - } - if ( !( x->x_coeffs = ( t_float* ) getbytes( COEFFSIZE*NBCOEFFS*sizeof( t_float ) ) ) ) - { - post ("wahwah~ : could not allocate coeffs" ); - return NULL; - } - - // set default parameters - wahwah_preset( x, 1 ); - wahwah_set_coeffs( x ); - - return (x); -} - -void wahwah_tilde_setup(void) -{ - post( wahwah_version ); - wahwah_class = class_new(gensym("wahwah~"), (t_newmethod)wahwah_new, (t_method)wahwah_free, - sizeof(t_wahwah), 0, 0); - - CLASS_MAINSIGNALIN( wahwah_class, t_wahwah, x_f ); - class_addmethod(wahwah_class, (t_method)wahwah_step, gensym("step"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_minfreq, gensym("minfreq"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_maxfreq, gensym("maxfreq"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_sensibility, gensym("sensibility"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_maxstep, gensym("maxstep"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_dbgain, gensym("dbgain"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_bandwidth, gensym("bandwidth"), A_FLOAT, 0); - class_addmethod(wahwah_class, (t_method)wahwah_dsp, gensym("dsp"), 0); - class_addmethod(wahwah_class, (t_method)wahwah_preset, gensym("preset"), A_FLOAT, 0); -} diff --git a/xmms.pd b/xmms.pd new file mode 100644 index 0000000..b9282cd --- /dev/null +++ b/xmms.pd @@ -0,0 +1,144 @@ +#N canvas 146 29 755 574 10; +#X obj 411 144 mp3fileout~; +#X floatatom 411 165 5 0 0; +#X floatatom 456 165 5 0 0; +#X msg 409 113 open \$1; +#X msg 466 113 start; +#X msg 511 114 stop; +#X text 534 154 Number of frames emitted; +#X text 396 184 Connection state; +#X symbolatom 127 286 80 0 0; +#X floatatom 520 63 5 0 0; +#X obj 20 57 playlist mp3 300 200; +#X msg 651 37 bang; +#X text 23 17 Step 1 : point to your MP3s directory; +#X obj 357 513 dac~; +#X symbolatom 131 438 10 0 0; +#X text 127 452 Incomer's address; +#X obj 349 470 *~ 1; +#X floatatom 461 513 5 0 0; +#X obj 427 513 / 100; +#X obj 390 470 *~ 1; +#X text 501 515 Volume; +#X msg 336 38 connect localhost 5672; +#X obj 95 341 mp3streamin~ 5672 1; +#X text 295 15 Step 2 : connect to the streamer; +#X text 65 285 Playing :; +#X msg 463 64 seek \$1; +#X text 566 11 Step 3 :start random play; +#X obj 657 410 loadbang; +#X msg 656 434 \; pd dsp 1; +#X msg 379 220 seek \$1; +#X obj 437 219 hsl 128 15 0 1e+07 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 0; +#X msg 547 114 disconnect; +#X obj 573 37 random 1000; +#X msg 620 73 seed \$1; +#X floatatom 673 73 5 0 0; +#X msg 634 220 bang; +#X text 575 264 Step 3 bis :start seq play; +#X obj 592 220 countn; +#X obj 578 242 - 1; +#X floatatom 531 243 5 0 0; +#X obj 551 187 spigot; +#X obj 599 186 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X msg 624 186 1; +#X obj 618 95 spigot; +#X obj 666 94 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 1 +; +#X msg 691 94 1; +#X obj 362 441 ekwalizer --------------------------; +#X msg 544 315 100; +#X obj 385 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 7900 1; +#X obj 408 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 7900 1; +#X obj 432 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 7900 1; +#X obj 454 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 7900 1; +#X obj 477 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 498 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 516 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 534 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 552 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 573 343 vsl 15 80 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 579 315 loadbang; +#X obj 494 539 loadbang; +#X msg 463 539 50; +#X obj 259 486 compressor~; +#X floatatom 279 434 5 0 0; +#X obj 241 509 env~; +#X obj 266 463 / 100; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 0 2 40 0; +#X connect 0 2 43 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 10 0 8 0; +#X connect 10 0 3 0; +#X connect 11 0 32 0; +#X connect 11 0 45 0; +#X connect 16 0 61 0; +#X connect 17 0 18 0; +#X connect 18 0 16 1; +#X connect 18 0 19 1; +#X connect 19 0 61 0; +#X connect 21 0 0 0; +#X connect 21 0 4 0; +#X connect 22 0 46 0; +#X connect 22 1 46 0; +#X connect 22 2 14 0; +#X connect 25 0 10 0; +#X connect 27 0 28 0; +#X connect 29 0 0 0; +#X connect 30 0 29 0; +#X connect 31 0 0 0; +#X connect 32 0 9 0; +#X connect 32 0 25 0; +#X connect 33 0 32 0; +#X connect 34 0 33 0; +#X connect 35 0 37 0; +#X connect 35 0 42 0; +#X connect 37 0 38 0; +#X connect 38 0 25 0; +#X connect 38 0 39 0; +#X connect 40 0 37 0; +#X connect 41 0 40 1; +#X connect 42 0 41 0; +#X connect 43 0 32 0; +#X connect 44 0 43 1; +#X connect 45 0 44 0; +#X connect 46 0 19 0; +#X connect 46 0 16 0; +#X connect 47 0 48 0; +#X connect 47 0 49 0; +#X connect 47 0 50 0; +#X connect 47 0 51 0; +#X connect 48 0 46 1; +#X connect 49 0 46 2; +#X connect 50 0 46 3; +#X connect 51 0 46 4; +#X connect 52 0 46 5; +#X connect 53 0 46 6; +#X connect 54 0 46 7; +#X connect 55 0 46 8; +#X connect 56 0 46 9; +#X connect 57 0 46 10; +#X connect 58 0 47 0; +#X connect 59 0 60 0; +#X connect 60 0 17 0; +#X connect 61 0 13 0; +#X connect 61 0 13 1; +#X connect 61 0 63 0; +#X connect 62 0 64 0; +#X connect 64 0 61 1; -- cgit v1.2.1