Merge pull request #869 from jpcima/puredata

External for puredata
This commit is contained in:
JP Cimalando 2021-04-30 08:24:48 +02:00 committed by GitHub
commit 9d8e184d05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1299 additions and 0 deletions

View file

@ -28,6 +28,7 @@ option_ex (SFIZZ_LV2_UI "Enable LV2 plug-in user interface" ON)
option_ex (SFIZZ_VST "Enable VST plug-in build" ON)
option_ex (SFIZZ_AU "Enable AU plug-in build" APPLE)
option_ex (SFIZZ_VST2 "Enable VST2 plug-in build (unsupported)" OFF)
option_ex (SFIZZ_PUREDATA "Enable Puredata plug-in build" OFF)
option_ex (SFIZZ_BENCHMARKS "Enable benchmarks build" OFF)
option_ex (SFIZZ_TESTS "Enable tests build" OFF)
option_ex (SFIZZ_DEMOS "Enable feature demos build" OFF)

View file

@ -0,0 +1,16 @@
find_path(PUREDATA_INCLUDE_DIR "m_pd.h" PATH_SUFFIXES "pd")
if(PUREDATA_INCLUDE_DIR)
message(STATUS "Puredata headers: ${PUREDATA_INCLUDE_DIR}")
else()
message(STATUS "Puredata headers not found, using our own")
set(PUREDATA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/plugins/puredata/external/pd/include")
endif()
if(WIN32)
set(PUREDATA_SUFFIX ".dll")
elseif(APPLE)
set(PUREDATA_SUFFIX ".pd_darwin")
else()
set(PUREDATA_SUFFIX ".pd_linux")
endif()

View file

@ -58,3 +58,7 @@ endif()
if(SFIZZ_VST OR SFIZZ_AU OR SFIZZ_VST2)
add_subdirectory(vst)
endif()
if(SFIZZ_PUREDATA)
add_subdirectory(puredata)
endif()

View file

@ -0,0 +1,38 @@
# Puredata plugin specific settings
include(PuredataConfig)
set(PUREDATA_BINARY_DIR "${PROJECT_BINARY_DIR}/pd/sfizz")
set(PUREDATA_RESOURCES
"sfizz~-help.pd"
"example.sfz")
function(copy_puredata_resources TARGET SOURCE_DIR DESTINATION_DIR)
set(_deps)
foreach(res ${PUREDATA_RESOURCES})
get_filename_component(_dir "${res}" DIRECTORY)
file(MAKE_DIRECTORY "${DESTINATION_DIR}/${_dir}")
add_custom_command(
OUTPUT "${DESTINATION_DIR}/${res}"
COMMAND "${CMAKE_COMMAND}" "-E" "copy"
"${SOURCE_DIR}/${res}" "${DESTINATION_DIR}/${res}"
DEPENDS "${SOURCE_DIR}/${res}")
list(APPEND _deps "${DESTINATION_DIR}/${res}")
endforeach()
add_custom_target("${TARGET}_puredata_resources" DEPENDS ${_deps})
add_dependencies("${TARGET}" "${TARGET}_puredata_resources")
endfunction()
add_library(sfizz_puredata MODULE sfizz_puredata.c)
target_include_directories(sfizz_puredata PRIVATE "${PUREDATA_INCLUDE_DIR}")
target_link_libraries(sfizz_puredata PRIVATE sfizz::sfizz)
set_target_properties(sfizz_puredata PROPERTIES
PREFIX ""
SUFFIX "${PUREDATA_SUFFIX}"
OUTPUT_NAME "sfizz"
LIBRARY_OUTPUT_DIRECTORY "${PUREDATA_BINARY_DIR}/$<0:>")
copy_puredata_resources(sfizz_puredata
"${CMAKE_CURRENT_SOURCE_DIR}"
"${PUREDATA_BINARY_DIR}")

View file

@ -0,0 +1,22 @@
<group>
ampeg_attack=0.25
ampeg_decay=5
ampeg_sustain=50
ampeg_release=2
fil_type=lpf_4p
resonance=3
cutoff=2000
oscillator_phase=-1
cutoff_oncc300=3600
cutoff_curvecc300=1
<region>
sample=*saw
oscillator_multi=3
oscillator_detune=10
lfo1_freq=5
lfo1_pitch=30
<region>
sample=*triangle
transpose=-12

View file

@ -0,0 +1,30 @@
This software is copyrighted by Miller Puckette and others. The following
terms (the "Standard Improved BSD License") apply to all files associated with
the software unless explicitly disclaimed in individual files:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,911 @@
/* 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. */
#ifndef __m_pd_h_
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif
#define PD_MAJOR_VERSION 0
#define PD_MINOR_VERSION 51
#define PD_BUGFIX_VERSION 4
#define PD_TEST_VERSION ""
extern int pd_compatibilitylevel; /* e.g., 43 for pd 0.43 compatibility */
/* old name for "MSW" flag -- we have to take it for the sake of many old
"nmakefiles" for externs, which will define NT and not MSW */
#if defined(NT) && !defined(MSW)
#define MSW
#endif
/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */
#ifdef _MSC_VER
/* #pragma warning( disable : 4091 ) */
#pragma warning( disable : 4305 ) /* uncast const double to float */
#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */
#pragma warning( disable : 4101 ) /* unused automatic variables */
#endif /* _MSC_VER */
/* the external storage class is "extern" in UNIX; in MSW it's ugly. */
#ifdef _WIN32
#ifdef PD_INTERNAL
#define EXTERN __declspec(dllexport) extern
#else
#define EXTERN __declspec(dllimport) extern
#endif /* PD_INTERNAL */
#else
#define EXTERN extern
#endif /* _WIN32 */
/* On most c compilers, you can just say "struct foo;" to declare a
structure whose elements are defined elsewhere. On MSVC, when compiling
C (but not C++) code, you have to say "extern struct foo;". So we make
a stupid macro: */
#if defined(_MSC_VER) && !defined(_LANGUAGE_C_PLUS_PLUS) \
&& !defined(__cplusplus)
#define EXTERN_STRUCT extern struct
#else
#define EXTERN_STRUCT struct
#endif
/* Define some attributes, specific to the compiler */
#if defined(__GNUC__)
#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b)))
#else
#define ATTRIBUTE_FORMAT_PRINTF(a, b)
#endif
#if !defined(_SIZE_T) && !defined(_SIZE_T_)
#include <stddef.h> /* just for size_t -- how lame! */
#endif
/* Microsoft Visual Studio is not C99, but since VS2015 has included most C99 headers:
https://docs.microsoft.com/en-us/previous-versions/hh409293(v=vs.140)#c-runtime-library
These definitions recreate stdint.h types, but only in pre-2015 Visual Studio: */
#if defined(_MSC_VER) && _MSC_VER < 1900
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
# include <stdint.h>
#endif
/* for FILE, needed by sys_fopen() and sys_fclose() only */
#include <stdio.h>
#define MAXPDSTRING 1000 /* use this for anything you want */
#define MAXPDARG 5 /* max number of args we can typecheck today */
/* signed and unsigned integer types the size of a pointer: */
#if !defined(PD_LONGINTTYPE)
#if defined(_WIN32) && defined(_WIN64)
#define PD_LONGINTTYPE long long
#else
#define PD_LONGINTTYPE long
#endif
#endif
#if !defined(PD_FLOATSIZE)
/* normally, our floats (t_float, t_sample,...) are 32bit */
# define PD_FLOATSIZE 32
#endif
#if PD_FLOATSIZE == 32
# define PD_FLOATTYPE float
/* an unsigned int of the same size as FLOATTYPE: */
# define PD_FLOATUINTTYPE uint32_t
#elif PD_FLOATSIZE == 64
# define PD_FLOATTYPE double
# define PD_FLOATUINTTYPE uint64_t
#else
# error invalid FLOATSIZE: must be 32 or 64
#endif
typedef PD_LONGINTTYPE t_int; /* pointer-size integer */
typedef PD_FLOATTYPE t_float; /* a float type at most the same size */
typedef PD_FLOATTYPE t_floatarg; /* float type for function calls */
typedef struct _symbol
{
const char *s_name;
struct _class **s_thing;
struct _symbol *s_next;
} t_symbol;
EXTERN_STRUCT _array;
#define t_array struct _array /* g_canvas.h */
/* pointers to glist and array elements go through a "stub" which sticks
around after the glist or array is freed. The stub itself is deleted when
both the glist/array is gone and the refcount is zero, ensuring that no
gpointers are pointing here. */
#define GP_NONE 0 /* the stub points nowhere (has been cut off) */
#define GP_GLIST 1 /* the stub points to a glist element */
#define GP_ARRAY 2 /* ... or array */
typedef struct _gstub
{
union
{
struct _glist *gs_glist; /* glist we're in */
struct _array *gs_array; /* array we're in */
} gs_un;
int gs_which; /* GP_GLIST/GP_ARRAY */
int gs_refcount; /* number of gpointers pointing here */
} t_gstub;
typedef struct _gpointer /* pointer to a gobj in a glist */
{
union
{
struct _scalar *gp_scalar; /* scalar we're in (if glist) */
union word *gp_w; /* raw data (if array) */
} gp_un;
int gp_valid; /* number which must match gpointee */
t_gstub *gp_stub; /* stub which points to glist/array */
} t_gpointer;
typedef union word
{
t_float w_float;
t_symbol *w_symbol;
t_gpointer *w_gpointer;
t_array *w_array;
struct _binbuf *w_binbuf;
int w_index;
} t_word;
typedef enum
{
A_NULL,
A_FLOAT,
A_SYMBOL,
A_POINTER,
A_SEMI,
A_COMMA,
A_DEFFLOAT,
A_DEFSYM,
A_DOLLAR,
A_DOLLSYM,
A_GIMME,
A_CANT
} t_atomtype;
#define A_DEFSYMBOL A_DEFSYM /* better name for this */
typedef struct _atom
{
t_atomtype a_type;
union word a_w;
} t_atom;
EXTERN_STRUCT _class;
#define t_class struct _class
EXTERN_STRUCT _outlet;
#define t_outlet struct _outlet
EXTERN_STRUCT _inlet;
#define t_inlet struct _inlet
EXTERN_STRUCT _binbuf;
#define t_binbuf struct _binbuf
EXTERN_STRUCT _clock;
#define t_clock struct _clock
EXTERN_STRUCT _outconnect;
#define t_outconnect struct _outconnect
EXTERN_STRUCT _glist;
#define t_glist struct _glist
#define t_canvas struct _glist /* LATER lose this */
EXTERN_STRUCT _template;
typedef t_class *t_pd; /* pure datum: nothing but a class pointer */
typedef struct _gobj /* a graphical object */
{
t_pd g_pd; /* pure datum header (class) */
struct _gobj *g_next; /* next in list */
} t_gobj;
typedef struct _scalar /* a graphical object holding data */
{
t_gobj sc_gobj; /* header for graphical object */
t_symbol *sc_template; /* template name (LATER replace with pointer) */
t_word sc_vec[1]; /* indeterminate-length array of words */
} t_scalar;
typedef struct _text /* patchable object - graphical, with text */
{
t_gobj te_g; /* header for graphical object */
t_binbuf *te_binbuf; /* holder for the text */
t_outlet *te_outlet; /* linked list of outlets */
t_inlet *te_inlet; /* linked list of inlets */
short te_xpix; /* x&y location (within the toplevel) */
short te_ypix;
short te_width; /* requested width in chars, 0 if auto */
unsigned int te_type:2; /* from defs below */
} t_text;
#define T_TEXT 0 /* just a textual comment */
#define T_OBJECT 1 /* a MAX style patchable object */
#define T_MESSAGE 2 /* a MAX type message */
#define T_ATOM 3 /* a cell to display a number or symbol */
#define te_pd te_g.g_pd
/* t_object is synonym for t_text (LATER unify them) */
typedef struct _text t_object;
#define ob_outlet te_outlet
#define ob_inlet te_inlet
#define ob_binbuf te_binbuf
#define ob_pd te_g.g_pd
#define ob_g te_g
typedef void (*t_method)(void);
typedef void *(*t_newmethod)(void);
/* in ARM 64 a varargs prototype generates a different function call sequence
from a fixed one, so in that special case we make a more restrictive
definition for t_gotfn. This will break some code in the "chaos" package
in Pd extended. (that code will run incorrectly anyhow so why not catch it
at compile time anyhow.) */
#if defined(__APPLE__) && defined(__aarch64__)
typedef void (*t_gotfn)(void *x);
#else
typedef void (*t_gotfn)(void *x, ...);
#endif
/* ---------------- pre-defined objects and symbols --------------*/
EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */
EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */
/* --------- prototypes from the central message system ----------- */
EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv);
EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv);
EXTERN t_symbol *gensym(const char *s);
EXTERN t_gotfn getfn(const t_pd *x, t_symbol *s);
EXTERN t_gotfn zgetfn(const t_pd *x, t_symbol *s);
EXTERN void nullfn(void);
EXTERN void pd_vmess(t_pd *x, t_symbol *s, const char *fmt, ...);
/* the following macros are for sending non-type-checkable messages, i.e.,
using function lookup but circumventing type checking on arguments. Only
use for internal messaging protected by A_CANT so that the message can't
be generated at patch level. */
#define mess0(x, s) ((*getfn((x), (s)))((x)))
typedef void (*t_gotfn1)(void *x, void *arg1);
#define mess1(x, s, a) ((*(t_gotfn1)getfn((x), (s)))((x), (a)))
typedef void (*t_gotfn2)(void *x, void *arg1, void *arg2);
#define mess2(x, s, a,b) ((*(t_gotfn2)getfn((x), (s)))((x), (a),(b)))
typedef void (*t_gotfn3)(void *x, void *arg1, void *arg2, void *arg3);
#define mess3(x, s, a,b,c) ((*(t_gotfn3)getfn((x), (s)))((x), (a),(b),(c)))
typedef void (*t_gotfn4)(void *x,
void *arg1, void *arg2, void *arg3, void *arg4);
#define mess4(x, s, a,b,c,d) \
((*(t_gotfn4)getfn((x), (s)))((x), (a),(b),(c),(d)))
typedef void (*t_gotfn5)(void *x,
void *arg1, void *arg2, void *arg3, void *arg4, void *arg5);
#define mess5(x, s, a,b,c,d,e) \
((*(t_gotfn5)getfn((x), (s)))((x), (a),(b),(c),(d),(e)))
EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
EXTERN t_pd *pd_newest(void);
/* --------------- memory management -------------------- */
EXTERN void *getbytes(size_t nbytes);
EXTERN void *getzbytes(size_t nbytes);
EXTERN void *copybytes(const void *src, size_t nbytes);
EXTERN void freebytes(void *x, size_t nbytes);
EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize);
/* -------------------- atoms ----------------------------- */
#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0)
#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0)
#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \
(atom)->a_w.w_gpointer = (gp))
#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f))
#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \
(atom)->a_w.w_symbol = (s))
#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \
(atom)->a_w.w_index = (n))
#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \
(atom)->a_w.w_symbol= (s))
EXTERN t_float atom_getfloat(const t_atom *a);
EXTERN t_int atom_getint(const t_atom *a);
EXTERN t_symbol *atom_getsymbol(const t_atom *a);
EXTERN t_symbol *atom_gensym(const t_atom *a);
EXTERN t_float atom_getfloatarg(int which, int argc, const t_atom *argv);
EXTERN t_int atom_getintarg(int which, int argc, const t_atom *argv);
EXTERN t_symbol *atom_getsymbolarg(int which, int argc, const t_atom *argv);
EXTERN void atom_string(const t_atom *a, char *buf, unsigned int bufsize);
/* ------------------ binbufs --------------- */
EXTERN t_binbuf *binbuf_new(void);
EXTERN void binbuf_free(t_binbuf *x);
EXTERN t_binbuf *binbuf_duplicate(const t_binbuf *y);
EXTERN void binbuf_text(t_binbuf *x, const char *text, size_t size);
EXTERN void binbuf_gettext(const t_binbuf *x, char **bufp, int *lengthp);
EXTERN void binbuf_clear(t_binbuf *x);
EXTERN void binbuf_add(t_binbuf *x, int argc, const t_atom *argv);
EXTERN void binbuf_addv(t_binbuf *x, const char *fmt, ...);
EXTERN void binbuf_addbinbuf(t_binbuf *x, const t_binbuf *y);
EXTERN void binbuf_addsemi(t_binbuf *x);
EXTERN void binbuf_restore(t_binbuf *x, int argc, const t_atom *argv);
EXTERN void binbuf_print(const t_binbuf *x);
EXTERN int binbuf_getnatom(const t_binbuf *x);
EXTERN t_atom *binbuf_getvec(const t_binbuf *x);
EXTERN int binbuf_resize(t_binbuf *x, int newsize);
EXTERN void binbuf_eval(const t_binbuf *x, t_pd *target, int argc, const t_atom *argv);
EXTERN int binbuf_read(t_binbuf *b, const char *filename, const char *dirname,
int crflag);
EXTERN int binbuf_read_via_canvas(t_binbuf *b, const char *filename, const t_canvas *canvas,
int crflag);
EXTERN int binbuf_read_via_path(t_binbuf *b, const char *filename, const char *dirname,
int crflag);
EXTERN int binbuf_write(const t_binbuf *x, const char *filename, const char *dir,
int crflag);
EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir);
EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, const t_atom *av,
int tonew);
/* ------------------ clocks --------------- */
EXTERN t_clock *clock_new(void *owner, t_method fn);
EXTERN void clock_set(t_clock *x, double systime);
EXTERN void clock_delay(t_clock *x, double delaytime);
EXTERN void clock_unset(t_clock *x);
EXTERN void clock_setunit(t_clock *x, double timeunit, int sampflag);
EXTERN double clock_getlogicaltime(void);
EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */
EXTERN double clock_gettimesince(double prevsystime);
EXTERN double clock_gettimesincewithunits(double prevsystime,
double units, int sampflag);
EXTERN double clock_getsystimeafter(double delaytime);
EXTERN void clock_free(t_clock *x);
/* ----------------- pure data ---------------- */
EXTERN t_pd *pd_new(t_class *cls);
EXTERN void pd_free(t_pd *x);
EXTERN void pd_bind(t_pd *x, t_symbol *s);
EXTERN void pd_unbind(t_pd *x, t_symbol *s);
EXTERN t_pd *pd_findbyclass(t_symbol *s, const t_class *c);
EXTERN void pd_pushsym(t_pd *x);
EXTERN void pd_popsym(t_pd *x);
EXTERN void pd_bang(t_pd *x);
EXTERN void pd_pointer(t_pd *x, t_gpointer *gp);
EXTERN void pd_float(t_pd *x, t_float f);
EXTERN void pd_symbol(t_pd *x, t_symbol *s);
EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv);
#define pd_class(x) (*(x))
/* ----------------- pointers ---------------- */
EXTERN void gpointer_init(t_gpointer *gp);
EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto);
EXTERN void gpointer_unset(t_gpointer *gp);
EXTERN int gpointer_check(const t_gpointer *gp, int headok);
/* ----------------- patchable "objects" -------------- */
EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1,
t_symbol *s2);
EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp);
EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f);
EXTERN void inlet_free(t_inlet *x);
EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s);
EXTERN void outlet_bang(t_outlet *x);
EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp);
EXTERN void outlet_float(t_outlet *x, t_float f);
EXTERN void outlet_symbol(t_outlet *x, t_symbol *s);
EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
EXTERN t_symbol *outlet_getsymbol(t_outlet *x);
EXTERN void outlet_free(t_outlet *x);
EXTERN t_object *pd_checkobject(t_pd *x);
/* -------------------- canvases -------------- */
EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir);
EXTERN void canvas_setargs(int argc, const t_atom *argv);
EXTERN void canvas_getargs(int *argcp, t_atom **argvp);
EXTERN t_symbol *canvas_getcurrentdir(void);
EXTERN t_glist *canvas_getcurrent(void);
EXTERN void canvas_makefilename(const t_glist *c, const char *file,
char *result, int resultsize);
EXTERN t_symbol *canvas_getdir(const t_glist *x);
EXTERN char sys_font[]; /* default typeface set in s_main.c */
EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */
EXTERN int sys_hostfontsize(int fontsize, int zoom);
EXTERN int sys_zoomfontwidth(int fontsize, int zoom, int worstcase);
EXTERN int sys_zoomfontheight(int fontsize, int zoom, int worstcase);
EXTERN int sys_fontwidth(int fontsize);
EXTERN int sys_fontheight(int fontsize);
EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b);
EXTERN int canvas_open(const t_canvas *x, const char *name, const char *ext,
char *dirresult, char **nameresult, unsigned int size, int bin);
/* ---------------- widget behaviors ---------------------- */
EXTERN_STRUCT _widgetbehavior;
#define t_widgetbehavior struct _widgetbehavior
EXTERN_STRUCT _parentwidgetbehavior;
#define t_parentwidgetbehavior struct _parentwidgetbehavior
EXTERN const t_parentwidgetbehavior *pd_getparentwidget(t_pd *x);
/* -------------------- classes -------------- */
#define CLASS_DEFAULT 0 /* flags for new classes below */
#define CLASS_PD 1
#define CLASS_GOBJ 2
#define CLASS_PATCHABLE 3
#define CLASS_NOINLET 8
#define CLASS_TYPEMASK 3
EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod,
t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
EXTERN t_class *class_new64(t_symbol *name, t_newmethod newmethod,
t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
EXTERN void class_free(t_class *c);
#ifdef PDINSTANCE
EXTERN t_class *class_getfirst(void);
#endif
EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s,
t_atomtype type1, ...);
EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
t_atomtype arg1, ...);
EXTERN void class_addbang(t_class *c, t_method fn);
EXTERN void class_addpointer(t_class *c, t_method fn);
EXTERN void class_doaddfloat(t_class *c, t_method fn);
EXTERN void class_addsymbol(t_class *c, t_method fn);
EXTERN void class_addlist(t_class *c, t_method fn);
EXTERN void class_addanything(t_class *c, t_method fn);
EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s);
EXTERN void class_setwidget(t_class *c, const t_widgetbehavior *w);
EXTERN void class_setparentwidget(t_class *c, const t_parentwidgetbehavior *w);
EXTERN const char *class_getname(const t_class *c);
EXTERN const char *class_gethelpname(const t_class *c);
EXTERN const char *class_gethelpdir(const t_class *c);
EXTERN void class_setdrawcommand(t_class *c);
EXTERN int class_isdrawcommand(const t_class *c);
EXTERN void class_domainsignalin(t_class *c, int onset);
EXTERN void class_set_extern_dir(t_symbol *s);
#define CLASS_MAINSIGNALIN(c, type, field) \
class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0)
/* prototype for functions to save Pd's to a binbuf */
typedef void (*t_savefn)(t_gobj *x, t_binbuf *b);
EXTERN void class_setsavefn(t_class *c, t_savefn f);
EXTERN t_savefn class_getsavefn(const t_class *c);
EXTERN void obj_saveformat(const t_object *x, t_binbuf *bb); /* add format to bb */
/* prototype for functions to open properties dialogs */
typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist);
EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f);
EXTERN t_propertiesfn class_getpropertiesfn(const t_class *c);
typedef void (*t_classfreefn)(t_class *);
EXTERN void class_setfreefn(t_class *c, t_classfreefn fn);
#ifndef PD_CLASS_DEF
#define class_addbang(x, y) class_addbang((x), (t_method)(y))
#define class_addpointer(x, y) class_addpointer((x), (t_method)(y))
#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y))
#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y))
#define class_addlist(x, y) class_addlist((x), (t_method)(y))
#define class_addanything(x, y) class_addanything((x), (t_method)(y))
#endif
#if PD_FLOATSIZE == 64
# define class_new class_new64
#endif
/* ------------ printing --------------------------------- */
EXTERN void post(const char *fmt, ...);
EXTERN void startpost(const char *fmt, ...);
EXTERN void poststring(const char *s);
EXTERN void postfloat(t_floatarg f);
EXTERN void postatom(int argc, const t_atom *argv);
EXTERN void endpost(void);
EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
EXTERN void pd_error(const void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
EXTERN void logpost(const void *object, const int level, const char *fmt, ...)
ATTRIBUTE_FORMAT_PRINTF(3, 4);
/* ------------ system interface routines ------------------- */
EXTERN int sys_isabsolutepath(const char *dir);
EXTERN void sys_bashfilename(const char *from, char *to);
EXTERN void sys_unbashfilename(const char *from, char *to);
EXTERN int open_via_path(const char *dir, const char *name, const char *ext,
char *dirresult, char **nameresult, unsigned int size, int bin);
EXTERN int sched_geteventno(void);
EXTERN double sys_getrealtime(void);
EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */
/* Win32's open()/fopen() do not handle UTF-8 filenames so we need
* these internal versions that handle UTF-8 filenames the same across
* all platforms. They are recommended for use in external
* objectclasses as well so they work with Unicode filenames on Windows */
EXTERN int sys_open(const char *path, int oflag, ...);
EXTERN int sys_close(int fd);
EXTERN FILE *sys_fopen(const char *filename, const char *mode);
EXTERN int sys_fclose(FILE *stream);
/* ------------ threading ------------------- */
EXTERN void sys_lock(void);
EXTERN void sys_unlock(void);
EXTERN int sys_trylock(void);
/* --------------- signals ----------------------------------- */
typedef PD_FLOATTYPE t_sample;
typedef union _sampleint_union {
t_sample f;
PD_FLOATUINTTYPE i;
} t_sampleint_union;
#define MAXLOGSIG 32
#define MAXSIGSIZE (1 << MAXLOGSIG)
typedef struct _signal
{
int s_n; /* number of points in the array */
t_sample *s_vec; /* the array */
t_float s_sr; /* sample rate */
int s_refcount; /* number of times used */
int s_isborrowed; /* whether we're going to borrow our array */
struct _signal *s_borrowedfrom; /* signal to borrow it from */
struct _signal *s_nextfree; /* next in freelist */
struct _signal *s_nextused; /* next in used list */
int s_vecsize; /* allocated size of array in points */
} t_signal;
typedef t_int *(*t_perfroutine)(t_int *args);
EXTERN t_int *plus_perform(t_int *args);
EXTERN t_int *zero_perform(t_int *args);
EXTERN t_int *copy_perform(t_int *args);
EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n);
EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n);
EXTERN void dsp_add_scalarcopy(t_float *in, t_sample *out, int n);
EXTERN void dsp_add_zero(t_sample *out, int n);
EXTERN int sys_getblksize(void);
EXTERN t_float sys_getsr(void);
EXTERN int sys_get_inchannels(void);
EXTERN int sys_get_outchannels(void);
EXTERN void dsp_add(t_perfroutine f, int n, ...);
EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec);
EXTERN void pd_fft(t_float *buf, int npoints, int inverse);
EXTERN int ilog2(int n);
EXTERN void mayer_fht(t_sample *fz, int n);
EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag);
EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag);
EXTERN void mayer_realfft(int n, t_sample *real);
EXTERN void mayer_realifft(int n, t_sample *real);
EXTERN float *cos_table;
#define LOGCOSTABSIZE 9
#define COSTABSIZE (1<<LOGCOSTABSIZE)
EXTERN int canvas_suspend_dsp(void);
EXTERN void canvas_resume_dsp(int oldstate);
EXTERN void canvas_update_dsp(void);
EXTERN int canvas_dspstate;
/* up/downsampling */
typedef struct _resample
{
int method; /* up/downsampling method ID */
int downsample; /* downsampling factor */
int upsample; /* upsampling factor */
t_sample *s_vec; /* here we hold the resampled data */
int s_n;
t_sample *coeffs; /* coefficients for filtering... */
int coefsize;
t_sample *buffer; /* buffer for filtering */
int bufsize;
} t_resample;
EXTERN void resample_init(t_resample *x);
EXTERN void resample_free(t_resample *x);
EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);
/* ----------------------- utility functions for signals -------------- */
EXTERN t_float mtof(t_float);
EXTERN t_float ftom(t_float);
EXTERN t_float rmstodb(t_float);
EXTERN t_float powtodb(t_float);
EXTERN t_float dbtorms(t_float);
EXTERN t_float dbtopow(t_float);
EXTERN t_float q8_sqrt(t_float);
EXTERN t_float q8_rsqrt(t_float);
#ifndef N32
EXTERN t_float qsqrt(t_float); /* old names kept for extern compatibility */
EXTERN t_float qrsqrt(t_float);
#endif
/* --------------------- data --------------------------------- */
/* graphical arrays */
EXTERN_STRUCT _garray;
#define t_garray struct _garray
EXTERN t_class *garray_class;
EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec);
EXTERN void garray_redraw(t_garray *x);
EXTERN int garray_npoints(t_garray *x);
EXTERN char *garray_vec(t_garray *x);
EXTERN void garray_resize(t_garray *x, t_floatarg f); /* avoid; use this: */
EXTERN void garray_resize_long(t_garray *x, long n); /* better version */
EXTERN void garray_usedindsp(t_garray *x);
EXTERN void garray_setsaveit(t_garray *x, int saveit);
EXTERN t_glist *garray_getglist(t_garray *x);
EXTERN t_array *garray_getarray(t_garray *x);
EXTERN t_class *scalar_class;
EXTERN t_float *value_get(t_symbol *s);
EXTERN void value_release(t_symbol *s);
EXTERN int value_getfloat(t_symbol *s, t_float *f);
EXTERN int value_setfloat(t_symbol *s, t_float f);
/* ------- GUI interface - functions to send strings to TK --------- */
typedef void (*t_guicallbackfn)(t_gobj *client, t_glist *glist);
EXTERN void sys_vgui(const char *fmt, ...);
EXTERN void sys_gui(const char *s);
EXTERN void sys_pretendguibytes(int n);
EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f);
EXTERN void sys_unqueuegui(void *client);
/* dialog window creation and destruction */
EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
EXTERN void gfxstub_deleteforkey(void *key);
extern t_class *glob_pdobject; /* object to send "pd" messages */
/*------------- Max 0.26 compatibility --------------------*/
/* the following reflects the new way classes are laid out, with the class
pointing to the messlist and not vice versa. Externs shouldn't feel it. */
typedef t_class *t_externclass;
EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
t_method freeroutine, t_symbol *name, size_t size, int tiny, \
t_atomtype arg1, ...);
EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);
#define t_getbytes getbytes
#define t_freebytes freebytes
#define t_resizebytes resizebytes
#define typedmess pd_typedmess
#define vmess pd_vmess
/* A definition to help gui objects straddle 0.34-0.35 changes. If this is
defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */
#define PD_USE_TE_XPIX
#ifndef _MSC_VER /* Microoft compiler can't handle "inline" function/macros */
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
/* a test for NANs and denormals. Should only be necessary on i386. */
#if PD_FLOATSIZE == 32
typedef union
{
t_float f;
unsigned int ui;
}t_bigorsmall32;
static inline int PD_BADFLOAT(t_float f) /* malformed float */
{
t_bigorsmall32 pun;
pun.f = f;
pun.ui &= 0x7f800000;
return((pun.ui == 0) | (pun.ui == 0x7f800000));
}
static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-64,64) */
{
t_bigorsmall32 pun;
pun.f = f;
return((pun.ui & 0x20000000) == ((pun.ui >> 1) & 0x20000000));
}
#elif PD_FLOATSIZE == 64
typedef union
{
t_float f;
unsigned int ui[2];
}t_bigorsmall64;
static inline int PD_BADFLOAT(t_float f) /* malformed double */
{
t_bigorsmall64 pun;
pun.f = f;
pun.ui[1] &= 0x7ff00000;
return((pun.ui[1] == 0) | (pun.ui[1] == 0x7ff00000));
}
static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-512,512) */
{
t_bigorsmall64 pun;
pun.f = f;
return((pun.ui[1] & 0x20000000) == ((pun.ui[1] >> 1) & 0x20000000));
}
#endif /* PD_FLOATSIZE */
#else /* not INTEL or ARM */
#define PD_BADFLOAT(f) 0
#define PD_BIGORSMALL(f) 0
#endif
#else /* _MSC_VER */
#if PD_FLOATSIZE == 32
#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
(((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
(((*(unsigned int*)&(f))&0x60000000)==0x60000000))
#else /* 64 bits... don't know what to do here */
#define PD_BADFLOAT(f) (!(((f) >= 0) || ((f) <= 0)))
#define PD_BIGORSMALL(f) ((f) > 1e150 || (f) < -1e150 \
|| (f) > -1e-150 && (f) < 1e-150 )
#endif
#endif /* _MSC_VER */
/* get version number at run time */
EXTERN void sys_getversion(int *major, int *minor, int *bugfix);
EXTERN_STRUCT _instancemidi;
#define t_instancemidi struct _instancemidi
EXTERN_STRUCT _instanceinter;
#define t_instanceinter struct _instanceinter
EXTERN_STRUCT _instancecanvas;
#define t_instancecanvas struct _instancecanvas
EXTERN_STRUCT _instanceugen;
#define t_instanceugen struct _instanceugen
EXTERN_STRUCT _instancestuff;
#define t_instancestuff struct _instancestuff
#ifndef PDTHREADS
#define PDTHREADS 1
#endif
struct _pdinstance
{
double pd_systime; /* global time in Pd ticks */
t_clock *pd_clock_setlist; /* list of set clocks */
t_canvas *pd_canvaslist; /* list of all root canvases */
struct _template *pd_templatelist; /* list of all templates */
int pd_instanceno; /* ordinal number of this instance */
t_symbol **pd_symhash; /* symbol table hash table */
t_instancemidi *pd_midi; /* private stuff for x_midi.c */
t_instanceinter *pd_inter; /* private stuff for s_inter.c */
t_instanceugen *pd_ugen; /* private stuff for d_ugen.c */
t_instancecanvas *pd_gui; /* semi-private stuff in g_canvas.h */
t_instancestuff *pd_stuff; /* semi-private stuff in s_stuff.h */
t_pd *pd_newest; /* most recently created object */
#ifdef PDINSTANCE
t_symbol pd_s_pointer;
t_symbol pd_s_float;
t_symbol pd_s_symbol;
t_symbol pd_s_bang;
t_symbol pd_s_list;
t_symbol pd_s_anything;
t_symbol pd_s_signal;
t_symbol pd_s__N;
t_symbol pd_s__X;
t_symbol pd_s_x;
t_symbol pd_s_y;
t_symbol pd_s_;
#endif
#if PDTHREADS
int pd_islocked;
#endif
};
#define t_pdinstance struct _pdinstance
EXTERN t_pdinstance pd_maininstance;
/* m_pd.c */
#ifdef PDINSTANCE
EXTERN t_pdinstance *pdinstance_new(void);
EXTERN void pd_setinstance(t_pdinstance *x);
EXTERN void pdinstance_free(t_pdinstance *x);
#endif /* PDINSTANCE */
#if defined(PDTHREADS) && defined(PDINSTANCE)
#ifdef _MSC_VER
#define PERTHREAD __declspec(thread)
#else
#define PERTHREAD __thread
#endif /* _MSC_VER */
#else
#define PERTHREAD
#endif
#ifdef PDINSTANCE
extern PERTHREAD t_pdinstance *pd_this;
EXTERN t_pdinstance **pd_instances;
EXTERN int pd_ninstances;
#else
#define pd_this (&pd_maininstance)
#endif /* PDINSTANCE */
#ifdef PDINSTANCE
#define s_pointer (pd_this->pd_s_pointer)
#define s_float (pd_this->pd_s_float)
#define s_symbol (pd_this->pd_s_symbol)
#define s_bang (pd_this->pd_s_bang)
#define s_list (pd_this->pd_s_list)
#define s_anything (pd_this->pd_s_anything)
#define s_signal (pd_this->pd_s_signal)
#define s__N (pd_this->pd_s__N)
#define s__X (pd_this->pd_s__X)
#define s_x (pd_this->pd_s_x)
#define s_y (pd_this->pd_s_y)
#define s_ (pd_this->pd_s_)
#else
EXTERN t_symbol s_pointer, s_float, s_symbol, s_bang, s_list, s_anything,
s_signal, s__N, s__X, s_x, s_y, s_;
#endif
EXTERN t_canvas *pd_getcanvaslist(void);
EXTERN int pd_getdspstate(void);
/* x_text.c */
EXTERN t_binbuf *text_getbufbyname(t_symbol *s); /* get binbuf from text obj */
EXTERN void text_notifybyname(t_symbol *s); /* notify it was modified */
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif
#define __m_pd_h_
#endif /* __m_pd_h_ */

View file

@ -0,0 +1,231 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include <m_pd.h>
#include <sfizz.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
static t_class* cls_sfizz_tilde;
typedef struct _sfizz_tilde {
t_object obj;
t_outlet* outputs[2];
sfizz_synth_t* synth;
int midi[3];
int midinum;
t_symbol* dir;
char* filepath;
} t_sfizz_tilde;
static void sfizz_tilde_set_file(t_sfizz_tilde* self, const char* file)
{
const char* dir = self->dir->s_name;
char* filepath;
if (file[0] != '\0') {
filepath = malloc(strlen(dir) + 1 + strlen(file) + 1);
sprintf(filepath, "%s/%s", dir, file);
}
else {
filepath = malloc(1);
*filepath = '\0';
}
free(self->filepath);
self->filepath = filepath;
}
static bool sfizz_tilde_do_load(t_sfizz_tilde* self)
{
bool loaded;
if (self->filepath[0] != '\0')
loaded = sfizz_load_file(self->synth, self->filepath);
else
loaded = sfizz_load_string(self->synth, "default.sfz", "<region>sample=*sine");
return loaded;
}
static void* sfizz_tilde_new(t_symbol* sym, int argc, t_atom argv[])
{
(void)sym;
t_sfizz_tilde* self = (t_sfizz_tilde*)pd_new(cls_sfizz_tilde);
const char* file;
if (argc == 0)
file = "";
else if (argc == 1 && argv[0].a_type == A_SYMBOL)
file = argv[0].a_w.w_symbol->s_name;
else {
pd_free((t_pd*)self);
return NULL;
}
self->dir = canvas_getcurrentdir();
self->outputs[0] = outlet_new(&self->obj, &s_signal);
self->outputs[1] = outlet_new(&self->obj, &s_signal);
sfizz_synth_t* synth = sfizz_create_synth();
self->synth = synth;
sfizz_set_sample_rate(synth, sys_getsr());
sfizz_set_samples_per_block(synth, sys_getblksize());
sfizz_tilde_set_file(self, file);
if (!sfizz_tilde_do_load(self)) {
pd_free((t_pd*)self);
return NULL;
}
return self;
}
static void sfizz_tilde_free(t_sfizz_tilde* self)
{
if (self->filepath)
free(self->filepath);
if (self->synth)
sfizz_free(self->synth);
if (self->outputs[0])
outlet_free(self->outputs[0]);
if (self->outputs[1])
outlet_free(self->outputs[1]);
}
static t_int* sfizz_tilde_perform(t_int* w)
{
t_sfizz_tilde* self;
t_sample* outputs[2];
t_int nframes;
w++;
self = (t_sfizz_tilde*)*w++;
outputs[0] = (t_sample*)*w++;
outputs[1] = (t_sample*)*w++;
nframes = (t_int)*w++;
sfizz_render_block(self->synth, outputs, 2, nframes);
return w;
}
static void sfizz_tilde_dsp(t_sfizz_tilde* self, t_signal** sp)
{
dsp_add(
&sfizz_tilde_perform, 4, (t_int)self,
(t_int)sp[0]->s_vec, (t_int)sp[1]->s_vec, (t_int)sp[0]->s_n);
}
static void sfizz_tilde_midiin(t_sfizz_tilde* self, t_float f)
{
int byte = (int)f;
bool isstatus = (byte & 0x80) != 0;
int* midi = self->midi;
int midinum = self->midinum;
//
if (isstatus) {
midi[0] = byte;
midinum = 1;
}
else if (midinum != -1 && midinum < 3)
midi[midinum++] = byte;
else
midinum = -1;
//
switch (midinum) {
case 2:
switch (midi[0] & 0xf0) {
case 0xd0: // channel aftertouch
sfizz_send_channel_aftertouch(self->synth, 0, midi[1]);
break;
}
break;
case 3:
switch (midi[0] & 0xf0) {
case 0x90: // note on
if (midi[2] == 0)
goto noteoff;
sfizz_send_note_on(self->synth, 0, midi[1], midi[2]);
break;
case 0x80: // note off
noteoff:
sfizz_send_note_off(self->synth, 0, midi[1], midi[2]);
break;
case 0xb0: // controller
sfizz_send_cc(self->synth, 0, midi[1], midi[2]);
break;
case 0xa0: // key aftertouch
sfizz_send_poly_aftertouch(self->synth, 0, midi[1], midi[2]);
break;
case 0xe0: // pitch bend
sfizz_send_pitch_wheel(self->synth, 0, (midi[1] + (midi[2] << 7)) - 8192);
break;
}
break;
}
self->midinum = midinum;
}
static void sfizz_tilde_load(t_sfizz_tilde* self, t_symbol* sym)
{
sfizz_tilde_set_file(self, sym->s_name);
sfizz_tilde_do_load(self);
}
static void sfizz_tilde_reload(t_sfizz_tilde* self, t_float value)
{
(void)value;
sfizz_tilde_do_load(self);
}
static void sfizz_tilde_hdcc(t_sfizz_tilde* self, t_float cc, t_float value)
{
sfizz_automate_hdcc(self->synth, 0, (int)cc, value);
}
static void sfizz_tilde_voices(t_sfizz_tilde* self, t_float value)
{
int numvoices = (int)value;
if (numvoices < 1)
numvoices = 1;
sfizz_set_num_voices(self->synth, numvoices);
}
#if defined(_WIN32)
__declspec(dllexport)
#else
__attribute__((visibility("default")))
#endif
void sfizz_setup()
{
post("sfizz external for Puredata");
cls_sfizz_tilde = class_new(
gensym("sfizz~"),
(t_newmethod)&sfizz_tilde_new,
(t_method)&sfizz_tilde_free,
sizeof(t_sfizz_tilde),
CLASS_DEFAULT, A_GIMME, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_dsp, gensym("dsp"), A_CANT, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_midiin, &s_float, A_FLOAT, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_load, gensym("load"), A_DEFSYM, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_reload, gensym("reload"), A_DEFFLOAT, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_hdcc, gensym("hdcc"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(
cls_sfizz_tilde, (t_method)&sfizz_tilde_voices, gensym("voices"), A_FLOAT, A_NULL);
}

View file

@ -0,0 +1,46 @@
#N canvas 932 395 659 405 12;
#X declare -lib sfizz;
#X obj 4 3 cnv 15 650 80 empty empty sfizz 20 30 0 40 -261682 -66577
0;
#X text 45 54 A synthesizer for instruments in SFZ format;
#X obj 241 165 r sfizz-ctl;
#X text 33 167 create a SFZ instrument;
#X obj 29 324 midiin;
#X obj 29 349 s sfizz-ctl;
#X text 26 301 connect MIDI-in;
#X obj 162 223 dac~;
#X msg 180 346 voices \$1;
#X obj 180 371 s sfizz-ctl;
#X text 178 302 modify the polyphony;
#X obj 183 326 hsl 128 15 1 256 0 1 empty empty empty -2 -8 0 10 -262144
-1 -1 3138 1;
#X floatatom 273 346 5 0 0 0 - - -;
#X obj 378 372 s sfizz-ctl;
#X obj 381 327 hsl 128 15 0 1 0 1 empty empty empty -2 -8 0 10 -262144
-1 -1 6350 1;
#X floatatom 471 347 5 0 0 0 - - -;
#X text 377 303 modulate a parameter;
#X msg 378 347 hdcc 300 \$1;
#X obj 27 115 declare -lib sfizz;
#X obj 163 192 sfizz~ example.sfz;
#X text 18 93 load the sfizz library;
#X msg 221 115 \; pd dsp 1;
#X text 218 94 click to turn on DSP;
#X text 153 247 output stereo audio;
#X msg 366 223 reload;
#X obj 366 248 s sfizz-ctl;
#X obj 466 248 s sfizz-ctl;
#X msg 466 223 load example.sfz;
#X text 364 200 reload the instrument or load another;
#X connect 2 0 19 0;
#X connect 4 0 5 0;
#X connect 8 0 9 0;
#X connect 11 0 8 0;
#X connect 11 0 12 0;
#X connect 14 0 17 0;
#X connect 14 0 15 0;
#X connect 17 0 13 0;
#X connect 19 0 7 0;
#X connect 19 1 7 1;
#X connect 24 0 25 0;
#X connect 27 0 26 0;