aboutsummaryrefslogtreecommitdiff
path: root/sndfiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'sndfiler/src')
-rwxr-xr-xsndfiler/src/Makefile95
-rwxr-xr-xsndfiler/src/Makefile.pd_main116
-rwxr-xr-xsndfiler/src/sndfiler.c504
3 files changed, 715 insertions, 0 deletions
diff --git a/sndfiler/src/Makefile b/sndfiler/src/Makefile
new file mode 100755
index 0000000..2b17d1c
--- /dev/null
+++ b/sndfiler/src/Makefile
@@ -0,0 +1,95 @@
+
+NAME=sndfiler
+CSYM=sndfiler
+
+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/home/tim/pd/devel_0_39/src
+
+LSTRIP = strip --strip-unneeded -R .note -R .comment
+
+.c.pd_linux:
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ cc -Wl,-export_dynamic --shared -o $*.pd_linux $*.o -lm -lsndfile
+# $(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..1b4c5ca
--- /dev/null
+++ b/sndfiler/src/Makefile.pd_main
@@ -0,0 +1,116 @@
+# ----------------------------------------------------------
+
+# adjust the next pathes to your system:
+
+# this should point to the directory which contains
+# m_pd.h and g_canvas.h
+PD_SCR = /home/holzi/pd-0.39-1/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/Georg/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
+
+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 $(THREADLIB_PATH)/threadlib.pd_linux
+
+.c.pd_linux:
+ $(CC) $(CC_UNIX) $(CC_FLAGS) $(INCLUDE) -o $*.o -c $*.c
+ $(LD) $(LD_FLAGS) $*.pd_linux $*.o $(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
+
+.c.pd_darwin:
+ $(CC) $(CC_FLAGS) $(CC_DARWIN) $(INCLUDE) -o $*.o -c $*.c
+ $(LD) $(LD_DARWIN) $*.pd_linux $*.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/sndfiler.c b/sndfiler/src/sndfiler.c
new file mode 100755
index 0000000..c1579ee
--- /dev/null
+++ b/sndfiler/src/sndfiler.c
@@ -0,0 +1,504 @@
+/*
+ *
+ * threaded soundfiler based on libsndfile
+ * 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.
+ */
+
+/* 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"
+
+/* forward declaration */
+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 */
+};
+
+#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 "stdlib.h"
+#include "sched.h" /* for thread priority */
+#include <string.h>
+
+/* for alloca */
+#ifdef MSW
+#include <malloc.h>
+#else
+#include "alloca.h"
+#endif
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+#include <sys/mman.h>
+#endif /* _POSIX_MEMLOCK */
+
+
+/************ forward declarations **************/
+
+#ifdef UNIX
+/* real-time flag, true if priority boosted */
+extern int sys_hipriority;
+#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;
+
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+} 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)
+{
+ while (1)
+ {
+ t_sfprocess * me;
+ pthread_cond_wait(&sndfiler_queue.cond, &sndfiler_queue.mutex);
+
+ 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();
+ pthread_mutex_init (&sndfiler_queue.mutex,NULL);
+ pthread_cond_init (&sndfiler_queue.cond,NULL);
+
+ // initialize thread
+ pthread_attr_init(&sf_attr);
+
+ sf_param.sched_priority=sched_get_priority_min(SCHED_OTHER);
+ pthread_attr_setschedparam(&sf_attr,&sf_param);
+
+#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);
+
+ pthread_cond_signal(&sndfiler_queue.cond);
+}
+
+static t_int sndfiler_synchonize(t_int * w);
+
+static void sndfiler_read_cb(t_sndfiler * x, int argc, t_atom* argv)
+{
+ int i, j;
+ int channel_count;
+ t_float** helper_arrays;
+
+ t_symbol* file;
+ t_garray ** arrays;
+
+ SNDFILE* sndfile;
+ SF_INFO info;
+
+ if (argc < 2)
+ {
+ pd_error(x, "usage: read soundfile array1 array2 ...");
+ return;
+ }
+
+ 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_garray * array = (t_garray *)pd_findbyclass(atom_getsymbolarg(i+1,
+ argc, argv), garray_class);
+
+ if (array)
+ arrays[i] = array;
+ else
+ {
+ pd_error(x, "%s: no such array", atom_getsymbolarg(i+1, argc, argv)->s_name);
+ return;
+ }
+ }
+
+ post("sndfiler: loading file ...");
+
+ sndfile = sf_open(file->s_name, SFM_READ, &info);
+
+ if (sndfile)
+ {
+ int maxchannels = (channel_count < info.channels) ?
+ channel_count : info.channels;
+
+ t_float * item = alloca(maxchannels * sizeof(t_float));
+
+ t_int ** syncdata = getbytes(sizeof(t_int*) * 5);
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ munlockall();
+#endif
+
+ for (i = 0; i != channel_count; ++i)
+ {
+ helper_arrays[i] = getalignedbytes(info.frames * sizeof(t_float));
+ }
+
+ for (i = 0; i != info.frames; ++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];
+ }
+ }
+ }
+
+#if (_POSIX_MEMLOCK - 0) >= 200112L
+ mlockall(MCL_FUTURE);
+#endif
+
+ sf_close(sndfile);
+
+ syncdata[0] = (t_int*)arrays;
+ syncdata[1] = (t_int*)helper_arrays;
+ syncdata[2] = (t_int*)channel_count;
+ syncdata[3] = (t_int*)(long)info.frames;
+ syncdata[4] = (t_int*)x;
+
+ sys_callback(sndfiler_synchonize, (t_int*)syncdata, 5);
+ }
+ else
+ pd_error(x, "Error opening file");
+}
+
+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);
+
+ pthread_cond_signal(&sndfiler_queue.cond);
+}
+
+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");
+}
+
+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();
+}