From 9340768f6c7dea7cb7fe348f6fdf52db75ce9d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 23 Nov 2004 15:29:47 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2300, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/iem16/; revision=2301 --- GnuGPL.LICENSE | 290 ++++++++++++++++++++++++++ examples/del16read~.pd | 41 ++++ examples/del16write~.pd | 25 +++ examples/tab16play~.pd | 56 ++++++ examples/tab16read.pd | 27 +++ examples/tab16read4~.pd | 39 ++++ examples/tab16receive~.pd | 18 ++ examples/tab16send~.pd | 20 ++ examples/tab16write.pd | 28 +++ examples/tab16write~.pd | 32 +++ examples/table16.pd | 60 ++++++ examples/vd16~.pd | 32 +++ src/iem16.c | 52 +++++ src/iem16.dsp | 99 +++++++++ src/iem16.dsw | 29 +++ src/iem16.h | 42 ++++ src/iem16_array.c | 173 ++++++++++++++++ src/iem16_array_tilde.c | 502 ++++++++++++++++++++++++++++++++++++++++++++++ src/iem16_delay.c | 285 ++++++++++++++++++++++++++ src/iem16_table.c | 141 +++++++++++++ src/iem16_table.h | 27 +++ src/makefile | 79 ++++++++ 22 files changed, 2097 insertions(+) create mode 100644 GnuGPL.LICENSE create mode 100644 examples/del16read~.pd create mode 100644 examples/del16write~.pd create mode 100644 examples/tab16play~.pd create mode 100644 examples/tab16read.pd create mode 100644 examples/tab16read4~.pd create mode 100644 examples/tab16receive~.pd create mode 100644 examples/tab16send~.pd create mode 100644 examples/tab16write.pd create mode 100644 examples/tab16write~.pd create mode 100644 examples/table16.pd create mode 100644 examples/vd16~.pd create mode 100644 src/iem16.c create mode 100755 src/iem16.dsp create mode 100755 src/iem16.dsw create mode 100644 src/iem16.h create mode 100644 src/iem16_array.c create mode 100644 src/iem16_array_tilde.c create mode 100755 src/iem16_delay.c create mode 100644 src/iem16_table.c create mode 100644 src/iem16_table.h create mode 100644 src/makefile diff --git a/GnuGPL.LICENSE b/GnuGPL.LICENSE new file mode 100644 index 0000000..fa0bef4 --- /dev/null +++ b/GnuGPL.LICENSE @@ -0,0 +1,290 @@ +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This General +Public License applies to most of the Free Software Foundation's +software and to any other program whose authors commit to using it. +(Some other Free Software Foundation software is covered by the +GNU Library General Public License instead.) You can apply it to your +programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone +to deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you distribute +copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis +or for a fee, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And +you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, +we want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent must +be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS FOR +COPYING, DISTRIBUTION AND +MODIFICATION + +0. This License applies to any program or other work which contains a +notice placed by the copyright holder saying it may be distributed under +the terms of this General Public License. The "Program", below, refers +to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, either +verbatim or with modifications and/or translated into another language. +(Hereinafter, translation is included without limitation in the term +"modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of running +the Program is not restricted, and the output from the Program is +covered only if its contents constitute a work based on the Program +(independent of having been made by running the Program). Whether +that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the notices +that refer to this License and to the absence of any warranty; and give +any other recipients of the Program a copy of this License along with the +Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, and +can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based on +the Program, the distribution of the whole must be on the terms of this +License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based +on the Program. + +In addition, mere aggregation of another work not based on the +Program with the Program (or with a work based on the Program) on a +volume of a storage or distribution medium does not bring the other +work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding + machine-readable source code, which must be distributed under + the terms of Sections 1 and 2 above on a medium customarily + used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your cost + of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with + such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to control +compilation and installation of the executable. However, as a special +exception, the source code distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies the +executable. + +If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy +the source code from the same place counts as distribution of the source +code, even though third parties are not compelled to copy the source +along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt otherwise +to copy, modify, sublicense or distribute the Program is void, and will +automatically terminate your rights under this License. However, parties +who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full +compliance. + +5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and all +its terms and conditions for copying, distributing or modifying the +Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms +and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. You are not responsible +for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot distribute +so as to satisfy simultaneously your obligations under this License and +any other pertinent obligations, then as a consequence you may not +distribute the Program at all. For example, if a patent license would not +permit royalty-free redistribution of the Program by all those who +receive copies directly or indirectly through you, then the only way you +could satisfy both it and this License would be to refrain entirely from +distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system, which is implemented by public license +practices. Many people have made generous contributions to the wide +range of software distributed through that system in reliance on +consistent application of that system; it is up to the author/donor to +decide if he or she is willing to distribute software through any other +system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be +a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an +explicit geographical distribution limitation excluding those countries, so +that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new +versions of the General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number +of this License, you may choose any version ever published by the Free +Software Foundation. + +10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we +sometimes make exceptions for this. Our decision will be guided by the +two goals of preserving the free status of all derivatives of our free +software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF +CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, +TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD +THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE +COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW +OR AGREED TO IN WRITING WILL ANY COPYRIGHT +HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED +ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING +ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT +LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE +WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR +OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS diff --git a/examples/del16read~.pd b/examples/del16read~.pd new file mode 100644 index 0000000..6d4d511 --- /dev/null +++ b/examples/del16read~.pd @@ -0,0 +1,41 @@ +#N canvas 24 20 800 531 12; +#X text 372 274 1st argument: name of delay line; +#X floatatom 116 253 0 0 0 0 - - -; +#X text 151 255 float input (delay time in ms); +#X text 127 310 signal output (delayed signal); +#X floatatom 383 177 0 0 0 0 - - -; +#X obj 116 375 snapshot~; +#X floatatom 116 399 0 0 0 0 - - -; +#X obj 24 246 loadbang; +#X obj 24 313 metro 200; +#X msg 32 273 \; pd dsp 1; +#X text 424 176 input to delay line; +#X obj 383 201 sig~; +#X text 372 290 2nd argument: (initial) delay time in ms; +#X text 36 443 see also:; +#X obj 116 286 del16read~ del_example 1000; +#X obj 383 226 del16write~ del_example 1000; +#X obj 24 16 del16read~; +#X obj 126 444 del16write~; +#X obj 239 444 vd16~; +#X text 133 14 - read a 16bit signal from a 16bit-delay line; +#X obj 368 52 delread~; +#X text 21 52 This is very similar to the pd-object; +#X text 49 82 It uses only 16bit to store the samples \, which will +need only half of the memory of pd's floatingpoint-based object.; +#X text 50 120 However \, there are 2 drawbacks: there will be some +additional noise (because floats are more precise than 16bit) \, and +you cannot have values>1 stored in the delay-line; +#X text 38 490 similar pd-objects:; +#X obj 223 489 delread~; +#X obj 307 489 delwrite~; +#X obj 400 489 vd~; +#X text 433 443 updated for iem16 version1.0; +#X connect 1 0 14 0; +#X connect 4 0 11 0; +#X connect 5 0 6 0; +#X connect 7 0 8 0; +#X connect 7 0 9 0; +#X connect 8 0 5 0; +#X connect 11 0 15 0; +#X connect 14 0 5 0; diff --git a/examples/del16write~.pd b/examples/del16write~.pd new file mode 100644 index 0000000..5aa280a --- /dev/null +++ b/examples/del16write~.pd @@ -0,0 +1,25 @@ +#N canvas 83 192 678 431 12; +#X text 88 202 signal input; +#X text 136 16 writes a signal in a delay line; +#X text 281 235 1st argument: name of delay line; +#X obj 24 203 sig~ 0; +#X text 304 265 (= max. delay time); +#X text 281 251 2nd argument: length of delay line in msec; +#X text 24 292 see also:; +#X obj 24 16 del16write~; +#X obj 112 294 delread16~; +#X obj 209 294 vd16~; +#X text 16 353 similar pd-objects:; +#X obj 201 352 delread~; +#X obj 285 352 delwrite~; +#X obj 378 352 vd~; +#X obj 24 237 del16write~ del_line_xxx 500; +#X text 21 51 This is very similar to the pd-object; +#X text 49 81 It uses only 16bit to store the samples \, which will +need only half of the memory of pd's floatingpoint-based object.; +#X text 50 119 However \, there are 2 drawbacks: there will be some +additional noise (because floats are more precise than 16bit) \, and +you cannot have values>1 stored in the delay-line; +#X obj 368 51 delwrite~; +#X text 411 306 updated for iem16 version1.0; +#X connect 3 0 14 0; diff --git a/examples/tab16play~.pd b/examples/tab16play~.pd new file mode 100644 index 0000000..8c53199 --- /dev/null +++ b/examples/tab16play~.pd @@ -0,0 +1,56 @@ +#N canvas 159 54 804 495 10; +#X msg 639 93 \; pd dsp 0; +#X floatatom 11 342 0 0 0 0 - - -; +#X msg 11 109 set array99; +#X text 93 109 "set" message permits you to switch between arrays; +#X text 138 228 creation argument initializes array name; +#X obj 11 316 env~ 16384; +#X obj 87 360 dac~ 1; +#X obj 87 323 *~; +#X obj 100 304 line~; +#X msg 100 263 0.1 100; +#X msg 116 284 0 100; +#X text 162 264 on; +#X text 157 283 off; +#X text 148 301 envelope; +#X text 148 312 generator; +#X text 101 248 amplitude controls:; +#X text 131 362 audio output; +#X obj 87 342 hip~ 5; +#X msg 26 179 0 44100; +#X msg 27 158 44100; +#X msg 26 138 bang; +#X text 80 136 "bang" or 0 plays whole sample; +#X text 82 157 play starting at 44100th sample; +#X text 93 177 play starting at beginning for 44100 samples; +#X msg 25 199 44100 1000; +#X text 103 198 play from 44100 through 45099 (1000 samples); +#X obj 11 228 tab16play~ array99; +#X obj 589 205 table16 array99; +#X text 389 444 updated for iem16 version1.0; +#X obj 5 439 tab16write~; +#X obj 5 458 tab16read4~; +#X obj 89 458 tab16read; +#X obj 89 439 tab16write; +#X obj 166 439 tab16send~; +#X obj 166 458 tab16receive~; +#X obj 32 13 tab16play~; +#X text 29 43 The [tab16play~] object is the same as the [tabplay~] +object \, but it refers to 16bit-arrays stored in [table16] instead +of floating-point arrays (stored in normal pd-tables/arrays); +#X obj 328 444 table16; +#X text 11 417 see also:; +#X text 108 14 play a 16bit-table as a sample (non-transposing); +#X connect 2 0 26 0; +#X connect 5 0 1 0; +#X connect 7 0 17 0; +#X connect 8 0 7 1; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 17 0 6 0; +#X connect 18 0 26 0; +#X connect 19 0 26 0; +#X connect 20 0 26 0; +#X connect 24 0 26 0; +#X connect 26 0 5 0; +#X connect 26 0 7 0; diff --git a/examples/tab16read.pd b/examples/tab16read.pd new file mode 100644 index 0000000..fd34feb --- /dev/null +++ b/examples/tab16read.pd @@ -0,0 +1,27 @@ +#N canvas 245 143 703 316 12; +#X text 62 102 index; +#X floatatom 25 103 0 0 0 0 - - -; +#X floatatom 25 199 0 0 0 0 - - -; +#X text 70 197 output = array99[index]; +#X text 189 157 creation argument; +#X text 185 175 gives array name; +#X msg 35 125 set array99; +#X text 147 125 change array name; +#X obj 25 165 tab16read array99; +#X obj 422 131 table16 array99; +#X obj 17 13 tab16read; +#X text 412 257 updated for iem16 version1.0; +#X obj 16 252 tab16write~; +#X obj 16 271 tab16read4~; +#X obj 120 271 tab16read; +#X obj 120 252 tab16write; +#X obj 217 252 tab16send~; +#X obj 217 271 tab16receive~; +#X obj 339 257 table16; +#X text 108 15 - read numbers from a 16bit-table; +#X text 21 42 since [table16] can only hold 16bit values \, the output +of [tab16read] is limited to integer-values between -32768..+32767 +; +#X connect 1 0 8 0; +#X connect 6 0 8 0; +#X connect 8 0 2 0; diff --git a/examples/tab16read4~.pd b/examples/tab16read4~.pd new file mode 100644 index 0000000..6757552 --- /dev/null +++ b/examples/tab16read4~.pd @@ -0,0 +1,39 @@ +#N canvas 59 33 741 466 10; +#X text 21 207 signal input x(n); +#X text 127 21 4-point-interpolating table lookup; +#X obj 11 316 snapshot~; +#X obj 30 290 metro 200; +#X obj 11 124 sig~; +#X floatatom 11 98 0 0 0 0 - - -; +#X obj 30 264 r readout; +#X floatatom 11 342 0 0 0 0 - - -; +#X text 49 94 incoming signal is index. Indices should range from 1 +to (size-2) so that the 4-point interpolation is meaningful. You can +shift-drag the number box to see the effect of interpolation.; +#X msg 34 158 set array99; +#X text 116 158 "set" message permits you to switch between arrays +; +#X text 149 228 creation argument initializes array name; +#X obj 10 228 tab16read4~ array99; +#X obj 460 301 table16 array99; +#X text 395 400 updated for iem16 version1.0; +#X obj 11 395 tab16write~; +#X obj 11 414 tab16read4~; +#X obj 95 414 tab16read; +#X obj 95 395 tab16write; +#X obj 172 395 tab16send~; +#X obj 172 414 tab16receive~; +#X obj 334 400 table16; +#X obj 47 21 tab16read4~; +#X text 7 51 tab16read4~ is used to build samplers and other table +lookup algorithms. The interpolation scheme is 4-point polynomial. +; +#X text 185 266 since [table16] can only hold 16bit-values \, the stored +integer values -32768..+32767 are converted to floats -1.0..+1.0; +#X connect 2 0 7 0; +#X connect 3 0 2 0; +#X connect 4 0 12 0; +#X connect 5 0 4 0; +#X connect 6 0 3 0; +#X connect 9 0 12 0; +#X connect 12 0 2 0; diff --git a/examples/tab16receive~.pd b/examples/tab16receive~.pd new file mode 100644 index 0000000..292ec2b --- /dev/null +++ b/examples/tab16receive~.pd @@ -0,0 +1,18 @@ +#N canvas 109 83 646 239 12; +#X text 17 53 creation argument: name of array; +#X text 16 83 By default a block is 64 samples \; this can be reset +using the block~ object.; +#X obj 21 18 tab16receive~; +#X text 376 199 updated for iem16 version1.0; +#X obj 5 176 tab16write~; +#X obj 5 195 tab16read4~; +#X obj 109 195 tab16read; +#X obj 109 176 tab16write; +#X obj 204 176 tab16send~; +#X obj 204 195 tab16receive~; +#X obj 328 181 table16; +#X text 17 155 see also:; +#X text 129 18 - read a block of a 16bit-signal from an array continuously +; +#X text 10 129 16bit-signals are limited to 65536 values between -1.0..+1.0 +; diff --git a/examples/tab16send~.pd b/examples/tab16send~.pd new file mode 100644 index 0000000..918d75a --- /dev/null +++ b/examples/tab16send~.pd @@ -0,0 +1,20 @@ +#N canvas 151 91 705 277 12; +#X text 113 26 writes one block of a signal continuously to an array +; +#X text 41 60 creation argument: name of array; +#X text 29 96 By default a block is 64 samples \; this can be reset +using the block~ object.; +#X text 376 239 updated for iem16 version1.0; +#X obj 5 216 tab16write~; +#X obj 5 235 tab16read4~; +#X obj 109 235 tab16read; +#X obj 109 216 tab16write; +#X obj 204 216 tab16send~; +#X obj 204 235 tab16receive~; +#X obj 328 221 table16; +#X text 17 195 see also:; +#X text 14 137 16bit-signals are limited to 65536 values between -1.0..+1.0 +; +#X text 16 157 if your signal has absolute values >1.0 \, these are +wrapped around...; +#X obj 11 27 tab16send~; diff --git a/examples/tab16write.pd b/examples/tab16write.pd new file mode 100644 index 0000000..209df02 --- /dev/null +++ b/examples/tab16write.pd @@ -0,0 +1,28 @@ +#N canvas 44 17 653 456 12; +#X floatatom 39 96 0 0 0 0 - - -; +#X floatatom 176 170 0 0 0 0 - - -; +#X text 208 192 creation argument; +#X text 210 210 is array name; +#X text 76 87 set y value; +#X text 74 152 right inlet selects x value; +#X msg 55 117 set array99; +#X text 163 116 change array name; +#X obj 39 195 tab16write array99; +#X obj 31 27 tab16write; +#X text 388 378 updated for iem16 version1.0; +#X obj 17 355 tab16write~; +#X obj 17 374 tab16read4~; +#X obj 121 374 tab16read; +#X obj 121 355 tab16write; +#X obj 216 355 tab16send~; +#X obj 216 374 tab16receive~; +#X obj 340 360 table16; +#X text 29 334 see also:; +#X obj 438 156 table16 array99; +#X text 133 28 write numbers to a 16bit-table; +#X text 20 256 since [table16] can only hold 16bit-values \, the stored +numbers have to be integer (ok \, we take care of this!) values between +-32768..+32767.; +#X connect 0 0 8 0; +#X connect 1 0 8 1; +#X connect 6 0 8 0; diff --git a/examples/tab16write~.pd b/examples/tab16write~.pd new file mode 100644 index 0000000..0904d65 --- /dev/null +++ b/examples/tab16write~.pd @@ -0,0 +1,32 @@ +#N canvas 119 134 697 433 10; +#X msg 43 131 bang; +#X obj 23 82 sig~ 3000; +#X obj 23 110 phasor~; +#X text 158 213 creation argument initializes array name; +#X msg 40 181 set array99; +#X msg 445 35 \; pd dsp 1; +#X msg 524 37 \; pd dsp 0; +#X text 85 133 bang to start recording; +#X text 126 180 set the destination array; +#X msg 43 153 stop; +#X text 85 154 stop recording; +#X text 385 366 updated for iem16 version1.0; +#X obj 14 343 tab16write~; +#X obj 14 362 tab16read4~; +#X obj 118 362 tab16read; +#X obj 118 343 tab16write; +#X obj 213 343 tab16send~; +#X obj 213 362 tab16receive~; +#X obj 337 348 table16; +#X text 26 322 see also:; +#X obj 22 211 tab16write~ array99; +#X obj 492 160 table16 array99; +#X obj 31 27 tab16write~; +#X text 120 27 object to write a 16bit-signal in an array; +#X text 261 261 since [table16] can only hold 16bit-values \, the incoming +signal (-1.0..+1.0) is stored as integer values -32768..+32767; +#X connect 0 0 20 0; +#X connect 1 0 2 0; +#X connect 2 0 20 0; +#X connect 4 0 20 0; +#X connect 9 0 20 0; diff --git a/examples/table16.pd b/examples/table16.pd new file mode 100644 index 0000000..50e6ccb --- /dev/null +++ b/examples/table16.pd @@ -0,0 +1,60 @@ +#N canvas 37 0 856 640 10; +#X obj 30 21 table16; +#X text 97 22 16bit-table; +#X text 32 51 [table16] stores 16bit values. The normal pd-tables ([table] +\, array) store the values as floating-points. While floating points +are (often) more precise (this is of course not really true... \, esp. +when comparing integer(4byte) to floating-point.) they use a lot of +memory (4byte).; +#X text 32 121 [table16] uses only 16bit (2bytes) to store the values +\, which is half of the memory.; +#X text 32 155 However there are 2 major drawbacks; +#X text 53 172 a) less precision means less SNR - you can only store +65536 different values \, but this is what CD-quality is (should be +good enough for most musical applications); +#X text 55 221 b) the 65536 values (-32678..+32767) are mapped to -1.0..+1.0! +This means you cannot store signals that exceed this magical limit. +Please make sure \, that the signal has correct values (use [clip~]) +or the unclipped values will get wrapped!; +#X text 20 323 There are several objects to access the data of [table16]: +; +#X obj 55 344 tab16write~; +#X obj 55 363 tab16read4~; +#X obj 279 363 tab16read; +#X obj 279 344 tab16write; +#X obj 164 344 tab16send~; +#X obj 164 363 tab16receive~; +#X obj 55 382 tab16read~; +#X text 19 410 The message-objects [tab16read]/[tab16write] store the +values directly (-32767..+32768) \, while the signal-objects convert +the floats -1.0..+1.0 to the correct values or vice-versa.; +#X text 270 21 updated for iem16 version1.0; +#X msg 496 53 resize 100; +#X obj 496 308 table16 array16 99; +#N canvas 0 0 450 300 graph6 0; +#X array array100 10 float 1; +#A 0 1 2 3 4 5 6 7 8 9 0; +#X coords 0 10 9 0 200 140 1; +#X restore 477 452 graph; +#X msg 478 409 \; array100 0 1 2 3 4 5 6 7 8 9; +#X text 481 389 click to init float-array; +#X msg 502 114 from array100; +#X text 21 497 There is no beautiful graphical representation as with +pd's arrays.; +#X msg 508 139 from array100 resize; +#X msg 516 190 from array100 20 30; +#X msg 517 213 from array100 20 30 resize; +#X msg 527 259 from array100 20 30 95; +#X msg 527 279 from array100 20 30 95 resize; +#X text 502 95 copy the data from a float-array; +#X text 603 117 and resize the 16bit-array; +#X text 513 173 copy floats (index20..30); +#X text 653 192 and resize to 30-20; +#X text 526 241 copy indexed values and insert at index95; +#X connect 17 0 18 0; +#X connect 22 0 18 0; +#X connect 24 0 18 0; +#X connect 25 0 18 0; +#X connect 26 0 18 0; +#X connect 27 0 18 0; +#X connect 28 0 18 0; diff --git a/examples/vd16~.pd b/examples/vd16~.pd new file mode 100644 index 0000000..cf59065 --- /dev/null +++ b/examples/vd16~.pd @@ -0,0 +1,32 @@ +#N canvas 88 40 717 480 12; +#X floatatom 50 254 0 0 0 0 - - -; +#X obj 50 347 outlet~; +#X text 130 346 signal output (delayed signal); +#X obj 50 282 sig~; +#X text 99 279 signal input (delay time in ms); +#X text 218 310 creation argument: name of delay line; +#X text 35 400 see also:; +#X obj 24 16 vd16~; +#X text 77 10 reads a signal from a 16bit delay line at a variable +delay time (4-point-interpolation); +#X text 31 51 vd16~ implements a 4-point interpolating delay tap from +a corresponding delwrite~ object. The delay in milliseconds of the +tap is specified by the incoming signal.; +#X obj 50 314 vd16~ del_example; +#X text 16 433 similar pd-objects:; +#X obj 201 432 delread~; +#X obj 285 432 delwrite~; +#X obj 378 432 vd~; +#X obj 123 403 del16write~; +#X obj 242 403 del16read~; +#X text 411 386 updated for iem16 version1.0; +#X text 28 116 This is very similar to the pd-object; +#X text 56 137 It uses only 16bit to store the samples \, which will +need only half of the memory of pd's floatingpoint-based object.; +#X text 57 175 However \, there are 2 drawbacks: there will be some +additional noise (because floats are more precise than 16bit) \, and +you cannot have values>1 stored in the delay-line; +#X obj 375 112 vd~; +#X connect 0 0 3 0; +#X connect 3 0 10 0; +#X connect 10 0 1 0; diff --git a/src/iem16.c b/src/iem16.c new file mode 100644 index 0000000..d916ddc --- /dev/null +++ b/src/iem16.c @@ -0,0 +1,52 @@ +/* ...this is a very IEM16 external ... + it allows for 16bit-constructs where float would eat too much memory + + forum::für::umläute@IEM:2003 +*/ + +#include "iem16.h" + +/* do a little help thing */ + +typedef struct iem16 { + t_object t_ob; +} t_iem16; + +t_class *iem16_class; + +void *iem16_new(void){ + t_iem16 *x = (t_iem16 *)pd_new(iem16_class); + post("iem16: 16bit objects for low memory usage"); + return (void *)x; +} + +/* include some externals */ +void iem16_table_setup(); +void iem16_array_setup(); +void iem16_array_tilde_setup(); +void iem16_delay_setup(); + +void iem16_setup(void) { + iem16_table_setup(); + iem16_array_setup(); + iem16_array_tilde_setup(); + iem16_delay_setup(); + + /* ************************************** */ + post("iem16:\t16bit-objects for low memory usage"); + post("iem16:\t(l) forum::für::umläute\t\tIOhannes m zmölnig"); + post("iem16:\tInstitute of Electronic Music and Acoustics, Graz - iem"); + post("iem16:\tcompiled: "__DATE__); + + + iem16_class = class_new(gensym("iem16"), + iem16_new, + 0, + sizeof(t_iem16), CLASS_NOINLET, A_NULL); + class_addcreator((t_newmethod)iem16_new, + gensym("IEM16"), A_NULL); +} + +void IEM16_setup(void){ + iem16_setup(); +} diff --git a/src/iem16.dsp b/src/iem16.dsp new file mode 100755 index 0000000..1c2f7fc --- /dev/null +++ b/src/iem16.dsp @@ -0,0 +1,99 @@ +# Microsoft Developer Studio Project File - Name="iem16" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=IEM16 - WIN32 RELEASE +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "iem16.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "iem16.mak" CFG="IEM16 - WIN32 RELEASE" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "iem16 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 1 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "obj\" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IEM16_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /I "..\..\pd\src" /D "WIN32" /D "NT" /D "_WINDOWS" /D "IEM16" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /win32 +# SUBTRACT MTL /mktyplib203 +# ADD BASE RSC /l 0xc07 /d "NDEBUG" +# ADD RSC /l 0xc07 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib wsock32.lib uuid.lib libc.lib oldnames.lib pd.lib /nologo /dll /machine:I386 /nodefaultlib /out:"..\iem16.dll" /libpath:"../../pd/bin" /export:iem16_setup +# SUBTRACT LINK32 /pdb:none +# Begin Target + +# Name "iem16 - Win32 Release" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\iem16.c +# End Source File +# Begin Source File + +SOURCE=.\iem16_array.c +# End Source File +# Begin Source File + +SOURCE=.\iem16_array_tilde.c +# End Source File +# Begin Source File + +SOURCE=.\iem16_delay.c +# End Source File +# Begin Source File + +SOURCE=.\iem16_table.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\iem16.h +# End Source File +# Begin Source File + +SOURCE=.\iem16_table.h +# End Source File +# Begin Source File + +SOURCE=..\..\pd\src\m_pd.h +# End Source File +# End Group +# End Target +# End Project diff --git a/src/iem16.dsw b/src/iem16.dsw new file mode 100755 index 0000000..0e01cda --- /dev/null +++ b/src/iem16.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "iem16"=.\iem16.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/iem16.h b/src/iem16.h new file mode 100644 index 0000000..f9649cd --- /dev/null +++ b/src/iem16.h @@ -0,0 +1,42 @@ +/* ********************************************** */ +/* the IEM16 external */ +/* ********************************************** */ +/* forum::für::umläute */ +/* ********************************************** */ + +/* the IEM16 external is a runtime-library for miller s. puckette's realtime-computermusic-software "pure data" + * therefore you NEED "pure data" to make any use of the IEM16 external + * (except if you want to use the code for other things) + * download "pure data" at + + http://pd.iem.at + ftp://iem.at/pd + + * + * if you are looking for the latest release of the IEM16-external you should have another look at + + ftp://iem.at/pd/Externals/IEM16 + + * + * IEM16 is published under the GNU GeneralPublicLicense, that must be shipped with IEM16. + * if you are using Debian GNU/linux, the GNU-GPL can be found under /usr/share/common-licenses/GPL + * if you still haven't found a copy of the GNU-GPL, have a look at http://www.gnu.org + * + * "pure data" has it's own license, that comes shipped with "pure data". + * + * there are ABSOLUTELY NO WARRANTIES for anything + */ + +#ifndef INCLUDE_IEM16_H__ +#define INCLUDE_IEM16_H__ + +#include "m_pd.h" + +typedef short t_iem16_16bit; + +#define IEM16_SCALE_UP (32767) +#define IEM16_SCALE_DOWN (1./32767) + +#define VERSION "0.1" + +#endif diff --git a/src/iem16_array.c b/src/iem16_array.c new file mode 100644 index 0000000..22ee35d --- /dev/null +++ b/src/iem16_array.c @@ -0,0 +1,173 @@ +/* copyleft (c) 2003 forum::für::umläute -- IOhannes m zmölnig @ IEM + * based on d_array.c from pd: + * Copyright (c) 1997-1999 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* tab16read, tab16read4, tab16write */ + +#include "iem16_table.h" + +/* ---------- tab16read: control, non-interpolating ------------------------ */ + +static t_class *tab16read_class; + +typedef struct _tab16read{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tab16read; + +static void tab16read_float(t_tab16read *x, t_float f){ + t_table16 *a; + int npoints; + t_iem16_16bit *vec; + + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!table16_getarray16(a, &npoints, &vec)) + error("%s: bad template for tab16read", x->x_arrayname->s_name); + else { + int n = f; + if (n < 0) n = 0; + else if (n >= npoints) n = npoints - 1; + outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n] : 0)); + } +} + +static void tab16read_set(t_tab16read *x, t_symbol *s){ + x->x_arrayname = s; +} + +static void *tab16read_new(t_symbol *s){ + t_tab16read *x = (t_tab16read *)pd_new(tab16read_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void tab16read_setup(void){ + tab16read_class = class_new(gensym("tab16read"), (t_newmethod)tab16read_new, + 0, sizeof(t_tab16read), 0, A_DEFSYM, 0); + class_addfloat(tab16read_class, (t_method)tab16read_float); + class_addmethod(tab16read_class, (t_method)tab16read_set, gensym("set"), + A_SYMBOL, 0); +} + +/* ---------- tab16read4: control, non-interpolating ------------------------ */ + +static t_class *tab16read4_class; + +typedef struct _tab16read4{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tab16read4; + +static void tab16read4_float(t_tab16read4 *x, t_float f){ + t_table16 *a; + int npoints; + t_iem16_16bit *vec; + + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!table16_getarray16(a, &npoints, &vec)) + error("%s: bad template for tab16read4", x->x_arrayname->s_name); + else if (npoints < 4) + outlet_float(x->x_obj.ob_outlet, 0); + else if (f <= 1) + outlet_float(x->x_obj.ob_outlet, vec[1]); + else if (f >= npoints - 2) + outlet_float(x->x_obj.ob_outlet, vec[npoints - 2]); + else { + int n = f; + float a, b, c, d, cminusb, frac; + t_iem16_16bit *fp; + if (n >= npoints - 2) n = npoints - 3; + fp = vec + n; + frac = f - n; + a = fp[-1]; + b = fp[0]; + c = fp[1]; + d = fp[2]; + cminusb = c-b; + outlet_float(x->x_obj.ob_outlet, b + frac * ( + cminusb - 0.5f * (frac-1.) * ( + (a - d + 3.0f * cminusb) * frac + (b - a - cminusb)))); + } +} + +static void tab16read4_set(t_tab16read4 *x, t_symbol *s){ + x->x_arrayname = s; +} + +static void *tab16read4_new(t_symbol *s){ + t_tab16read4 *x = (t_tab16read4 *)pd_new(tab16read4_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void tab16read4_setup(void){ + tab16read4_class = class_new(gensym("tab16read4"), (t_newmethod)tab16read4_new, + 0, sizeof(t_tab16read4), 0, A_DEFSYM, 0); + class_addfloat(tab16read4_class, (t_method)tab16read4_float); + class_addmethod(tab16read4_class, (t_method)tab16read4_set, gensym("set"), + A_SYMBOL, 0); +} + +/* ------------------ tab16write: control ------------------------ */ + +static t_class *tab16write_class; + +typedef struct _tab16write { + t_object x_obj; + t_symbol *x_arrayname; + float x_ft1; + int x_set; +} t_tab16write; + +static void tab16write_float(t_tab16write *x, t_float f) { + int vecsize; + t_table16 *a; + t_iem16_16bit *vec; + + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!table16_getarray16(a, &vecsize, &vec)) + error("%s: bad template for tab16write", x->x_arrayname->s_name); + else { + int n = x->x_ft1; + if (n < 0) n = 0; + else if (n >= vecsize) n = vecsize-1; + vec[n] = f; + } +} + +static void tab16write_set(t_tab16write *x, t_symbol *s){ + x->x_arrayname = s; +} + +static void tab16write_free(t_tab16write *x){} + +static void *tab16write_new(t_symbol *s){ + t_tab16write *x = (t_tab16write *)pd_new(tab16write_class); + x->x_ft1 = 0; + x->x_arrayname = s; + floatinlet_new(&x->x_obj, &x->x_ft1); + return (x); +} + +void tab16write_setup(void){ + tab16write_class = class_new(gensym("tab16write"), (t_newmethod)tab16write_new, + (t_method)tab16write_free, sizeof(t_tab16write), 0, A_DEFSYM, 0); + class_addfloat(tab16write_class, (t_method)tab16write_float); + class_addmethod(tab16write_class, (t_method)tab16write_set, gensym("set"), A_SYMBOL, 0); +} + +/* ------------------------ global setup routine ------------------------- */ + +void iem16_array_setup(void){ + tab16read_setup(); + tab16read4_setup(); + tab16write_setup(); +} + diff --git a/src/iem16_array_tilde.c b/src/iem16_array_tilde.c new file mode 100644 index 0000000..2cda11f --- /dev/null +++ b/src/iem16_array_tilde.c @@ -0,0 +1,502 @@ +/* copyleft (c) 2003 forum::für::umläute -- IOhannes m zmölnig @ IEM + * based on d_array.c from pd: + * Copyright (c) 1997-1999 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* tab16write~, tab16play~, tab16read~, tab16read4~, tab16send~, tab16receive~ */ + +#include "iem16_table.h" + +/* ------------------------- tab16write~ -------------------------- */ + +static t_class *tab16write_tilde_class; + +typedef struct _tab16write_tilde { + t_object x_obj; + int x_phase; + int x_nsampsintab; + short *x_vec; + t_symbol *x_arrayname; + float x_f; +} t_tab16write_tilde; + +static void *tab16write_tilde_new(t_symbol *s) { + t_tab16write_tilde *x = (t_tab16write_tilde *)pd_new(tab16write_tilde_class); + x->x_phase = 0x7fffffff; + x->x_arrayname = s; + x->x_f = 0; + return (x); +} + +static t_int *tab16write_tilde_perform(t_int *w) { + t_tab16write_tilde *x = (t_tab16write_tilde *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = (int)(w[3]), phase = x->x_phase, endphase = x->x_nsampsintab; + if (!x->x_vec) goto bad; + + if (endphase > phase) { + int nxfer = endphase - phase; + t_iem16_16bit *fp = x->x_vec + phase; + if (nxfer > n) nxfer = n; + phase += nxfer; + while (nxfer--)*fp++ = *in++*IEM16_SCALE_UP; + x->x_phase = phase; + } + bad: + return (w+4); +} + +void tab16write_tilde_set(t_tab16write_tilde *x, t_symbol *s){ + t_table16 *a; + + x->x_arrayname = s; + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*s->s_name) pd_error(x, "tab16write~: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!table16_getarray16(a, &x->x_nsampsintab, &x->x_vec)) { + error("%s: bad template for tab16write~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else table16_usedindsp(a); +} + +static void tab16write_tilde_dsp(t_tab16write_tilde *x, t_signal **sp){ + tab16write_tilde_set(x, x->x_arrayname); + dsp_add(tab16write_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void tab16write_tilde_bang(t_tab16write_tilde *x){ + x->x_phase = 0; +} + +static void tab16write_tilde_stop(t_tab16write_tilde *x){} + +static void tab16write_tilde_free(t_tab16write_tilde *x){} + +static void tab16write_tilde_setup(void){ + tab16write_tilde_class = class_new(gensym("tab16write~"), + (t_newmethod)tab16write_tilde_new, (t_method)tab16write_tilde_free, + sizeof(t_tab16write_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tab16write_tilde_class, t_tab16write_tilde, x_f); + class_addmethod(tab16write_tilde_class, (t_method)tab16write_tilde_dsp, + gensym("dsp"), 0); + class_addmethod(tab16write_tilde_class, (t_method)tab16write_tilde_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(tab16write_tilde_class, (t_method)tab16write_tilde_stop, + gensym("stop"), 0); + class_addbang(tab16write_tilde_class, tab16write_tilde_bang); +} + +/* ------------ tab16play~ - non-transposing sample playback --------------- */ + +static t_class *tab16play_tilde_class; + +typedef struct _tab16play_tilde{ + t_object x_obj; + t_outlet *x_bangout; + int x_phase; + int x_nsampsintab; + int x_limit; + t_iem16_16bit *x_vec; + t_symbol *x_arrayname; +} t_tab16play_tilde; + +static void *tab16play_tilde_new(t_symbol *s){ + t_tab16play_tilde *x = (t_tab16play_tilde *)pd_new(tab16play_tilde_class); + x->x_phase = 0x7fffffff; + x->x_limit = 0; + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_signal); + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + return (x); +} + +static t_int *tab16play_tilde_perform(t_int *w){ + t_tab16play_tilde *x = (t_tab16play_tilde *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_iem16_16bit *fp; + int n = (int)(w[3]), phase = x->x_phase, + endphase = (x->x_nsampsintab < x->x_limit ? + x->x_nsampsintab : x->x_limit), nxfer, n3; + if (!x->x_vec || phase >= endphase) goto zero; + + nxfer = endphase - phase; + fp = x->x_vec + phase; + if (nxfer > n) + nxfer = n; + n3 = n - nxfer; + phase += nxfer; + while (nxfer--) *out++ = *fp++*IEM16_SCALE_DOWN; + if (phase >= endphase) { + x->x_phase = 0x7fffffff; + while (n3--) *out++ = 0; + } + else x->x_phase = phase; + + return (w+4); + zero: + while (n--) *out++ = 0; + return (w+4); +} + +void tab16play_tilde_set(t_tab16play_tilde *x, t_symbol *s){ + t_table16 *a; + + x->x_arrayname = s; + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*s->s_name) pd_error(x, "tab16play~: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!table16_getarray16(a, &x->x_nsampsintab, &x->x_vec)) { + error("%s: bad template for tab16play~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else table16_usedindsp(a); +} + +static void tab16play_tilde_dsp(t_tab16play_tilde *x, t_signal **sp){ + tab16play_tilde_set(x, x->x_arrayname); + dsp_add(tab16play_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void tab16play_tilde_list(t_tab16play_tilde *x, t_symbol *s, + int argc, t_atom *argv){ + long start = atom_getfloatarg(0, argc, argv); + long length = atom_getfloatarg(1, argc, argv); + if (start < 0) start = 0; + if (length <= 0)x->x_limit = 0x7fffffff; + else x->x_limit = start + length; + x->x_phase = start; +} + +static void tab16play_tilde_stop(t_tab16play_tilde *x){ + x->x_phase = 0x7fffffff; +} + +static void tab16play_tilde_free(t_tab16play_tilde *x){} + +static void tab16play_tilde_setup(void){ + tab16play_tilde_class = class_new(gensym("tab16play~"), + (t_newmethod)tab16play_tilde_new, (t_method)tab16play_tilde_free, + sizeof(t_tab16play_tilde), 0, A_DEFSYM, 0); + class_addmethod(tab16play_tilde_class, (t_method)tab16play_tilde_dsp, + gensym("dsp"), 0); + class_addmethod(tab16play_tilde_class, (t_method)tab16play_tilde_stop, + gensym("stop"), 0); + class_addmethod(tab16play_tilde_class, (t_method)tab16play_tilde_set, + gensym("set"), A_DEFSYM, 0); + class_addlist(tab16play_tilde_class, tab16play_tilde_list); +} + +/* ------------------------ tab16send~ ------------------------- */ + +static t_class *tab16send_class; + +typedef struct _tab16send{ + t_object x_obj; + t_iem16_16bit *x_vec; + int x_graphperiod; + int x_graphcount; + t_symbol *x_arrayname; + float x_f; +} t_tab16send; + +static void *tab16send_new(t_symbol *s){ + t_tab16send *x = (t_tab16send *)pd_new(tab16send_class); + x->x_graphcount = 0; + x->x_arrayname = s; + x->x_f = 0; + return (x); +} + +static t_int *tab16send_perform(t_int *w){ + t_tab16send *x = (t_tab16send *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = w[3]; + t_iem16_16bit *dest = x->x_vec; + int i = x->x_graphcount; + if (!x->x_vec) goto bad; + + while (n--) *dest = *in++*IEM16_SCALE_UP; + if (!i--)i = x->x_graphperiod; + x->x_graphcount = i; + bad: + return (w+4); +} + +static void tab16send_dsp(t_tab16send *x, t_signal **sp){ + int vecsize; + t_table16 *a; + + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*x->x_arrayname->s_name) + error("tab16send~: %s: no such array", x->x_arrayname->s_name); + } + else if (!table16_getarray16(a, &vecsize, &x->x_vec)) + error("%s: bad template for tab16send~", x->x_arrayname->s_name); + else { + int n = sp[0]->s_n; + int ticksper = sp[0]->s_sr/n; + if (ticksper < 1) ticksper = 1; + x->x_graphperiod = ticksper; + if (x->x_graphcount > ticksper) x->x_graphcount = ticksper; + if (n < vecsize) vecsize = n; + table16_usedindsp(a); + dsp_add(tab16send_perform, 3, x, sp[0]->s_vec, vecsize); + } +} + +static void tab16send_free(t_tab16send *x){} + +static void tab16send_setup(void){ + tab16send_class = class_new(gensym("tab16send~"), (t_newmethod)tab16send_new, + (t_method)tab16send_free, sizeof(t_tab16send), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tab16send_class, t_tab16send, x_f); + class_addmethod(tab16send_class, (t_method)tab16send_dsp, gensym("dsp"), 0); +} + +/* ------------------------ tab16receive~ ------------------------- */ + +static t_class *tab16receive_class; + +typedef struct _tab16receive{ + t_object x_obj; + t_iem16_16bit *x_vec; + t_symbol *x_arrayname; +} t_tab16receive; + +static t_int *tab16receive_perform(t_int *w){ + t_tab16receive *x = (t_tab16receive *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = w[3]; + t_iem16_16bit *from = x->x_vec; + if (from) while (n--) *out++ = *from++*IEM16_SCALE_DOWN; + else while (n--) *out++ = 0; + return (w+4); +} + +static void tab16receive_dsp(t_tab16receive *x, t_signal **sp){ + t_table16 *a; + int vecsize; + + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*x->x_arrayname->s_name) + error("tab16send~: %s: no such array", x->x_arrayname->s_name); + } + else if (!table16_getarray16(a, &vecsize, &x->x_vec)) + error("%s: bad template for tab16receive~", x->x_arrayname->s_name); + else { + int n = sp[0]->s_n; + if (n < vecsize) vecsize = n; + table16_usedindsp(a); + dsp_add(tab16receive_perform, 3, x, sp[0]->s_vec, vecsize); + } +} + +static void *tab16receive_new(t_symbol *s){ + t_tab16receive *x = (t_tab16receive *)pd_new(tab16receive_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static void tab16receive_setup(void){ + tab16receive_class = class_new(gensym("tab16receive~"), + (t_newmethod)tab16receive_new, 0, + sizeof(t_tab16receive), 0, A_DEFSYM, 0); + class_addmethod(tab16receive_class, (t_method)tab16receive_dsp, + gensym("dsp"), 0); +} + +/******************** tab16read~ ***********************/ + +static t_class *tab16read_tilde_class; + +typedef struct _tab16read_tilde{ + t_object x_obj; + int x_npoints; + t_iem16_16bit *x_vec; + t_symbol *x_arrayname; + float x_f; +} t_tab16read_tilde; + +static void *tab16read_tilde_new(t_symbol *s){ + t_tab16read_tilde *x = (t_tab16read_tilde *)pd_new(tab16read_tilde_class); + x->x_arrayname = s; + x->x_vec = 0; + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *tab16read_tilde_perform(t_int *w){ + t_tab16read_tilde *x = (t_tab16read_tilde *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + int maxindex; + t_iem16_16bit *buf = x->x_vec; + int i; + + maxindex = x->x_npoints - 1; + if (!buf) goto zero; + + for (i = 0; i < n; i++) { + int index = *in++; + if (index < 0) index = 0; + else if (index > maxindex) index = maxindex; + *out++ = buf[index]*IEM16_SCALE_DOWN; + } + return (w+5); + zero: + while (n--) *out++ = 0; + + return (w+5); +} + +void tab16read_tilde_set(t_tab16read_tilde *x, t_symbol *s){ + t_table16 *a; + + x->x_arrayname = s; + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*s->s_name) + error("tab16read~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!table16_getarray16(a, &x->x_npoints, &x->x_vec)) { + error("%s: bad template for tab16read~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else table16_usedindsp(a); +} + +static void tab16read_tilde_dsp(t_tab16read_tilde *x, t_signal **sp){ + tab16read_tilde_set(x, x->x_arrayname); + + dsp_add(tab16read_tilde_perform, 4, x, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); + +} + +static void tab16read_tilde_free(t_tab16read_tilde *x){} + +static void tab16read_tilde_setup(void){ + tab16read_tilde_class = class_new(gensym("tab16read~"), + (t_newmethod)tab16read_tilde_new, (t_method)tab16read_tilde_free, + sizeof(t_tab16read_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tab16read_tilde_class, t_tab16read_tilde, x_f); + class_addmethod(tab16read_tilde_class, (t_method)tab16read_tilde_dsp, + gensym("dsp"), 0); + class_addmethod(tab16read_tilde_class, (t_method)tab16read_tilde_set, + gensym("set"), A_SYMBOL, 0); +} + +/******************** tab16read4~ ***********************/ + +static t_class *tab16read4_tilde_class; + +typedef struct _tab16read4_tilde{ + t_object x_obj; + int x_npoints; + t_iem16_16bit *x_vec; + t_symbol *x_arrayname; + float x_f; +} t_tab16read4_tilde; + +static void *tab16read4_tilde_new(t_symbol *s){ + t_tab16read4_tilde *x = (t_tab16read4_tilde *)pd_new(tab16read4_tilde_class); + x->x_arrayname = s; + x->x_vec = 0; + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *tab16read4_tilde_perform(t_int *w){ + t_tab16read4_tilde *x = (t_tab16read4_tilde *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + int maxindex; + t_iem16_16bit *buf = x->x_vec; + t_iem16_16bit *fp; + int i; + + maxindex = x->x_npoints - 3; + + if (!buf) goto zero; + + for (i = 0; i < n; i++) { + float findex = *in++; + int index = findex; + float frac, a, b, c, d, cminusb; + if (index < 1) index = 1, frac = 0; + else if (index > maxindex) index = maxindex, frac = 1; + else frac = findex - index; + fp = buf + index; + a = fp[-1]*IEM16_SCALE_DOWN; + b = fp[0]*IEM16_SCALE_DOWN; + c = fp[1]*IEM16_SCALE_DOWN; + d = fp[2]*IEM16_SCALE_DOWN; + cminusb = c-b; + *out++ = b + frac * ( + cminusb - 0.5f * (frac-1.) * ( + (a - d + 3.0f * cminusb) * frac + (b - a - cminusb) + ) + ); + } + return (w+5); + zero: + while (n--) *out++ = 0; + + return (w+5); +} + +void tab16read4_tilde_set(t_tab16read4_tilde *x, t_symbol *s){ + t_table16 *a; + + x->x_arrayname = s; + if (!(a = (t_table16 *)pd_findbyclass(x->x_arrayname, table16_class))) { + if (*s->s_name) + error("tab16read4~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!table16_getarray16(a, &x->x_npoints, &x->x_vec)) { + error("%s: bad template for tab16read4~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else table16_usedindsp(a); +} + +static void tab16read4_tilde_dsp(t_tab16read4_tilde *x, t_signal **sp){ + tab16read4_tilde_set(x, x->x_arrayname); + + dsp_add(tab16read4_tilde_perform, 4, x, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void tab16read4_tilde_setup(void){ + tab16read4_tilde_class = class_new(gensym("tab16read4~"), + (t_newmethod)tab16read4_tilde_new, 0, + sizeof(t_tab16read4_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tab16read4_tilde_class, t_tab16read4_tilde, x_f); + class_addmethod(tab16read4_tilde_class, (t_method)tab16read4_tilde_dsp, + gensym("dsp"), 0); + class_addmethod(tab16read4_tilde_class, (t_method)tab16read4_tilde_set, + gensym("set"), A_SYMBOL, 0); +} +/* ------------------------ global setup routine ------------------------- */ + +void iem16_array_tilde_setup(void){ + tab16write_tilde_setup(); + tab16play_tilde_setup(); + tab16read_tilde_setup(); + tab16read4_tilde_setup(); + tab16send_setup(); + tab16receive_setup(); +} + diff --git a/src/iem16_delay.c b/src/iem16_delay.c new file mode 100755 index 0000000..24a45d3 --- /dev/null +++ b/src/iem16_delay.c @@ -0,0 +1,285 @@ +/* copyleft (c) 2003 forum::für::umläute -- IOhannes m zmölnig @ IEM + * based on d_delay.c from pd: + * Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* del16read~, del16write~, vd16~ */ + +#include "iem16_table.h" +#ifdef NT +static int ugen_getsortno(void){return 0;} +#else +extern int ugen_getsortno(void); +#endif + +#define DEFDELVS 64 /* LATER get this from canvas at DSP time */ + +/* ----------------------------- del16write~ ----------------------------- */ +static t_class *sigdel16write_class; + +typedef struct del16writectl{ + int c_n; + t_iem16_16bit *c_vec; + int c_phase; +} t_del16writectl; + +typedef struct _sigdel16write{ + t_object x_obj; + t_symbol *x_sym; + t_del16writectl x_cspace; + int x_sortno; /* DSP sort number at which this was last put on chain */ + int x_rsortno; /* DSP sort # for first del16read or write in chain */ + int x_vecsize; /* vector size for del16read~ to use */ + float x_f; +} t_sigdel16write; + +#define XTRASAMPS 4 +#define SAMPBLK 4 + +/* routine to check that all del16writes/del16reads/vds have same vecsize */ +static void sigdel16write_checkvecsize(t_sigdel16write *x, int vecsize){ + if (x->x_rsortno != ugen_getsortno()) { + x->x_vecsize = vecsize; + x->x_rsortno = ugen_getsortno(); + } + else if (vecsize != x->x_vecsize) + pd_error(x, "del16read/del16write/vd vector size mismatch"); +} + +static void *sigdel16write_new(t_symbol *s, t_floatarg msec){ + int nsamps; + t_sigdel16write *x = (t_sigdel16write *)pd_new(sigdel16write_class); + if (!*s->s_name) s = gensym("del16write~"); + pd_bind(&x->x_obj.ob_pd, s); + x->x_sym = s; + nsamps = msec * sys_getsr() * (float)(0.001f); + if (nsamps < 1) nsamps = 1; + nsamps += ((- nsamps) & (SAMPBLK - 1)); + nsamps += DEFDELVS; + x->x_cspace.c_n = nsamps; + x->x_cspace.c_vec = + (t_iem16_16bit *)getbytes((nsamps + XTRASAMPS) * sizeof(t_iem16_16bit)); + x->x_cspace.c_phase = XTRASAMPS; + x->x_sortno = 0; + x->x_vecsize = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigdel16write_perform(t_int *w){ + t_float *in = (t_float *)(w[1]); + t_del16writectl *c = (t_del16writectl *)(w[2]); + int n = (int)(w[3]); + int phase = c->c_phase, nsamps = c->c_n; + t_iem16_16bit *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); + phase += n; + while (n--) { + *bp++ = (*in++*IEM16_SCALE_UP); + if (bp == ep) { + vp[0] = ep[-4]; + vp[1] = ep[-3]; + vp[2] = ep[-2]; + vp[3] = ep[-1]; + bp = vp + XTRASAMPS; + phase -= nsamps; + } + } + c->c_phase = phase; + return (w+4); +} + +static void sigdel16write_dsp(t_sigdel16write *x, t_signal **sp){ + dsp_add(sigdel16write_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n); + x->x_sortno = ugen_getsortno(); + sigdel16write_checkvecsize(x, sp[0]->s_n); +} + +static void sigdel16write_free(t_sigdel16write *x){ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + freebytes(x->x_cspace.c_vec, + (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_iem16_16bit)); +} + +static void sigdel16write_setup(void){ + sigdel16write_class = class_new(gensym("del16write~"), + (t_newmethod)sigdel16write_new, (t_method)sigdel16write_free, + sizeof(t_sigdel16write), 0, A_DEFSYM, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigdel16write_class, t_sigdel16write, x_f); + class_addmethod(sigdel16write_class, (t_method)sigdel16write_dsp, + gensym("dsp"), 0); +} + +/* ----------------------------- del16read~ ----------------------------- */ +static t_class *sigdel16read_class; + +typedef struct _sigdel16read{ + t_object x_obj; + t_symbol *x_sym; + t_float x_deltime; /* delay in msec */ + int x_delsamps; /* delay in samples */ + t_float x_sr; /* samples per msec */ + t_float x_n; /* vector size */ + int x_zerodel; /* 0 or vecsize depending on read/write order */ +} t_sigdel16read; + +static void sigdel16read_16bit(t_sigdel16read *x, t_float f); + +static void *sigdel16read_new(t_symbol *s, t_floatarg f){ + t_sigdel16read *x = (t_sigdel16read *)pd_new(sigdel16read_class); + x->x_sym = s; + x->x_sr = 1; + x->x_n = 1; + x->x_zerodel = 0; + sigdel16read_16bit(x, f); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static void sigdel16read_16bit(t_sigdel16read *x, t_float f){ + t_sigdel16write *delwriter = + (t_sigdel16write *)pd_findbyclass(x->x_sym, sigdel16write_class); + x->x_deltime = f; + if (delwriter) { + x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime) + + x->x_n - x->x_zerodel; + if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n; + else if (x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS) + x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS; + } +} + +static t_int *sigdel16read_perform(t_int *w){ + t_float *out = (t_float *)(w[1]); + t_del16writectl *c = (t_del16writectl *)(w[2]); + int delsamps = *(int *)(w[3]); + int n = (int)(w[4]); + int phase = c->c_phase - delsamps, nsamps = c->c_n; + t_iem16_16bit *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); + + if (phase < 0) phase += nsamps; + bp = vp + phase; + while (n--) { + *out++ = *bp++*IEM16_SCALE_DOWN; + if (bp == ep) bp -= nsamps; + } + return (w+5); +} + +static void sigdel16read_dsp(t_sigdel16read *x, t_signal **sp){ + t_sigdel16write *delwriter = + (t_sigdel16write *)pd_findbyclass(x->x_sym, sigdel16write_class); + x->x_sr = sp[0]->s_sr * 0.001; + x->x_n = sp[0]->s_n; + if (delwriter) { + sigdel16write_checkvecsize(delwriter, sp[0]->s_n); + x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? + 0 : delwriter->x_vecsize); + sigdel16read_16bit(x, x->x_deltime); + dsp_add(sigdel16read_perform, 4, + sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n); + } + else if (*x->x_sym->s_name) + error("delread~: %s: no such delwrite~",x->x_sym->s_name); +} + +static void sigdel16read_setup(void){ + sigdel16read_class = class_new(gensym("del16read~"), + (t_newmethod)sigdel16read_new, 0, + sizeof(t_sigdel16read), 0, A_DEFSYM, A_DEFFLOAT, 0); + class_addmethod(sigdel16read_class, (t_method)sigdel16read_dsp, + gensym("dsp"), 0); + class_addfloat(sigdel16read_class, (t_method)sigdel16read_16bit); +} + + +/* ----------------------------- vd~ ----------------------------- */ +static t_class *sig16vd_class; + +typedef struct _sig16vd{ + t_object x_obj; + t_symbol *x_sym; + t_float x_sr; /* samples per msec */ + int x_zerodel; /* 0 or vecsize depending on read/write order */ + float x_f; +} t_sig16vd; + +static void *sig16vd_new(t_symbol *s){ + t_sig16vd *x = (t_sig16vd *)pd_new(sig16vd_class); + if (!*s->s_name) s = gensym("vd~"); + x->x_sym = s; + x->x_sr = 1; + x->x_zerodel = 0; + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); +} + +static t_int *sig16vd_perform(t_int *w){ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_del16writectl *ctl = (t_del16writectl *)(w[3]); + t_sig16vd *x = (t_sig16vd *)(w[4]); + int n = (int)(w[5]); + + int nsamps = ctl->c_n; + float limit = nsamps - n - 1; + float fn = n-4; + t_iem16_16bit *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase; + float zerodel = x->x_zerodel; + while (n--) { + float delsamps = x->x_sr * *in++ - zerodel, frac; + int idelsamps; + float a, b, c, d, cminusb; + if (delsamps < 1.00001f) delsamps = 1.00001f; + if (delsamps > limit) delsamps = limit; + delsamps += fn; + fn = fn - 1.0f; + idelsamps = delsamps; + frac = delsamps - (float)idelsamps; + bp = wp - (idelsamps + 3); + if (bp < vp + 4) bp += nsamps; + d = bp[-3]*IEM16_SCALE_DOWN; + c = bp[-2]*IEM16_SCALE_DOWN; + b = bp[-1]*IEM16_SCALE_DOWN; + a = bp[00]*IEM16_SCALE_DOWN; + cminusb = c-b; + *out++ = b + frac * ( + cminusb - 0.5f * (frac-1.) * ( + (a - d + 3.0f * cminusb) * frac + (b - a - cminusb) + ) + ); + } + return (w+6); +} + +static void sig16vd_dsp(t_sig16vd *x, t_signal **sp){ + t_sigdel16write *delwriter = + (t_sigdel16write *)pd_findbyclass(x->x_sym, sigdel16write_class); + x->x_sr = sp[0]->s_sr * 0.001; + if (delwriter) { + sigdel16write_checkvecsize(delwriter, sp[0]->s_n); + x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? + 0 : delwriter->x_vecsize); + dsp_add(sig16vd_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, + &delwriter->x_cspace, x, sp[0]->s_n); + } + else error("vd~: %s: no such delwrite~",x->x_sym->s_name); +} + +static void sig16vd_setup(void){ + sig16vd_class = class_new(gensym("vd16~"), (t_newmethod)sig16vd_new, 0, + sizeof(t_sig16vd), 0, A_DEFSYM, 0); + class_addmethod(sig16vd_class, (t_method)sig16vd_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(sig16vd_class, t_sig16vd, x_f); +} + +/* ----------------------- global setup routine ---------------- */ + +void iem16_delay_setup(void){ + sigdel16write_setup(); + sigdel16read_setup(); + sig16vd_setup(); +} + diff --git a/src/iem16_table.c b/src/iem16_table.c new file mode 100644 index 0000000..f43e2bb --- /dev/null +++ b/src/iem16_table.c @@ -0,0 +1,141 @@ +/* copyleft (c) 2003 forum::für::umläute -- IOhannes m zmölnig @ IEM + * based on d_array.c from pd: + * Copyright (c) 1997-1999 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sampling */ + +#include "iem16_table.h" +static void table16_const(t_table16*x, t_float f); + +static void *table16_new(t_symbol *s, t_float f){ + t_table16 *x = (t_table16*)pd_new(table16_class); + int i=f; + if(i<1)i=100; + x->x_tablename=s; + x->x_size=i; + x->x_table=getbytes(x->x_size*sizeof(t_iem16_16bit)); + x->x_usedindsp=0; + pd_bind(&x->x_obj.ob_pd, x->x_tablename); + + table16_const(x, 0); + return(x); +} + +static void table16_free(t_table16 *x){ + if(x->x_table)freebytes(x->x_table, x->x_size*sizeof(t_iem16_16bit)); + pd_unbind(&x->x_obj.ob_pd, x->x_tablename); +} + +int table16_getarray16(t_table16*x, int*size,t_iem16_16bit**vec){ + *size=x->x_size; + *vec =x->x_table; + return 1; +} +void table16_usedindsp(t_table16*x){ + x->x_usedindsp=1; +} +static void table16_resize(t_table16*x, t_float f){ + int i=f; + int was=x->x_size; + if (i<1){ + error("can only resize to sizes >0"); + return; + } + x->x_table=resizebytes(x->x_table, was*sizeof(t_iem16_16bit), i*sizeof(t_iem16_16bit)); + if(i>was)memset(x->x_table+was, 0, (i-was)*sizeof(t_iem16_16bit)); + x->x_size =i; + if (x->x_usedindsp) canvas_update_dsp(); +} + +static void table16_const(t_table16*x, t_float f){ + t_iem16_16bit s = (t_iem16_16bit)f; + int i = x->x_size; + t_iem16_16bit*buf=x->x_table; + while(i--)*buf++=s; +} + + +static void table16_from(t_table16*x, t_symbol*s, int argc, t_atom*argv){ + float scale=IEM16_SCALE_UP; + int resize=0; + int startfrom=0, startto=0, endfrom=0, endto=x->x_size; + t_garray *a=0; + int npoints; + t_float *vec, *src; + t_iem16_16bit *dest; + + int i,length=0; + + if(argc<1 || argv->a_type!=A_SYMBOL){ + error("you have to specify the from-table !"); + return; + } + s=atom_getsymbol(argv); argc--;argv++; + if (!(a = (t_garray *)pd_findbyclass(s, garray_class))){ + error("%s: no such array", s->s_name); + return; + } else if (!garray_getfloatarray(a, &npoints, &vec)){ + error("%s: bad template for tabread4", s->s_name); + return; + } + + if(argc>0 && atom_getsymbol(argv+argc-1)==gensym("resize")){ + resize=1; + argc--; + } + endfrom=npoints; + + switch(argc){ + case 0:break; + case 4: + endto =atom_getfloat(argv+3); + case 3: + startto =atom_getfloat(argv+2); + case 2: + endfrom =atom_getfloat(argv+1); + case 1: + startfrom=atom_getfloat(argv); + break; + default: + error("table16: from [ [ [ []]]] [resize]"); + return; + } + if(startfrom<0)startfrom=0; + if (startto<0)startto=0; + if(endfrom<=startfrom)return; + if(endto <=startto) return; + + length=endfrom-startfrom; + if(resize){ + if(x->x_size < (startto+length))table16_resize(x, startto+length); + } else{ + if(x->x_size < (startto+length))length=x->x_size-startto; + } + endfrom=startfrom+length; + endto =startto+length; + + dest=x->x_table+startto; + src =vec+startfrom; + i=length; + while(i--)*dest++=(*src++)*scale; + post("from %s (%d, %d) --> (%d, %d)\tresize=%s", s->s_name, startfrom, endfrom, startto, endto, (resize)?"yes":"no"); +} + + +static void table16_setup(void){ + table16_class = class_new(gensym("table16"), + (t_newmethod)table16_new, (t_method)table16_free, + sizeof(t_table16), 0, A_DEFSYM, A_DEFFLOAT, 0); + class_addmethod(table16_class, (t_method)table16_resize, gensym("resize"), A_DEFFLOAT); + class_addmethod(table16_class, (t_method)table16_const, gensym("const"), A_DEFFLOAT); + class_addmethod(table16_class, (t_method)table16_from, gensym("from"), A_GIMME); +} + + +void iem16_table_setup(void) +{ + table16_setup(); +} + diff --git a/src/iem16_table.h b/src/iem16_table.h new file mode 100644 index 0000000..4810312 --- /dev/null +++ b/src/iem16_table.h @@ -0,0 +1,27 @@ +/* copyleft (c) 2003 forum::für::umläute -- IOhannes m zmölnig @ IEM + * based on d_array.c from pd: + * Copyright (c) 1997-1999 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sampling */ + +#include "iem16.h" +#include +/* ------------------------- table16 -------------------------- */ +/* a 16bit table */ + +t_class *table16_class; +typedef struct _table16 { + t_object x_obj; + + t_symbol *x_tablename; + long x_size; + t_iem16_16bit *x_table; // hold the data + + int x_usedindsp; +} t_table16; + + +EXTERN int table16_getarray16(t_table16*x, int*size,t_iem16_16bit**vec); +EXTERN void table16_usedindsp(t_table16*x); diff --git a/src/makefile b/src/makefile new file mode 100644 index 0000000..d8e6685 --- /dev/null +++ b/src/makefile @@ -0,0 +1,79 @@ +current: all + +# the IEM16-EXTERNAL-makefile +# everything is GnuGPL that should come with the iem16.tgz +# NO WARRANTIES FOR ANYTHING +# et cetera +# forum::für::umläute@IEM:2003 + +# make sure that the "m_pd.h" is somehow available either by putting it into this +# directory, by adding it's path to the INCLUDE-path or by putting it into an +# already included path, e.g. "/usr/local/include/" + +#these are the user adjustables : adjust them to fit into your system +# PD will install to $(DESTDIR)$(INSTALLL_PREFIX)$(PDLIBDIR), which is /usr/local/lib/pd +# by default +DESTDIR = +INSTALL_PREFIX = /usr +PDLIBDIR = /lib/pd +#these were the user adjustables + + +TARGETS = iem16 \ + iem16_table \ + iem16_array iem16_array_tilde \ + iem16_delay + +# ----------------------- LINUX ---------------------------- +.SUFFIXES: .pd_linux + + +LINUXOBJECTS = $(TARGETS:%=%.o) +ARCH = $(shell uname --machine) + +PD_DIR = $(DESTDIR)$(INSTALL_PREFIX)$(PDLIBDIR) + +ifeq (${ARCH},alpha) +AFLAGS = -mieee -mcpu=ev56 +endif + +LINCLUDE = + +$(LINUXOBJECTS): *.h + +#CFLAGS = -O2 -g -Wall $(LINCLUDE) $(UCFLAGS) $(AFLAGS) +CFLAGS = -O3 -g -Wall $(LINCLUDE) $(UCFLAGS) $(AFLAGS) + + +everything: clean all install distclean + +distclean: + touch dummy.o + touch dummy.pd_linux + touch dummy~ + touch _dummy + rm *.o *.pd_linux *~ _* + +clean: + touch dummy.o + touch dummy.pd_linux + rm *.o *.pd_linux + +all: $(LINUXOBJECTS) + + @echo :: $(LINUXOBJECTS) + + ld -export_dynamic -shared -o iem16.pd_linux *.o -lc -lm + strip --strip-unneeded iem16.pd_linux + +.c.pd_linux: + cc $(CFLAGS) -O2 -DPD -fPIC $(INCLUDE) -c -o $*.o $*.c + + +install: installdocs + install -d $(PD_DIR)/extra + install -m 644 iem16.pd_linux $(PD_DIR)/extra + +installdocs: + install -d $(PD_DIR)/doc/5.reference/iem16 + install -m644 ../examples/*.pd $(PD_DIR)/doc/5.reference/iem16 -- cgit v1.2.1