aboutsummaryrefslogtreecommitdiff
path: root/sndfiler
diff options
context:
space:
mode:
Diffstat (limited to 'sndfiler')
-rw-r--r--sndfiler/GnuGPL.txt290
-rwxr-xr-xsndfiler/INSTALL55
-rwxr-xr-xsndfiler/README24
-rw-r--r--sndfiler/build/config-lnx.def1
-rw-r--r--sndfiler/build/config-mac.def1
-rw-r--r--sndfiler/build/config-win.def5
-rw-r--r--sndfiler/build/gnumake-lnx-gcc.inc1
-rw-r--r--sndfiler/build/gnumake-mac-gcc.inc1
-rw-r--r--sndfiler/build/gnumake-win-cygwin.inc3
-rw-r--r--sndfiler/build/gnumake-win-mingw.inc3
-rw-r--r--sndfiler/build/nmake-win-msvc.inc3
-rw-r--r--sndfiler/doc/sndfiler-help.pd54
-rw-r--r--sndfiler/package.txt4
-rwxr-xr-xsndfiler/src/Makefile98
-rwxr-xr-xsndfiler/src/Makefile.pd_main122
-rw-r--r--sndfiler/src/file_input.c253
-rw-r--r--sndfiler/src/file_input.h66
-rw-r--r--sndfiler/src/sndfiler.c498
-rw-r--r--sndfiler/src/sndfiler.h87
19 files changed, 1569 insertions, 0 deletions
diff --git a/sndfiler/GnuGPL.txt b/sndfiler/GnuGPL.txt
new file mode 100644
index 0000000..fa0bef4
--- /dev/null
+++ b/sndfiler/GnuGPL.txt
@@ -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/sndfiler/INSTALL b/sndfiler/INSTALL
new file mode 100755
index 0000000..8aa5e6a
--- /dev/null
+++ b/sndfiler/INSTALL
@@ -0,0 +1,55 @@
+
+[sndfiler] installation instructions:
+
+-------------------------------------------------------
+ MAIN PD
+-------------------------------------------------------
+
+- INSTALLATION:
+
+1) first install threadlib, get it from
+ http://grh.mur.at/software/threadlib.html
+
+2) download binaries for your platform at
+ http://grh.mur.at/software/sndfiler.html
+
+3) WIN: copy sndfiler.dll to path\to\pd\extra
+ copy libsndfile.dll to windows\system
+
+ LINUX: copy sndfiler.pd_linux to path/to/pd/extra
+ install libsndfile (via apt-get or something
+ similar)
+
+ MAC: copy sndfiler.pd_darwin to path/to/pd/extra
+ install libsndfile
+
+4) copy helpfile to path/to/pd/doc/5.reference
+
+- COMPILATION:
+
+1) install libsndfile on your platform
+
+2) adapt the pathes in src/Makefile.pd_main to fit into
+ your system
+
+3) make -f Makefile.pd_main pd_linux/pd_darwin/pd_win
+ (windows: you will need MinGW !)
+
+4) make -f Makefile.pd_main install
+
+-------------------------------------------------------
+ PD DEVEL
+-------------------------------------------------------
+
+- COMPILATION:
+
+1) install libsndfile on your platform
+
+2) adapt src/Makefile to fit into your system
+
+3) make pd_linux/pd_darwin/pd_nt
+
+-------------------------------------------------------
+
+in case of problems:
+grh@mur.at
diff --git a/sndfiler/README b/sndfiler/README
new file mode 100755
index 0000000..15995b3
--- /dev/null
+++ b/sndfiler/README
@@ -0,0 +1,24 @@
+
+[sndfiler]
+
+a threaded soundfiler for PD using libsndfile
+
+
+REQUIREMENTS:
+ - pd >= 0.39
+ - libsndfile
+ - for main PD you will also need threadlib:
+ http://grh.mur.at/software/threadlib.html
+
+FEATURES:
+ - threaded reading of multichannel soundfiles into arrays
+ - threaded resize of arrays
+
+
+For more information look at the help patch !
+
+See the file INSTALL for installation instructions.
+
+
+(C) 2005, Tim Blechmann <TimBlechmann@gmx.de>,
+ Georg Holzmann <grh@mur.at>
diff --git a/sndfiler/build/config-lnx.def b/sndfiler/build/config-lnx.def
new file mode 100644
index 0000000..fc37b7e
--- /dev/null
+++ b/sndfiler/build/config-lnx.def
@@ -0,0 +1 @@
+# nothing to set
diff --git a/sndfiler/build/config-mac.def b/sndfiler/build/config-mac.def
new file mode 100644
index 0000000..fc37b7e
--- /dev/null
+++ b/sndfiler/build/config-mac.def
@@ -0,0 +1 @@
+# nothing to set
diff --git a/sndfiler/build/config-win.def b/sndfiler/build/config-win.def
new file mode 100644
index 0000000..bd7bf72
--- /dev/null
+++ b/sndfiler/build/config-win.def
@@ -0,0 +1,5 @@
+# where is the libsndfile installation?
+SNDFILEPATH=%programfiles%\libsndfile
+
+SNDFILEINC=$(SNDFILEPATH)\src
+SNDFILELIB=$(SNDFILEPATH)
diff --git a/sndfiler/build/gnumake-lnx-gcc.inc b/sndfiler/build/gnumake-lnx-gcc.inc
new file mode 100644
index 0000000..3314475
--- /dev/null
+++ b/sndfiler/build/gnumake-lnx-gcc.inc
@@ -0,0 +1 @@
+LIBS += -lsndfile
diff --git a/sndfiler/build/gnumake-mac-gcc.inc b/sndfiler/build/gnumake-mac-gcc.inc
new file mode 100644
index 0000000..3314475
--- /dev/null
+++ b/sndfiler/build/gnumake-mac-gcc.inc
@@ -0,0 +1 @@
+LIBS += -lsndfile
diff --git a/sndfiler/build/gnumake-win-cygwin.inc b/sndfiler/build/gnumake-win-cygwin.inc
new file mode 100644
index 0000000..3b7c000
--- /dev/null
+++ b/sndfiler/build/gnumake-win-cygwin.inc
@@ -0,0 +1,3 @@
+INCPATH += -I$(SNDFILEINC)
+LIBPATH += -L$(SNDFILELIB)
+LIBS += -lsndfile
diff --git a/sndfiler/build/gnumake-win-mingw.inc b/sndfiler/build/gnumake-win-mingw.inc
new file mode 100644
index 0000000..3b7c000
--- /dev/null
+++ b/sndfiler/build/gnumake-win-mingw.inc
@@ -0,0 +1,3 @@
+INCPATH += -I$(SNDFILEINC)
+LIBPATH += -L$(SNDFILELIB)
+LIBS += -lsndfile
diff --git a/sndfiler/build/nmake-win-msvc.inc b/sndfiler/build/nmake-win-msvc.inc
new file mode 100644
index 0000000..9b832cc
--- /dev/null
+++ b/sndfiler/build/nmake-win-msvc.inc
@@ -0,0 +1,3 @@
+INCPATH=$(INCPATH) /I$(SNDFILEINC)
+LIBPATH=$(LIBPATH) /LIBPATH:$(SNDFILELIB)
+LIBS=$(LIBS) libsndfile.lib
diff --git a/sndfiler/doc/sndfiler-help.pd b/sndfiler/doc/sndfiler-help.pd
new file mode 100644
index 0000000..1e4dbeb
--- /dev/null
+++ b/sndfiler/doc/sndfiler-help.pd
@@ -0,0 +1,54 @@
+#N canvas 135 0 465 772 10;
+#X obj 29 23 cnv 15 404 54 empty empty empty 22 25 0 18 -1 -66577 0
+;
+#X obj 31 25 cnv 15 400 50 empty empty sndfiler 22 25 0 18 -228992
+-66577 0;
+#X obj 55 667 print THREADED_SF;
+#X obj 55 622 r \$0-tsf;
+#X obj 48 440 openpanel;
+#X obj 48 484 s \$0-tsf;
+#X obj 48 420 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 241 645 table array1;
+#X text 69 419 <- read;
+#X obj 239 566 s \$0-tsf;
+#X msg 239 540 resize array1 4410;
+#X text 46 386 for mono files:;
+#X obj 239 442 openpanel;
+#X obj 239 486 s \$0-tsf;
+#X obj 239 422 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 260 421 <- read;
+#X text 235 386 for multichannel specify;
+#X text 237 399 more arrays:;
+#X msg 239 464 read \$1 array1 array2;
+#X obj 241 667 table array2;
+#X obj 55 645 sndfiler;
+#X text 288 34 threaded soundfiler;
+#X text 161 113 ::: SNDFILER :::;
+#X text 65 182 REQUIREMENTS:;
+#X text 118 199 - pd >= 0.39;
+#X text 118 231 - threadlib (for main pd);
+#X text 48 539 threaded resize of arrays:;
+#X text 33 267 read a file: read [flags] filename array1 array2 ...
+;
+#X msg 48 462 read -resize \$1 array1;
+#X text 32 287 FLAGS:;
+#X text 32 305 -resize: resize the array(s) to the size of the soundfile
+;
+#X text 33 324 -skip <sample>: skip nr. of samples in soundfile \,
+if negative \, it will be counted from the end of the file !;
+#X text 82 722 (c) 2005 \, Tim Blechmann \, Georg Holzmann;
+#X text 184 53 using libsndfile and libvorbisfile;
+#X text 53 140 A threaded soundfiler for PD using libsndfile and libvorbisfile
+(for ogg files).;
+#X text 118 215 - libsndfile + libvorbisfile;
+#X connect 3 0 20 0;
+#X connect 4 0 28 0;
+#X connect 6 0 4 0;
+#X connect 10 0 9 0;
+#X connect 12 0 18 0;
+#X connect 14 0 12 0;
+#X connect 18 0 13 0;
+#X connect 20 0 2 0;
+#X connect 28 0 5 0;
diff --git a/sndfiler/package.txt b/sndfiler/package.txt
new file mode 100644
index 0000000..8f4281e
--- /dev/null
+++ b/sndfiler/package.txt
@@ -0,0 +1,4 @@
+NAME=sndfiler
+SRCDIR=src
+SRCS=sndfiler.c
+BUILDDIR=build
diff --git a/sndfiler/src/Makefile b/sndfiler/src/Makefile
new file mode 100755
index 0000000..3bcd658
--- /dev/null
+++ b/sndfiler/src/Makefile
@@ -0,0 +1,98 @@
+
+NAME=sndfiler
+CSYM=sndfiler
+
+OBJ=sndfiler.o file_input.o
+
+current: pd_linux
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I..\..\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ ..\..\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I../../src
+
+.c.pd_irix5:
+ $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -Ofast=ip32
+
+.c.pd_irix6:
+ $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -DPD -O3 -fPIC -funroll-loops -fomit-frame-pointer \
+ -Wall -W -Wshadow -Wstrict-prototypes -Werror \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+LINUXINCLUDE = -I../../../../pd/src
+
+LSTRIP = strip --strip-unneeded -R .note -R .comment
+
+.c.pd_linux:
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o sndfiler.o -c sndfiler.c
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o file_input.o -c file_input.c
+ cc -Wl,--export-dynamic --shared -o $*.pd_linux $(OBJ) -lm -lsndfile -lvorbisfile
+# $(LSTRIP) $*.pd_linux
+ rm -f $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: $(NAME).pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.pd_darwin:
+ $(CC) $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ $(CC) -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o
+
+# ----------------------------------------------------------
+
+clean:
+ rm -f *.o *.pd_darwin *.pd_linux *.dll so_locations
diff --git a/sndfiler/src/Makefile.pd_main b/sndfiler/src/Makefile.pd_main
new file mode 100755
index 0000000..29bde80
--- /dev/null
+++ b/sndfiler/src/Makefile.pd_main
@@ -0,0 +1,122 @@
+# ----------------------------------------------------------
+
+# adjust the next pathes to your system:
+
+# this should point to the directory which contains
+# m_pd.h and g_canvas.h
+PD_SCR = /usr/local/src/pd/src
+#PD_SCR = c:/pd/src
+
+# this is the pd directory, usually /usr/lib/pd
+# or c:/pd etc.
+PD_PATH = /usr/lib/pd
+#PD_PATH = c:/pd
+
+# path of sndfile.h from libsndfile, usually it's in
+# /usr/include and so detected automatically
+SNDFILE_SRC = /usr/include
+
+# the directory, where libsndfile is located
+# (in linux it' normally not necessary, in windows it's
+# normally in c:/windwos/system or so)
+#SNDFILE_PATH = c:/windows/system
+
+# path to threadlib.h
+THREADLIB_SRC = /home/holzi/pd-cvs/externals/grh/threadlib/src
+#THREADLIB_SRC = c:/Georg/pd-cvs/externals/grh/threadlib/src
+
+# path to threadlib.pd_linux/dll/pd_darwin
+# (usually path/to/pd/extra)
+THREADLIB_PATH = $(PD_PATH)/extra
+
+# ----------------------------------------------------------
+
+NAME=sndfiler
+
+CC = gcc
+LD = gcc
+INCLUDE= -I. -I$(PD_SCR) -I$(SNDFILE_SRC) -I$(THREADLIB_SRC)
+CC_FLAGS = -DPD -DUSE_PD_MAIN -O3 -funroll-loops \
+ -Wall -W -Wshadow -Wno-parentheses -Wno-switch \
+ -Wno-unused -fomit-frame-pointer
+LD_FLAGS = --export-dynamic -shared -o
+
+OBJ=sndfiler.o file_input.o
+
+current:
+ @echo ----------------------------
+ @echo USAGE:
+ @echo linux: make pd_linux
+ @echo windows: make pd_win
+ @echo darwin: make pd_darwin
+ @echo ----------------------------
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux
+
+.SUFFIXES: .pd_linux
+
+CC_UNIX = -DUNIX -fPIC -pthread
+LIB_UNIX = -lc -lm -lsndfile -lvorbisfile $(THREADLIB_PATH)/threadlib.pd_linux
+
+.c.pd_linux:
+ $(CC) $(CC_UNIX) $(CC_FLAGS) $(INCLUDE) -o sndfiler.o -c sndfiler.c
+ $(CC) $(CC_UNIX) $(CC_FLAGS) $(INCLUDE) -o file_input.o -c file_input.c
+ $(LD) $(LD_FLAGS) $*.pd_linux $(OBJ) $(LIB_UNIX)
+ strip --strip-unneeded $*.pd_linux
+ chmod 755 $*.pd_linux
+ @test -d ../bin || mkdir -p ../bin
+ cp $*.pd_linux ../bin
+ rm -f $*.o
+
+# ------------------------ WIN MinGW -----------------------
+
+pd_win: $(NAME).dll
+
+.SUFFIXES: .dll
+
+CC_WIN = -DMSW -mms-bitfields
+LIB_WIN = $(PD_PATH)/bin/pd.dll \
+ $(SNDFILE_PATH)/pthreadGC.dll \
+ $(SNDFILE_PATH)/libsndfile.dll \
+ $(THREADLIB_PATH)/threadlib.dll
+
+.c.dll:
+ $(CC) $(CC_WIN) $(CC_FLAGS) $(INCLUDE) -o $*.o -c $*.c
+ $(LD) $(LD_FLAGS) $*.dll $*.o $(LIB_WIN)
+ strip --strip-unneeded $*.dll
+ chmod 755 $*.dll
+ @test -d ../bin || mkdir -p ../bin
+ cp $*.dll ../bin
+ rm -f $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: $(NAME).pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+CC_DARWIN = -pthread
+LD_DARWIN = -bundle -undefined suppress -flat_namespace \
+ -bundle_loader $(PD_PATH)/bin/pd --export-dynamic \
+ -L/sw/lib -L/opt/local/lib -lsndfile -lvorbisfile \
+ $(THREADLIB_PATH)/threadlib.pd_darwin
+
+.c.pd_darwin:
+ $(CC) $(CC_UNIX) $(CC_FLAGS) $(INCLUDE) -o sndfiler.o -c sndfiler.c
+ $(CC) $(CC_UNIX) $(CC_FLAGS) $(INCLUDE) -o file_input.o -c file_input.c
+ $(LD) $(LD_DARWIN) -o $*.pd_darwin $*.o $(LIB)
+ chmod 755 $*.pd_darwin
+ @test -d ../bin || mkdir -p ../bin
+ cp $*.pd_darwin ../bin
+ rm -f $*.o
+
+# ----------------------------------------------------------
+
+clean:
+ rm -f *.o *.pd_darwin *.pd_linux *.dll
+
+install:
+ install ../bin/$(NAME).* $(PD_PATH)/extra
+ install ../doc/*.pd $(PD_PATH)/doc/5.reference
diff --git a/sndfiler/src/file_input.c b/sndfiler/src/file_input.c
new file mode 100644
index 0000000..79ad27e
--- /dev/null
+++ b/sndfiler/src/file_input.c
@@ -0,0 +1,253 @@
+/*
+ * threaded soundfiler for PD
+ * Copyright (C) 2005, Georg Holzmann <grh@mur.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "sndfiler.h"
+#include "file_input.h"
+
+int check_fileformat(t_symbol* file)
+{
+ FILE *fp = NULL;
+ OggVorbis_File vorbisfile;
+
+ // partially opens a vorbis file to test for Vorbis-ness
+ if( !(fp = fopen(file->s_name, "r")) )
+ return -1;
+
+ if( ov_test(fp, &vorbisfile, NULL, 0) < 0 )
+ {
+ fclose(fp);
+ return USE_LIBSNDFILE;
+ }
+
+ ov_clear(&vorbisfile);
+ return USE_LIBVORBISFILE;
+}
+
+int read_libsndfile(t_float** helper_arrays, int channel_count, int seek,
+ int resize, int array_size, t_symbol* file)
+{
+ int arraysize = array_size;
+ int writesize = 0, i=0, j=0;
+ SNDFILE* sndfile;
+ SF_INFO info;
+
+ sndfile = sf_open(file->s_name, SFM_READ, &info);
+
+ if(!sndfile)
+ return -1;
+
+ int pos = 0;
+ int maxchannels = (channel_count < info.channels) ?
+ channel_count : info.channels;
+
+ t_float * item = alloca(maxchannels * sizeof(t_float));
+
+ // negative seek: offset from the end of the file
+ if(seek<0)
+ {
+ if(CHECK_SEEK(seek+info.frames, info.frames))
+ pos = sf_seek(sndfile, seek, SEEK_END);
+ else pos = -1;
+ }
+ if(seek>0)
+ {
+ if(CHECK_SEEK(seek, info.frames))
+ pos = sf_seek(sndfile, seek, SEEK_SET);
+ else pos = -1;
+ }
+ if(pos == -1)
+ {
+ sf_close(sndfile);
+ post("invalid seek in soundfile");
+ return -1;
+ }
+
+ if(resize)
+ {
+ writesize = (info.frames-pos);
+ arraysize = writesize;
+ }
+ else
+ writesize = (arraysize>(info.frames-pos)) ?
+ info.frames-pos : arraysize;
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ munlockall();
+#endif
+
+ for (i = 0; i != channel_count; ++i)
+ {
+ helper_arrays[i] = getalignedbytes(arraysize * sizeof(t_float));
+ }
+
+ for (i = 0; i != writesize; ++i)
+ {
+ sf_read_float(sndfile, item, info.channels);
+
+ for (j = 0; j != info.channels; ++j)
+ {
+ if (j < channel_count)
+ {
+ helper_arrays[j][i] = item[j];
+ }
+ }
+ }
+
+ // fill remaining elements with zero
+ if(!resize && (arraysize > (info.frames-pos)))
+ {
+ for (i = writesize; i != arraysize; ++i)
+ {
+ for (j = 0; j != info.channels; ++j)
+ {
+ if (j < channel_count)
+ {
+ helper_arrays[j][i] = 0;
+ }
+ }
+ }
+ }
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ mlockall(MCL_FUTURE);
+#endif
+
+ sf_close(sndfile);
+ return arraysize;
+}
+
+int read_libvorbisfile(t_float** helper_arrays, int channel_count, int seek,
+ int resize, int array_size, t_symbol* file)
+{
+ int arraysize = array_size;
+ int writesize = 0, i=0, j=0;
+ int pos=0, maxchannels=0, frames=0, frames_read=0;
+ int current_section=0, finished=0;
+ float **buftmp = NULL;
+ FILE *fp = NULL;
+ OggVorbis_File vorbisfile;
+ vorbis_info *info;
+
+ if( !(fp = fopen(file->s_name, "r")) )
+ return -1;
+
+ if( ov_open(fp, &vorbisfile, NULL, 0) < 0 )
+ {
+ fclose(fp);
+ return -1;
+ }
+
+ info = ov_info(&vorbisfile, -1);
+ frames = ov_pcm_total(&vorbisfile, -1);
+ if( !info || frames==OV_EINVAL )
+ {
+ ov_clear(&vorbisfile);
+ post("failed to get info about vorbis file");
+ return -1;
+ }
+
+ maxchannels = (channel_count < info->channels) ?
+ channel_count : info->channels;
+
+ // negative seek: offset from the end of the file
+ if(seek<0)
+ {
+ if(CHECK_SEEK(frames+seek, frames))
+ {
+ int ret = ov_pcm_seek(&vorbisfile, frames+seek);
+ if(ret!=0)
+ pos =-1;
+ else
+ pos = frames+seek;
+ }
+ else pos = -1;
+ }
+ if(seek>0)
+ {
+ if(CHECK_SEEK(seek, frames))
+ {
+ int ret = ov_pcm_seek(&vorbisfile, seek);
+ if(ret!=0)
+ pos =-1;
+ else
+ pos = seek;
+ }
+ else pos = -1;
+ }
+ if(pos == -1)
+ {
+ ov_clear(&vorbisfile);
+ post("invalid seek in vorbis file");
+ return -1;
+ }
+
+ if(resize)
+ {
+ writesize = (frames-pos);
+ arraysize = writesize;
+ }
+ else
+ writesize = (arraysize>(frames-pos)) ?
+ frames-pos : arraysize;
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ munlockall();
+#endif
+
+ for (i = 0; i != channel_count; ++i)
+ {
+ helper_arrays[i] = getalignedbytes(arraysize * sizeof(t_float));
+ }
+
+ for (i = 0; i != writesize; ++i)
+ {
+ int ret = ov_read_float(&vorbisfile, &buftmp, 1,
+ &current_section);
+ if(ret!=1)
+ post("wrong return type while ogg decoding!");
+
+ for (j = 0; j != channel_count; ++j)
+ {
+ helper_arrays[j][i] = buftmp[j][0];
+ }
+ }
+
+ // fill remaining elements with zero
+ if(!resize && (arraysize > (frames-pos)))
+ {
+ for (i = writesize; i != arraysize; ++i)
+ {
+ for (j = 0; j != info->channels; ++j)
+ {
+ if (j < channel_count)
+ {
+ helper_arrays[j][i] = 0;
+ }
+ }
+ }
+ }
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ mlockall(MCL_FUTURE);
+#endif
+
+ ov_clear(&vorbisfile);
+ return arraysize;
+}
diff --git a/sndfiler/src/file_input.h b/sndfiler/src/file_input.h
new file mode 100644
index 0000000..e5b5232
--- /dev/null
+++ b/sndfiler/src/file_input.h
@@ -0,0 +1,66 @@
+/*
+ * threaded soundfiler for PD
+ * Copyright (C) 2005, Georg Holzmann <grh@mur.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _FILE_INPUT__
+#define _FILE_INPUT__
+
+#define USE_LIBSNDFILE 0
+#define USE_LIBVORBISFILE 1
+
+//! returns 1 if s is in [0,c)
+#define CHECK_SEEK(s, c) (s<0 ? 0 : (s>=c ? 0 : 1))
+
+/*!
+ * checks which library to use
+ *
+ * @param file filename
+ * @return USE_LIBSNDFILE or USE_LIBVORBISFILE, -1 if there was an error
+ */
+int check_fileformat(t_symbol* file);
+
+/*!
+ * read audio data with libsndfile
+ *
+ * @param helper_arrays (unallocated) pointer to the data
+ * @param channel_count nr of channels
+ * @param seek frames to seek in file
+ * @param resize 1 if array should be resized
+ * @param array_size size of the array in samples
+ * @param file filename
+ * @return new arraysiize, -1 if there was a failure
+ */
+int read_libsndfile(t_float** helper_arrays, int channel_count, int seek,
+ int resize, int array_size, t_symbol* file);
+
+/*!
+ * read audio data with libvorbisfile
+ *
+ * @param helper_arrays (unallocated) pointer to the data
+ * @param channel_count nr of channels
+ * @param seek frames to seek in file
+ * @param resize 1 if array should be resized
+ * @param array_size size of the array in samples
+ * @param file filename
+ * @return new arraysiize, -1 if there was a failure
+ */
+int read_libvorbisfile(t_float** helper_arrays, int channel_count, int seek,
+ int resize, int array_size, t_symbol* file);
+
+#endif //_FILE_INPUT__
diff --git a/sndfiler/src/sndfiler.c b/sndfiler/src/sndfiler.c
new file mode 100644
index 0000000..4cd14d9
--- /dev/null
+++ b/sndfiler/src/sndfiler.c
@@ -0,0 +1,498 @@
+/*
+ *
+ * threaded soundfiler for pd
+ * Copyright (C) 2005, Tim Blechmann
+ * (C) 2005, Georg Holzmann <grh@mur.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "sndfiler.h"
+#include "file_input.h"
+
+
+/************ forward declarations **************/
+
+#ifdef UNIX
+/* real-time flag, true if priority boosted */
+extern int sys_hipriority;
+#endif
+
+#ifdef USE_PD_MAIN
+struct _garray
+{
+ t_gobj x_gobj;
+ t_scalar *x_scalar; /* scalar "containing" the array */
+ t_glist *x_glist; /* containing glist */
+ t_symbol *x_name; /* unexpanded name (possibly with leading '$') */
+ t_symbol *x_realname; /* expanded name (symbol we're bound to) */
+ char x_usedindsp; /* true if some DSP routine is using this */
+ char x_saveit; /* true if we should save this with parent */
+ char x_listviewing; /* true if list view window is open */
+};
+#endif
+
+/* get a garray's "array" structure. */
+t_array *h_garray_getarray(t_garray *x)
+{
+ int zonset, ztype;
+ t_symbol *zarraytype;
+ t_scalar *sc = x->x_scalar;
+ t_symbol *templatesym = sc->sc_template;
+ t_template *_template = template_findbyname(templatesym);
+ if (!_template)
+ {
+ error("array: couldn't find template %s", templatesym->s_name);
+ return (0);
+ }
+ if (!template_find_field(_template, gensym("z"),
+ &zonset, &ztype, &zarraytype))
+ {
+ error("array: template %s has no 'z' field", templatesym->s_name);
+ return (0);
+ }
+ if (ztype != DT_ARRAY)
+ {
+ error("array: template %s, 'z' field is not an array",
+ templatesym->s_name);
+ return (0);
+ }
+ return (sc->sc_vec[zonset].w_array);
+}
+
+
+/************ sndfiler **************/
+
+static t_class *sndfiler_class;
+
+typedef struct _sndfiler
+{
+ t_object x_obj;
+ t_canvas *x_canvas;
+} t_sndfiler;
+
+typedef struct _sfprocess
+{
+ void* padding;
+ /* callback function */
+ void (* process) (t_sndfiler *, int, t_atom *);
+ t_sndfiler * x; /* soundfiler */
+ int argc;
+ t_atom * argv;
+} t_sfprocess;
+
+/* this is the queue for all soundfiler objects */
+typedef struct _sfqueue
+{
+ t_fifo* x_jobs;
+ SEM_T sem;
+} t_sfqueue;
+
+typedef struct _syncdata
+{
+ t_garray** arrays;
+ t_float** helper_arrays;
+ int argc;
+ t_int frames;
+} t_syncdata;
+
+static t_sfqueue sndfiler_queue;
+static pthread_t sf_thread_id; /* id of soundfiler thread */
+
+static t_sndfiler *sndfiler_new(void)
+{
+ t_sndfiler *x = (t_sndfiler *)pd_new(sndfiler_class);
+ x->x_canvas = canvas_getcurrent();
+ outlet_new(&x->x_obj, &s_float);
+ return (x);
+}
+
+/* global soundfiler thread ... sleeping until signaled */
+static void sndfiler_thread(void)
+{
+ for(;;)
+ {
+ t_sfprocess * me;
+ SEM_WAIT(sndfiler_queue.sem);
+
+ while (me = (t_sfprocess *)fifo_get(sndfiler_queue.x_jobs))
+ {
+ (me->process)(me->x, me->argc, me->argv);
+
+ /* freeing the argument vector */
+ freebytes(me->argv, sizeof(t_atom) * me->argc);
+ freebytes(me, sizeof(t_sfprocess));
+ }
+ }
+}
+
+static void sndfiler_start_thread(void)
+{
+ pthread_attr_t sf_attr;
+ struct sched_param sf_param;
+ int status;
+
+ //initialize queue
+ sndfiler_queue.x_jobs = fifo_init();
+
+ status = SEM_INIT(sndfiler_queue.sem);
+ if(!status)
+ error("Couldn't create sndfiler semaphore: %i",status);
+
+ // initialize thread
+ pthread_attr_init(&sf_attr);
+
+ sf_param.sched_priority=sched_get_priority_min(SCHED_OTHER);
+ pthread_attr_setschedparam(&sf_attr,&sf_param);
+
+ /* 1mb of stack should be enough */
+ pthread_attr_setstacksize(&sf_attr,1048576);
+
+#ifdef UNIX
+ if (sys_hipriority == 1/* && getuid() == 0 */)
+ {
+ sf_param.sched_priority=sched_get_priority_min(SCHED_RR);
+ pthread_attr_setschedpolicy(&sf_attr,SCHED_RR);
+ }
+#endif /* UNIX */
+
+ //start thread
+ status = pthread_create(&sf_thread_id, &sf_attr,
+ (void *) sndfiler_thread,NULL);
+
+ if (status != 0)
+ error("Couldn't create sndfiler thread: %d",status);
+ else
+ post("Global sndfiler thread launched, priority: %d",
+ sf_param.sched_priority);
+}
+
+static void sndfiler_read_cb(t_sndfiler * x, int argc, t_atom* argv);
+
+/* syntax:
+ * read soundfile array0..n
+ * if the soundfile has less channels than arrays are given, these arrays are
+ * set to zero
+ * if there are too little arrays given, only the first n channels will be used
+ * */
+static void sndfiler_read(t_sndfiler * x, t_symbol *s, int argc, t_atom* argv)
+{
+ t_sfprocess * process = getbytes(sizeof(t_sfprocess));
+
+ process->process = &sndfiler_read_cb;
+ process->x = x;
+ process->argc = argc;
+ process->argv = (t_atom*) copybytes(argv, sizeof(t_atom) * argc);
+
+ fifo_put(sndfiler_queue.x_jobs, process);
+
+ SEM_SIGNAL(sndfiler_queue.sem);
+}
+
+static t_int sndfiler_synchonize(t_int * w);
+
+static void sndfiler_read_cb(t_sndfiler * x, int argc, t_atom* argv)
+{
+ int i, j, lib;
+ int channel_count;
+ t_float** helper_arrays;
+ int resize = 0;
+ int seek = 0, arraysize = 0;
+
+ t_symbol* file;
+ t_garray ** arrays;
+
+ // parse flags
+ while (argc > 0 && argv->a_type == A_SYMBOL &&
+ *argv->a_w.w_symbol->s_name == '-')
+ {
+ char *flag = argv->a_w.w_symbol->s_name + 1;
+ if (!strcmp(flag, "resize"))
+ {
+ resize = 1;
+ argc -= 1; argv += 1;
+ }
+ else if (!strcmp(flag, "skip"))
+ {
+ if (argc < 2 || argv[1].a_type != A_FLOAT)
+ goto usage;
+ else
+ seek = argv[1].a_w.w_float;
+ argc -= 2; argv += 2;
+ }
+ else goto usage;
+ }
+
+ if (argc < 2)
+ goto usage;
+
+ file = atom_getsymbolarg(0, argc, argv);
+
+ channel_count = argc - 1;
+ helper_arrays = getbytes(channel_count * sizeof(t_float*));
+
+ arrays = getbytes(channel_count * sizeof(t_garray*));
+ for (i = 0; i != channel_count; ++i)
+ {
+ t_float *dummy;
+ int size;
+ t_garray *array;
+
+ if(!(array = (t_garray *)pd_findbyclass(
+ atom_getsymbolarg(i+1, argc, argv), garray_class)))
+ {
+ pd_error(x, "%s: no such array", atom_getsymbolarg(i+1,
+ argc, argv)->s_name);
+ return;
+ }
+
+ if(garray_getfloatarray(array, &size, &dummy))
+ arrays[i] = array;
+ else
+ {
+ pd_error(x, "%s: bad template for sndfiler", atom_getsymbolarg(i+1,
+ argc, argv)->s_name);
+ return;
+ }
+
+ // in multichannel mode: check if arrays have different length
+ if (arraysize && arraysize != size && !resize)
+ {
+ post("sndfiler: arrays have different lengths, resizing to last one ...");
+ }
+ arraysize = size;
+ }
+
+ lib = check_fileformat(file);
+ if(lib == USE_LIBSNDFILE)
+ arraysize = read_libsndfile(helper_arrays, channel_count, seek,
+ resize, arraysize, file);
+ else if(lib == USE_LIBVORBISFILE)
+ arraysize = read_libvorbisfile(helper_arrays, channel_count, seek,
+ resize, arraysize, file);
+ else
+ {
+ pd_error(x, "Error opening file");
+ return;
+ }
+
+ if(arraysize > 0)
+ {
+ t_int ** syncdata = getbytes(sizeof(t_int*) * 5);
+
+ syncdata[0] = (t_int*)arrays;
+ syncdata[1] = (t_int*)helper_arrays;
+ syncdata[2] = (t_int*)channel_count;
+ syncdata[3] = (t_int*)arraysize;
+ syncdata[4] = (t_int*)x;
+
+ sys_callback(sndfiler_synchonize, (t_int*)syncdata, 5);
+ return;
+ }
+ else
+ {
+ pd_error(x, "Error opening file");
+ return;
+ }
+
+ usage:
+ pd_error(x, "usage: read [flags] filename array1 array2 ...");
+ post("flags: -skip <n> -resize ");
+}
+
+static t_int sndfiler_synchonize(t_int * w)
+{
+ int i;
+ t_garray** arrays = (t_garray**) w[0];
+ t_float** helper_arrays = (t_float**) w[1];
+ t_int channel_count = (t_int)w[2];
+ t_int frames = (t_int)w[3];
+ t_sndfiler* x = (t_sndfiler*)w[4];
+
+ for (i = 0; i != channel_count; ++i)
+ {
+ t_garray * garray = arrays[i];
+ t_array * array = h_garray_getarray(garray);
+ t_glist * gl = garray->x_glist;;
+
+ freealignedbytes(array->a_vec, array->a_n);
+ array->a_vec = (char*)helper_arrays[i];
+ array->a_n = frames;
+
+ if (gl->gl_list == &garray->x_gobj && !garray->x_gobj.g_next)
+ {
+ vmess(&gl->gl_pd, gensym("bounds"), "ffff", 0., gl->gl_y1,
+ (double)(frames > 1 ? frames-1 : 1), gl->gl_y2);
+
+ /* close any dialogs that might have the wrong info now... */
+ gfxstub_deleteforkey(gl);
+ }
+ else
+ garray_redraw(garray);
+ }
+
+ free(arrays);
+ free(helper_arrays);
+
+ canvas_update_dsp();
+
+ outlet_float(x->x_obj.ob_outlet, frames);
+
+ return 0;
+}
+
+static void sndfiler_t_resize(t_sndfiler * y, int argc, t_atom* argv);
+
+/* syntax:
+ * resize table size
+ * */
+static void sndfiler_resize(t_sndfiler * x, t_symbol *s, int argc, t_atom* argv)
+{
+ t_sfprocess * process = getbytes(sizeof(t_sfprocess));
+
+ process->process = &sndfiler_t_resize;
+ process->x = x;
+ process->argc = argc;
+ process->argv = (t_atom*) copybytes(argv, sizeof(t_atom) * argc);
+
+ fifo_put(sndfiler_queue.x_jobs, process);
+
+ SEM_SIGNAL(sndfiler_queue.sem);
+}
+
+static void sndfiler_t_resize(t_sndfiler *y, int argc, t_atom *argv)
+{
+ int was, elemsize; /* array contains was elements of size elemsize */
+ t_float * vec; /* old array */
+ t_glist *gl;
+ int n; /* resize of n elements */
+ char *nvec; /* new array */
+
+ t_garray * x = (t_garray *)pd_findbyclass(argv[0].a_w.w_symbol, garray_class);
+ t_array *data = h_garray_getarray(x);
+
+ if (!(x))
+ {
+ pd_error(y, "%s: no such table", argv[0].a_w.w_symbol->s_name);
+ goto usage;
+ }
+
+ vec = (t_float*) data->a_vec;
+ was = data->a_n;
+
+ if ((argv+1)->a_type == A_FLOAT)
+ n = (int) (argv+1)->a_w.w_float;
+ else
+ goto usage;
+
+ if (n == was) return;
+
+ if (n < 1) n = 1;
+ elemsize = template_findbyname(data->a_templatesym)->t_n * sizeof(t_word);
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ munlockall();
+#endif
+
+ if (was > n)
+ nvec = (char*)copybytes(data->a_vec, was * elemsize);
+ else
+ {
+ nvec = getbytes(n * elemsize);
+ memcpy (nvec, data->a_vec, was * elemsize);
+
+ /* LATER should check t_resizebytes result */
+ memset(nvec + was*elemsize, 0, (n - was) * elemsize);
+ }
+
+ if (!nvec)
+ {
+ pd_error(x, "array resize failed: out of memory");
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ mlockall(MCL_FUTURE);
+#endif
+
+ return;
+ }
+
+ /* TB: we'll have to be sure that no one is accessing the array */
+ sys_lock();
+
+#ifdef GARRAY_THREAD_LOCK
+ garray_lock(x);
+#endif
+
+ data->a_vec = nvec;
+ data->a_n = n;
+
+#ifdef GARRAY_THREAD_LOCK
+ garray_unlock(x);
+#endif
+
+ if (x->x_usedindsp) canvas_update_dsp();
+ sys_unlock();
+
+ /* if this is the only array in the graph,
+ reset the graph's coordinates */
+ gl = x->x_glist;
+ if (gl->gl_list == &x->x_gobj && !x->x_gobj.g_next)
+ {
+ vmess(&gl->gl_pd, gensym("bounds"), "ffff",
+ 0., gl->gl_y1, (double)(n > 1 ? n-1 : 1), gl->gl_y2);
+ /* close any dialogs that might have the wrong info now... */
+ gfxstub_deleteforkey(gl);
+ }
+ else garray_redraw(x);
+
+ freebytes (vec, was * elemsize);
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ mlockall(MCL_FUTURE);
+#endif
+
+ sys_lock();
+ outlet_float(y->x_obj.ob_outlet, (float)atom_getintarg(1,argc,argv));
+ sys_unlock();
+
+ return;
+
+ usage:
+ pd_error(x, "usage: resize tablename size");
+}
+
+#ifdef _MSC_VER
+__declspec(dllexport)
+#endif
+void sndfiler_setup(void)
+{
+ sndfiler_class = class_new(gensym("sndfiler"),
+ (t_newmethod)sndfiler_new, 0,
+ sizeof(t_sndfiler), 0, 0);
+
+ class_addmethod(sndfiler_class, (t_method)sndfiler_read,
+ gensym("read"), A_GIMME, 0);
+ class_addmethod(sndfiler_class, (t_method)sndfiler_resize,
+ gensym("resize"), A_GIMME, 0);
+
+#ifdef USE_PD_MAIN
+ // needed to start thread callback system
+ threadlib_setup();
+#endif
+
+ // starts helper thread
+ sndfiler_start_thread();
+}
diff --git a/sndfiler/src/sndfiler.h b/sndfiler/src/sndfiler.h
new file mode 100644
index 0000000..f5fbd2c
--- /dev/null
+++ b/sndfiler/src/sndfiler.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * threaded soundfiler for pd
+ * Copyright (C) 2005, Tim Blechmann
+ * (C) 2005, Georg Holzmann <grh@mur.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SND_FILER__
+#define _SND_FILER__
+
+
+/* to be compatible with main pd */
+#ifdef USE_PD_MAIN
+
+#define getalignedbytes(a) getbytes(a)
+#define freealignedbytes(a,b) freebytes(a,b)
+#include "threadlib.h"
+
+#else /* now for pd_devel */
+
+#include "m_pd.h"
+#include "m_fifo.h"
+
+#include "pthread.h"
+
+#endif /* USE_PD_MAIN */
+
+
+#include "g_canvas.h"
+#include "sndfile.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisfile.h"
+
+#include "stdlib.h"
+#include <stdio.h>
+#include "sched.h" /* for thread priority */
+#include <string.h>
+#include "semaphore.h"
+
+#ifdef MSW
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+/* for alloca */
+#ifdef MSW
+#include <malloc.h>
+#else
+#include "alloca.h"
+#endif
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+#include <sys/mman.h>
+#endif /* _POSIX_MEMLOCK */
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#include <mach/task.h>
+#include <mach/semaphore.h>
+#define SEM_T semaphore_t
+#define SEM_INIT(s) (semaphore_create(mach_task_self(),&s,SYNC_POLICY_FIFO,0) == 0)
+#define SEM_SIGNAL(s) semaphore_signal(s)
+#define SEM_WAIT(s) semaphore_wait(s)
+#else
+#define SEM_T sem_t
+#define SEM_INIT(s) (sem_init(&s,0,0) == 0)
+#define SEM_SIGNAL(s) sem_post(&s)
+#define SEM_WAIT(s) sem_wait(&s)
+#endif
+
+
+#endif // _SND_FILER__