commit
9d8e184d05
9 changed files with 1299 additions and 0 deletions
|
|
@ -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)
|
||||
|
|
|
|||
16
cmake/PuredataConfig.cmake
Normal file
16
cmake/PuredataConfig.cmake
Normal 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()
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
38
plugins/puredata/CMakeLists.txt
Normal file
38
plugins/puredata/CMakeLists.txt
Normal 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}")
|
||||
22
plugins/puredata/example.sfz
Normal file
22
plugins/puredata/example.sfz
Normal 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
|
||||
30
plugins/puredata/external/pd/LICENSE.txt
vendored
Normal file
30
plugins/puredata/external/pd/LICENSE.txt
vendored
Normal 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.
|
||||
911
plugins/puredata/external/pd/include/m_pd.h
vendored
Normal file
911
plugins/puredata/external/pd/include/m_pd.h
vendored
Normal 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_ */
|
||||
231
plugins/puredata/sfizz_puredata.c
Normal file
231
plugins/puredata/sfizz_puredata.c
Normal 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);
|
||||
}
|
||||
46
plugins/puredata/sfizz~-help.pd
Normal file
46
plugins/puredata/sfizz~-help.pd
Normal 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;
|
||||
Loading…
Add table
Reference in a new issue