aboutsummaryrefslogtreecommitdiff
path: root/sonogram~
diff options
context:
space:
mode:
Diffstat (limited to 'sonogram~')
-rw-r--r--sonogram~/CHANGES.LOG23
-rw-r--r--sonogram~/INSTALL15
-rw-r--r--sonogram~/Makefile82
-rw-r--r--sonogram~/README25
-rw-r--r--sonogram~/help-sonogram~.pd10
-rw-r--r--sonogram~/help-sonograph~.pd10
-rw-r--r--sonogram~/rs-sonogram~.pd307
-rw-r--r--sonogram~/rs-sonograph~.pd217
-rw-r--r--sonogram~/sonogram~-joge.c2024
-rw-r--r--sonogram~/sonogram~-yves.c1995
-rw-r--r--sonogram~/sonogram~.c2061
11 files changed, 6769 insertions, 0 deletions
diff --git a/sonogram~/CHANGES.LOG b/sonogram~/CHANGES.LOG
new file mode 100644
index 0000000..64161e7
--- /dev/null
+++ b/sonogram~/CHANGES.LOG
@@ -0,0 +1,23 @@
+0.11
+ allow backwards reading
+0.10
+ change allocation algorithm
+0.9
+ use copy buffers for cut and paste
+ one level undo on sonogram part with 'undo' message
+0.8
+ check boundaries before updating
+0.7
+ use static buffers to avoid some crashes
+0.6
+ fixed simultaneous record/play to use it in a real-time chain
+0.5
+ even safer cut and paste code !!!
+0.4
+ safer cut and paste code
+0.3
+ added phasogram
+0.2
+ added transfroamtions
+0.1
+ first implementation
diff --git a/sonogram~/INSTALL b/sonogram~/INSTALL
new file mode 100644
index 0000000..d69da45
--- /dev/null
+++ b/sonogram~/INSTALL
@@ -0,0 +1,15 @@
+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~/Makefile b/sonogram~/Makefile
new file mode 100644
index 0000000..b3d37a1
--- /dev/null
+++ b/sonogram~/Makefile
@@ -0,0 +1,82 @@
+NAME=sonogram~
+CSYM=sonogram_tilde
+
+current: pd_linux
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I\tcl\include /I\ftp\pd\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ \ftp\pd\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I../../src
+
+.c.pd_irix5:
+ cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -Ofast=ip32
+
+.c.pd_irix6:
+ cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -DPD -DUNIX -DICECAST -O2 -funroll-loops -fomit-frame-pointer \
+ -Wall -W -Wno-shadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch -g #-Werror
+
+LINUXINCLUDE = -I../../src
+
+.c.pd_linux:
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
+ strip --strip-unneeded $*.pd_linux
+ rm -f $*.o ../$*.pd_linux
+ ln -s $*/$*.pd_linux ..
+
+# ----------------------------------------------------------
+
+install:
+ cp help-*.pd rs-*.pd ../../doc/5.reference
+
+clean:
+ rm -f *.o *.pd_* so_locations
diff --git a/sonogram~/README b/sonogram~/README
new file mode 100644
index 0000000..2d8b212
--- /dev/null
+++ b/sonogram~/README
@@ -0,0 +1,25 @@
+Version 0.01
+copyleft 2001 by Yves Degoyon
+tarballs and updates available @ http://ydegoyon.free.fr
+
+sonogram~.dll : displays, plays back and lets you modify a recorded sonogram.
+
+The real and imaginery part of an fft~ is stored in a sonogram~
+and, then, you can apply modifications to it
+or do mouse-based graphic modifications.
+The set of modifications provided for now consists of
+matrix operations but it will be improved soon.
+
+To install sonogram~, follow the steps from INSTALL
+
+This software is published under GPL terms.
+
+This is software with ABSOLUTELY NO WARRANTY.
+Use it at your OWN RISK. It's possible to damage e.g. hardware or your hearing
+due to a bug or for other reasons.
+We do not warrant that the program is free of infringement of any third-party
+patents.
+
+*****************************************************************************
+
+
diff --git a/sonogram~/help-sonogram~.pd b/sonogram~/help-sonogram~.pd
new file mode 100644
index 0000000..ab00898
--- /dev/null
+++ b/sonogram~/help-sonogram~.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~/help-sonograph~.pd b/sonogram~/help-sonograph~.pd
new file mode 100644
index 0000000..4352c3d
--- /dev/null
+++ b/sonogram~/help-sonograph~.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/sonogram~/rs-sonogram~.pd b/sonogram~/rs-sonogram~.pd
new file mode 100644
index 0000000..864666f
--- /dev/null
+++ b/sonogram~/rs-sonogram~.pd
@@ -0,0 +1,307 @@
+#N canvas 43 28 986 681 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;
+#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 309 22 600 544 modifications 0;
+#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 msg 113 395 average 100;
+#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;
+#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 connect 3 0 38 0;
+#X connect 4 0 8 0;
+#X connect 5 0 38 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 41 0;
+#X connect 14 0 44 0;
+#X connect 16 0 38 0;
+#X connect 17 0 38 0;
+#X connect 20 0 38 0;
+#X connect 22 0 38 0;
+#X connect 23 0 38 0;
+#X connect 26 0 38 0;
+#X connect 27 0 26 0;
+#X connect 30 0 31 0;
+#X connect 31 0 38 0;
+#X connect 33 0 34 0;
+#X connect 34 0 38 0;
+#X connect 36 0 38 0;
+#X connect 39 0 38 0;
+#X connect 40 0 38 0;
+#X connect 41 0 38 0;
+#X connect 42 0 38 0;
+#X connect 43 0 42 0;
+#X connect 44 0 38 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 80 275 sonogram~ 463 1 1 1;
+#X msg 467 608 zoom 1;
+#X msg 484 99 readspeed \$1;
+#X floatatom 617 99 5 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;
+#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 <shift>click :;
+#X text 128 579 add modstep to the selected data;
+#X text 43 590 <alt>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 <shift><alt>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 obj 829 571 block~ 256;
+#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;
+#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;
+#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;
+#X obj 263 174 *~ 1;
+#X obj 261 149 /~ 256;
+#X text 332 129 Volume;
+#X text 31 631 <shift>click :;
+#X text 44 642 <alt>click :;
+#X text 3 652 <shift><alt>click :;
+#X msg 488 630 undo;
+#X text 526 630 One level undo;
+#X obj 21 192 makefilename %d-sonosample;
+#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 90 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 98 0;
+#X connect 64 0 41 0;
+#X connect 78 0 36 0;
+#X connect 82 0 91 0;
+#X connect 83 0 41 0;
+#X connect 86 0 14 0;
+#X connect 87 0 41 0;
+#X connect 88 0 90 1;
+#X connect 89 0 88 0;
+#X connect 90 0 16 0;
+#X connect 90 0 51 0;
+#X connect 90 0 51 1;
+#X connect 91 0 90 0;
+#X connect 96 0 41 0;
+#X connect 98 0 9 1;
diff --git a/sonogram~/rs-sonograph~.pd b/sonogram~/rs-sonograph~.pd
new file mode 100644
index 0000000..c8795ec
--- /dev/null
+++ b/sonogram~/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~ 215 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~-joge.c b/sonogram~/sonogram~-joge.c
new file mode 100644
index 0000000..6fc2153
--- /dev/null
+++ b/sonogram~/sonogram~-joge.c
@@ -0,0 +1,2024 @@
+/*------------------------ sonogram~ ------------------------------------------ */
+/* */
+/* sonogram~ : lets you record, play back and modify a sonogram */
+/* constructor : sonogram <size> <graphical=0|1> <phasogram=0|1> */
+/* */
+/* 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 <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <ctype.h>
+#ifdef UNIX
+#include <unistd.h>
+#include <pthread.h>
+#endif
+#ifdef NT
+#define M_PI 3.14159265358979323846
+#include "pthread.h"
+#include <windows.h>
+#endif
+#include <math.h>
+
+#include "m_imp.h"
+#include "g_canvas.h"
+#include "t_tk.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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; fi<x->x_blocksize/2; fi++)
+ {
+ {
+ int i;
+
+ for ( i=0; i<x->x_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( glist_getcanvas(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,
+ gensym("sonogram~"), 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_getcanvas(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; fi<x->x_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( glist_getcanvas(x->x_glist), (t_text*)x );
+ }
+
+ bi = 0;
+ while (bi<n)
+ {
+ // eventually records input
+ if ( x->x_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( glist_getcanvas( 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; fi<x->x_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; fi<x->x_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; sp<fnbpoints; sp++ ) {
+#ifdef NT
+ s1 = samplestart + (rand()%(sampleend-samplestart));
+ s2 = samplestart + (rand()%(sampleend-samplestart));
+ f1 = rand()%( x->x_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; fi<x->x_blocksize; fi++ ) {
+ for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) {
+ fraverage=fiaverage=0.0;
+ for ( ssi=0; ssi<fnbblocks; ssi++ ) {
+ fraverage += *(x->x_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; ssi<fnbblocks; ssi++ ) {
+ *(x->x_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; sf<fgoup; 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);
+}
+
+ /* 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; sf<froll; sf++ ) {
+ *(fprvalues+sf) =
+ *(x->x_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; sf<froll; sf++ ) {
+ *(x->x_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; sf<x->x_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);
+ class_sethelpsymbol( sonogram_class, gensym("help-sonogram~.pd") );
+
+ // 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;
+ sonogram_widgetbehavior.w_propertiesfn = NULL;
+ sonogram_widgetbehavior.w_savefn = sonogram_save;
+
+ 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~/sonogram~-yves.c b/sonogram~/sonogram~-yves.c
new file mode 100644
index 0000000..0d2a721
--- /dev/null
+++ b/sonogram~/sonogram~-yves.c
@@ -0,0 +1,1995 @@
+/*------------------------ sonogram~ ------------------------------------------ */
+/* */
+/* sonogram~ : lets you record, play back and modify a sonogram */
+/* constructor : sonogram <size> <graphical=0|1> <phasogram=0|1> */
+/* */
+/* 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 <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <ctype.h>
+#include <pthread.h>
+#ifdef UNIX
+#include <unistd.h>
+#endif
+#ifdef NT
+#define M_PI 3.14159265358979323846
+#endif
+#include <math.h>
+
+#include "m_imp.h"
+#include "g_canvas.h"
+#include "t_tk.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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; fi<x->x_blocksize/2; fi++)
+ {
+ {
+ int i;
+
+ for ( i=0; i<x->x_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( glist_getcanvas(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,
+ gensym("sonogram~"), 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_getcanvas(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; fi<x->x_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( glist_getcanvas(x->x_glist), (t_text*)x );
+ }
+
+ bi = 0;
+ while (bi<n)
+ {
+ // eventually records input
+ if ( x->x_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( glist_getcanvas( 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; fi<x->x_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; fi<x->x_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; sp<fnbpoints; sp++ ) {
+ s1 = samplestart + (random()%(sampleend-samplestart));
+ s2 = samplestart + (random()%(sampleend-samplestart));
+ f1 = random()%( x->x_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; fi<x->x_blocksize; fi++ ) {
+ for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) {
+ fraverage=fiaverage=0.0;
+ for ( ssi=0; ssi<fnbblocks; ssi++ ) {
+ fraverage += *(x->x_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; ssi<fnbblocks; ssi++ ) {
+ *(x->x_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; sf<fgoup; 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);
+}
+
+ /* 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; sf<froll; sf++ ) {
+ *(fprvalues+sf) =
+ *(x->x_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; sf<froll; sf++ ) {
+ *(x->x_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; sf<x->x_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);
+ class_sethelpsymbol( sonogram_class, gensym("help-sonogram~.pd") );
+
+ // 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;
+ sonogram_widgetbehavior.w_propertiesfn = NULL;
+ sonogram_widgetbehavior.w_savefn = sonogram_save;
+
+ 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~/sonogram~.c b/sonogram~/sonogram~.c
new file mode 100644
index 0000000..d16f6ca
--- /dev/null
+++ b/sonogram~/sonogram~.c
@@ -0,0 +1,2061 @@
+/*------------------------ sonogram~ ------------------------------------------ */
+/* */
+/* sonogram~ : lets you record, play back and modify a sonogram */
+/* constructor : sonogram <size> <graphical=0|1> <phasogram=0|1> */
+/* */
+/* 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 <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <ctype.h>
+#include <pthread.h>
+#ifdef UNIX
+#include <unistd.h>
+#endif
+#ifdef NT
+#define M_PI 3.14159265358979323846
+#endif
+#include <math.h>
+
+#include "m_pd.h"
+#include "m_imp.h"
+#include "g_canvas.h"
+#include "t_tk.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.11, 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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ sprintf( x->x_gifdata, "%s", strcat( newColor, " ") );
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; i<x->x_zoom; i++ )
+ {
+ strncpy( x->x_gifdata+((x->x_blocksize/2-fi-1)*x->x_zoom+i)*8, strcat( color, " "), 8 );
+ }
+ }
+ for ( i=0; i<x->x_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; fi<x->x_blocksize/2; fi++)
+ {
+ {
+ int i;
+
+ for ( i=0; i<x->x_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( glist_getcanvas(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,
+ gensym("sonogram~"), 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_getcanvas(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; fi<x->x_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( glist_getcanvas(x->x_glist), (t_text*)x );
+ }
+
+ bi = 0;
+ while (bi<n)
+ {
+ // eventually records input
+ if ( x->x_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;
+
+ 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",
+ 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;
+ 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",
+ 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_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( glist_getcanvas( 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; fi<x->x_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; fi<x->x_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; sp<fnbpoints; sp++ ) {
+ s1 = samplestart + (random()%(sampleend-samplestart));
+ s2 = samplestart + (random()%(sampleend-samplestart));
+ f1 = random()%( x->x_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; fi<x->x_blocksize; fi++ ) {
+ for ( si=samplestart; si<=sampleend-fnbblocks; si+=fnbblocks ) {
+ fraverage=fiaverage=0.0;
+ for ( ssi=0; ssi<fnbblocks; ssi++ ) {
+ fraverage += *(x->x_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; ssi<fnbblocks; ssi++ ) {
+ *(x->x_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; sf<fgoup; 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);
+}
+
+ /* 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; sf<froll; sf++ ) {
+ *(fprvalues+sf) =
+ *(x->x_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; sf<froll; sf++ ) {
+ *(x->x_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; sf<x->x_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);
+ class_sethelpsymbol( sonogram_class, gensym("help-sonogram~.pd") );
+
+ // 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;
+ sonogram_widgetbehavior.w_propertiesfn = NULL;
+ sonogram_widgetbehavior.w_savefn = sonogram_save;
+
+ 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);
+}