From eba585829684fcf54a0c8614709d2c10c75032b4 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sat, 8 Jan 2005 04:59:44 +0000 Subject: merge in branch "20041229-unify" - some small cleanups os x fixes minor updates improved buffer handling simplify updates Mac adaptations - made xcode project preparing xsample 0.3.0 release updated for build system some optimizations - fixed loop record bug Completion of attribute functionality, revisited and updated help files svn path=/trunk/; revision=2477 --- externals/grill/xsample/license.txt | 4 +- externals/grill/xsample/maxmsp/xsample.help | Bin 18907 -> 18925 bytes externals/grill/xsample/package.txt | 23 +- externals/grill/xsample/pd/xgroove~.pd | 139 ++-- externals/grill/xsample/pd/xplay~.pd | 48 +- externals/grill/xsample/pd/xrecord~.pd | 36 +- externals/grill/xsample/readme.txt | 90 +-- externals/grill/xsample/source/groove.cpp | 788 ++++++++------------- externals/grill/xsample/source/inter.cpp | 128 ++-- externals/grill/xsample/source/inter.h | 511 ++++++++----- externals/grill/xsample/source/main.cpp | 244 +++---- externals/grill/xsample/source/main.h | 306 +++++--- externals/grill/xsample/source/play.cpp | 86 +-- externals/grill/xsample/source/prefix.h | 1 + externals/grill/xsample/source/record.cpp | 336 ++++----- externals/grill/xsample/xsample.cw | Bin 399047 -> 0 bytes externals/grill/xsample/xsample.mcp | Bin 0 -> 457399 bytes externals/grill/xsample/xsample.vcproj | 41 +- .../grill/xsample/xsample.xcode/project.pbxproj | 92 ++- 19 files changed, 1482 insertions(+), 1391 deletions(-) delete mode 100755 externals/grill/xsample/xsample.cw create mode 100755 externals/grill/xsample/xsample.mcp (limited to 'externals') diff --git a/externals/grill/xsample/license.txt b/externals/grill/xsample/license.txt index d59706ef..3f8ead45 100644 --- a/externals/grill/xsample/license.txt +++ b/externals/grill/xsample/license.txt @@ -1,5 +1,5 @@ xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (C) 2001-2003 Thomas Grill +Copyright (C) 2001-2005 Thomas Grill This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -30,7 +30,7 @@ See the license texts below: --- flext ---------------------------------------------- flext - C++ layer for Max/MSP and pd (pure data) externals -Copyright (C) 2001-2003 Thomas Grill +Copyright (C) 2001-2005 Thomas Grill This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/externals/grill/xsample/maxmsp/xsample.help b/externals/grill/xsample/maxmsp/xsample.help index 47fae9fb..82d19cd0 100755 Binary files a/externals/grill/xsample/maxmsp/xsample.help and b/externals/grill/xsample/maxmsp/xsample.help differ diff --git a/externals/grill/xsample/package.txt b/externals/grill/xsample/package.txt index 7274807e..2d8ef2f2 100644 --- a/externals/grill/xsample/package.txt +++ b/externals/grill/xsample/package.txt @@ -1,12 +1,23 @@ +# xsample - extended sample objects for Max/MSP and PD (pure data) +# +# Copyright (c)2001-2005 Thomas Grill (gr@grrrr.org) +# For information on usage and redistribution, and for a DISCLAIMER OF ALL +# WARRANTIES, see the file, "license.txt," in this distribution. +# +# more information on http://grrrr.org/ext +# ------------------------------------------------------------------------ +# +# This file contains information for the building process +# +# DO NOT EDIT!! +# +# ------------------------------------------------------------------------ + NAME=xsample -BUILDCLASS=ext -BUILDMODE=release -BUILDTYPE=single +SRCDIR=source PRECOMPILE=prefix.h -SRCDIR=source - SRCS=main.cpp play.cpp groove.cpp record.cpp inter.cpp -HDRS=main.h inter.h +HDRS=prefix.h main.h inter.h diff --git a/externals/grill/xsample/pd/xgroove~.pd b/externals/grill/xsample/pd/xgroove~.pd index 86d879b5..0f4c37e9 100644 --- a/externals/grill/xsample/pd/xgroove~.pd +++ b/externals/grill/xsample/pd/xgroove~.pd @@ -1,7 +1,6 @@ -#N canvas 69 62 929 594 12; +#N canvas 69 62 941 606 12; #X obj 215 253 hsl 128 15 0.001 3 1 1 empty empty speed 0 -8 0 10 -225271 --1 -1 10800 1; -#X floatatom 212 271 8 0 0 0 - - -; +-1 -1 10400 1; #X msg 603 169 loop \$1; #X obj 28 72 bng 15 250 50 0 empty empty empty 20 8 0 8 -258699 -1 -1; @@ -10,7 +9,7 @@ #X array \$0-buf 10000 float 0; #X coords 0 1 9999 -1 300 150 1; #X restore 573 269 graph; -#X obj 44 529 dac~; +#X obj 17 556 dac~; #X msg 120 73 reset; #X text 299 321 min/max points; #X text 50 69 start; @@ -30,27 +29,27 @@ #X text 244 142 s; #X text 377 127 buffer; #X text 377 142 loop; -#X obj 491 223 bng 15 250 50 0 empty empty empty 0 -6 0 8 -228992 -1 +#X obj 487 208 bng 15 250 50 0 empty empty empty 0 -6 0 8 -228992 -1 -1; #X obj 335 349 print A; #N canvas 0 0 450 300 graph2 0; #X array \$0-scp 300 float 0; #X coords 0 1 299 -1 300 100 1; #X restore 573 447 graph; -#X obj 53 498 *~; -#X obj 89 486 hsl 128 15 0.0001 1 1 0 empty empty volume -2 -6 0 8 --261689 -1 -1 10900 1; -#X obj 86 504 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 -10 -261689 -1 -1 0.271063 256; +#X obj 26 525 *~; +#X obj 82 491 hsl 128 15 0.0001 1 1 0 empty empty volume -2 -6 0 8 +-261689 -1 -1 0 1; +#X obj 79 509 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 +10 -261689 -1 -1 0 256; #X msg 25 249 pos \$1; #X msg 63 220 200; #X msg 25 221 100; -#X obj 511 224 nbx 5 14 0 1e+037 0 1 empty empty frq 0 -6 0 10 -228992 --1 -1 144 256; -#N canvas 19 334 415 321 loopzone 0; +#X obj 507 209 nbx 5 14 0 1e+037 0 1 empty empty frq 0 -6 0 10 -228992 +-1 -1 220 256; +#N canvas 19 334 427 333 loopzone 0; #X msg 28 84 xzone \$1; #X obj 31 43 hsl 128 15 0 300 0 0 empty empty empty -2 -6 0 8 -262131 --1 -1 12700 1; +-1 -1 0 1; #X floatatom 28 64 5 0 0 0 - - -; #X msg 203 207 xfade \$1; #X obj 203 142 vdl 15 0 0 4 empty empty empty 0 -6 0 8 -262144 -1 -1 @@ -79,21 +78,21 @@ #X connect 9 0 19 0; #X connect 10 0 9 0; #X restore 23 414 pd loopzone; -#X text 118 137 set buffer; +#X text 64 147 set buffer; #X text 23 383 settings for; #X text 22 395 cross-fading loop zone; #X text 399 349 print attributes; -#X obj 300 393 bng 15 250 50 0 empty empty loop_bang 0 -6 0 8 -262131 +#X obj 357 394 bng 15 250 50 0 empty empty loop_bang 0 -6 0 8 -262131 -1 -1; #X text 357 60 scale mode; #X text 354 75 (pos message and position outlet); #X text 622 148 bidirectional; #X text 244 111 buffer size; #X obj 574 419 hsl 300 15 0 10000 0 0 empty bufpos empty -2 -6 0 8 --262144 -1 -1 20832 1; +-262144 -1 -1 0 1; #X obj 236 527 nbx 5 14 -1e+037 1e+037 0 0 empty empty position 0 -6 -0 10 -228992 -1 -1 6967.26 256; -#N canvas 0 0 470 320 watch 0; +0 10 -228992 -1 -1 0 256; +#N canvas 0 0 474 324 watch 0; #X obj 163 18 loadbang; #X obj 88 80 snapshot~; #X obj 164 44 metro 50; @@ -123,17 +122,17 @@ #X connect 2 0 3 0; #X connect 2 1 1 0; #X connect 4 0 3 0; -#X restore 491 244 pd genosc; +#X restore 487 229 pd genosc; #X text 600 97 loop mode; #X text 23 201 set position; #X obj 299 426 nbx 5 14 0 1e+037 0 1 empty empty min 0 -6 0 10 -262131 --1 -1 0 256; +-1 -1 1004 256; #X obj 356 426 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -262131 --1 -1 10000 256; +-1 -1 8996 256; #X obj 298 309 nbx 5 14 0 1e+037 0 1 empty empty min 0 -6 0 10 -225271 --1 -1 0 256; +-1 -1 1004 256; #X obj 355 309 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -225271 --1 -1 30000 256; +-1 -1 8996 256; #X text 244 95 frames (def.); #X text 377 96 units in buffer (def.); #X text 622 132 forward (def.); @@ -178,10 +177,9 @@ #X connect 20 0 24 0; #X restore 24 343 pd attributes; #X text 23 324 attribute stuff; -#X text 490 264 generate; +#X text 484 177 generate; #X obj 26 10 cnv 15 850 40 empty empty xgroove~ 10 22 0 24 -260818 -1 0; -#X text 227 29 http://www.parasitaere-kapazitaeten.net; #X msg 105 221 1000; #X msg 96 249 posmod \$1; #X text 146 227 modulo; @@ -195,52 +193,55 @@ -1 0; #X obj 358 99 vradio 15 1 0 4 empty empty empty 0 -6 0 8 -225271 -1 -1 0; -#X obj 136 168 s to-g; +#X obj 65 164 s to-g; #X obj 298 197 s to-g; #X obj 61 278 s to-g; #X obj 180 304 r to-g; #X obj 704 201 s to-g; #X obj 191 349 xgroove~ \$0-buf; -#X msg 26 136 set \$0-buf; -#X msg 25 161 set \$0-buf2; -#X text 227 10 varispeed sample player \, (C)2001-2004 Thomas Grill +#X text 227 29 http://grrrr.org/ext; +#X obj 79 550 line~; +#X msg 79 527 \$1 50; +#X obj 212 271 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 +10 -225271 -1 -1 0.703731 256; +#X text 227 10 varispeed sample player \, (C)2001-2005 Thomas Grill ; -#X connect 0 0 1 0; -#X connect 1 0 80 0; -#X connect 2 0 79 0; -#X connect 3 0 75 0; -#X connect 4 0 75 0; -#X connect 7 0 75 0; -#X connect 11 0 75 0; -#X connect 13 0 79 0; -#X connect 14 0 80 0; -#X connect 20 0 76 0; -#X connect 21 0 76 0; -#X connect 26 0 50 0; -#X connect 29 0 6 0; -#X connect 29 0 6 1; -#X connect 30 0 29 1; -#X connect 30 0 31 0; -#X connect 32 0 77 0; -#X connect 33 0 32 0; -#X connect 34 0 32 0; -#X connect 35 0 50 0; -#X connect 48 0 47 0; -#X connect 55 0 80 1; -#X connect 56 0 80 2; -#X connect 66 0 67 0; -#X connect 67 0 77 0; -#X connect 71 0 2 0; -#X connect 72 0 13 0; -#X connect 73 0 20 0; -#X connect 74 0 21 0; -#X connect 78 0 80 0; -#X connect 80 0 29 0; -#X connect 80 0 48 0; -#X connect 80 1 48 1; -#X connect 80 2 53 0; -#X connect 80 3 54 0; -#X connect 80 4 41 0; -#X connect 80 5 27 0; -#X connect 81 0 75 0; -#X connect 82 0 75 0; +#X connect 0 0 82 0; +#X connect 1 0 77 0; +#X connect 2 0 73 0; +#X connect 3 0 73 0; +#X connect 6 0 73 0; +#X connect 10 0 73 0; +#X connect 12 0 77 0; +#X connect 13 0 78 0; +#X connect 19 0 74 0; +#X connect 20 0 74 0; +#X connect 25 0 49 0; +#X connect 28 0 5 0; +#X connect 28 0 5 1; +#X connect 29 0 30 0; +#X connect 30 0 81 0; +#X connect 31 0 75 0; +#X connect 32 0 31 0; +#X connect 33 0 31 0; +#X connect 34 0 49 0; +#X connect 47 0 46 0; +#X connect 54 0 78 1; +#X connect 55 0 78 2; +#X connect 64 0 65 0; +#X connect 65 0 75 0; +#X connect 69 0 1 0; +#X connect 70 0 12 0; +#X connect 71 0 19 0; +#X connect 72 0 20 0; +#X connect 76 0 78 0; +#X connect 78 0 28 0; +#X connect 78 0 47 0; +#X connect 78 1 47 1; +#X connect 78 2 52 0; +#X connect 78 3 53 0; +#X connect 78 4 40 0; +#X connect 78 5 26 0; +#X connect 80 0 28 1; +#X connect 81 0 80 0; +#X connect 82 0 78 0; diff --git a/externals/grill/xsample/pd/xplay~.pd b/externals/grill/xsample/pd/xplay~.pd index da9d3a7a..a079a361 100644 --- a/externals/grill/xsample/pd/xplay~.pd +++ b/externals/grill/xsample/pd/xplay~.pd @@ -1,12 +1,12 @@ -#N canvas 165 149 700 428 12; +#N canvas 165 149 716 444 12; #X obj 21 75 bng 15 250 50 0 empty empty empty 20 8 0 8 -258699 -1 -1; #X msg 21 95 stop; #X msg 107 99 reset; #X text 43 72 start; #X text 60 93 stop; -#X obj 158 219 *~ 300; -#X text 164 240 position signal; +#X obj 159 217 *~ 300; +#X text 161 239 position signal; #X msg 107 75 help; #N canvas 0 0 450 300 graph7 0; #X array \$0-buf 300 float 1; @@ -54,19 +54,18 @@ #X coords 0 1 299 -1 300 200 1; #X restore 370 80 graph; #X obj 162 174 hsl 128 15 1 100 1 1 empty empty speed 0 -8 0 10 -225271 --1 -1 4200 1; +-1 -1 9300 1; #X msg 107 123 print; #X obj 159 194 phasor~ 100; -#X obj 198 280 print A; -#X obj 28 373 dac~; -#X obj 37 342 *~; -#X obj 73 330 hsl 128 15 0.0001 1 1 0 empty empty volume -2 -6 0 8 +#X obj 180 311 print A; +#X obj 37 389 dac~; +#X obj 46 358 *~; +#X obj 87 360 hsl 128 15 0.0001 1 1 0 empty empty volume -2 -6 0 8 -261689 -1 -1 0 1; -#X obj 70 348 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 +#X obj 84 378 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -261689 -1 -1 0 256; #X obj 21 10 cnv 15 650 40 empty empty xplay~ 10 22 0 24 -260818 -1 0; -#X text 180 29 http://www.parasitaere-kapazitaeten.net; #N canvas 0 0 450 300 graph2 0; #X array \$0-scp 300 float 0; #X coords 0 1 299 -1 300 100 1; @@ -79,7 +78,7 @@ #X connect 0 0 1 0; #X connect 1 0 3 0; #X connect 2 0 3 0; -#X restore 205 376 pd watch; +#X restore 90 310 pd watch; #N canvas 33 327 454 231 attributes 0; #X msg 85 60 getattributes; #X obj 22 181 s to; @@ -101,23 +100,24 @@ #X restore 22 210 pd attributes; #X text 21 192 attributes; #X obj 21 154 s to-p; -#X obj 81 257 r to-p; +#X obj 21 250 r to-p; #X obj 81 280 xplay~ \$0-buf; -#X text 180 10 buffer-based sample player \, (C)2001-2004 Thomas Grill +#X text 180 29 http://grrrr.org/ext; +#X text 179 11 buffer-based sample player \, (C)2001-2005 Thomas Grill ; -#X connect 0 0 23 0; -#X connect 1 0 23 0; -#X connect 2 0 23 0; -#X connect 5 0 25 0; -#X connect 7 0 23 0; +#X connect 0 0 22 0; +#X connect 1 0 22 0; +#X connect 2 0 22 0; +#X connect 5 0 24 0; +#X connect 7 0 22 0; #X connect 9 0 11 0; -#X connect 10 0 23 0; +#X connect 10 0 22 0; #X connect 11 0 5 0; #X connect 14 0 13 0; #X connect 14 0 13 1; -#X connect 15 0 14 1; #X connect 15 0 16 0; -#X connect 24 0 25 0; -#X connect 25 0 14 0; -#X connect 25 0 20 0; -#X connect 25 1 12 0; +#X connect 16 0 14 1; +#X connect 23 0 24 0; +#X connect 24 0 14 0; +#X connect 24 0 19 0; +#X connect 24 1 12 0; diff --git a/externals/grill/xsample/pd/xrecord~.pd b/externals/grill/xsample/pd/xrecord~.pd index f1145fb8..cccbdee9 100644 --- a/externals/grill/xsample/pd/xrecord~.pd +++ b/externals/grill/xsample/pd/xrecord~.pd @@ -1,4 +1,4 @@ -#N canvas 58 17 869 651 12; +#N canvas 58 17 877 659 12; #X obj 18 83 bng 15 250 50 0 empty empty empty 20 8 0 8 -258699 -1 -1; #X msg 17 103 stop; @@ -34,7 +34,7 @@ #X msg 572 320 sigmode \$1; #X msg 425 417 print; #X obj 579 425 hsl 128 15 -0.001 1 0 1 empty empty empty 20 8 0 8 -225271 --1 -1 3200 1; +-1 -1 2800 1; #X msg 601 347 mixmode \$1; #X floatatom 645 443 8 0 0 0 - - -; #X obj 427 530 metro 30; @@ -83,14 +83,11 @@ #X obj 516 529 xrecord~ \$0-buf; #X obj 18 12 cnv 15 800 40 empty empty xrecord~ 10 22 0 24 -260818 -1 0; -#X text 224 31 http://www.parasitaere-kapazitaeten.net; -#X text 224 12 buffer-based signal recorder \, (C)2001-2004 Thomas -Grill; #X text 202 253 min/max points; #X obj 201 241 nbx 5 14 0 1e+037 0 1 empty empty min 0 -6 0 10 -225271 --1 -1 78 256; +-1 -1 0 256; #X obj 258 241 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -225271 --1 -1 276 256; +-1 -1 10002 256; #X obj 190 365 nbx 5 14 0 1e+037 0 1 empty empty min 0 -6 0 10 -262131 -1 -1 0 256; #X obj 247 365 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -262131 @@ -104,9 +101,12 @@ Grill; #X obj 674 574 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -262131 -1 -1 10000 256; #X obj 618 500 nbx 5 14 0 1e+037 0 1 empty empty min 0 -6 0 10 -225271 --1 -1 78 256; +-1 -1 0 256; #X obj 675 500 nbx 5 14 0 1e+037 0 1 empty empty max 0 -6 0 10 -225271 --1 -1 276 256; +-1 -1 10000 256; +#X text 224 31 http://grrrr.org/ext; +#X text 224 12 buffer-based signal recorder \, (C)2001-2005 Thomas +Grill; #X connect 0 0 67 0; #X connect 1 0 67 0; #X connect 3 0 67 0; @@ -155,14 +155,14 @@ Grill; #X connect 62 0 60 0; #X connect 63 0 27 0; #X connect 67 0 4 0; -#X connect 67 1 75 0; -#X connect 67 2 76 0; -#X connect 67 3 78 0; +#X connect 67 1 73 0; +#X connect 67 2 74 0; +#X connect 67 3 76 0; #X connect 67 4 58 0; #X connect 68 0 16 0; -#X connect 68 1 80 0; -#X connect 68 2 81 0; -#X connect 73 0 67 2; -#X connect 74 0 67 3; -#X connect 82 0 68 2; -#X connect 83 0 68 3; +#X connect 68 1 78 0; +#X connect 68 2 79 0; +#X connect 71 0 67 2; +#X connect 72 0 67 3; +#X connect 80 0 68 2; +#X connect 81 0 68 3; diff --git a/externals/grill/xsample/readme.txt b/externals/grill/xsample/readme.txt index 777453b5..9383a120 100644 --- a/externals/grill/xsample/readme.txt +++ b/externals/grill/xsample/readme.txt @@ -1,6 +1,6 @@ -xsample - extended sample objects for Max/MSP and pd (pure data) +xsample - extended sample objects for Max/MSP and PD (pure data) -Copyright (c)2001-2004 Thomas Grill (t.grill@gmx.net) +Copyright (c)2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -9,11 +9,11 @@ WARRANTIES, see the file, "license.txt," in this distribution. Maximum care has been taken to prepare a delightful experience for you electronic artists. Donations for further development of the package are HIGHLY APPRECIATED. -Visit https://www.paypal.com/xclick/business=t.grill%40gmx.net&item_name=xsample&no_note=1&tax=0¤cy_code=EUR +Visit https://www.paypal.com/xclick/business=gr%40grrrr.org&item_name=xsample&no_note=1&tax=0¤cy_code=EUR ---------------------------------------------------------------------------- -IMPORTANT INFORMATION for all MaxMSP users: +IMPORTANT INFORMATION for all Max/MSP users: 1) For Mac OSX it is best to put the max-osx/xsample.mxd file into the folder @@ -42,68 +42,40 @@ by adding "-lib xsample" to the PD command line. ---------------------------------------------------------------------------- -You will need the flext C++ layer for PD and Max/MSP externals to compile this. -see http://www.parasitaere-kapazitaeten.net/ext - - -Package files: -- readme.txt: this one -- gpl.txt,license.txt: GPL license stuff -- main.h,main.cpp,inter.cpp,inter.h: base class definition for all the other objects -- record.cpp: xrecord~ -- play.cpp: xplay~ -- groove.cpp: xgroove~ - ----------------------------------------------------------------------------- BUILDING XSAMPLE from source ---------------------------- -The package should at least compile (and is tested) with the following compilers: - -pd - Windows: -------------- -o Microsoft Visual C++ 6 or .NET command line: edit "config-pd-msvc.txt" and run "build-pd-msvc.bat" - -o BCC: edit "config-pd-bcc.txt" and run "build-pd-bcc.bat" - -o Cygwin GCC: edit "config-pd-cygwin.txt" and run "sh ./build-pd-cygwin.sh" -> various versions of GCC die during compile with template optimization turned on - -o MinGW: edit "config-pd-mingw.txt" and run "build-pd-mingw.bat" -> MinGW binary folder must be included in the system path! - -pd - linux: ------------ -o GCC: edit "config-pd-linux.txt" and run "sh ./build-pd-linux.sh" -> various versions of GCC die during compile with template optimization turned on - -pd - OSX: ------------ -o GCC: edit "config-pd-darwin.txt" and run "sh ./build-pd-darwin.sh" -> various versions of GCC die during compile with template optimization turned on +You will need the flext C++ layer for PD and Max/MSP externals to compile this. +See http://grrrr.org/ext/flext +Download, install and compile the package. +Afterwards you can proceed with building xsample. -o XCode: use "xsample.xcode" project -Max/MSP - MacOS9: ----------------- -o Metrowerks CodeWarrior: "xsample.cw" project file +pd/Max - Windows - Microsoft Visual C, Borland C++, MinGW: +---------------------------------------------------------- +Start a command shell with your eventual build environment +(e.g. run vcvars32.bat for Microsoft Visual Studio) -o Apple MPW-PR: edit & use the "flext.mpw" makefile +then run + ..\flext\build.bat +(you would have to substitute ..\flext with the respective path to the flext package) -Max/MSP - MacOSX: ----------------- -o Metrowerks CodeWarrior: "xsample.cw" project file -o XCode: use "xsample.xcode" project +pd/Max - OSX/Linux - GCC: +------------------------- +From a shell run +bash ../flext/build.sh +(you would have to substitute ../flext with the respective path to the flext package) -Max/MSP - Windows: ----------------- -o Microsoft Visual C++ 6 or .NET command line: edit "config-max-msvc.txt" and run "build-max-msvc.bat" +Max - OS9 - Metrowerks CodeWarrior: +----------------------------------- +use the "xsample.mcp" project file ---------------------------------------------------------------------------- + Goals/features of the package: - portable and effective sample recording/playing objects for pd and Max/MSP @@ -126,6 +98,9 @@ Version history: - different initialization on buffer absence - renew units and scalemode on buffer change - fixed looped recording bug (thanks to Tatama Suomo) +- reconsidered all state changes +- more optimizations for interpolation functions +- use the new flext build system 0.3.0: - added resources to MaxMSP build @@ -183,25 +158,14 @@ Version history: --------------------------------------------------------------------------- - TODO list: -general: - -- do a smooth (line~) mixin in xrecord~ help patch - features: - multi-buffer handling (aka multi-channel for pd) -- vasp handling -- performance comparison to respective PD/Max objects - anti-alias filter? (possible?) - delay min/max changes when cur pos in cross-fade zone -tests: -- reconsider startup sequence of set buffer,set units,set sclmode,set pos/min/max - bugs: - PD: problems with timed buffer redrawing (takes a lot of cpu time) - flext bug? -- Apple MPW doesn't correctly compile template optimization - Max help files aren't correctly opened due to xsample objects residing in a library (FIXED for OSX!!!) diff --git a/externals/grill/xsample/source/groove.cpp b/externals/grill/xsample/source/groove.cpp index 341d241f..507cf349 100644 --- a/externals/grill/xsample/source/groove.cpp +++ b/externals/grill/xsample/source/groove.cpp @@ -1,11 +1,9 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #include "main.h" @@ -26,110 +24,96 @@ class xgroove: FLEXT_HEADER_S(xgroove,xinter,setup) public: - xgroove(I argc,const t_atom *argv); - ~xgroove(); - - virtual BL Init(); - - virtual V m_help(); - virtual V m_print(); - - virtual V m_units(xs_unit mode = xsu__); + xgroove(int argc,const t_atom *argv); + virtual ~xgroove(); - virtual BL m_reset(); + void m_pos(float pos) + { + setpos(s2u?pos/s2u:0); + Update(xsc_pos,true); + } - virtual V m_pos(F pos); - inline V m_posmod(F pos) { setposmod(pos?pos/s2u:0); } // motivated by Tim Blechmann - virtual V m_all(); - virtual V m_min(F mn); - virtual V m_max(F mx); + inline void m_posmod(float pos) { setposmod(pos?pos/s2u:0); } // motivated by Tim Blechmann - V ms_xfade(I xf); - V ms_xshape(I sh); + inline void mg_pos(float &v) const { v = curpos*s2u; } - V ms_xzone(F xz); - V mg_xzone(F &xz) { xz = _xzone*s2u; } - - enum xs_loop { - xsl__ = -1, // don't change - xsl_once = 0,xsl_loop,xsl_bidir - }; enum xs_fade { - xsf__ = -1, // don't change xsf_keeplooppos = 0,xsf_keeplooplen,xsf_keepfade,xsf_inside }; enum xs_shape { - xss__ = -1, // don't change xss_lin = 0,xss_qsine,xss_hsine }; - V m_loop(xs_loop lp = xsl__); + + void ms_xfade(int xf) + { + xfade = (xs_fade)xf; + Update(xsc_fade,true); + } + + void ms_xshape(int sh); + + void ms_xzone(float xz); + void mg_xzone(float &xz) { xz = _xzone*s2u; } + + void m_loop(xs_loop lp) + { + loopmode = lp,bidir = 1; + Update(xsc_loop,true); + } protected: - xs_loop loopmode; - D curpos; // in samples - I bidir; + double curpos; // in samples + float bidir; // +1 or -1 - F _xzone,xzone; - L znsmin,znsmax; + float _xzone,xzone; + long znsmin,znsmax; xs_fade xfade; - I xshape; - S **znbuf; - S *znpos,*znmul,*znidx; - I pblksz; + int xshape; + t_sample **znbuf; + t_sample *znpos,*znmul,*znidx; + int pblksz; - inline V outputmin() { ToOutFloat(outchns+1,curmin*s2u); } - inline V outputmax() { ToOutFloat(outchns+2,curmax*s2u); } - - inline V setpos(D pos) + inline void setpos(double pos) { if(pos < znsmin) curpos = znsmin; else if(pos > znsmax) curpos = znsmax; else curpos = pos; } - inline V setposmod(D pos) + inline void setposmod(double pos) { - D p = pos-znsmin; + double p = pos-znsmin; if(p >= 0) curpos = znsmin+fmod(p,znsmax-znsmin); else curpos = znsmax+fmod(p,znsmax-znsmin); } - inline V mg_pos(F &v) const { v = curpos*s2u; } + virtual void DoReset(); + virtual void DoUpdate(unsigned int flags); + + virtual void m_help(); + virtual void m_print(); + virtual void m_signal(int n,t_sample *const *in,t_sample *const *out); private: - static V setup(t_classid c); + static void setup(t_classid c); - virtual V s_dsp(); + //! return true if something has changed + bool do_xzone(); DEFSIGFUN(s_pos_off); DEFSIGFUN(s_pos_once); - DEFSIGFUN(s_pos_c_once); - DEFSIGFUN(s_pos_a_once); DEFSIGFUN(s_pos_loop); - DEFSIGFUN(s_pos_c_loop); - DEFSIGFUN(s_pos_a_loop); DEFSIGFUN(s_pos_loopzn); DEFSIGFUN(s_pos_bidir); DEFSIGCALL(posfun); - DEFSTCALL(zonefun); - V do_xzone(); - - virtual V m_signal(I n,S *const *in,S *const *out) - { - if(bufchk()) - posfun(n,in,out); - else - zerofun(n,in,out); - } - - static S fade_lin[],fade_qsine[],fade_hsine[]; + static t_sample fade_lin[],fade_qsine[],fade_hsine[]; FLEXT_CALLBACK_F(m_pos) FLEXT_CALLBACK_F(m_posmod) @@ -137,6 +121,8 @@ private: FLEXT_CALLBACK_F(m_max) FLEXT_CALLBACK(m_all) + FLEXT_CALLSET_E(m_loop,xs_loop) + FLEXT_CALLSET_I(ms_xfade) FLEXT_ATTRGET_I(xfade) FLEXT_CALLSET_I(ms_xshape) @@ -147,23 +133,21 @@ private: FLEXT_CALLVAR_F(mg_pos,m_pos) FLEXT_CALLSET_F(m_min) FLEXT_CALLSET_F(m_max) - FLEXT_CALLSET_E(m_loop,xs_loop) - FLEXT_ATTRGET_E(loopmode,xs_loop) }; FLEXT_LIB_DSP_V("xgroove~",xgroove) -S xgroove::fade_lin[XZONE_TABLE+1]; -S xgroove::fade_qsine[XZONE_TABLE+1]; -S xgroove::fade_hsine[XZONE_TABLE+1]; +t_sample xgroove::fade_lin[XZONE_TABLE+1]; +t_sample xgroove::fade_qsine[XZONE_TABLE+1]; +t_sample xgroove::fade_hsine[XZONE_TABLE+1]; #ifndef PI #define PI 3.14159265358979f #endif -V xgroove::setup(t_classid c) +void xgroove::setup(t_classid c) { DefineHelp(c,"xgroove~"); @@ -196,14 +180,14 @@ V xgroove::setup(t_classid c) } } -xgroove::xgroove(I argc,const t_atom *argv): - loopmode(xsl_loop),curpos(0),bidir(1), +xgroove::xgroove(int argc,const t_atom *argv): + curpos(0),bidir(1), _xzone(0),xzone(0), xfade(xsf_keeplooppos),xshape(xss_lin), znpos(NULL),znmul(NULL),znidx(NULL), pblksz(0) { - I argi = 0; + int argi = 0; #if FLEXT_SYS == FLEXT_SYS_MAX if(argc > argi && CanbeInt(argv[argi])) { outchns = GetAInt(argv[argi]); @@ -211,11 +195,9 @@ xgroove::xgroove(I argc,const t_atom *argv): } #endif - if(argc > argi && IsSymbol(argv[argi])) { - buf = new buffer(GetSymbol(argv[argi]),true); - + buf.Set(GetSymbol(argv[argi]),true); argi++; #if FLEXT_SYS == FLEXT_SYS_MAX @@ -227,14 +209,12 @@ xgroove::xgroove(I argc,const t_atom *argv): } #endif } - else - buf = new buffer(NULL,true); - AddInSignal("Signal of playing speed"); // speed signal + AddInSignal("Signal of playing speed"); // speed signal AddInFloat("Starting point"); // min play pos AddInFloat("Ending point"); // max play pos - for(I ci = 0; ci < outchns; ++ci) { - C tmp[30]; + for(int ci = 0; ci < outchns; ++ci) { + char tmp[30]; STD::sprintf(tmp,"Audio signal channel %i",ci+1); AddOutSignal(tmp); // output } @@ -244,16 +224,17 @@ xgroove::xgroove(I argc,const t_atom *argv): AddOutBang("Bang on loop end/rollover"); // loop bang // don't know vector size yet -> wait for m_dsp - znbuf = new S *[outchns]; - for(I i = 0; i < outchns; ++i) znbuf[i] = NULL; + znbuf = new t_sample *[outchns]; + for(int i = 0; i < outchns; ++i) znbuf[i] = NULL; - ms_xshape(xshape); + // initialize crossfade shape + ms_xshape(xshape); } xgroove::~xgroove() { if(znbuf) { - for(I i = 0; i < outchns; ++i) if(znbuf[i]) FreeAligned(znbuf[i]); + for(int i = 0; i < outchns; ++i) if(znbuf[i]) FreeAligned(znbuf[i]); delete[] znbuf; } @@ -261,80 +242,22 @@ xgroove::~xgroove() if(znidx) FreeAligned(znidx); } -BL xgroove::Init() -{ - if(xinter::Init()) { - m_reset(); - return true; - } - else - return false; -} - -V xgroove::m_units(xs_unit mode) -{ - xsample::m_units(mode); // calls bufchk() - - m_sclmode(); // calls bufchk() again.... \todo optimize that!! - outputmin(); - outputmax(); -} - -V xgroove::m_min(F mn) -{ - xsample::m_min(mn); - m_pos(curpos*s2u); -// do_xzone(); - s_dsp(); - outputmin(); -} - -V xgroove::m_max(F mx) -{ - xsample::m_max(mx); - m_pos(curpos*s2u); -// do_xzone(); - s_dsp(); - outputmax(); -} - -V xgroove::m_pos(F pos) -{ - setpos(pos && s2u?pos/s2u:0); -} - -V xgroove::m_all() -{ - xsample::m_all(); -// do_xzone(); - s_dsp(); - outputmin(); - outputmax(); -} - -BL xgroove::m_reset() +void xgroove::DoReset() { + xinter::DoReset(); curpos = 0; bidir = 1; - return xsample::m_reset(); } -V xgroove::ms_xfade(I xf) +void xgroove::ms_xzone(float xz) { - xfade = (xs_fade)xf; - // do_xzone(); - s_dsp(); -} + ChkBuffer(true); -V xgroove::ms_xzone(F xz) -{ - bufchk(); - _xzone = xz < 0 || !s2u?0:xz/s2u; -// do_xzone(); - s_dsp(); + _xzone = (xz < 0 || !s2u)?0:xz/s2u; + Update(xsc_fade,true); } -V xgroove::ms_xshape(I sh) +void xgroove::ms_xshape(int sh) { xshape = (xs_shape)sh; switch(xshape) { @@ -349,105 +272,10 @@ V xgroove::ms_xshape(I sh) // no need to recalc the fade zone here } -V xgroove::do_xzone() -{ - // \todo do we really need this? - if(!s2u) return; // this can happen if DSP is off - - xzone = _xzone; // make a copy for changing it - - if(xfade == xsf_inside) { - // fade zone goes inside the loop -> loop becomes shorter - - // \todo what about round-off? - const L maxfd = (curmax-curmin)/2; - if(xzone > maxfd) xzone = maxfd; - - znsmin = curmin,znsmax = curmax; - } - else if(xfade == xsf_keepfade) { - // try to keep fade zone - // change of loop bounds may happen - // restrict xzone to half of buffer - const L maxfd = buf->Frames()/2; - if(xzone > maxfd) xzone = maxfd; - - // \todo what about round-off? - znsmin = curmin-(L)(xzone/2); - znsmax = curmax+(L)(xzone/2); - - // widen loop if xzone doesn't fit into it - // \todo check formula - L lack = (L)ceil((xzone*2-(znsmax-znsmin))/2); - if(lack > 0) znsmin -= lack,znsmax += lack; - - // check buffer limits and shift bounds if necessary - if(znsmin < 0) { - znsmax -= znsmin; - znsmin = 0; - } - if(znsmax > buf->Frames()) - znsmax = buf->Frames(); - } - else if(xfade == xsf_keeplooplen) { - // try to keep loop length - // shifting of loop bounds may happen - - const L plen = curmax-curmin; - if(xzone > plen) xzone = plen; - const L maxfd = buf->Frames()-plen; - if(xzone > maxfd) xzone = maxfd; - - // \todo what about round-off? - znsmin = curmin-(L)(xzone/2); - znsmax = curmax+(L)(xzone/2); - - // check buffer limits and shift bounds if necessary - // both cases can't happen because of xzone having been limited above - if(znsmin < 0) { - znsmax -= znsmin; - znsmin = 0; - } - else if(znsmax > buf->Frames()) { - znsmin -= znsmax-buf->Frames(); - znsmax = buf->Frames(); - } - } - else if(xfade == xsf_keeplooppos) { - // try to keep loop position and length - - // restrict fade zone to maximum length - const L plen = curmax-curmin; - if(xzone > plen) xzone = plen; - - // \todo what about round-off? - znsmin = curmin-(L)(xzone/2); - znsmax = curmax+(L)(xzone/2); - - L ovr = znsmax-buf->Frames(); - if(-znsmin > ovr) ovr = -znsmin; - if(ovr > 0) { - znsmin += ovr; - znsmax -= ovr; - xzone -= ovr*2; - } - } - - FLEXT_ASSERT(znsmin <= znsmax && (znsmax-znsmin) >= xzone*2); -} - -V xgroove::m_loop(xs_loop lp) -{ - loopmode = lp; - bidir = 1; - s_dsp(); -} - - -V xgroove::s_pos_off(I n,S *const *invecs,S *const *outvecs) +void xgroove::s_pos_off(int n,t_sample *const *invecs,t_sample *const *outvecs) { - S *pos = outvecs[outchns]; + t_sample *pos = outvecs[outchns]; SetSamples(pos,n,curpos); @@ -456,19 +284,19 @@ V xgroove::s_pos_off(I n,S *const *invecs,S *const *outvecs) SetSamples(pos,n,scale(curpos)); } -V xgroove::s_pos_once(I n,S *const *invecs,S *const *outvecs) +void xgroove::s_pos_once(int n,t_sample *const *invecs,t_sample *const *outvecs) { - const S *speed = invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; + const t_sample *speed = invecs[0]; + t_sample *pos = outvecs[outchns]; + bool lpbang = false; - const D smin = curmin,smax = curmax,plen = smax-smin; + const double smin = curmin,smax = curmax,plen = smax-smin; - if(buf && plen > 0) { - register D o = curpos; + if(plen > 0) { + register double o = curpos; - for(I i = 0; i < n; ++i) { - const S spd = speed[i]; // must be first because the vector is reused for output! + for(int i = 0; i < n; ++i) { + const t_sample spd = speed[i]; // must be first because the vector is reused for output! if(!(o < smax)) { o = smax; lpbang = true; } else if(o < smin) { o = smin; lpbang = true; } @@ -489,66 +317,24 @@ V xgroove::s_pos_once(I n,S *const *invecs,S *const *outvecs) if(lpbang) ToOutBang(outchns+3); } -// \TODO optimize that for spd = const! -V xgroove::s_pos_c_once(I n,S *const *invecs,S *const *outvecs) +void xgroove::s_pos_loop(int n,t_sample *const *invecs,t_sample *const *outvecs) { - const S spd = *invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; - - const D smin = curmin,smax = curmax,plen = smax-smin; - - if(buf && plen > 0) { - register D o = curpos; - - for(I i = 0; i < n; ++i) { - if(!(o < smax)) { o = smax; lpbang = true; } - else if(o < smin) { o = smin; lpbang = true; } - - pos[i] = o; - o += spd; - } - // normalize and store current playing position - setpos(o); - - playfun(n,&pos,outvecs); - - arrscale(n,pos,pos); - } - else - s_pos_off(n,invecs,outvecs); - - if(lpbang) ToOutBang(outchns+3); -} - -V xgroove::s_pos_a_once(I n,S *const *invecs,S *const *outvecs) -{ - const S *speed = invecs[0]; - if(speed[0] == speed[n-1]) - // assume constant speed - s_pos_c_once(n,invecs,outvecs); - else - s_pos_once(n,invecs,outvecs); -} - -V xgroove::s_pos_loop(I n,S *const *invecs,S *const *outvecs) -{ - const S *speed = invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; + const t_sample *speed = invecs[0]; + t_sample *pos = outvecs[outchns]; + bool lpbang = false; #ifdef __VEC__ // prefetch cache vec_dst(speed,GetPrefetchConstant(1,n>>2,0),0); #endif - const D smin = curmin,smax = curmax,plen = smax-smin; + const double smin = curmin,smax = curmax,plen = smax-smin; - if(buf && plen > 0) { - register D o = curpos; + if(plen > 0) { + register double o = curpos; - for(I i = 0; i < n; ++i) { - const S spd = speed[i]; // must be first because the vector is reused for output! + for(int i = 0; i < n; ++i) { + const t_sample spd = speed[i]; // must be first because the vector is reused for output! // normalize offset if(!(o < smax)) { // faster than o >= smax @@ -580,82 +366,33 @@ V xgroove::s_pos_loop(I n,S *const *invecs,S *const *outvecs) if(lpbang) ToOutBang(outchns+3); } -// \TODO optimize that for spd = const! -V xgroove::s_pos_c_loop(I n,S *const *invecs,S *const *outvecs) +void xgroove::s_pos_loopzn(int n,t_sample *const *invecs,t_sample *const *outvecs) { - const S spd = *invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; - - const D smin = curmin,smax = curmax,plen = smax-smin; - - if(buf && plen > 0) { - register D o = curpos; - - for(I i = 0; i < n; ++i) { - // normalize offset - if(!(o < smax)) { // faster than o >= smax - o = fmod(o-smin,plen)+smin; - lpbang = true; - } - else if(o < smin) { - o = fmod(o-smin,plen)+smax; - lpbang = true; - } - - pos[i] = o; - o += spd; - } - // normalize and store current playing position - setpos(o); - - playfun(n,&pos,outvecs); - - arrscale(n,pos,pos); - } - else - s_pos_off(n,invecs,outvecs); - - if(lpbang) ToOutBang(outchns+3); -} - -V xgroove::s_pos_a_loop(I n,S *const *invecs,S *const *outvecs) -{ - const S *speed = invecs[0]; - if(speed[0] == speed[n-1]) - // assume constant speed - s_pos_c_loop(n,invecs,outvecs); - else - s_pos_loop(n,invecs,outvecs); -} - -V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) -{ - const S *speed = invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; + const t_sample *speed = invecs[0]; + t_sample *pos = outvecs[outchns]; + bool lpbang = false; FLEXT_ASSERT(xzone); - const F xz = xzone,xf = (F)XZONE_TABLE/xz; + const float xz = xzone,xf = (float)XZONE_TABLE/xz; // adapt the playing bounds to the current cross-fade zone - const L smin = znsmin,smax = znsmax,plen = smax-smin; + const long smin = znsmin,smax = znsmax,plen = smax-smin; // temporary storage - const L cmin = curmin,cmax = curmax; + const long cmin = curmin,cmax = curmax; // hack -> set curmin/curmax to loop extremes so that sampling functions (playfun) don't get confused curmin = smin,curmax = smax; - if(buf && plen > 0) { - BL inzn = false; - register D o = curpos; + if(plen > 0) { + bool inzn = false; + register double o = curpos; // calculate inner cross-fade boundaries - const D lmin = smin+xz,lmax = smax-xz,lsh = lmax-lmin+xz; - const D lmin2 = lmin-xz/2,lmax2 = lmax+xz/2; + const double lmin = smin+xz,lmax = smax-xz,lsh = lmax-lmin+xz; + const double lmin2 = lmin-xz/2,lmax2 = lmax+xz/2; - for(I i = 0; i < n; ++i) { + for(int i = 0; i < n; ++i) { // normalize offset if(o < smin) { o = fmod(o-smin,plen)+smax; @@ -666,9 +403,8 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) lpbang = true; } -#if 1 if(o < lmin) { - register F inp; + register float inp; if(o < lmin2) { // in first half of early cross-fade zone // this happens only once, then the offset is normalized to the end @@ -678,20 +414,20 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) // now lmax <= o <= lmax2 lpbang = true; - inp = xz-(F)(o-lmax); // 0 <= inp < xz + inp = xz-(float)(o-lmax); // 0 <= inp < xz znpos[i] = lmin-inp; } else { // in second half of early cross-fade zone - inp = xz+(F)(o-lmin); // 0 <= inp < xz + inp = xz+(float)(o-lmin); // 0 <= inp < xz znpos[i] = lmax+inp; } znidx[i] = inp*xf; inzn = true; } else if(!(o < lmax)) { - register F inp; + register float inp; if(!(o < lmax2)) { // in second half of late cross-fade zone // this happens only once, then the offset is normalized to the beginning @@ -700,12 +436,12 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) // now lmin2 <= o <= lmin lpbang = true; - inp = xz+(F)(o-lmin); // 0 <= inp < xz + inp = xz+(float)(o-lmin); // 0 <= inp < xz znpos[i] = lmax+inp; } else { // in first half of late cross-fade zone - inp = xz-(F)(o-lmax); // 0 <= inp < xz + inp = xz-(float)(o-lmax); // 0 <= inp < xz znpos[i] = lmin-inp; } znidx[i] = inp*xf; @@ -714,30 +450,9 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) else znidx[i] = XZONE_TABLE,znpos[i] = 0; - const S spd = speed[i]; // must be first because the vector is reused for output! + const t_sample spd = speed[i]; // must be first because the vector is reused for output! pos[i] = o; o += spd; -#else - if(o >= lmax) { - o -= lsh; - lpbang = true; - } - - if(o < lmin) { - register F inp = (F)(o-smin); // 0 <= inp < xz - znpos[i] = lmax+inp; - znidx[i] = inp*xf; - inzn = true; - } - else { - znpos[i] = 0; - znidx[i] = XZONE_TABLE; - } - - const S spd = speed[i]; // must be first because the vector is reused for output! - pos[i] = o; - o += spd; -#endif } // normalize and store current playing position @@ -759,11 +474,11 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) arrscale(n,znidx,znpos,XZONE_TABLE,-1); // calculate fade coefficients by sampling from the fade curve - zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znidx,&znidx); - zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znpos,&znpos); + zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znidx,&znidx,false); + zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znpos,&znpos,false); // mix voices for all channels - for(I o = 0; o < outchns; ++o) { + for(int o = 0; o < outchns; ++o) { MulSamples(outvecs[o],outvecs[o],znidx,n); MulSamples(znbuf[o],znbuf[o],znpos,n); AddSamples(outvecs[o],outvecs[o],znbuf[o],n); @@ -778,29 +493,30 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs) if(lpbang) ToOutBang(outchns+3); } -V xgroove::s_pos_bidir(I n,S *const *invecs,S *const *outvecs) +void xgroove::s_pos_bidir(int n,t_sample *const *invecs,t_sample *const *outvecs) { - const S *speed = invecs[0]; - S *pos = outvecs[outchns]; - BL lpbang = false; + const t_sample *speed = invecs[0]; + t_sample *pos = outvecs[outchns]; + bool lpbang = false; - const I smin = curmin,smax = curmax,plen = smax-smin; + const int smin = curmin,smax = curmax,plen = smax-smin; - if(buf && plen > 0) { - register D o = curpos; - register F bd = bidir; + if(plen > 0) { + register double o = curpos; + register float bd = bidir; - for(I i = 0; i < n; ++i) { - const S spd = speed[i]; // must be first because the vector is reused for output! + for(int i = 0; i < n; ++i) { + const t_sample spd = speed[i]; // must be first because the vector is reused for output! // normalize offset + // \todo at the moment fmod doesn't take bidirectionality into account!! if(!(o < smax)) { - o = smax-fmod(o-smin,plen); // mirror the position at smax + o = smax-fmod(o-smax,plen); // mirror the position at smax bd = -bd; lpbang = true; } else if(o < smin) { - o = smin-fmod(o-smin,plen); // mirror the position at smin + o = smin+fmod(smin-o,plen); // mirror the position at smin bd = -bd; lpbang = true; } @@ -811,79 +527,202 @@ V xgroove::s_pos_bidir(I n,S *const *invecs,S *const *outvecs) // normalize and store current playing position setpos(o); - bidir = (I)bd; + bidir = bd; playfun(n,&pos,outvecs); arrscale(n,pos,pos); } - else + else s_pos_off(n,invecs,outvecs); if(lpbang) ToOutBang(outchns+3); } +void xgroove::m_signal(int n,t_sample *const *in,t_sample *const *out) +{ + int ret = ChkBuffer(true); + + if(ret) { + FLEXT_ASSERT(buf.Valid()); + + const lock_t l = Lock(); + posfun(n,in,out); + Unlock(l); + + Refresh(); + } + else + zerofun(n,in,out); +} + -V xgroove::s_dsp() +void xgroove::DoUpdate(unsigned int flags) { - if(doplay) { - // xzone might not be set yet (is done in do_xzone() ) - do_xzone(); // recalculate (s2u may have been 0 before) - - switch(loopmode) { - case xsl_once: - SETSIGFUN(posfun,SIGFUN(s_pos_once)); - break; - case xsl_loop: - if(xzone > 0) { - const I blksz = Blocksize(); - - if(pblksz != blksz) { - for(I o = 0; o < outchns; ++o) { - if(znbuf[o]) FreeAligned(znbuf[o]); - znbuf[o] = (S *)NewAligned(blksz*sizeof(S)); - } - - if(znpos) FreeAligned(znpos); - znpos = (S *)NewAligned(blksz*sizeof(S)); - if(znidx) FreeAligned(znidx); - znidx = (S *)NewAligned(blksz*sizeof(S)); - - pblksz = blksz; - } + xinter::DoUpdate(flags); + + if(flags&xsc_range) { + // output new range + ToOutFloat(outchns+1,curmin*s2u); + ToOutFloat(outchns+2,curmax*s2u); + } + + if(flags&(xsc_fade|xsc_range)) + if(do_xzone()) flags |= xsc_play; + + if(flags&(xsc_pos|xsc_range)) + // normalize position + setpos(curpos); + + // loop zone must already be set + if(flags&xsc_play) { + if(doplay) { + switch(loopmode) { + case xsl_once: + SETSIGFUN(posfun,SIGFUN(s_pos_once)); + break; + case xsl_loop: + if(xzone > 0) { + const int blksz = Blocksize(); + + if(pblksz != blksz) { + for(int o = 0; o < outchns; ++o) { + if(znbuf[o]) FreeAligned(znbuf[o]); + znbuf[o] = (t_sample *)NewAligned(blksz*sizeof(t_sample)); + } + + if(znpos) FreeAligned(znpos); + znpos = (t_sample *)NewAligned(blksz*sizeof(t_sample)); + if(znidx) FreeAligned(znidx); + znidx = (t_sample *)NewAligned(blksz*sizeof(t_sample)); + + pblksz = blksz; + } + + SETSIGFUN(posfun,SIGFUN(s_pos_loopzn)); + + // linear interpolation should be just ok for fade zone, no? + switch(outchns) { + case 1: SETSTFUN(zonefun,TMPLSTF(st_play2,1,1)); break; + case 2: SETSTFUN(zonefun,TMPLSTF(st_play2,1,2)); break; + case 4: SETSTFUN(zonefun,TMPLSTF(st_play2,1,4)); break; + default: SETSTFUN(zonefun,TMPLSTF(st_play2,1,-1)); + } + } + else + SETSIGFUN(posfun,SIGFUN(s_pos_loop)); + break; + case xsl_bidir: + SETSIGFUN(posfun,SIGFUN(s_pos_bidir)); + break; + default: ; // just to prevent warning + } + } + else + SETSIGFUN(posfun,SIGFUN(s_pos_off)); + } +} - SETSIGFUN(posfun,SIGFUN(s_pos_loopzn)); +bool xgroove::do_xzone() +{ + // \todo do we really need this? + if(!s2u) return false; // this can happen if DSP is off - // linear interpolation should be just ok for fade zone, no? - switch(outchns) { - case 1: SETSTFUN(zonefun,TMPLSTF(st_play2,1,1)); break; - case 2: SETSTFUN(zonefun,TMPLSTF(st_play2,1,2)); break; - case 4: SETSTFUN(zonefun,TMPLSTF(st_play2,1,4)); break; - default: SETSTFUN(zonefun,TMPLSTF(st_play2,1,-1)); - } - } - else - SETSIGFUN(posfun,SIGFUN(s_pos_loop)); - break; - case xsl_bidir: - SETSIGFUN(posfun,SIGFUN(s_pos_bidir)); - break; - default: ; // just to prevent warning + const long frames = buf.Frames(); + if(!frames) return false; + + xzone = _xzone; // make a copy for changing it + + if(xfade == xsf_inside) { + // fade zone goes inside the loop -> loop becomes shorter + + // \todo what about round-off? + const long maxfd = (curmax-curmin)/2; + if(xzone > maxfd) xzone = maxfd; + + znsmin = curmin,znsmax = curmax; + } + else if(xfade == xsf_keepfade) { + // try to keep fade zone + // change of loop bounds may happen + + // restrict xzone to half of buffer + const long maxfd = frames/2; + if(xzone > maxfd) xzone = maxfd; + + // \todo what about round-off? + const long hzone = CASTINT(xzone/2.f); + znsmin = curmin-hzone; + znsmax = curmax+hzone; + + // widen loop if xzone doesn't fit into it + // \todo check formula + long lack = CASTINT(ceil((xzone*2.f-(znsmax-znsmin))/2.f)); + if(lack > 0) znsmin -= lack,znsmax += lack; + + // check buffer limits and shift bounds if necessary + if(znsmin < 0) { + znsmax -= znsmin; + znsmin = 0; } + if(znsmax > frames) + znsmax = frames; } - else - SETSIGFUN(posfun,SIGFUN(s_pos_off)); - xinter::s_dsp(); -} + else if(xfade == xsf_keeplooplen) { + // try to keep loop length + // shifting of loop bounds may happen + const long plen = curmax-curmin; + if(xzone > plen) xzone = plen; + const long maxfd = frames-plen; + if(xzone > maxfd) xzone = maxfd; + // \todo what about round-off? + const long hzone = CASTINT(xzone/2.f); + znsmin = curmin-hzone; + znsmax = curmax+hzone; + + // check buffer limits and shift bounds if necessary + // both cases can't happen because of xzone having been limited above + if(znsmin < 0) { + znsmax -= znsmin; + znsmin = 0; + } + else if(znsmax > frames) { + znsmin -= znsmax-frames; + znsmax = frames; + } + } + else if(xfade == xsf_keeplooppos) { + // try to keep loop position and length + + // restrict fade zone to maximum length + const long plen = curmax-curmin; + if(xzone > plen) xzone = plen; -V xgroove::m_help() + // \todo what about round-off? + const long hzone = CASTINT(xzone/2.f); + znsmin = curmin-hzone; + znsmax = curmax+hzone; + + long ovr = znsmax-frames; + if(-znsmin > ovr) ovr = -znsmin; + if(ovr > 0) { + znsmin += ovr; + znsmax -= ovr; + xzone -= ovr*2; + } + } + + FLEXT_ASSERT(znsmin <= znsmax && (znsmax-znsmin) >= xzone*2.f); + + return true; +} + + +void xgroove::m_help() { post("%s - part of xsample objects, version " XSAMPLE_VERSION,thisName()); -#ifdef FLEXT_DEBUG - post("compiled on " __DATE__ " " __TIME__); -#endif - post("(C) Thomas Grill, 2001-2004"); + post("(C) Thomas Grill, 2001-2005"); #if FLEXT_SYS == FLEXT_SYS_MAX post("Arguments: %s [channels=1] [buffer]",thisName()); #else @@ -915,18 +754,17 @@ V xgroove::m_help() post(""); } -V xgroove::m_print() +void xgroove::m_print() { - static const C *sclmode_txt[] = {"units","units in loop","buffer","loop"}; - static const C *interp_txt[] = {"off","4-point","linear"}; - static const C *loop_txt[] = {"once","looping","bidir"}; + static const char *sclmode_txt[] = {"units","units in loop","buffer","loop"}; + static const char *interp_txt[] = {"off","4-point","linear"}; + static const char *loop_txt[] = {"once","looping","bidir"}; // print all current settings post("%s - current settings:",thisName()); - post("bufname = '%s', length = %.3f, channels = %i",buf->Name(),(F)(buf->Frames()*s2u),buf->Channels()); - post("out channels = %i, frames/unit = %.3f, scale mode = %s",outchns,(F)(1./s2u),sclmode_txt[sclmode]); - post("loop = %s, interpolation = %s",loop_txt[(I)loopmode],interp_txt[interp >= xsi_none && interp <= xsi_lin?interp:xsi_none]); - post("loop crossfade zone = %.3f",(F)(xzone*s2u)); + post("bufname = '%s', length = %.3f, channels = %i",buf.Name(),(float)(buf.Frames()*s2u),buf.Channels()); + post("out channels = %i, frames/unit = %.3f, scale mode = %s",outchns,(float)(1./s2u),sclmode_txt[sclmode]); + post("loop = %s, interpolation = %s",loop_txt[(int)loopmode],interp_txt[interp >= xsi_none && interp <= xsi_lin?interp:xsi_none]); + post("loop crossfade zone = %.3f",(float)(xzone*s2u)); post(""); } - diff --git a/externals/grill/xsample/source/inter.cpp b/externals/grill/xsample/source/inter.cpp index fe63fce8..418726fc 100644 --- a/externals/grill/xsample/source/inter.cpp +++ b/externals/grill/xsample/source/inter.cpp @@ -1,11 +1,9 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #include "main.h" @@ -21,80 +19,64 @@ WARRANTIES, see the file, "license.txt," in this distribution. void xinter::setup(t_classid c) { + FLEXT_CADDBANG(c,0,m_start); + FLEXT_CADDMETHOD_(c,0,"start",m_start); + FLEXT_CADDMETHOD_(c,0,"stop",m_stop); + FLEXT_CADDATTR_VAR_E(c,"interp",interp,m_interp); } -I xinter::m_set(I argc,const t_atom *argv) +void xinter::DoUpdate(unsigned int flags) { - I r = xsample::m_set(argc,argv); - if(r) - // buffer parameters have changed, reset pos/min/max - m_reset(); - return r; -} + xsample::DoUpdate(flags); -V xinter::m_start() -{ - m_refresh(); - doplay = true; - s_dsp(); -} + if(flags&xsc_play) { + switch(outchns) { + case 1: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,1)); break; + case 2: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,2)); break; + case 4: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,4)); break; + default: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,-1)); + } -V xinter::m_stop() -{ - doplay = false; - s_dsp(); + if(doplay && buf.Ok()) { + if(interp == xsi_4p) + switch(buf.Channels()*1000+outchns) { + case 1001: SETSIGFUN(playfun,TMPLFUN(s_play4,1,1)); break; + case 1002: SETSIGFUN(playfun,TMPLFUN(s_play4,1,2)); break; + case 2001: SETSIGFUN(playfun,TMPLFUN(s_play4,2,1)); break; + case 2002: SETSIGFUN(playfun,TMPLFUN(s_play4,2,2)); break; + case 4001: + case 4002: + case 4003: SETSIGFUN(playfun,TMPLFUN(s_play4,4,-1)); break; + case 4004: SETSIGFUN(playfun,TMPLFUN(s_play4,4,4)); break; + default: SETSIGFUN(playfun,TMPLFUN(s_play4,-1,-1)); + } + else if(interp == xsi_lin) + switch(buf.Channels()*1000+outchns) { + case 1001: SETSIGFUN(playfun,TMPLFUN(s_play2,1,1)); break; + case 1002: SETSIGFUN(playfun,TMPLFUN(s_play2,1,2)); break; + case 2001: SETSIGFUN(playfun,TMPLFUN(s_play2,2,1)); break; + case 2002: SETSIGFUN(playfun,TMPLFUN(s_play2,2,2)); break; + case 4001: + case 4002: + case 4003: SETSIGFUN(playfun,TMPLFUN(s_play2,4,-1)); break; + case 4004: SETSIGFUN(playfun,TMPLFUN(s_play2,4,4)); break; + default: SETSIGFUN(playfun,TMPLFUN(s_play2,-1,-1)); + } + else + switch(buf.Channels()*1000+outchns) { + case 1001: SETSIGFUN(playfun,TMPLFUN(s_play1,1,1)); break; + case 1002: SETSIGFUN(playfun,TMPLFUN(s_play1,1,2)); break; + case 2001: SETSIGFUN(playfun,TMPLFUN(s_play1,2,1)); break; + case 2002: SETSIGFUN(playfun,TMPLFUN(s_play1,2,2)); break; + case 4001: + case 4002: + case 4003: SETSIGFUN(playfun,TMPLFUN(s_play1,4,-1)); break; + case 4004: SETSIGFUN(playfun,TMPLFUN(s_play1,4,4)); break; + default: SETSIGFUN(playfun,TMPLFUN(s_play1,-1,-1)); + } + } + else + SETSIGFUN(playfun,TMPLFUN(s_play0,-1,-1)); + } } - -V xinter::s_dsp() -{ - switch(outchns) { - case 1: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,1)); break; - case 2: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,2)); break; - case 4: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,4)); break; - default: SETSIGFUN(zerofun,TMPLFUN(s_play0,-1,-1)); - } - - if(doplay) { - if(interp == xsi_4p) - switch(buf->Channels()*1000+outchns) { - case 1001: SETSIGFUN(playfun,TMPLFUN(s_play4,1,1)); break; - case 1002: SETSIGFUN(playfun,TMPLFUN(s_play4,1,2)); break; - case 2001: SETSIGFUN(playfun,TMPLFUN(s_play4,2,1)); break; - case 2002: SETSIGFUN(playfun,TMPLFUN(s_play4,2,2)); break; - case 4001: - case 4002: - case 4003: SETSIGFUN(playfun,TMPLFUN(s_play4,4,-1)); break; - case 4004: SETSIGFUN(playfun,TMPLFUN(s_play4,4,4)); break; - default: SETSIGFUN(playfun,TMPLFUN(s_play4,-1,-1)); - } - else if(interp == xsi_lin) - switch(buf->Channels()*1000+outchns) { - case 1001: SETSIGFUN(playfun,TMPLFUN(s_play2,1,1)); break; - case 1002: SETSIGFUN(playfun,TMPLFUN(s_play2,1,2)); break; - case 2001: SETSIGFUN(playfun,TMPLFUN(s_play2,2,1)); break; - case 2002: SETSIGFUN(playfun,TMPLFUN(s_play2,2,2)); break; - case 4001: - case 4002: - case 4003: SETSIGFUN(playfun,TMPLFUN(s_play2,4,-1)); break; - case 4004: SETSIGFUN(playfun,TMPLFUN(s_play2,4,4)); break; - default: SETSIGFUN(playfun,TMPLFUN(s_play2,-1,-1)); - } - else - switch(buf->Channels()*1000+outchns) { - case 1001: SETSIGFUN(playfun,TMPLFUN(s_play1,1,1)); break; - case 1002: SETSIGFUN(playfun,TMPLFUN(s_play1,1,2)); break; - case 2001: SETSIGFUN(playfun,TMPLFUN(s_play1,2,1)); break; - case 2002: SETSIGFUN(playfun,TMPLFUN(s_play1,2,2)); break; - case 4001: - case 4002: - case 4003: SETSIGFUN(playfun,TMPLFUN(s_play1,4,-1)); break; - case 4004: SETSIGFUN(playfun,TMPLFUN(s_play1,4,4)); break; - default: SETSIGFUN(playfun,TMPLFUN(s_play1,-1,-1)); - } - } - else - SETSIGFUN(playfun,TMPLFUN(s_play0,-1,-1)); -} - - diff --git a/externals/grill/xsample/source/inter.h b/externals/grill/xsample/source/inter.h index e3bdd5c8..d0ab3994 100755 --- a/externals/grill/xsample/source/inter.h +++ b/externals/grill/xsample/source/inter.h @@ -1,225 +1,420 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #ifndef __INTER_H #define __INTER_H -TMPLDEF V xinter::st_play0(const S *,const I ,const I ,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play0(const t_sample *,const int ,const int ,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { // stopped/invalid buffer -> output zero - for(I ci = 0; ci < outchns; ++ci) ZeroSamples(outvecs[ci],n); + for(int ci = 0; ci < outchns; ++ci) ZeroSamples(outvecs[ci],n); } -TMPLDEF V xinter::st_play1(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play1(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // no interpolation // ---------------- - - for(I i = 0; i < n; ++i,++si) { - register const I oint = (I)(*(pos++)); - register const S *fp; - - if(oint >= smin) - if(oint < smax) { - // normal - fp = bdt+oint*BCHNS; - } - else { - // position > last sample ... take only last sample - fp = bdt+(smin == smax?smin:smax-1)*BCHNS; - } - else { - // position < 0 ... take only 0th sample - fp = bdt+smin*BCHNS; - } - - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + if(smin == smax) { + // zero loop length -> assume that smin is a valid sample position... + + int ci; + for(ci = 0; ci < OCHNS; ++ci) SetSamples(sig[ci],n,bdt[smin*BCHNS]); + // clear rest of output channels (if buffer has less channels) + for(; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } + else if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + register long oint = CASTINT(*(pos++)); + + // for xplay oint can be out of bounds -> check + if(oint >= smin) + if(oint < smax) { + // normal + *(sig0++) = bdt[oint*BCHNS]; + } + else { + // position > last sample ... take only last sample + *(sig0++) = bdt[(smax-1)*BCHNS]; + } + else { + // position < 0 ... take only 0th sample + *(sig0++) = bdt[smin*BCHNS]; + } + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + register long oint = CASTINT(*(pos++)); + register const t_sample *fp; + + // for xplay oint can be out of bounds -> check + if(oint >= smin) + if(oint < smax) { + // normal + fp = bdt+oint*BCHNS; + } + else { + // position > last sample ... take only last sample + fp = bdt+(smax-1)*BCHNS; + } + else { + // position < 0 ... take only 0th sample + fp = bdt+smin*BCHNS; + } + + for(int ci = 0; ci < OCHNS; ++ci) + sig[ci][si] = fp[ci]; + } + + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF V xinter::st_play2(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play2(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { - const I plen = smax-smin; //curlen; + const int plen = smax-smin; if(plen < 2) { - st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); + st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); return; } SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // linear interpolation // -------------------- - const I maxo = smax-1; // last sample in buffer - - for(I i = 0; i < n; ++i,++si) { - const F o = *(pos++); - register const I oint = (I)o; - - if(oint >= smin) - if(oint < maxo) { - // normal interpolation - register const F frac = o-oint; - register const S *const fp0 = bdt+oint*BCHNS; - register const S *const fp1 = fp0+BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp0[ci]+frac*(fp1[ci]-fp0[ci]); - } - else { - // position is past last sample -> take the last sample - register const S *const fp = bdt+maxo*BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - else { - // position is before first sample -> take the first sample - register const S *const fp = bdt+smin*BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - } + const int maxo = smax-1; // last sample in buffer + + if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + const float o = *(pos++); + register long oint = CASTINT(o); + const float frac = o-oint; + t_sample fp0,fp1; + + if(oint >= smin) + if(oint < maxo) { + // normal interpolation + fp0 = bdt[oint*BCHNS]; + fp1 = bdt[(oint+1)*BCHNS]; + } + else { + // position is past last sample + if(looped) { + oint = smin+(oint-smin)%plen; + fp0 = bdt[oint*BCHNS]; + fp1 = oint >= maxo?bdt[smin]:fp0; + } + else + fp0 = fp1 = bdt[maxo*BCHNS]; + } + else { + // position is before first sample + if(looped) { + oint = smax-(smin-oint)%plen; + fp0 = bdt[oint*BCHNS]; + fp1 = oint >= maxo?bdt[smin]:fp0; + } + else + fp0 = fp1 = bdt[smin*BCHNS]; + } + + *(sig0++) = fp0+frac*(fp1-fp0); + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + const float o = *(pos++); + register long oint = CASTINT(o); + const t_sample *fp0,*fp1; + const float frac = o-oint; + + if(oint >= smin) + if(oint < maxo) { + // normal interpolation + fp0 = bdt+oint*BCHNS; + fp1 = fp0+BCHNS; + } + else { + // position is past last sample + if(looped) { + oint = smin+(oint-smin)%plen; + fp0 = bdt+oint*BCHNS; + fp1 = oint >= maxo?bdt+smin:fp0; + } + else + fp0 = fp1 = bdt+maxo*BCHNS; + } + else { + // position is before first sample + if(looped) { + oint = smax-(smin-oint)%plen; + fp0 = bdt+oint*BCHNS; + fp1 = oint >= maxo?bdt+smin:fp0; + } + else + fp0 = fp1 = bdt+smin*BCHNS; + } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + for(int ci = 0; ci < OCHNS; ++ci) + sig[ci][si] = fp0[ci]+frac*(fp1[ci]-fp0[ci]); + } + + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF V xinter::st_play4(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play4(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { - const I plen = smax-smin; //curlen; + const int plen = smax-smin; //curlen; if(plen < 4) { - if(plen < 2) st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); - else st_play2 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); + if(plen < 2) st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); + else st_play2 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); return; } SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - -#ifdef __VEC__ - // prefetch cache - vec_dst(pos,GetPrefetchConstant(1,n>>2,0),0); - const int pf = GetPrefetchConstant(BCHNS,1,16*BCHNS); -#endif - - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // 4-point interpolation // --------------------- - const I maxo = smax-1; // last sample in play region - const S *maxp = bdt+maxo*BCHNS; // pointer to last sample - - for(I i = 0; i < n; ++i,++si) { - F o = *(pos++); - register I oint = (I)o; - register F frac; - register const S *fa,*fb,*fc,*fd; - - if(oint > smin) - if(oint < maxo-2) { - // normal case - - fa = bdt+oint*BCHNS-BCHNS; - frac = o-oint; - fb = fa+BCHNS; - #ifdef __VEC__ - vec_dst(fa,pf,0); - #endif - fc = fb+BCHNS; - fd = fc+BCHNS; - } - else { - // after the end - - if(oint > maxo) oint = maxo,o = (float)smax; - frac = o-oint; - - fb = bdt+oint*BCHNS; - fa = fb-BCHNS; - - // \TODO what about wraparound (in loop/palindrome mode) ? - fc = fb >= maxp?maxp:fb+BCHNS; - fd = fc >= maxp?maxp:fc+BCHNS; - } - else { - // before the beginning - - // if oint < first sample set it to first sample - // \TODO what about wraparound (in loop/palindrome mode) ? - if(oint < smin) oint = smin,o = (float)smin; - - // position is first sample - fa = bdt+smin*BCHNS; - - fb = bdt+oint*BCHNS; - frac = o-oint; - fc = fb+BCHNS; - fd = fc+BCHNS; - } - - register F f1 = 0.5f*(frac-1.0f); - register F f3 = frac*3.0f-1.0f; - - for(I ci = 0; ci < OCHNS; ++ci) { - const F amdf = (fa[ci]-fd[ci])*frac; - const F cmb = fc[ci]-fb[ci]; - const F bma = fb[ci]-fa[ci]; - sig[ci][si] = fb[ci] + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); - } - } - -#ifdef __VEC__ - vec_dss(0); -#endif + const int maxo = smax-1; // last sample in play region + + if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + float o = *(pos++); + register long oint = CASTINT(o); + register t_sample fa,fb,fc,fd; + const float frac = o-oint; + register const t_sample *ptr = bdt+oint*BCHNS; + + if(oint > smin) { + if(oint < maxo-2) { + // normal case + fa = ptr[-BCHNS]; + fb = ptr[0]; + fc = ptr[BCHNS]; + fd = ptr[BCHNS*2]; + } + else { + // not enough space at the end + + if(looped) { + // normalize position + oint = smin+(oint-smin)%plen; + goto looped1; + } + else { + // last sample is outside in any case + fd = bdt[maxo*BCHNS]; + + if(oint-1 >= maxo) + // if first is outside, all are outside + fa = fb = fc = fd; + else { + fa = ptr[-BCHNS]; + if(oint >= maxo) + fb = fc = fd; + else { + fb = ptr[0]; + fc = oint+1 < maxo?ptr[BCHNS]:fd; + } + } + } + } + } + else { + // not enough space at the beginning + + if(looped) { + // normalize position + oint = smax-(smin-oint)%plen; +looped1: + ptr = bdt+oint*BCHNS; + + // inside in any case + fb = ptr[0]; + + if(oint < maxo-1) { + fa = oint > smin?ptr[-BCHNS]:bdt[maxo*BCHNS]; + fc = ptr[BCHNS]; + fd = ptr[BCHNS*2]; + } + else { + fa = ptr[-BCHNS]; + fc = oint < maxo?ptr[BCHNS]:ptr[(1-plen)*BCHNS]; + fd = ptr[(2-plen)*BCHNS]; + } + } + else { + // first sample is outside in any case + fa = bdt[smin*BCHNS]; + + if(oint+2 < smin) + // if last is outside, all are outside + fb = fc = fd = fa; + else { + fd = ptr[BCHNS*2]; + if(oint+1 < smin) + fb = fc = fa; + else { + fc = ptr[BCHNS]; + fb = oint < smin?fa:ptr[0]; + } + } + } + } + + const float f1 = 0.5f*(frac-1.0f); + const float f3 = frac*3.0f-1.0f; + + const float amdf = (fa-fd)*frac; + const float cmb = fc-fb; + const float bma = fb-fa; + *(sig0++) = fb + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + float o = *(pos++); + register long oint = CASTINT(o); + const float frac = o-oint; + register const t_sample *ptr = bdt+oint*BCHNS; + register const t_sample *fa,*fb,*fc,*fd; + + if(oint > smin) + if(oint < maxo-2) { + // normal case + fb = ptr; + fa = fb-BCHNS; + fc = fb+BCHNS; + fd = fc+BCHNS; + } + else { + // not enough space at the end + + if(looped) { + // normalize position + oint = smin+(oint-smin)%plen; + goto looped2; + } + else { + // last sample is outside in any case + fd = bdt+maxo*BCHNS; + + if(oint-1 >= maxo) + // if first is outside, all are outside + fa = fb = fc = fd; + else { + fa = ptr-BCHNS; + if(oint >= maxo) + fb = fc = fd; + else { + fb = ptr; + fc = oint+1 < maxo?ptr+BCHNS:fd; + } + } + } + } + else { + // not enough space at the beginning + + if(looped) { + // normalize position + oint = smax-(smin-oint)%plen; +looped2: + // inside in any case + fb = bdt+oint*BCHNS; + + if(oint < maxo-1) { + fa = oint > smin?fb-BCHNS:bdt+maxo*BCHNS; + fc = fb+BCHNS; + fd = fc+BCHNS; + } + else { + fa = fb-BCHNS; + fc = oint < maxo?fb+BCHNS:bdt+(oint-plen+1)*BCHNS; + fd = bdt+(oint-plen+2)*BCHNS; + } + } + else { + // first sample is outside in any case + fa = bdt+smin*BCHNS; + + if(oint+2 < smin) + // if last is outside, all are outside + fb = fc = fd = fa; + else { + fd = ptr+BCHNS*2; + if(oint+1 < smin) + fb = fc = fa; + else { + fc = ptr+BCHNS; + fb = oint < smin?fa:ptr; + } + } + } + } + + const float f1 = 0.5f*(frac-1.0f); + const float f3 = frac*3.0f-1.0f; + + for(int ci = 0; ci < OCHNS; ++ci) { + const float amdf = (fa[ci]-fd[ci])*frac; + const float cmb = fc[ci]-fb[ci]; + const float bma = fb[ci]-fa[ci]; + sig[ci][si] = fb[ci] + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); + } + } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF inline V xinter::s_play0(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play0(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play0 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play0 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play1(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play1(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play1 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play1 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play2(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play2(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play2 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play2 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play4(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play4(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play4 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play4 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } #endif diff --git a/externals/grill/xsample/source/main.cpp b/externals/grill/xsample/source/main.cpp index 3cec1b66..030c2675 100644 --- a/externals/grill/xsample/source/main.cpp +++ b/externals/grill/xsample/source/main.cpp @@ -1,26 +1,25 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #include "main.h" // Initialization function for xsample library -static V xsample_main() +static void xsample_main() { flext::post("-------------------------------"); flext::post("xsample objects, version " XSAMPLE_VERSION); flext::post(""); flext::post(" xrecord~, xplay~, xgroove~ "); - flext::post(" (C)2001-2004 Thomas Grill "); + flext::post(" (C)2001-2005 Thomas Grill "); #ifdef FLEXT_DEBUG - flext::post(" DEBUG BUILD "); + flext::post(""); + flext::post("DEBUG BUILD - " __DATE__ " " __TIME__); #endif flext::post("-------------------------------"); @@ -37,10 +36,6 @@ FLEXT_LIB_SETUP(xsample,xsample_main) void xsample::setup(t_classid c) { - FLEXT_CADDBANG(c,0,m_start); - FLEXT_CADDMETHOD_(c,0,"start",m_start); - FLEXT_CADDMETHOD_(c,0,"stop",m_stop); - FLEXT_CADDMETHOD_(c,0,"set",m_set); FLEXT_CADDMETHOD_(c,0,"print",m_print); FLEXT_CADDMETHOD_(c,0,"refresh",m_refresh); @@ -53,163 +48,160 @@ void xsample::setup(t_classid c) } xsample::xsample(): - buf(NULL), + update(xsc_all), #if FLEXT_SYS == FLEXT_SYS_MAX unitmode(xsu_ms), // Max/MSP defaults to milliseconds #else unitmode(xsu_sample), // PD defaults to samples #endif sclmode(xss_unitsinbuf), - curmin(0),curmax(1<<31) + curmin(0),curmax(1<<(sizeof(curmax)*8-2)) {} -xsample::~xsample() +xsample::~xsample() {} + +bool xsample::Finalize() { -// m_enable(false); // switch off DSP + if(!flext_dsp::Finalize()) return false; - if(buf) delete buf; + // flags have been set in constructor + Refresh(); + return true; } - -BL xsample::bufchk() -{ - if(buf->Valid()) { - if(buf->Update()) { -// post("%s - buffer updated",thisName()); - m_refresh(); - } - return true; - } - else - return false; +int xsample::ChkBuffer(bool refresh) +{ + if(!buf.Ok()) return 0; + + if(buf.Update()) { +#ifdef FLEXT_DEBUG + post("%s - buffer update!",thisName()); +#endif + Update(xsc_buffer); + if(refresh) { + Refresh(); + return buf.Ok() && buf.Valid()?1:0; + } + else + return buf.Valid()?1:0; + } + else + return buf.Valid()?-1:0; } -I xsample::m_set(I argc,const t_atom *argv) +/* called after all buffer objects have been created in the patch */ +void xsample::m_loadbang() { - const t_symbol *sym = argc >= 1?GetASymbol(argv[0]):NULL; - int r = buf->Set(sym); - if(sym && r < 0) post("%s - can't find buffer %s",thisName(),GetString(sym)); - return r; + ChkBuffer(true); } -BL xsample::m_refresh() +void xsample::m_set(int argc,const t_atom *argv) { - BL ret; - if(buf->Set()) { s_dsp(); ret = true; } // channel count may have changed - else ret = false; - - m_units(); - m_sclmode(); - // realize positions... 2 times bufchk()!! - m_min((F)curmin*s2u); // also checks pos - m_max((F)curmax*s2u); // also checks pos - - return ret; + const t_symbol *sym = argc >= 1?GetASymbol(argv[0]):NULL; + int r = buf.Set(sym); + if(sym && r < 0) + post("%s - can't find buffer %s",thisName(),GetString(sym)); + Update(xsc_buffer,true); } -BL xsample::m_reset() +void xsample::m_min(float mn) { - BL ret; - if(buf->Set()) { s_dsp(); ret = true; } // channel count may have changed - else ret = false; - - // now... 4 times bufchk()!! \todo get rid of that - m_units(); - m_sclmode(); - m_min(0); - m_max(buf->Frames()*s2u); + int ret = ChkBuffer(true); - return ret; -} + if(ret && s2u) { + long cmn = CASTINT(mn/s2u+0.5f); // conversion to samples -V xsample::m_loadbang() -{ - m_reset(); -} + if(cmn < 0) + curmin = 0; + else if(cmn > curmax) + curmin = curmax; + else + curmin = cmn; -V xsample::m_units(xs_unit mode) -{ - if(mode != xsu__) unitmode = mode; - - switch(unitmode) { - case xsu_sample: // samples - s2u = 1; - break; - case xsu_buffer: // buffer size - s2u = bufchk()?1.f/buf->Frames():0; - break; - case xsu_ms: // ms - s2u = 1000.f/Samplerate(); - break; - case xsu_s: // s - s2u = 1.f/Samplerate(); - break; - default: - post("%s: Unknown unit mode",thisName()); + Update(xsc_range,true); } } -V xsample::m_sclmode(xs_sclmd mode) +void xsample::m_max(float mx) { - if(mode != xss__) sclmode = mode; - - switch(sclmode) { - case 0: // samples/units - sclmin = 0; sclmul = s2u; - break; - case 1: // samples/units from recmin to recmax - sclmin = curmin; sclmul = s2u; - break; - case 2: // unity between 0 and buffer size - sclmin = 0; sclmul = (bufchk() && buf->Frames())?1.f/buf->Frames():0; - break; - case 3: // unity between recmin and recmax - sclmin = curmin; sclmul = curmin != curmax?1.f/(curmax-curmin):0; - break; - default: - post("%s: Unknown scale mode",thisName()); - } -} + int ret = ChkBuffer(true); -V xsample::m_min(F mn) -{ -// if(!bufchk()) return; // if invalid do nothing (actually, it should be delayed) + if(ret && s2u) { + long cmx = CASTINT(mx/s2u+0.5f); // conversion to samples - if(s2u) { - mn /= s2u; // conversion to samples - if(mn < 0) mn = 0; - else if(mn > curmax) mn = (F)curmax; - curmin = (I)(mn+.5); + if(cmx > buf.Frames()) + curmax = buf.Frames(); + else if(cmx < curmin) + curmax = curmin; + else + curmax = cmx; - m_sclmode(); + Update(xsc_range,true); } } -V xsample::m_max(F mx) +void xsample::m_dsp(int /*n*/,t_sample *const * /*insigs*/,t_sample *const * /*outsigs*/) { -// if(!bufchk()) return; // if invalid do nothing (actually, it should be delayed) + // this is hopefully called at change of sample rate ?! - if(s2u) { - mx /= s2u; // conversion to samples - if(mx > buf->Frames()) mx = (F)buf->Frames(); - else if(mx < curmin) mx = (F)curmin; - curmax = (I)(mx+.5); +#ifdef FLEXT_DEBUG + post("%s - DSP reset!",thisName()); +#endif - m_sclmode(); - } + // for PD at least this is also called if a table has been deleted... + // then we must reset the buffer + + Update(xsc_srate|xsc_buffer,true); } -V xsample::m_all() +void xsample::DoReset() { - if(!bufchk()) return; // if invalid do nothing (actually, it should be delayed) - - curmin = 0; curmax = buf->Frames(); - m_sclmode(); + ResetRange(); } -V xsample::m_dsp(I /*n*/,S *const * /*insigs*/,S *const * /*outsigs*/) +void xsample::DoUpdate(unsigned int flags) { - // this is hopefully called at change of sample rate ?! - - if(!m_refresh()) s_dsp(); + if(flags&xsc_buffer) + buf.Set(); + + if(flags&xsc_range && buf.Ok()) { + if(curmin < 0) curmin = 0; + if(curmax > buf.Frames()) curmax = buf.Frames(); + } + + if(flags&xsc_units) { + switch(unitmode) { + case xsu_sample: // samples + s2u = 1; + break; + case xsu_buffer: // buffer size + s2u = buf.Ok() && buf.Frames()?1.f/buf.Frames():0; + break; + case xsu_ms: // ms + s2u = 1000.f/Samplerate(); + break; + case xsu_s: // s + s2u = 1.f/Samplerate(); + break; + default: + post("%s - Unknown unit mode",thisName()); + } + + switch(sclmode) { + case xss_unitsinbuf: // samples/units + sclmin = 0; sclmul = s2u; + break; + case xss_unitsinloop: // samples/units from recmin to recmax + sclmin = curmin; sclmul = s2u; + break; + case xss_buffer: // unity between 0 and buffer size + sclmin = 0; sclmul = buf.Ok() && buf.Frames()?1.f/buf.Frames():0; + break; + case xss_loop: // unity between recmin and recmax + sclmin = curmin; sclmul = curmin < curmax?1.f/(curmax-curmin):0; + break; + default: + post("%s - Unknown scale mode",thisName()); + } + } } diff --git a/externals/grill/xsample/source/main.h b/externals/grill/xsample/source/main.h index 3608a55c..97e4516d 100644 --- a/externals/grill/xsample/source/main.h +++ b/externals/grill/xsample/source/main.h @@ -1,11 +1,9 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #ifndef __XSAMPLE_H @@ -13,18 +11,19 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "prefix.h" -#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 406) -#error You need at least flext version 0.4.6 +#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) +#error You need at least flext version 0.5.0 #endif -#define XSAMPLE_VERSION "0.3.1pre3" +#define XSAMPLE_VERSION "0.3.1pre4" // most compilers are somehow broken - in other words - can't handle all C++ features #if defined(_MSC_VER) // MS VC 6.0 can't handle templates?! -> no optimization - #if _MSC_VER >= 1300 +// MS VC .NET 2002 just dies with template optimization switched on + #if _MSC_VER >= 1310 #define TMPLOPT #endif #elif defined(__BORLANDC__) @@ -51,17 +50,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif -// lazy me -#define F float -#define D double -#define I int -#define L long -#define C char -#define V void -#define BL bool -#define S t_sample - - #if defined(__MWERKS__) && !defined(__MACH__) #define STD std #else @@ -92,6 +80,32 @@ WARRANTIES, see the file, "license.txt," in this distribution. } #endif +#if FLEXT_CPU == FLEXT_CPU_INTEL && defined(__GNUC__) +template inline I CASTINT(F o) { return lrintf(o); } +#elif FLEXT_CPU == FLEXT_CPU_INTEL && defined(_MSC_VER) +template +inline I CASTINT(F x) { +// by Laurent de Soras (http://ldesoras.free.fr) +// assert (x > static_cast (INT_MIN / 2) + 1.0); +// assert (x < static_cast (INT_MAX / 2) + 1.0); + const float round_towards_m_i = -0.5f; + I i; + __asm + { + fld x + fadd st,st + fabs + fadd round_towards_m_i + fistp i + sar i, 1 + } + if(x < 0) i = -i; + return i; +} +#else +template inline I CASTINT(F o) { return static_cast(o); } +#endif + class xsample: public flext_dsp @@ -101,73 +115,133 @@ class xsample: public: xsample(); ~xsample(); + + enum xs_change { + xsc__ = 0, + xsc_units = 0x0001, + xsc_play = 0x0002, + xsc_pos = 0x0008, + xsc_range = 0x0010, + xsc_transport = 0x0020, + xsc_fade = 0x0040, + + xsc_intp = xsc_play, + xsc_srate = xsc_play|xsc_units, + xsc_chns = xsc_play, + xsc_loop = xsc_play, + xsc_startstop = xsc_play|xsc_transport, + xsc_buffer = xsc_units|xsc_pos|xsc_range|xsc_play, + xsc_reset = xsc_buffer, + xsc_all = 0xffff + }; - enum xs_unit { - xsu__ = -1, // don't change - xsu_sample = 0,xsu_buffer,xsu_ms,xsu_s - }; + enum xs_unit { + xsu_sample = 0,xsu_buffer,xsu_ms,xsu_s + }; enum xs_intp { - xsi__ = -1, // don't change xsi_none = 0,xsi_4p,xsi_lin }; enum xs_sclmd { - xss__ = -1, // don't change xss_unitsinbuf = 0,xss_unitsinloop,xss_buffer,xss_loop }; protected: - buffer *buf; - - virtual V m_start() = 0; - virtual V m_stop() = 0; - virtual BL m_reset(); - - virtual I m_set(I argc,const t_atom *argv); - virtual V m_print() = 0; - virtual BL m_refresh(); - virtual V m_loadbang(); - - virtual V m_units(xs_unit u = xsu__); - virtual V m_sclmode(xs_sclmd u = xss__); - - virtual V m_all(); - virtual V m_min(F mn); - virtual V m_max(F mx); - - virtual V m_dsp(I n,S *const *insigs,S *const *outsigs); - virtual V s_dsp() = 0; - - xs_unit unitmode; //iunitmode,ounitmode; - xs_sclmd sclmode; //isclmode,osclmode; - - L curmin,curmax; //,curlen; // in samples - I sclmin; // in samples - F sclmul; - F s2u; // sample to unit conversion factor - - inline F scale(F smp) const { return (smp-sclmin)*sclmul; } + virtual bool Finalize(); + + buffer buf; + + void m_reset() + { + ChkBuffer(true); + DoReset(); + Refresh(); + } + + void m_set(int argc,const t_atom *argv); + + void m_refresh() + { + Update(xsc_buffer,true); + } + + void m_units(xs_unit mode) + { + unitmode = mode; + Update(xsc_units,true); + } + + void m_sclmode(xs_sclmd mode) + { + sclmode = mode; + Update(xsc_units,true); + } + + void m_all() + { + ChkBuffer(true); + ResetRange(); + Refresh(); + } + + void m_min(float mn); + void m_max(float mx); + + xs_unit unitmode; + xs_sclmd sclmode; + + long curmin,curmax; //,curlen; // in samples + long sclmin; // in samples + float sclmul; + float s2u; // sample to unit conversion factor + + inline float scale(float smp) const { return (smp-sclmin)*sclmul; } - static V arrscale(I n,const S *in,S *out,S add,S mul) { flext::ScaleSamples(out,in,mul,add,n); } - inline V arrscale(I n,const S *in,S *out) const { arrscale(n,in,out,-sclmin*sclmul,sclmul); } + static void arrscale(int n,const t_sample *in,t_sample *out,t_sample add,t_sample mul) { flext::ScaleSamples(out,in,mul,add,n); } + inline void arrscale(int n,const t_sample *in,t_sample *out) const { arrscale(n,in,out,-sclmin*sclmul,sclmul); } - static V arrmul(I n,const S *in,S *out,S mul) { flext::MulSamples(out,in,mul,n); } - inline V arrmul(I n,const S *in,S *out) const { arrmul(n,in,out,(S)(1./s2u)); } - - BL bufchk(); - - V mg_buffer(AtomList &l) { if(buf && buf->Symbol()) { l(1); SetSymbol(l[0],buf->Symbol()); } else l(); } - inline V ms_buffer(const AtomList &l) { m_set(l.Count(),l.Atoms()); } - - inline V mg_min(F &v) const { v = curmin*s2u; } - inline V mg_max(F &v) const { v = curmax*s2u; } + static void arrmul(int n,const t_sample *in,t_sample *out,t_sample mul) { flext::MulSamples(out,in,mul,n); } + inline void arrmul(int n,const t_sample *in,t_sample *out) const { arrmul(n,in,out,(t_sample)(1.f/s2u)); } + + void mg_buffer(AtomList &l) { if(buf.Symbol()) { l(1); SetSymbol(l[0],buf.Symbol()); } } + inline void ms_buffer(const AtomList &l) { m_set(l.Count(),l.Atoms()); } + + inline void mg_min(float &v) const { v = curmin*s2u; } + inline void mg_max(float &v) const { v = curmax*s2u; } + + void Refresh() { if(update && !Initing()) { DoUpdate(update); update = xsc__; } } + void Update(unsigned int f,bool refr = false) { update |= f; if(refr) Refresh(); } + + //! return 0...invalid, 1...changed, -1...unchanged + int ChkBuffer(bool refr = false); + + typedef flext::buffer::lock_t lock_t; + + //! Lock buffer (buffer must be checked ok) + lock_t Lock() { return buf.Lock(); } + //! Unlock buffer (buffer must be checked ok) + void Unlock(lock_t l) { buf.Unlock(l); } + + void ResetRange() + { + curmin = 0; + curmax = buf.Frames(); + Update(xsc_range); + } + + virtual void DoReset(); + virtual void DoUpdate(unsigned int flags); + + virtual void m_loadbang(); + virtual void m_print() = 0; + virtual void m_dsp(int n,t_sample *const *insigs,t_sample *const *outsigs); private: - static V setup(t_classid c); - FLEXT_CALLBACK(m_start) - FLEXT_CALLBACK(m_stop) + unsigned int update; + + static void setup(t_classid c); FLEXT_CALLBACK_V(m_set) FLEXT_CALLBACK(m_print) @@ -206,25 +280,25 @@ protected: #endif #define DEFSIGFUN(NAME) \ - static V st_##NAME(thisType *obj,I n,S *const *in,S *const *out) { obj->NAME (n,in,out); } \ - V NAME(I n,S *const *in,S *const *out) + static void st_##NAME(thisType *obj,int n,t_sample *const *in,t_sample *const *out) { obj->NAME (n,in,out); } \ + void NAME(int n,t_sample *const *in,t_sample *const *out) #define TMPLSIGFUN(NAME) \ - TMPLDEF static V st_##NAME(thisType *obj,I n,S *const *in,S *const *out) { obj->NAME TMPLCALL (n,in,out); } \ - TMPLDEF V NAME(I n,S *const *in,S *const *out) + TMPLDEF static void st_##NAME(thisType *obj,int n,t_sample *const *in,t_sample *const *out) { obj->NAME TMPLCALL (n,in,out); } \ + TMPLDEF void NAME(int n,t_sample *const *in,t_sample *const *out) - #define TMPLSTFUN(NAME) TMPLDEF static V NAME(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) + #define TMPLSTFUN(NAME) TMPLDEF static void NAME(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs) #define SETSIGFUN(VAR,FUN) v_##VAR = FUN #define SETSTFUN(VAR,FUN) VAR = FUN #define DEFSIGCALL(NAME) \ - inline V NAME(I n,S *const *in,S *const *out) { (*v_##NAME)(this,n,in,out); } \ - V (*v_##NAME)(thisType *obj,I n,S *const *in,S *const *out) + inline void NAME(int n,t_sample *const *in,t_sample *const *out) { (*v_##NAME)(this,n,in,out); } \ + void (*v_##NAME)(thisType *obj,int n,t_sample *const *in,t_sample *const *out) #define DEFSTCALL(NAME) \ - V (*NAME)(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) + void (*NAME)(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs) #else #ifdef TMPLOPT @@ -241,20 +315,20 @@ protected: #define TMPLSTF(FUN,BCHNS,IOCHNS) TMPLFUN(FUN,BCHNS,IOCHNS) - #define DEFSIGFUN(NAME) V NAME(I n,S *const *in,S *const *out) - #define TMPLSIGFUN(NAME) TMPLDEF V NAME(I n,S *const *in,S *const *out) - #define TMPLSTFUN(NAME) TMPLDEF static V NAME(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) + #define DEFSIGFUN(NAME) void NAME(int n,t_sample *const *in,t_sample *const *out) + #define TMPLSIGFUN(NAME) TMPLDEF void NAME(int n,t_sample *const *in,t_sample *const *out) + #define TMPLSTFUN(NAME) TMPLDEF static void NAME(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) #define SETSIGFUN(VAR,FUN) v_##VAR = FUN #define DEFSIGCALL(NAME) \ - inline V NAME(I n,S *const *in,S *const *out) { (this->*v_##NAME)(n,in,out); } \ - V (thisType::*v_##NAME)(I n,S *const *invecs,S *const *outvecs) + inline void NAME(int n,t_sample *const *in,t_sample *const *out) { (this->*v_##NAME)(n,in,out); } \ + void (thisType::*v_##NAME)(int n,t_sample *const *invecs,t_sample *const *outvecs) #define SETSTFUN(VAR,FUN) VAR = FUN #define DEFSTCALL(NAME) \ - V (*NAME)(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) + void (*NAME)(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) #endif @@ -269,18 +343,18 @@ protected: #ifdef TMPLOPT // optimization by using constants for channel numbers #define SIGCHNS(BCHNS,bchns,IOCHNS,iochns) \ - const I BCHNS = _BCHNS_ < 0?(bchns):_BCHNS_; \ - const I IOCHNS = _IOCHNS_ < 0?MIN(iochns,BCHNS):MIN(_IOCHNS_,BCHNS) + const int BCHNS = _BCHNS_ < 0?(bchns):_BCHNS_; \ + const int IOCHNS = _IOCHNS_ < 0?MIN(iochns,BCHNS):MIN(_IOCHNS_,BCHNS) #else // no template optimization #if FLEXT_SYS == FLEXT_SYS_PD // only mono buffers #define SIGCHNS(BCHNS,bchns,IOCHNS,iochns) \ - const I BCHNS = 1; \ - const I IOCHNS = MIN(iochns,BCHNS) + const int BCHNS = 1; \ + const int IOCHNS = MIN(iochns,BCHNS) #else // MAXMSP #define SIGCHNS(BCHNS,bchns,IOCHNS,iochns) \ - const I BCHNS = bchns; \ - const I IOCHNS = MIN(iochns,BCHNS) + const int BCHNS = bchns; \ + const int IOCHNS = MIN(iochns,BCHNS) #endif #endif @@ -291,19 +365,42 @@ class xinter: FLEXT_HEADER_S(xinter,xsample,setup) public: - xinter(): outchns(1),doplay(false),interp(xsi_4p) {} - -protected: - virtual I m_set(I argc,const t_atom *argv); - virtual V m_start(); - virtual V m_stop(); + enum xs_loop { + xsl_once = 0,xsl_loop,xsl_bidir + }; + + xinter() + : outchns(1),doplay(false) + , interp(xsi_4p),loopmode(xsl_loop) + {} + + void m_start() + { + ChkBuffer(); + doplay = true; + Update(xsc_startstop,true); + } + + void m_stop() + { + ChkBuffer(); + doplay = false; + Update(xsc_startstop,true); + } + + void m_interp(xs_intp mode) + { + interp = mode; + Update(xsc_intp,true); + } - inline V m_interp(xs_intp mode = xsi__) { interp = mode; s_dsp(); } +protected: - I outchns; - BL doplay; + int outchns; + bool doplay; xs_intp interp; + xs_loop loopmode; TMPLSIGFUN(s_play0); TMPLSIGFUN(s_play1); @@ -318,13 +415,18 @@ protected: DEFSIGCALL(playfun); DEFSIGCALL(zerofun); - virtual V s_dsp(); + virtual void DoUpdate(unsigned int flags); -private: - static V setup(t_classid c); + FLEXT_CALLBACK(m_start) + FLEXT_CALLBACK(m_stop) FLEXT_CALLSET_E(m_interp,xs_intp) FLEXT_ATTRGET_E(interp,xs_intp) + + FLEXT_ATTRGET_E(loopmode,xs_loop) + +private: + static void setup(t_classid c); }; #ifdef TMPLOPT @@ -332,5 +434,3 @@ private: #endif #endif - - diff --git a/externals/grill/xsample/source/play.cpp b/externals/grill/xsample/source/play.cpp index d5c9fb94..268b853a 100644 --- a/externals/grill/xsample/source/play.cpp +++ b/externals/grill/xsample/source/play.cpp @@ -1,11 +1,9 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #include "main.h" @@ -22,29 +20,40 @@ class xplay: FLEXT_HEADER_S(xplay,xinter,setup) public: - xplay(I argc,const t_atom *argv); + xplay(int argc,const t_atom *argv); + + void m_loop(xs_loop lp) + { + loopmode = lp; + Update(xsc_loop,true); + } - virtual BL Init(); - - virtual V m_help(); - virtual V m_print(); +protected: + virtual void m_help(); + virtual void m_print(); + virtual void m_signal(int n,t_sample *const *in,t_sample *const *out); private: - static V setup(t_classid c); + static void setup(t_classid c); - virtual V m_signal(I n,S *const *in,S *const *out); + FLEXT_CALLSET_E(m_loop,xs_loop) }; FLEXT_LIB_DSP_V("xplay~",xplay) -V xplay::setup(t_classid c) +void xplay::setup(t_classid c) { DefineHelp(c,"xplay~"); + + FLEXT_CADDATTR_VAR_E(c,"loop",loopmode,m_loop); } -xplay::xplay(I argc,const t_atom *argv) +xplay::xplay(int argc,const t_atom *argv) { - I argi = 0; + // set the loopmode to non-wrapping (for sample interpolation) + loopmode = xsl_once; + + int argi = 0; #if FLEXT_SYS == FLEXT_SYS_MAX if(argc > argi && CanbeInt(argv[argi])) { outchns = GetAInt(argv[argi]); @@ -53,7 +62,7 @@ xplay::xplay(I argc,const t_atom *argv) #endif if(argc > argi && IsSymbol(argv[argi])) { - buf = new buffer(GetSymbol(argv[argi]),true); + buf.Set(GetSymbol(argv[argi]),true); argi++; #if FLEXT_SYS == FLEXT_SYS_MAX @@ -65,37 +74,31 @@ xplay::xplay(I argc,const t_atom *argv) } #endif } - else - buf = new buffer(NULL,true); - AddInSignal("Messages and Signal of playing position"); // pos signal - for(I ci = 0; ci < outchns; ++ci) { - C tmp[30]; + AddInSignal("Messages and Signal of playing position"); // pos signal + for(int ci = 0; ci < outchns; ++ci) { + char tmp[30]; STD::sprintf(tmp,"Audio signal channel %i",ci+1); AddOutSignal(tmp); } - - m_reset(); } -BL xplay::Init() -{ - if(xinter::Init()) { - m_reset(); - return true; - } - else - return false; -} - -V xplay::m_signal(I n,S *const *in,S *const *out) +void xplay::m_signal(int n,t_sample *const *in,t_sample *const *out) { + int ret = ChkBuffer(true); + // check whether buffer is invalid or changed - if(bufchk()) { + if(ret) { + const lock_t l = Lock(); + // convert position units to frames arrmul(n,in[0],out[0]); // call resample routine playfun(n,out,out); + + Unlock(l); + + Refresh(); } else zerofun(n,out,out); @@ -103,13 +106,13 @@ V xplay::m_signal(I n,S *const *in,S *const *out) -V xplay::m_help() +void xplay::m_help() { post("%s - part of xsample objects, version " XSAMPLE_VERSION,thisName()); #ifdef FLEXT_DEBUG post("compiled on " __DATE__ " " __TIME__); #endif - post("(C) Thomas Grill, 2001-2004"); + post("(C) Thomas Grill, 2001-2005"); #if FLEXT_SYS == FLEXT_SYS_MAX post("Arguments: %s [channels=1] [buffer]",thisName()); #else @@ -120,7 +123,7 @@ V xplay::m_help() post("Methods:"); post("\thelp: shows this help"); post("\tset name: set buffer"); - post("\tenable 0/1: turn dsp calculation off/on"); + post("\tenable 0/1: turn dsp calculation off/on"); post("\tprint: print current settings"); post("\tbang/start: begin playing"); post("\tstop: stop playing"); @@ -128,17 +131,16 @@ V xplay::m_help() post("\trefresh: checks buffer and refreshes outlets"); post("\t@units 0/1/2/3: set units to samples/buffer size/ms/s"); post("\t@interp 0/1/2: set interpolation to off/4-point/linear"); + post("\t@loop 0/1/2: sets looping (interpolation) to off/forward/bidirectional"); post(""); } -V xplay::m_print() +void xplay::m_print() { - const C *interp_txt[] = {"off","4-point","linear"}; + const char *interp_txt[] = {"off","4-point","linear"}; // print all current settings post("%s - current settings:",thisName()); - post("bufname = '%s', length = %.3f, channels = %i",buf->Name(),(F)(buf->Frames()*s2u),buf->Channels()); - post("out channels = %i, samples/unit = %.3f, interpolation = %s",outchns,(F)(1./s2u),interp_txt[interp >= xsi_none && interp <= xsi_lin?interp:xsi_none]); + post("bufname = '%s', length = %.3f, channels = %i",buf.Name(),(float)(buf.Frames()*s2u),buf.Channels()); + post("out channels = %i, samples/unit = %.3f, interpolation = %s",outchns,(float)(1./s2u),interp_txt[interp >= xsi_none && interp <= xsi_lin?interp:xsi_none]); post(""); } - - diff --git a/externals/grill/xsample/source/prefix.h b/externals/grill/xsample/source/prefix.h index ef9cb7ea..415f07c3 100644 --- a/externals/grill/xsample/source/prefix.h +++ b/externals/grill/xsample/source/prefix.h @@ -12,3 +12,4 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include +#include diff --git a/externals/grill/xsample/source/record.cpp b/externals/grill/xsample/source/record.cpp index a30f87cb..1df51c81 100644 --- a/externals/grill/xsample/source/record.cpp +++ b/externals/grill/xsample/source/record.cpp @@ -1,11 +1,9 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #include "main.h" @@ -22,53 +20,54 @@ class xrecord: FLEXT_HEADER_S(xrecord,xsample,setup) public: - xrecord(I argc,const t_atom *argv); - - virtual BL Init(); - - virtual V m_help(); - virtual V m_print(); + xrecord(int argc,const t_atom *argv); - virtual I m_set(I argc,const t_atom *argv); - - virtual V m_pos(F pos); - virtual V m_all(); - virtual V m_start(); - virtual V m_stop(); + void m_pos(float pos) + { + curpos = pos?CASTINT(pos/s2u+.5):0; + Update(xsc_pos); + Refresh(); + } - virtual BL m_reset(); + inline void mg_pos(float &v) const { v = curpos*s2u; } - virtual V m_units(xs_unit md = xsu__); - virtual V m_min(F mn); - virtual V m_max(F mx); + void m_start(); + void m_stop(); - inline V m_append(BL app) { if(!(appmode = app)) m_pos(0); } + inline void m_append(bool app) + { + appmode = app; + Update(xsc_play); + if(!appmode) m_pos(0); + } - virtual V m_draw(I argc,const t_atom *argv); + void m_draw(int argc,const t_atom *argv); protected: - I inchns; - BL sigmode,appmode; - F drintv; - - BL dorec,doloop; - I mixmode; - L curpos; // in samples + int inchns; + bool sigmode,appmode; + float drintv; - inline V outputmin() { ToOutFloat(1,curmin*s2u); } - inline V outputmax() { ToOutFloat(2,curmax*s2u); } + bool dorec,doloop; + int mixmode; + long curpos; // in samples - inline V mg_pos(F &v) const { v = curpos*s2u; } + virtual void DoReset(); + virtual void DoUpdate(unsigned int flags); + + virtual void m_help(); + virtual void m_print(); + virtual void m_signal(int n,t_sample *const *in,t_sample *const *out); private: - static V setup(t_classid c); - - virtual V s_dsp(); + static void setup(t_classid c); TMPLSIGFUN(s_rec); DEFSIGCALL(recfun); - virtual V m_signal(I n,S *const *in,S *const *out); + + FLEXT_CALLBACK(m_start) + FLEXT_CALLBACK(m_stop) FLEXT_CALLVAR_F(mg_pos,m_pos) FLEXT_CALLBACK(m_all) @@ -90,10 +89,14 @@ private: FLEXT_LIB_DSP_V("xrecord~",xrecord) -V xrecord::setup(t_classid c) +void xrecord::setup(t_classid c) { DefineHelp(c,"xrecord~"); + FLEXT_CADDBANG(c,0,m_start); + FLEXT_CADDMETHOD_(c,0,"start",m_start); + FLEXT_CADDMETHOD_(c,0,"stop",m_stop); + FLEXT_CADDATTR_VAR(c,"pos",mg_pos,m_pos); FLEXT_CADDATTR_VAR(c,"min",mg_min,m_min); FLEXT_CADDATTR_VAR(c,"max",mg_max,m_max); @@ -107,14 +110,14 @@ V xrecord::setup(t_classid c) FLEXT_CADDATTR_VAR(c,"append",appmode,m_append); } -xrecord::xrecord(I argc,const t_atom *argv): +xrecord::xrecord(int argc,const t_atom *argv): inchns(1), sigmode(false),appmode(true), drintv(0), dorec(false),doloop(false), mixmode(0) { - I argi = 0; + int argi = 0; #if FLEXT_SYS == FLEXT_SYS_MAX if(argc > argi && CanbeInt(argv[argi])) { inchns = GetAInt(argv[argi]); @@ -123,7 +126,7 @@ xrecord::xrecord(I argc,const t_atom *argv): #endif if(argc > argi && IsSymbol(argv[argi])) { - buf = new buffer(GetSymbol(argv[argi]),true); + buf.Set(GetSymbol(argv[argi]),true); argi++; #if FLEXT_SYS == FLEXT_SYS_MAX @@ -135,11 +138,9 @@ xrecord::xrecord(I argc,const t_atom *argv): } #endif } - else - buf = new buffer(NULL,true); - for(I ci = 0; ci < inchns; ++ci) { - C tmp[40]; + for(int ci = 0; ci < inchns; ++ci) { + char tmp[40]; STD::sprintf(tmp,ci == 0?"Messages/audio channel %i":"Audio channel %i",ci+1); AddInSignal(tmp); // audio signals } @@ -155,127 +156,69 @@ xrecord::xrecord(I argc,const t_atom *argv): FLEXT_ADDMETHOD(inchns+2,m_max); } +void xrecord::m_start() +{ + ChkBuffer(); -BL xrecord::Init() -{ - if(xsample::Init()) { - m_reset(); - return true; - } - else - return false; -} - -V xrecord::m_units(xs_unit mode) -{ - xsample::m_units(mode); - - m_sclmode(); - outputmin(); - outputmax(); -} - -V xrecord::m_min(F mn) -{ - xsample::m_min(mn); - m_pos(curpos*s2u); - outputmin(); -} - -V xrecord::m_max(F mx) -{ - xsample::m_max(mx); - m_pos(curpos*s2u); - outputmax(); -} - -V xrecord::m_all() -{ - xsample::m_all(); - outputmin(); - outputmax(); -} - -V xrecord::m_pos(F pos) -{ - curpos = pos?(L)(pos/s2u+.5):0; - - if(curpos < curmin) curpos = curmin; - else if(curpos > curmax) curpos = curmax; -} - - -I xrecord::m_set(I argc,const t_atom *argv) -{ - I r = xsample::m_set(argc,argv); - if(r) - // buffer parameters have changed, reset pos/min/max - m_reset(); - return r; -} + if(!sigmode && !appmode) { curpos = 0; Update(xsc_pos); } -V xrecord::m_start() -{ - if(!sigmode && !appmode) m_pos(0); - m_refresh(); - dorec = true; - buf->SetRefrIntv(drintv); - s_dsp(); + dorec = true; + Update(xsc_startstop); + Refresh(); } -V xrecord::m_stop() +void xrecord::m_stop() { - dorec = false; - buf->Dirty(true); - buf->SetRefrIntv(0); - s_dsp(); + ChkBuffer(); + dorec = false; + Update(xsc_startstop); + Refresh(); } -BL xrecord::m_reset() +void xrecord::DoReset() { + xsample::DoReset(); curpos = 0; - return xsample::m_reset(); } -V xrecord::m_draw(I argc,const t_atom *argv) +void xrecord::m_draw(int argc,const t_atom *argv) { if(argc >= 1) { - drintv = GetInt(argv[0]); - if(dorec) buf->SetRefrIntv(drintv); + drintv = GetAInt(argv[0]); + if(dorec) buf.SetRefrIntv(drintv); } else - buf->Dirty(true); + buf.Dirty(true); } - -TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) +TMPLDEF void xrecord::s_rec(int n,t_sample *const *invecs,t_sample *const *outvecs) { - SIGCHNS(BCHNS,buf->Channels(),ICHNS,inchns); + SIGCHNS(BCHNS,buf.Channels(),ICHNS,inchns); - const S *const *sig = invecs; - register I si = 0; - const S *on = invecs[inchns]; - S *pos = outvecs[0]; + const t_sample *const *sig = invecs; + register int si = 0; + const t_sample *on = invecs[inchns]; + t_sample *pos = outvecs[0]; - BL lpbang = false; - register const F pf = sclmul; - register L o = curpos; + bool lpbang = false; + register const float pf = sclmul; + register long o = curpos; if(o < curmin) o = curmin; -// if(buf && dorec && curlen > 0) { - if(buf && dorec && curmax > curmin) { + if(dorec && curmax > curmin) { while(n) { - L ncur = curmax-o; // at max to buffer or recording end + long ncur = curmax-o; // at max to buffer or recording end if(ncur <= 0) { // end of buffer if(doloop) { - o = curmin; -// ncur = curlen; - ncur = curmax-o; + ncur = curmax-(o = curmin); } - else - m_stop(); // loop expired; + else { + // loop expired; + dorec = false; + Update(xsc_startstop); + } lpbang = true; } @@ -284,9 +227,9 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) if(ncur > n) ncur = n; - register I i; - register S *bf = buf->Data()+o*BCHNS; - register F p = scale(o); + register int i; + register t_sample *bf = buf.Data()+o*BCHNS; + register float p = scale(o); if(sigmode) { if(appmode) { @@ -295,7 +238,7 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) switch(mixmode) { case 0: for(i = 0; i < ncur; ++i,++si) { - if(*(on++) >= 0) { + if(!(*(on++) < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] = sig[ci][si]; bf += BCHNS; @@ -307,8 +250,8 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) break; case 1: for(i = 0; i < ncur; ++i,++si) { - register const S g = *(on++); - if(g >= 0) { + register const t_sample g = *(on++); + if(!(g < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] = bf[ci]*(1.-g)+sig[ci][si]*g; bf += BCHNS; @@ -320,7 +263,7 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) break; case 2: for(i = 0; i < ncur; ++i,++si) { - if(*(on++) >= 0) { + if(!(*(on++) < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] += sig[ci][si]; bf += BCHNS; @@ -337,7 +280,7 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) switch(mixmode) { case 0: { for(i = 0; i < ncur; ++i,++si) { - if(*(on++) >= 0) + if(!(*(on++) < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] = sig[ci][si]; @@ -346,15 +289,15 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } else { *(pos++) = p = scale(o = 0); - bf = buf->Data(); + bf = buf.Data(); } } break; } case 1: { for(i = 0; i < ncur; ++i,++si) { - register const S g = *(on++); - if(g >= 0) { + register const t_sample g = *(on++); + if(!(g < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] = bf[ci]*(1.-g)+sig[ci][si]*g; bf += BCHNS; @@ -362,14 +305,14 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } else { *(pos++) = p = scale(o = 0); - bf = buf->Data(); + bf = buf.Data(); } } break; } case 2: { for(i = 0; i < ncur; ++i,++si) { - if(*(on++) >= 0) + if(!(*(on++) < 0)) { for(int ci = 0; ci < ICHNS; ++ci) bf[ci] += sig[ci][si]; @@ -378,7 +321,7 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } else { *(pos++) = p = scale(o = 0); - bf = buf->Data(); + bf = buf.Data(); } } break; @@ -393,8 +336,8 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) switch(mixmode) { case 0: { for(int ci = 0; ci < ICHNS; ++ci) { - register S *b = bf+ci; - register const F *s = sig[ci]+si; + register t_sample *b = bf+ci; + register const float *s = sig[ci]+si; for(i = 0; i < ncur; ++i,b += BCHNS,++s) *b = *s; } @@ -403,7 +346,7 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } case 1: { for(i = 0; i < ncur; ++i,++si) { - register const S w = *(on++); + register const t_sample w = *(on++); for(int ci = 0; ci < ICHNS; ++ci) bf[ci] = bf[ci]*(1.-w)+sig[ci][si]*w; bf += BCHNS; @@ -412,9 +355,10 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } case 2: { for(int ci = 0; ci < ICHNS; ++ci) { - register S *b = bf+ci; - register const F *s = sig[ci]+si; - for(i = 0; i < ncur; ++i,b += BCHNS,++s) *b += *s; + register t_sample *b = bf+ci; + register const float *s = sig[ci]+si; + for(i = 0; i < ncur; ++i,b += BCHNS,++s) + *b += *s; } si += ncur; break; @@ -430,52 +374,81 @@ TMPLDEF V xrecord::s_rec(I n,S *const *invecs,S *const *outvecs) } curpos = o; - buf->Dirty(); + buf.Dirty(); } if(n) { - register F p = scale(o); + register float p = scale(o); while(n--) *(pos++) = p; } if(lpbang) ToOutBang(3); } -V xrecord::m_signal(I n,S *const *in,S *const *out) +void xrecord::m_signal(int n,t_sample *const *in,t_sample *const *out) { - if(bufchk()) + int ret = ChkBuffer(true); + + if(ret) { // call the appropriate dsp function - recfun(n,in,out); + + const lock_t l = Lock(); + recfun(n,in,out); + Unlock(l); + + Refresh(); + } else // set position signal to zero ZeroSamples(out[0],n); } -V xrecord::s_dsp() +void xrecord::DoUpdate(unsigned int flags) { - switch(buf->Channels()*1000+inchns) { - case 1001: SETSIGFUN(recfun,TMPLFUN(s_rec,1,1)); break; - case 1002: SETSIGFUN(recfun,TMPLFUN(s_rec,1,2)); break; - case 2001: SETSIGFUN(recfun,TMPLFUN(s_rec,2,1)); break; - case 2002: SETSIGFUN(recfun,TMPLFUN(s_rec,2,2)); break; - case 4001: - case 4002: - case 4003: SETSIGFUN(recfun,TMPLFUN(s_rec,4,-1)); break; - case 4004: SETSIGFUN(recfun,TMPLFUN(s_rec,4,4)); break; - default: SETSIGFUN(recfun,TMPLFUN(s_rec,-1,-1)); break; - } + xsample::DoUpdate(flags); + + if(flags&(xsc_pos|xsc_range)) { + if(curpos < curmin) curpos = curmin; + else if(curpos > curmax) curpos = curmax; + } + + if(flags&xsc_range) { + ToOutFloat(1,curmin*s2u); + ToOutFloat(2,curmax*s2u); + } + + if(flags&xsc_transport && buf.Ok()) { + if(dorec) + buf.SetRefrIntv(drintv); + else { + buf.Dirty(true); + buf.SetRefrIntv(0); + } + } + + if(flags&xsc_play) { + switch(buf.Channels()*1000+inchns) { + case 1001: SETSIGFUN(recfun,TMPLFUN(s_rec,1,1)); break; + case 1002: SETSIGFUN(recfun,TMPLFUN(s_rec,1,2)); break; + case 2001: SETSIGFUN(recfun,TMPLFUN(s_rec,2,1)); break; + case 2002: SETSIGFUN(recfun,TMPLFUN(s_rec,2,2)); break; + case 4001: + case 4002: + case 4003: SETSIGFUN(recfun,TMPLFUN(s_rec,4,-1)); break; + case 4004: SETSIGFUN(recfun,TMPLFUN(s_rec,4,4)); break; + default: SETSIGFUN(recfun,TMPLFUN(s_rec,-1,-1)); break; + } + } } - - -V xrecord::m_help() +void xrecord::m_help() { post("%s - part of xsample objects, version " XSAMPLE_VERSION,thisName()); #ifdef FLEXT_DEBUG post("compiled on " __DATE__ " " __TIME__); #endif - post("(C) Thomas Grill, 2001-2004"); + post("(C) Thomas Grill, 2001-2005"); #if FLEXT_SYS == FLEXT_SYS_MAX post("Arguments: %s [channels=1] [buffer]",thisName()); #else @@ -506,15 +479,14 @@ V xrecord::m_help() post(""); } -V xrecord::m_print() +void xrecord::m_print() { - static const C sclmode_txt[][20] = {"units","units in loop","buffer","loop"}; + static const char sclmode_txt[][20] = {"units","units in loop","buffer","loop"}; // print all current settings post("%s - current settings:",thisName()); - post("bufname = '%s', length = %.3f, channels = %i",buf->Name(),(F)(buf->Frames()*s2u),buf->Channels()); - post("in channels = %i, frames/unit = %.3f, scale mode = %s",inchns,(F)(1./s2u),sclmode_txt[sclmode]); + post("bufname = '%s', length = %.3f, channels = %i",buf.Name(),(float)(buf.Frames()*s2u),buf.Channels()); + post("in channels = %i, frames/unit = %.3f, scale mode = %s",inchns,(float)(1./s2u),sclmode_txt[sclmode]); post("sigmode = %s, append = %s, loop = %s, mixmode = %i",sigmode?"yes":"no",appmode?"yes":"no",doloop?"yes":"no",mixmode); post(""); } - diff --git a/externals/grill/xsample/xsample.cw b/externals/grill/xsample/xsample.cw deleted file mode 100755 index 2deb0271..00000000 Binary files a/externals/grill/xsample/xsample.cw and /dev/null differ diff --git a/externals/grill/xsample/xsample.mcp b/externals/grill/xsample/xsample.mcp new file mode 100755 index 00000000..f22426ba Binary files /dev/null and b/externals/grill/xsample/xsample.mcp differ diff --git a/externals/grill/xsample/xsample.vcproj b/externals/grill/xsample/xsample.vcproj index 9eaacb77..c3d5de2c 100644 --- a/externals/grill/xsample/xsample.vcproj +++ b/externals/grill/xsample/xsample.vcproj @@ -20,17 +20,22 @@ @@ -40,7 +45,7 @@ OutputFile="pd-msvc\xsample.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="c:\programme\audio\pd\bin,..\flext\pd-msvc\" + AdditionalLibraryDirectories="c:\programme\audio\pd\bin" ImportLibrary=".\pd-msvc\r/xsample.lib" TargetMachine="1"/> @@ -154,6 +160,7 @@ RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" UsePrecompiledHeader="2" + PrecompiledHeaderThrough="prefix.h" WarningLevel="3" SuppressStartupBanner="TRUE" CompileAs="0"/> @@ -275,9 +282,10 @@ AdditionalIncludeDirectories=""C:\data\prog\audio\maxmspsdk_win\4.5 headers\c74support\max-includes";"C:\data\prog\audio\maxmspsdk_win\4.5 headers\c74support\msp-includes";..\flext\source" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FLEXT_SYS=1" StringPooling="TRUE" - RuntimeLibrary="1" + RuntimeLibrary="0" StructMemberAlignment="2" UsePrecompiledHeader="2" + PrecompiledHeaderThrough="prefix.h" WarningLevel="3" SuppressStartupBanner="TRUE" DebugInformationFormat="3" @@ -332,17 +340,21 @@ CharacterSet="2"> @@ -393,9 +405,6 @@ - - diff --git a/externals/grill/xsample/xsample.xcode/project.pbxproj b/externals/grill/xsample/xsample.xcode/project.pbxproj index c9df035c..5027e5a0 100644 --- a/externals/grill/xsample/xsample.xcode/project.pbxproj +++ b/externals/grill/xsample/xsample.xcode/project.pbxproj @@ -56,8 +56,9 @@ }; 0867D69AFE84028FC02AAC07 = { children = ( - E9974E060770761500206F68, - E9974E04077075E800206F68, + E98C3076078D948800EC0264, + E94AC9630789EEA300AE1770, + E94AC9610789EE8700AE1770, E9974DFA0770750400206F68, E9974DFB0770750400206F68, ); @@ -105,6 +106,7 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/prefix.h; + GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) _DEBUG FLEXT_USESIMD"; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = YES; }; @@ -118,6 +120,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/prefix.h; + GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NDEBUG FLEXT_USESIMD"; ZERO_LINK = NO; }; isa = PBXBuildStyle; @@ -158,7 +161,8 @@ D2AAC09B05546B4700DB518D = { buildActionMask = 2147483647; files = ( - E9974E05077075E800206F68, + E94AC9640789EEA300AE1770, + E98C3077078D948800EC0264, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -210,6 +214,54 @@ //E92 //E93 //E94 + E94AC9610789EE8700AE1770 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = "libflext-max_sd.a"; + path = "/usr/local/lib/libflext-max_sd.a"; + refType = 0; + sourceTree = ""; + }; + E94AC9620789EE8700AE1770 = { + fileRef = E94AC9610789EE8700AE1770; + isa = PBXBuildFile; + settings = { + }; + }; + E94AC9630789EEA300AE1770 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = "libflext-pd_sd.a"; + path = "/usr/local/lib/libflext-pd_sd.a"; + refType = 0; + sourceTree = ""; + }; + E94AC9640789EEA300AE1770 = { + fileRef = E94AC9630789EEA300AE1770; + isa = PBXBuildFile; + settings = { + }; + }; + E98C3076078D948800EC0264 = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + name = vecLib.framework; + path = /System/Library/Frameworks/vecLib.framework; + refType = 0; + sourceTree = ""; + }; + E98C3077078D948800EC0264 = { + fileRef = E98C3076078D948800EC0264; + isa = PBXBuildFile; + settings = { + }; + }; + E98C3078078D948800EC0264 = { + fileRef = E98C3076078D948800EC0264; + isa = PBXBuildFile; + settings = { + }; + }; E9974DE50770749400206F68 = { fileEncoding = 30; isa = PBXFileReference; @@ -331,28 +383,6 @@ refType = 0; sourceTree = ""; }; - E9974E04077075E800206F68 = { - isa = PBXFileReference; - lastKnownFileType = archive.ar; - name = libflext_s.a; - path = /Volumes/Daten/Prog/pdmax/flext/build/libflext_s.a; - refType = 0; - sourceTree = ""; - }; - E9974E05077075E800206F68 = { - fileRef = E9974E04077075E800206F68; - isa = PBXBuildFile; - settings = { - }; - }; - E9974E060770761500206F68 = { - isa = PBXFileReference; - lastKnownFileType = archive.ar; - name = "libflext-max_s.a"; - path = "/Volumes/Daten/Prog/pdmax/flext/build/libflext-max_s.a"; - refType = 0; - sourceTree = ""; - }; E9974E2B07707D1400206F68 = { fileEncoding = 4; isa = PBXFileReference; @@ -397,7 +427,8 @@ files = ( E9974E5C0770851700206F68, E9974E5B0770851500206F68, - E9974E5A0770851200206F68, + E94AC9620789EE8700AE1770, + E98C3078078D948800EC0264, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -415,10 +446,9 @@ GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=1"; HEADER_SEARCH_PATHS = "$(Max SDK)/max-includes $(Max SDK)/msp-includes $(Flext)/source"; INFOPLIST_FILE = "source/xsample-Info.plist"; - INSTALL_PATH = "\"/Library/Application Support/Cycling '74/externals\""; + INSTALL_PATH = "/Library/Application Support/Cycling 74/externals"; LIBRARY_SEARCH_PATHS = "$(Flext)/build"; LIBRARY_STYLE = DYNAMIC; - OPTIMIZATION_CFLAGS = ""; OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = xsample; @@ -480,12 +510,6 @@ settings = { }; }; - E9974E5A0770851200206F68 = { - fileRef = E9974E060770761500206F68; - isa = PBXBuildFile; - settings = { - }; - }; E9974E5B0770851500206F68 = { fileRef = E9974DFA0770750400206F68; isa = PBXBuildFile; -- cgit v1.2.1