1
0
Fork 0
forked from len0rd/rockbox

pdbox: Source cleanup. Removed unneeded files.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26497 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Wincent Balin 2010-06-03 00:39:13 +00:00
parent 5edd8cf736
commit c1ae4414d4
44 changed files with 17 additions and 19949 deletions

View file

@ -1,189 +0,0 @@
/*
Written by Matt Wright, The Center for New Music and Audio Technologies,
University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
The Regents of the University of California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
OSC-client.h: library for constructing OpenSoundControl messages.
Derived from SynthControl.h
Author: Matt Wright
Version 0.1: 6/13/97
Version 0.2: 7/21/2000: Support for type-tagged messages
General notes:
This library abstracts away the data format for the OpenSoundControl
protocol. Users of this library can construct OpenSoundControl packets
with a function call interface instead of knowing how to lay out the bits.
All issues of memory allocation are deferred to the user of this library.
There are two data structures that the user must allocate. The first
is the actual buffer that the message will be written into. This buffer
can be any size, but if it's too small there's a possibility that it
will become overfull. The other data structure is called an OSCbuf,
and it holds all the state used by the library as it's constructing
a buffer.
All procedures that have the possibility of an error condition return int,
with 0 indicating no error and nonzero indicating an error. The variable
OSC_errorMessage will be set to point to a string containing an error
message explaining what the problem is.
*/
/* The int4byte type has to be a 4-byte integer. You may have to
change this to long or something else on your system. */
#ifdef __MWERKS__
/* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is
always 4 bytes */
typedef long int4byte;
#else
typedef int int4byte;
#endif
/* OSC_timetag.h */
typedef struct {
int seconds;
int fraction;
} OSCTimeTag;
OSCTimeTag OSCTT_Immediately(void);
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
OSCTimeTag OSCTT_CurrentTime(void);
/* The maximum depth of bundles within bundles within bundles within...
This is the size of a static array. If you exceed this limit you'll
get an error message. */
#define MAX_BUNDLE_NESTING 32
/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
declared here in the header file only so your program will be able to
declare variables of type OSCbuf and have the right amount of memory
be allocated.) */
typedef struct OSCbuf_struct {
char *buffer; /* The buffer to hold the OSC packet */
int size; /* Size of the buffer */
char *bufptr; /* Current position as we fill the buffer */
int state; /* State of partially-constructed message */
int4byte *thisMsgSize; /* Pointer to count field before
currently-being-written message */
int4byte *prevCounts[MAX_BUNDLE_NESTING];
/* Pointers to count field before each currently
open bundle */
int bundleDepth; /* How many sub-sub-bundles are we in now? */
char *typeStringPtr; /* This pointer advances through the type
tag string as you add arguments. */
int gettingFirstUntypedArg; /* nonzero if this message doesn't have
a type tag and we're waiting for the 1st arg */
} OSCbuf;
/* Initialize the given OSCbuf. The user of this module must pass in the
block of memory that this OSCbuf will use for a buffer, and the number of
bytes in that block. (It's the user's job to allocate the memory because
you do it differently in different systems.) */
void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray);
/* Reset the given OSCbuf. Do this after you send out the contents of
the buffer and want to start writing new data into it. */
void OSC_resetBuffer(OSCbuf *buf);
/* Is the buffer empty? (I.e., would it be stupid to send the buffer
contents to the synth?) */
int OSC_isBufferEmpty(OSCbuf *buf);
/* How much space is left in the buffer? */
int OSC_freeSpaceInBuffer(OSCbuf *buf);
/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
int OSC_isBufferDone(OSCbuf *buf);
/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
returns true), call these two procedures to get the OSC packet that's been
assembled and its size in bytes. (And then call OSC_resetBuffer() if you
want to re-use this OSCbuf for the next packet.) */
char *OSC_getPacket(OSCbuf *buf);
int OSC_packetSize(OSCbuf *buf);
/* Here's the basic model for building up OSC messages in an OSCbuf:
- Make sure the OSCbuf has been initialized with OSC_initBuffer().
- To open a bundle, call OSC_openBundle(). You can then write
messages or open new bundles within the bundle you opened.
Call OSC_closeBundle() to close the bundle. Note that a packet
does not have to have a bundle; it can instead consist of just a
single message.
- For each message you want to send:
- Call OSC_writeAddress() with the name of your message. (In
addition to writing your message name into the buffer, this
procedure will also leave space for the size count of this message.)
- Alternately, call OSC_writeAddressAndTypes() with the name of
your message and with a type string listing the types of all the
arguments you will be putting in this message.
- Now write each of the arguments into the buffer, by calling one of:
OSC_writeFloatArg()
OSC_writeFloatArgs()
OSC_writeIntArg()
OSC_writeStringArg()
- Now your message is complete; you can send out the buffer or you can
add another message to it.
*/
int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
int OSC_closeBundle(OSCbuf *buf);
int OSC_closeAllBundles(OSCbuf *buf);
int OSC_writeAddress(OSCbuf *buf, char *name);
int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types);
int OSC_writeFloatArg(OSCbuf *buf, float arg);
int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args);
int OSC_writeIntArg(OSCbuf *buf, int4byte arg);
int OSC_writeStringArg(OSCbuf *buf, char *arg);
extern char *OSC_errorMessage;
/* How many bytes will be needed in the OSC format to hold the given
string? The length of the string, plus the null char, plus any padding
needed for 4-byte alignment. */
int OSC_effectiveStringLength(char *string);

View file

@ -1,14 +0,0 @@
#N canvas 0 0 240 300 10;
#X obj 32 185 dumpOSC 5550;
#X obj 32 217 OSCroute /hello;
#X obj 32 239 print;
#X obj 133 238 print;
#X obj 26 87 sendOSC;
#X msg 50 43 connect localhost 5550;
#X msg 21 13 send /hello PDa;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 1 1 3 0;
#X connect 5 0 4 0;
#X connect 6 0 4 0;

View file

@ -1,628 +0,0 @@
/*
Written by Adrian Freed, The Center for New Music and Audio Technologies,
University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
The Regents of the University of California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
*/
/* OSC-route.c
Max object for OSC-style dispatching
To-do:
Match a pattern against a pattern?
Declare outlet types / distinguish leaf nodes from other children
More sophisticated (2-pass?) allmessages scheme
set message?
pd
-------------
-- tweaks for Win32 www.zeggz.com/raf 13-April-2002
*/
#ifdef ROCKBOX
#include "plugin.h"
#include "../../pdbox.h"
#else /* ROCKBOX */
#ifdef WIN32
#include <stdlib.h>
#include <string.h>
#endif
#ifdef __APPLE__
#include <stdio.h>
#endif
#ifdef UNIX
#include <stdio.h>
#endif
#endif /* ROCKBOX */
/* structure definition of your object */
#define MAX_NUM 20
#define OSC_ROUTE_VERSION "1.05"
#define OSCWarning(x...) post(x)
/* the required include files */
#include "../src/m_pd.h"
#ifndef TRUE
typedef int Boolean;
#define TRUE 1
#define FALSE 0
#endif
/* Fixed byte width types */
typedef int int4; /* 4 byte int */
Boolean PatternMatch (const char *pattern, const char *test);
/* Version 1.04: Allows #1 thru #9 as typed-in arguments
Version 1.05: Allows "list" messages as well as "message" messages.
*/
static t_class *OSCroute_class;
typedef struct _OSCroute
{
t_object x_obj; // required header
t_int x_num; // Number of address prefixes we store
t_int x_complainmode; // Do we print a message if no match?
t_int x_sendmode; // use pd internal sends instead of outlets
char *x_prefixes[MAX_NUM];
void *x_outlets[MAX_NUM+1];
} t_OSCroute;
t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
/* prototypes */
void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */
void *OSCroute_new(t_symbol *s, int argc, t_atom *argv);
void OSCroute_version (t_OSCroute *x);
/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */
/* char *dstString); */
void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
static char *NextSlashOrNull(char *p);
static void StrCopyUntilSlash(char *target, const char *source);
// free
static void OSCroute_free(t_OSCroute *x)
{
#ifdef ROCKBOX
(void) x;
#endif
// freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
}
/* initialization routine */
// setup
#ifdef WIN32
OSC_API void OSCroute_setup(void) {
#else
void OSCroute_setup(void) {
#endif
OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new,
(t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0);
class_addlist(OSCroute_class, OSCroute_list);
class_addanything(OSCroute_class, OSCroute_anything);
class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0);
class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd"));
/*
class_addmethod(OSCroute_class, (t_method)OSCroute_connect,
gensym("connect"), A_SYMBOL, A_FLOAT, 0);
class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect,
gensym("disconnect"), 0);
class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"),
A_GIMME, 0);
*/
/* ps_list = gensym("list"); */
/* ps_complain = gensym("complain"); */
ps_emptySymbol = gensym("");
post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf.");
post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved.");
}
/* instance creation routine */
void *OSCroute_new(t_symbol *s, int argc, t_atom *argv)
{
#ifdef ROCKBOX
(void) s;
#endif
t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize
int i; //{{raf}} n not used
// EnterCallback();
if (argc > MAX_NUM) {
post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM);
// ExitCallback();
return 0;
}
x->x_complainmode = 0;
x->x_num = 0;
for (i = 0; i < argc; ++i) {
if (argv[i].a_type == A_SYMBOL) {
if (argv[i].a_w.w_symbol->s_name[0] == '/') {
/* Now that's a nice prefix */
x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
++(x->x_num);
} else if (argv[i].a_w.w_symbol->s_name[0] == '#' &&
argv[i].a_w.w_symbol->s_name[1] >= '1' &&
argv[i].a_w.w_symbol->s_name[1] <= '9') {
/* The Max programmer is trying to make a patch that will be
a subpatch with arguments. We have to make an outlet for this
argument. */
x->x_prefixes[i] = "dummy";
++(x->x_num);
} else {
/* Maybe this is an option we support */
/* if (argv[i].a_w.w_sym == ps_complain) { */
/* x->x_complainmode = 1; */
/* } else { */
/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */
/* } */
}
// no LONG
/* } else if (argv[i].a_type == A_FLOAD) { */
/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */
/* char *string = getbytes(12); */
/* // I can't be bothered to plug this 12 byte memory leak */
/* if (string == 0) { */
/* post("* OSC-route: out of memory!"); */
/* // ExitCallback(); */
/* return 0; */
/* } */
/* sprintf(string, "%d", argv[i].a_w.w_long); */
/* x->x_prefixes[i] = string; */
/* ++(x->x_num); */
} else if (argv[i].a_type == A_FLOAT) {
post("* OSC-route: float arguments are not OK.");
// ExitCallback();
return 0;
} else {
post("* OSC-route: unrecognized argument type!");
// ExitCallback();
return 0;
}
}
/* Have to create the outlets in reverse order */
/* well, not in pd ? */
// for (i = x->x_num-1; i >= 0; --i) {
// for (i = 0; i <= x->x_num-1; i++) {
for (i = 0; i <= x->x_num; i++) {
// x->x_outlets[i] = listout(x);
x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
}
// ExitCallback();
return (x);
}
void OSCroute_version (t_OSCroute *x) {
#ifdef ROCKBOX
(void) x;
#endif
// EnterCallback();
post("OSCroute Version " OSC_ROUTE_VERSION
", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__);
// ExitCallback();
}
/* I don't know why these aren't defined in some Max #include file. */
#define ASSIST_INLET 1
#define ASSIST_OUTLET 2
void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg,
char *dstString) {
#ifdef ROCKBOX
(void) box;
#endif
// EnterCallback();
if (msg==ASSIST_INLET) {
#ifdef ROCKBOX
strcpy(dstString, "Incoming OSC messages");
#else
sprintf(dstString, "Incoming OSC messages");
#endif
} else if (msg==ASSIST_OUTLET) {
if (arg < 0 || arg >= x->x_num) {
post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg);
} else {
#ifdef ROCKBOX
strcpy(dstString, "subaddress + args for prefix ");
strcat(dstString, x->x_prefixes[arg]);
#else
sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]);
#endif
}
} else {
post("* OSCroute_assist: unrecognized message %ld", msg);
}
// ExitCallback();
}
void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
#ifdef ROCKBOX
(void) s;
#endif
// EnterCallback();
if (argc > 0 && argv[0].a_type == A_SYMBOL) {
/* Ignore the fact that this is a "list" */
OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1);
} else {
// post("* OSC-route: invalid list beginning with a number");
// output on unmatched outlet jdl 20020908
if (argv[0].a_type == A_FLOAT) {
outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float);
} else {
post("* OSC-route: unrecognized atom type!");
}
}
// ExitCallback();
}
void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
// EnterCallback();
OSCroute_doanything(x, s, argc, argv);
// ExitCallback();
}
void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
char *pattern, *nextSlash;
int i;
int matchedAnything;
// post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc);
pattern = s->s_name;
if (pattern[0] != '/') {
post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name);
outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
return;
}
matchedAnything = 0;
nextSlash = NextSlashOrNull(pattern+1);
if (*nextSlash == '\0') {
/* last level of the address, so we'll output the argument list */
#ifdef NULL_IS_DIFFERENT_FROM_BANG
if (argc==0) {
post("* OSC-route: why are you matching one level pattern %s with no args?",
pattern);
return;
}
#endif
for (i = 0; i < x->x_num; ++i) {
if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) {
++matchedAnything;
// I hate stupid Max lists with a special first element
if (argc == 0) {
outlet_bang(x->x_outlets[i]);
} else if (argv[0].a_type == A_SYMBOL) {
// Promote the symbol that was argv[0] to the special symbol
outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
} else if (argc > 1) {
// Multiple arguments starting with a number, so naturally we have
// to use a special function to output this "list", since it's what
// Max originally meant by "list".
outlet_list(x->x_outlets[i], 0L, argc, argv);
} else {
// There was only one argument, and it was a number, so we output it
// not as a list
/* if (argv[0].a_type == A_LONG) { */
/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */
// } else
if (argv[0].a_type == A_FLOAT) {
outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
} else {
post("* OSC-route: unrecognized atom type!");
}
}
}
}
} else {
/* There's more address after this part, so our output list will begin with
the next slash. */
t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
char patternBegin[1000];
/* Get the first level of the incoming pattern to match against all our prefixes */
StrCopyUntilSlash(patternBegin, pattern+1);
for (i = 0; i < x->x_num; ++i) {
if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) {
++matchedAnything;
if (restOfPattern == 0) {
restOfPattern = gensym(nextSlash);
}
outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
}
}
}
if (x->x_complainmode) {
if (!matchedAnything) {
post("* OSC-route: pattern %s did not match any prefixes", pattern);
}
}
// output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
if (!matchedAnything) {
outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
}
}
static char *NextSlashOrNull(char *p) {
while (*p != '/' && *p != '\0') {
p++;
}
return p;
}
static void StrCopyUntilSlash(char *target, const char *source) {
while (*source != '/' && *source != '\0') {
*target = *source;
++target;
++source;
}
*target = 0;
}
static int MyStrCopy(char *target, const char *source) {
int i = 0;
while (*source != '\0') {
*target = *source;
++target;
++source;
++i;
}
*target = 0;
return i;
}
void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
int i;
t_symbol *prefixSymbol = 0;
char prefixBuf[1000];
char *endOfPrefix;
t_atom a[1];
if (argc >= 1 && argv[0].a_type == A_SYMBOL) {
prefixSymbol = argv[0].a_w.w_symbol;
endOfPrefix = prefixBuf + MyStrCopy(prefixBuf,
prefixSymbol->s_name);
} else {
prefixSymbol = ps_emptySymbol;
prefixBuf[0] = '\0';
endOfPrefix = prefixBuf;
}
for (i = 0; i < x->x_num; ++i) {
post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]);
MyStrCopy(endOfPrefix, x->x_prefixes[i]);
SETSYMBOL(a, gensym(prefixBuf));
outlet_anything(x->x_outlets[i], s, 1, a);
}
}
/* --------------------------------------------------- */
static const char *theWholePattern; /* Just for warning messages */
static Boolean MatchBrackets (const char *pattern, const char *test);
static Boolean MatchList (const char *pattern, const char *test);
Boolean PatternMatch (const char * pattern, const char * test) {
theWholePattern = pattern;
if (pattern == 0 || pattern[0] == 0) {
return test[0] == 0;
}
if (test[0] == 0) {
if (pattern[0] == '*')
return PatternMatch (pattern+1,test);
else
return FALSE;
}
switch (pattern[0]) {
case 0 : return test[0] == 0;
case '?' : return PatternMatch (pattern + 1, test + 1);
case '*' :
if (PatternMatch (pattern+1, test)) {
return TRUE;
} else {
return PatternMatch (pattern, test+1);
}
case ']' :
case '}' :
OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
return FALSE;
case '[' :
return MatchBrackets (pattern,test);
case '{' :
return MatchList (pattern,test);
case '\\' :
if (pattern[1] == 0) {
return test[0] == 0;
} else if (pattern[1] == test[0]) {
return PatternMatch (pattern+2,test+1);
} else {
return FALSE;
}
default :
if (pattern[0] == test[0]) {
return PatternMatch (pattern+1,test+1);
} else {
return FALSE;
}
}
}
/* we know that pattern[0] == '[' and test[0] != 0 */
static Boolean MatchBrackets (const char *pattern, const char *test) {
Boolean result;
Boolean negated = FALSE;
const char *p = pattern;
if (pattern[1] == 0) {
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return FALSE;
}
if (pattern[1] == '!') {
negated = TRUE;
p++;
}
while (*p != ']') {
if (*p == 0) {
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return FALSE;
}
if (p[1] == '-' && p[2] != 0) {
if (test[0] >= p[0] && test[0] <= p[2]) {
result = !negated;
goto advance;
}
}
if (p[0] == test[0]) {
result = !negated;
goto advance;
}
p++;
}
result = negated;
advance:
if (!result)
return FALSE;
while (*p != ']') {
if (*p == 0) {
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return FALSE;
}
p++;
}
return PatternMatch (p+1,test+1);
}
static Boolean MatchList (const char *pattern, const char *test) {
const char *restOfPattern, *tp = test;
for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
if (*restOfPattern == 0) {
OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
return FALSE;
}
}
restOfPattern++; /* skip close curly brace */
pattern++; /* skip open curly brace */
while (1) {
if (*pattern == ',') {
if (PatternMatch (restOfPattern, tp)) {
return TRUE;
} else {
tp = test;
++pattern;
}
} else if (*pattern == '}') {
return PatternMatch (restOfPattern, tp);
} else if (*pattern == *tp) {
++pattern;
++tp;
} else {
tp = test;
while (*pattern != ',' && *pattern != '}') {
pattern++;
}
if (*pattern == ',') {
pattern++;
}
}
}
}

View file

@ -1,18 +0,0 @@
#N canvas 428 285 240 300 8;
#X obj 24 78 noise~;
#X obj 15 215 dac~;
#X obj 24 167 biquad~;
#X floatatom 67 76 5 0 0 0 - - -;
#X floatatom 83 111 5 0 0 0 - - -;
#X obj 67 138 bandpass 600 10;
#X text 77 97 bandwidth: 100 = 1 octave;
#X text 67 58 frequency;
#X text 8 11 Calculation of biquad coefficients;
#X text 7 21 ==================================;
#X connect 0 0 2 0;
#X connect 2 0 1 0;
#X connect 2 0 1 1;
#X connect 3 0 5 0;
#X connect 4 0 5 1;
#X connect 5 0 2 0;

File diff suppressed because it is too large Load diff

View file

@ -1,486 +0,0 @@
/* ------------------------ fatom ----------------------------- */
#define x_val a_pos.a_w.w_float
#define DEBUG(x)
#include <string.h>
#include <stdio.h>
typedef struct _fatom
{
t_object x_obj;
t_atom a_pos; /* the value of the fatom */
t_symbol* x_send;
t_symbol* x_receive;
t_glist * x_glist; /* value of the current canvas, intialized in _new */
int x_rect_width; /* width of the widget */
int x_rect_height; /* height of the widget */
t_symbol* x_sym; /* symbol for receiving callbacks from GUI */
t_symbol* x_type; /* type of fatom (vslider, hslider, checkbutton) */
t_symbol* x_text; /* associated widget text */
int x_max; /* maximum value of a_pos (x_val) */
int x_min; /* minimum value of a_pos (x_val) */
int x_width; /* width of widget (e.g x_rect_height + 15 for hslider, x_rect_width + 15 for slider) */
t_symbol* x_color;
t_symbol* x_bgcolor;
} t_fatom;
/* widget helper functions */
static void draw_inlets(t_fatom *x, t_glist *glist, int firsttime, int nin, int nout)
{
int n = nin;
int nplus, i;
nplus = (n == 1 ? 1 : n-1);
DEBUG(post("draw inlet");)
for (i = 0; i < n; i++)
{
int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
if (firsttime)
sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
glist_getcanvas(glist),
onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height,
x, i);
else
sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
glist_getcanvas(glist), x, i,
onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height);
}
n = nout;
nplus = (n == 1 ? 1 : n-1);
for (i = 0; i < n; i++)
{
int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
if (firsttime)
sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
glist_getcanvas(glist),
onset, text_ypix(&x->x_obj, glist),
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1,
x, i);
else
sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
glist_getcanvas(glist), x, i,
onset, text_ypix(&x->x_obj, glist),
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1);
}
DEBUG(post("draw inlet end");)
}
static void draw_handle(t_fatom *x, t_glist *glist, int firsttime) {
int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2);
if (firsttime)
sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n",
glist_getcanvas(glist),
onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4,
x);
else
sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n",
glist_getcanvas(glist), x,
onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4);
}
static void create_widget(t_fatom *x, t_glist *glist)
{
t_canvas *canvas=glist_getcanvas(glist);
if (!strcmp(x->x_type->s_name,"vslider")) {
x->x_rect_width = x->x_width+15;
x->x_rect_height = x->x_max-x->x_min+26;
sys_vgui("scale .x%x.c.s%x \
-sliderlength 10 \
-showvalue 0 \
-length %d \
-resolution 0.01 \
-repeatinterval 20 \
-from %d -to %d \
-width %d \
-bg %s \
-activebackground %s \
-troughcolor %s \
-command fatom_cb%x\n",canvas,x,
x->x_max-x->x_min+14,
x->x_max,
x->x_min,
x->x_width,
x->x_color->s_name,
x->x_color->s_name,
x->x_bgcolor->s_name,
x);
} else if (!strcmp(x->x_type->s_name,"hslider")) {
x->x_rect_width = x->x_max-x->x_min + 24;
x->x_rect_height = x->x_width + 15;
sys_vgui("scale .x%x.c.s%x \
-sliderlength 10 \
-showvalue 0 \
-length %d \
-resolution 0.01 \
-orient horizontal \
-repeatinterval 20 \
-from %d -to %d \
-width %d \
-bg %s \
-activebackground %s \
-troughcolor %s \
-command fatom_cb%x\n",canvas,x,
x->x_max-x->x_min+14,
x->x_min,
x->x_max,
x->x_width,
x->x_color->s_name,
x->x_color->s_name,
x->x_bgcolor->s_name,
x);
} else if (!strcmp(x->x_type->s_name,"checkbutton")) {
x->x_rect_width = 32;
x->x_rect_height = 28;
sys_vgui("checkbutton .x%x.c.s%x \
-command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -text \"%s\" \
-bg %s \
-activebackground %s \
\n",canvas,x,x,x,x,
x->x_text->s_name,
x->x_color->s_name,
x->x_bgcolor->s_name);
} else if (!strcmp(x->x_type->s_name,"hradio")) {
int i;
x->x_rect_width = 8*20;
x->x_rect_height = 25;
for (i=0;i<8;i++) {
sys_vgui("radiobutton .x%x.c.s%x%d \
-command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
}
/* TODO pack them */
} else if (!strcmp(x->x_type->s_name,"vradio")) {
int i;
x->x_rect_width = 30;
x->x_rect_height = 20*8+5;
for (i=0;i<8;i++) {
sys_vgui("radiobutton .x%x.c.s%x%d \
-command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
}
/* TODO pack them */
} else {
x->x_rect_width = 32;
x->x_rect_height = 140;
sys_vgui("scale .x%x.c.s%x \
-sliderlength 10 \
-showvalue 0 \
-length 131 \
-from 127 -to 0 \
-command fatom_cb%x\n",canvas,x,x);
}
/* set the start value */
if (!strcmp(x->x_type->s_name,"checkbutton")) {
if (x->x_val)
sys_vgui(".x%x.c.s%x select\n",canvas,x,x->x_val);
else
sys_vgui(".x%x.c.s%x deselect\n",canvas,x,x->x_val);
} else
sys_vgui(".x%x.c.s%x set %f\n",canvas,x,x->x_val);
}
static void fatom_drawme(t_fatom *x, t_glist *glist, int firsttime)
{
t_canvas *canvas=glist_getcanvas(glist);// x->x_glist;//glist_getcanvas(glist);
DEBUG(post("drawme %d",firsttime);)
if (firsttime) {
DEBUG(post("glist %x canvas %x",x->x_glist,canvas));
create_widget(x,glist);
x->x_glist = canvas;
sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x -tags %xS\n",
canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2,x->x_glist,x,x);
}
else {
sys_vgui(".x%x.c coords %xS \
%d %d\n",
canvas, x,
text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2);
}
draw_inlets(x, glist, firsttime, 1,1);
// draw_handle(x, glist, firsttime);
}
static void fatom_erase(t_fatom* x,t_glist* glist)
{
int n;
DEBUG(post("erase");)
sys_vgui("destroy .x%x.c.s%x\n",glist_getcanvas(glist),x);
sys_vgui(".x%x.c delete %xS\n",glist_getcanvas(glist), x);
/* inlets and outlets */
sys_vgui(".x%x.c delete %xi%d\n",glist_getcanvas(glist),x,0);
sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,0);
sys_vgui(".x%x.c delete %xhandle\n",glist_getcanvas(glist),x,0);
}
/* ------------------------ fatom widgetbehaviour----------------------------- */
static void fatom_getrect(t_gobj *z, t_glist *owner,
int *xp1, int *yp1, int *xp2, int *yp2)
{
int width, height;
t_fatom* s = (t_fatom*)z;
width = s->x_rect_width;
height = s->x_rect_height;
*xp1 = text_xpix(&s->x_obj, owner);
*yp1 = text_ypix(&s->x_obj, owner);
*xp2 = text_xpix(&s->x_obj, owner) + width;
*yp2 = text_ypix(&s->x_obj, owner) + height;
}
static void fatom_displace(t_gobj *z, t_glist *glist,
int dx, int dy)
{
t_fatom *x = (t_fatom *)z;
DEBUG(post("displace");)
x->x_obj.te_xpix += dx;
x->x_obj.te_ypix += dy;
if (glist_isvisible(glist))
{
sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
glist_getcanvas(glist), x,
text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height);
fatom_drawme(x, glist, 0);
canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
}
DEBUG(post("displace end");)
}
static void fatom_select(t_gobj *z, t_glist *glist, int state)
{
t_fatom *x = (t_fatom *)z;
if (state) {
sys_vgui(".x%x.c create rectangle \
%d %d %d %d -tags %xSEL -outline blue\n",
glist_getcanvas(glist),
text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height,
x);
}
else {
sys_vgui(".x%x.c delete %xSEL\n",
glist_getcanvas(glist), x);
}
}
static void fatom_activate(t_gobj *z, t_glist *glist, int state)
{
/* t_text *x = (t_text *)z;
t_rtext *y = glist_findrtext(glist, x);
if (z->g_pd != gatom_class) rtext_activate(y, state);*/
}
static void fatom_delete(t_gobj *z, t_glist *glist)
{
t_text *x = (t_text *)z;
canvas_deletelinesfor(glist_getcanvas(glist), x);
}
static void fatom_vis(t_gobj *z, t_glist *glist, int vis)
{
t_fatom* s = (t_fatom*)z;
t_rtext *y;
DEBUG(post("vis: %d",vis);)
if (vis) {
#ifdef PD_MINOR_VERSION
y = (t_rtext *) rtext_new(glist, (t_text *)z);
#else
y = (t_rtext *) rtext_new(glist, (t_text *)z,0,0);
#endif
fatom_drawme(s, glist, 1);
}
else {
y = glist_findrtext(glist, (t_text *)z);
fatom_erase(s,glist);
rtext_free(y);
}
}
static void fatom_save(t_gobj *z, t_binbuf *b);
t_widgetbehavior fatom_widgetbehavior;
static void fatom_size(t_fatom* x,t_floatarg w,t_floatarg h) {
x->x_rect_width = w;
x->x_rect_height = h;
}
static void fatom_color(t_fatom* x,t_symbol* col)
{
}
static void fatom_f(t_fatom* x,t_floatarg f)
{
x->x_val = f;
if (x->x_send == &s_)
outlet_float(x->x_obj.ob_outlet,f);
else
if (x->x_send->s_thing) pd_float(x->x_send->s_thing,f);
}
static void fatom_float(t_fatom* x,t_floatarg f)
{
if (glist_isvisible(x->x_glist)) {
if (!strcmp(x->x_type->s_name,"checkbutton")) {
if (x->x_val)
sys_vgui(".x%x.c.s%x select\n",x->x_glist,x,f);
else
sys_vgui(".x%x.c.s%x deselect\n",x->x_glist,x,f);
} else
sys_vgui(".x%x.c.s%x set %f\n",x->x_glist,x,f);
}
fatom_f(x,f);
}
static void fatom_bang(t_fatom* x,t_floatarg f)
{
outlet_float(x->x_obj.ob_outlet,x->x_val);
}
static void fatom_properties(t_gobj *z, t_glist *owner)
{
post("N/I");
}
static void fatom_save(t_gobj *z, t_binbuf *b)
{
t_fatom *x = (t_fatom *)z;
binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"),
x->x_obj.te_xpix, x->x_obj.te_ypix ,
gensym("fatom"),x->x_type);
binbuf_addv(b, ";");
}
static void *fatom_new(t_fatom* x,int argc,t_atom* argv)
{
char buf[256];
int n = 0;
x->x_glist = canvas_getcurrent();
x->x_text = gensym("");
x->x_max = 127;
x->x_min = 0;
x->x_width = 15;
x->x_color = gensym("grey");
x->x_bgcolor = gensym("grey");
x->x_send = &s_;
while (argc) {
if (argv->a_type == A_FLOAT) {
if (n==0) x->x_max = atom_getfloat(argv);
if (n==1) x->x_min = atom_getfloat(argv);
if (n==2) x->x_width = atom_getfloat(argv);
}
if (argv->a_type == A_SYMBOL) {
post("%d: symbol value %s",n,atom_getsymbol(argv)->s_name);
if (n==3) x->x_send = atom_getsymbol(argv);
if (n==4) x->x_color = atom_getsymbol(argv);
if (n==5) x->x_bgcolor = atom_getsymbol(argv);
}
argv++;
argc--;
n++;
}
/* bind to a symbol for slider callback (later make this based on the
filepath ??) */
sprintf(buf,"fatom%x",(t_int)x);
x->x_sym = gensym(buf);
pd_bind(&x->x_obj.ob_pd, x->x_sym);
/* pipe startup code to tk */
sys_vgui("proc fatom_cb%x {v} {\n pd [concat fatom%x f $v \\;]\n }\n",x,x);
outlet_new(&x->x_obj, &s_float);
return (x);
}
static void fatom_setup_common(t_class* class)
{
fatom_widgetbehavior.w_getrectfn = fatom_getrect;
fatom_widgetbehavior.w_displacefn = fatom_displace;
fatom_widgetbehavior.w_selectfn = fatom_select;
fatom_widgetbehavior.w_activatefn = fatom_activate;
fatom_widgetbehavior.w_deletefn = fatom_delete;
fatom_widgetbehavior.w_visfn = fatom_vis;
#if PD_MINOR_VERSION < 37
fatom_widgetbehavior.w_savefn = fatom_save;
fatom_widgetbehavior.w_propertiesfn = NULL;
#endif
fatom_widgetbehavior.w_clickfn = NULL;
class_addfloat(class, (t_method)fatom_float);
class_addbang(class, (t_method)fatom_bang);
class_addmethod(class, (t_method)fatom_f, gensym("f"),
A_FLOAT, 0);
/*
class_addmethod(class, (t_method)fatom_size, gensym("size"),
A_FLOAT, A_FLOAT, 0);
class_addmethod(class, (t_method)fatom_color, gensym("color"),
A_SYMBOL, 0);
*/
/*
class_addmethod(class, (t_method)fatom_open, gensym("open"),
A_SYMBOL, 0);
*/
class_setwidget(class,&fatom_widgetbehavior);
#if PD_MINOR_VERSION >= 37
class_setsavefn(class,&fatom_save);
#endif
}

View file

@ -1,9 +0,0 @@
#N canvas 0 0 240 300 8;
#X obj 21 61 gcanvas 80 80;
#X text 14 9 gcanvas .. mouse coordinate enabled canvas;
#X text 13 22 ==========================================;
#X floatatom 21 148 5 0 0 0 - - -;
#X floatatom 94 147 5 0 0 0 - - -;
#X connect 0 0 3 0;
#X connect 0 1 4 0;

View file

@ -1,34 +0,0 @@
VERSION = 0.2
SOURCE = $(shell ls *.c)
TARGETS = $(SOURCE:.c=.pd_linux)
EXT= pd_linux
AFLAGS = -g -O2 -I./ -DFIXEDPOINT
EFLAGS = -shared -Wl,-export-dynamic
PREFIX = /usr
all: $(TARGETS)
clean:
-rm $(TARGETS)
-rm *.o *~
tar: clean
cd ..;tar czvf PDa-externals-$(VERSION).tgz PDa-externals
upload: tar
scp ../PDa-externals-$(VERSION).tgz gige@xdv.org:~/www/pda/release
install:
install -d $(DESTDIR)/$(PREFIX)/lib/pd/extra
cp $(TARGETS) $(DESTDIR)/$(PREFIX)/lib/pd/extra
%.$(EXT) : %.o
$(CC) -o $@ $(EFLAGS) $+
%.o : %.c
$(CC) -c $(AFLAGS) $(CFLAGS) $+

File diff suppressed because it is too large Load diff

View file

@ -1,56 +0,0 @@
#ifndef SFORMAT_H__
#define SFORMAT_H__
typedef unsigned short uint16;
typedef unsigned long uint32;
#define FORMAT_WAVE 0
#define FORMAT_AIFF 1
#define FORMAT_NEXT 2
/* the NeXTStep sound header structure; can be big or little endian */
typedef struct _nextstep
{
char ns_fileid[4]; /* magic number '.snd' if file is big-endian */
uint32 ns_onset; /* byte offset of first sample */
uint32 ns_length; /* length of sound in bytes */
uint32 ns_format; /* format; see below */
uint32 ns_sr; /* sample rate */
uint32 ns_nchans; /* number of channels */
char ns_info[4]; /* comment */
} t_nextstep;
#define NS_FORMAT_LINEAR_16 3
#define NS_FORMAT_LINEAR_24 4
#define NS_FORMAT_FLOAT 6
#define SCALE (1./(1024. * 1024. * 1024. * 2.))
/* the WAVE header. All Wave files are little endian. We assume
the "fmt" chunk comes first which is usually the case but perhaps not
always; same for AIFF and the "COMM" chunk. */
typedef unsigned word;
typedef unsigned long dword;
typedef struct _wave
{
char w_fileid[4]; /* chunk id 'RIFF' */
uint32 w_chunksize; /* chunk size */
char w_waveid[4]; /* wave chunk id 'WAVE' */
char w_fmtid[4]; /* format chunk id 'fmt ' */
uint32 w_fmtchunksize; /* format chunk size */
uint16 w_fmttag; /* format tag, 1 for PCM */
uint16 w_nchannels; /* number of channels */
uint32 w_samplespersec; /* sample rate in hz */
uint32 w_navgbytespersec; /* average bytes per second */
uint16 w_nblockalign; /* number of bytes per sample */
uint16 w_nbitspersample; /* number of bits in a sample */
char w_datachunkid[4]; /* data chunk id 'data' */
uint32 w_datachunksize; /* length of data chunk */
} t_wave;
#endif

View file

@ -1,312 +0,0 @@
/* (C) Guenter Geiger <geiger@epy.co.at> */
#include "../src/m_pd.h"
#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sched.h>
void sys_rmpollfn(int fd);
void sys_addpollfn(int fd, void* fn, void *ptr);
/* ------------------------ shell ----------------------------- */
#define INBUFSIZE 1024
static t_class *shell_class;
static void drop_priority(void)
{
#ifdef _POSIX_PRIORITY_SCHEDULING
struct sched_param par;
int p1 ,p2, p3;
par.sched_priority = 0;
sched_setscheduler(0,SCHED_OTHER,&par);
#endif
}
typedef struct _shell
{
t_object x_obj;
int x_echo;
char *sr_inbuf;
int sr_inhead;
int sr_intail;
void* x_binbuf;
int fdpipe[2];
int fdinpipe[2];
int pid;
int x_del;
t_outlet* x_done;
t_clock* x_clock;
} t_shell;
static int shell_pid;
void shell_cleanup(t_shell* x)
{
sys_rmpollfn(x->fdpipe[0]);
if (x->fdpipe[0]>0) close(x->fdpipe[0]);
if (x->fdpipe[1]>0) close(x->fdpipe[1]);
if (x->fdinpipe[0]>0) close(x->fdinpipe[0]);
if (x->fdinpipe[1]>0) close(x->fdinpipe[1]);
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
x->fdinpipe[0] = -1;
x->fdinpipe[1] = -1;
clock_unset(x->x_clock);
}
void shell_check(t_shell* x)
{
int ret;
int status;
ret = waitpid(x->pid,&status,WNOHANG);
if (ret == x->pid) {
shell_cleanup(x);
if (WIFEXITED(status)) {
outlet_float(x->x_done,WEXITSTATUS(status));
}
else outlet_float(x->x_done,0);
}
else {
if (x->x_del < 100) x->x_del+=2; /* increment poll times */
clock_delay(x->x_clock,x->x_del);
}
}
void shell_bang(t_shell *x)
{
post("bang");
}
/* snippet from pd's code */
static void shell_doit(void *z, t_binbuf *b)
{
t_shell *x = (t_shell *)z;
int msg, natom = binbuf_getnatom(b);
t_atom *at = binbuf_getvec(b);
for (msg = 0; msg < natom;)
{
int emsg;
for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
&& at[emsg].a_type != A_SEMI; emsg++)
;
if (emsg > msg)
{
int i;
for (i = msg; i < emsg; i++)
if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
{
pd_error(x, "netreceive: got dollar sign in message");
goto nodice;
}
if (at[msg].a_type == A_FLOAT)
{
if (emsg > msg + 1)
outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
}
else if (at[msg].a_type == A_SYMBOL)
outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
emsg-msg-1, at + msg + 1);
}
nodice:
msg = emsg + 1;
}
}
void shell_read(t_shell *x, int fd)
{
char buf[INBUFSIZE];
t_binbuf* bbuf = binbuf_new();
int i;
int readto =
(x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
int ret;
ret = read(fd, buf,INBUFSIZE-1);
buf[ret] = '\0';
for (i=0;i<ret;i++)
if (buf[i] == '\n') buf[i] = ';';
if (ret < 0)
{
error("shell: pipe read error");
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else if (ret == 0)
{
post("EOF on socket %d\n", fd);
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else
{
int natom;
t_atom *at;
binbuf_text(bbuf, buf, strlen(buf));
natom = binbuf_getnatom(bbuf);
at = binbuf_getvec(bbuf);
shell_doit(x,bbuf);
}
binbuf_free(bbuf);
}
static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
{
int i;
char tmp[MAXPDSTRING];
int size = 0;
if (x->fdinpipe[0] == -1) return; /* nothing to send to */
for (i=0;i<ac;i++) {
atom_string(at,tmp+size,MAXPDSTRING - size);
at++;
size=strlen(tmp);
tmp[size++] = ' ';
}
tmp[size-1] = '\0';
post("sending %s",tmp);
write(x->fdinpipe[0],tmp,strlen(tmp));
}
static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
{
int i;
char* argv[20];
t_symbol* sym;
if (!strcmp(s->s_name,"send")) {
post("send");
shell_send(x,s,ac,at);
return;
}
argv[0] = s->s_name;
if (x->fdpipe[0] != -1) {
post("shell: old process still running");
kill(x->pid,SIGKILL);
shell_cleanup(x);
}
if (pipe(x->fdpipe) < 0) {
error("unable to create pipe");
return;
}
if (pipe(x->fdinpipe) < 0) {
error("unable to create input pipe");
return;
}
sys_addpollfn(x->fdpipe[0],shell_read,x);
if (!(x->pid = fork())) {
int status;
char* cmd = getbytes(1024);
char* tcmd = getbytes(1024);
strcpy(cmd,s->s_name);
#if 0
for (i=1;i<=ac;i++) {
argv[i] = getbytes(255);
atom_string(at,argv[i],255);
/* post("argument %s",argv[i]); */
at++;
}
argv[i] = 0;
#endif
for (i=1;i<=ac;i++) {
atom_string(at,tcmd,255);
strcat(cmd," ");
strcat(cmd,tcmd);
at++;
}
/* reassign stdout */
dup2(x->fdpipe[1],1);
dup2(x->fdinpipe[1],0);
/* drop privileges */
drop_priority();
seteuid(getuid()); /* lose setuid priveliges */
post("executing %s",cmd);
system(cmd);
// execvp(s->s_name,argv);
exit(0);
}
x->x_del = 4;
clock_delay(x->x_clock,x->x_del);
if (x->x_echo)
outlet_anything(x->x_obj.ob_outlet, s, ac, at);
}
void shell_free(t_shell* x)
{
binbuf_free(x->x_binbuf);
}
static void *shell_new(void)
{
t_shell *x = (t_shell *)pd_new(shell_class);
x->x_echo = 0;
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
x->fdinpipe[0] = -1;
x->fdinpipe[1] = -1;
x->sr_inhead = x->sr_intail = 0;
if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
x->x_binbuf = binbuf_new();
outlet_new(&x->x_obj, &s_list);
x->x_done = outlet_new(&x->x_obj, &s_bang);
x->x_clock = clock_new(x, (t_method) shell_check);
return (x);
}
void shell_setup(void)
{
shell_class = class_new(gensym("shell"), (t_newmethod)shell_new,
(t_method)shell_free,sizeof(t_shell), 0,0);
class_addbang(shell_class,shell_bang);
class_addanything(shell_class, shell_anything);
}

View file

@ -1,54 +0,0 @@
#include <stdio.h>
#include "../src/m_pd.h"
#include "g_canvas.h" /* for widgetbehaviour */
#include "fatom.h"
static t_class *slider_class;
static void slider_save(t_gobj *z, t_binbuf *b)
{
t_fatom *x = (t_fatom *)z;
binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
x->x_obj.te_xpix, x->x_obj.te_ypix ,
gensym("slider"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
binbuf_addv(b, ";");
}
static void *slider_new(t_symbol* s,t_int argc, t_atom* argv)
{
t_fatom *x = (t_fatom *)pd_new(slider_class);
x->x_type = gensym("vslider");
return fatom_new(x,argc,argv);
}
t_widgetbehavior slider_widgetbehavior;
void slider_setup(void) {
slider_class = class_new(gensym("slider"), (t_newmethod)slider_new, 0,
sizeof(t_fatom),0,A_GIMME,0);
slider_widgetbehavior.w_getrectfn = fatom_getrect;
slider_widgetbehavior.w_displacefn = fatom_displace;
slider_widgetbehavior.w_selectfn = fatom_select;
slider_widgetbehavior.w_activatefn = fatom_activate;
slider_widgetbehavior.w_deletefn = fatom_delete;
slider_widgetbehavior.w_visfn= fatom_vis;
slider_widgetbehavior.w_clickfn = NULL;
fatom_setup_common(slider_class);
class_setwidget(slider_class,&slider_widgetbehavior);
#if PD_MINOR_VERSION < 37
slider_widgetbehavior.w_savefn = slider_save;
slider_widgetbehavior.w_propertiesfn = NULL;
#else
class_setsavefn(slider_class,&slider_save);
class_setpropertiesfn(slider_class,&fatom_properties);
#endif
}

View file

@ -1,64 +0,0 @@
#include "../src/m_pd.h"
#include "g_canvas.h"
#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif
#include "fatom.h"
/* can we use the normal text save function ?? */
static t_class *sliderh_class;
static void sliderh_save(t_gobj *z, t_binbuf *b)
{
t_fatom *x = (t_fatom *)z;
binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
x->x_obj.te_xpix, x->x_obj.te_ypix ,
gensym("sliderh"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
binbuf_addv(b, ";");
}
static void *sliderh_new(t_symbol* s, int argc, t_atom* argv)
{
t_fatom *x = (t_fatom *)pd_new(sliderh_class);
x->x_type = gensym("hslider");
return fatom_new(x,argc,argv);
}
t_widgetbehavior sliderh_widgetbehavior;
void sliderh_setup(void) {
sliderh_class = class_new(gensym("sliderh"), (t_newmethod)sliderh_new, 0,
sizeof(t_fatom),0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
fatom_setup_common(sliderh_class);
sliderh_widgetbehavior.w_getrectfn = fatom_getrect;
sliderh_widgetbehavior.w_displacefn= fatom_displace;
sliderh_widgetbehavior.w_selectfn= fatom_select;
sliderh_widgetbehavior.w_activatefn=fatom_activate;
sliderh_widgetbehavior.w_deletefn= fatom_delete;
sliderh_widgetbehavior.w_visfn= fatom_vis;
#if PD_MINOR_VERSION < 37
sliderh_widgetbehavior.w_savefn= sliderh_save;
sliderh_widgetbehavior.w_propertiesfn= NULL;
#endif
sliderh_widgetbehavior.w_clickfn= NULL;
class_setwidget(sliderh_class,&sliderh_widgetbehavior);
#if PD_MINOR_VERSION >= 37
class_setsavefn(sliderh_class,&sliderh_save);
#endif
}

View file

@ -1,14 +0,0 @@
#N canvas 0 0 240 300 10;
#X obj 57 84 clip~ -0.1 0.1;
#X obj 58 61 sig~;
#X obj 57 111 snapshot~;
#X floatatom 58 19 5 0 0 0 - - -;
#X floatatom 57 144 5 0 0 0 - - -;
#X obj 58 37 t f b;
#X connect 0 0 2 0;
#X connect 1 0 0 0;
#X connect 2 0 4 0;
#X connect 3 0 5 0;
#X connect 5 0 1 0;
#X connect 5 1 2 0;

View file

@ -1,19 +0,0 @@
#N canvas 0 0 240 300 10;
#X obj 38 93 noise~;
#X obj 44 161 vcf~;
#X obj 48 191 dac~;
#X floatatom 138 33 5 0 0 0 - - -;
#X obj 44 18 osc~ 1;
#X obj 46 75 *~ 800;
#X obj 48 48 +~ 2;
#X obj 106 125 sig~;
#X floatatom 132 77 5 0 0 0 - - -;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 1 0 2 1;
#X connect 3 0 1 2;
#X connect 4 0 6 0;
#X connect 6 0 5 0;
#X connect 7 0 1 1;
#X connect 8 0 7 0;

View file

@ -1,68 +0,0 @@
#include "../src/m_pd.h"
#include <../src/m_fixed.h>
static t_class *sig_tilde_class;
typedef struct _sig
{
t_object x_obj;
t_sample x_f;
} t_sig;
static t_int *sig_tilde_perform(t_int *w)
{
t_sample f = *(t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--)
*out++ = f;
return (w+4);
}
static t_int *sig_tilde_perf8(t_int *w)
{
t_sample f = *(t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
for (; n; n -= 8, out += 8)
{
out[0] = f;
out[1] = f;
out[2] = f;
out[3] = f;
out[4] = f;
out[5] = f;
out[6] = f;
out[7] = f;
}
return (w+4);
}
static void sig_tilde_float(t_sig *x, t_float f)
{
x->x_f = ftofix(f);
}
static void sig_tilde_dsp(t_sig *x, t_signal **sp)
{
dsp_add(sig_tilde_perform, 3, &x->x_f, sp[0]->s_vec, sp[0]->s_n);
}
static void *sig_tilde_new(t_floatarg f)
{
t_sig *x = (t_sig *)pd_new(sig_tilde_class);
x->x_f = ftofix(f);
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}
void sig_tilde_setup(void)
{
sig_tilde_class = class_new(gensym("sig~"), (t_newmethod)sig_tilde_new, 0,
sizeof(t_sig), 0, A_DEFFLOAT, 0);
class_addfloat(sig_tilde_class, (t_method)sig_tilde_float);
class_addmethod(sig_tilde_class, (t_method)sig_tilde_dsp, gensym("dsp"), 0);
}

View file

@ -1,6 +0,0 @@
# The compiler for iPod has a bug with -O6, thats why we try to compile twice
make CFLAGS="-O6 -ffast-math -fexpensive-optimizations -mcpu=arm7tdmi " -k ipod
make CFLAGS="-O2 -ffast-math -fexpensive-optimizations -mcpu=arm7tdmi" ipod

File diff suppressed because it is too large Load diff

View file

@ -1,319 +0,0 @@
/* 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. */
/* send~, delread~, throw~, catch~ */
#include "m_pd.h"
extern int ugen_getsortno(void);
#define DEFDELVS 64 /* LATER get this from canvas at DSP time */
static int delread_zero = 0; /* four bytes of zero for delread~, vd~ */
/* ----------------------------- delwrite~ ----------------------------- */
static t_class *sigdelwrite_class;
typedef struct delwritectl
{
int c_n;
float *c_vec;
int c_phase;
} t_delwritectl;
typedef struct _sigdelwrite
{
t_object x_obj;
t_symbol *x_sym;
t_delwritectl x_cspace;
int x_sortno; /* DSP sort number at which this was last put on chain */
int x_rsortno; /* DSP sort # for first delread or write in chain */
int x_vecsize; /* vector size for delread~ to use */
float x_f;
} t_sigdelwrite;
#define XTRASAMPS 4
#define SAMPBLK 4
/* routine to check that all delwrites/delreads/vds have same vecsize */
static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
{
/*
LATER this should really check sample rate and blocking, once that is
supported. Probably we don't actually care about vecsize.
For now just suppress this check... */
#if 0
if (x->x_rsortno != ugen_getsortno())
{
x->x_vecsize = vecsize;
x->x_rsortno = ugen_getsortno();
}
else if (vecsize != x->x_vecsize)
pd_error(x, "delread/delwrite/vd vector size mismatch");
#endif
}
static void *sigdelwrite_new(t_symbol *s, t_floatarg msec)
{
int nsamps;
t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class);
if (!*s->s_name) s = gensym("delwrite~");
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
nsamps = msec * sys_getsr() * (float)(0.001f);
if (nsamps < 1) nsamps = 1;
nsamps += ((- nsamps) & (SAMPBLK - 1));
nsamps += DEFDELVS;
x->x_cspace.c_n = nsamps;
x->x_cspace.c_vec =
(float *)getbytes((nsamps + XTRASAMPS) * sizeof(float));
x->x_cspace.c_phase = XTRASAMPS;
x->x_sortno = 0;
x->x_vecsize = 0;
x->x_f = 0;
return (x);
}
static t_int *sigdelwrite_perform(t_int *w)
{
t_float *in = (t_float *)(w[1]);
t_delwritectl *c = (t_delwritectl *)(w[2]);
int n = (int)(w[3]);
int phase = c->c_phase, nsamps = c->c_n;
float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS);
phase += n;
while (n--)
{
float f = *in++;
if (PD_BIGORSMALL(f))
f = 0;
*bp++ = f;
if (bp == ep)
{
vp[0] = ep[-4];
vp[1] = ep[-3];
vp[2] = ep[-2];
vp[3] = ep[-1];
bp = vp + XTRASAMPS;
phase -= nsamps;
}
}
c->c_phase = phase;
return (w+4);
}
static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp)
{
dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
x->x_sortno = ugen_getsortno();
sigdelwrite_checkvecsize(x, sp[0]->s_n);
}
static void sigdelwrite_free(t_sigdelwrite *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
freebytes(x->x_cspace.c_vec,
(x->x_cspace.c_n + XTRASAMPS) * sizeof(float));
}
static void sigdelwrite_setup(void)
{
sigdelwrite_class = class_new(gensym("delwrite~"),
(t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free,
sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f);
class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp,
gensym("dsp"), 0);
}
/* ----------------------------- delread~ ----------------------------- */
static t_class *sigdelread_class;
typedef struct _sigdelread
{
t_object x_obj;
t_symbol *x_sym;
t_float x_deltime; /* delay in msec */
int x_delsamps; /* delay in samples */
t_float x_sr; /* samples per msec */
t_float x_n; /* vector size */
int x_zerodel; /* 0 or vecsize depending on read/write order */
} t_sigdelread;
static void sigdelread_float(t_sigdelread *x, t_float f);
static void *sigdelread_new(t_symbol *s, t_floatarg f)
{
t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class);
x->x_sym = s;
x->x_sr = 1;
x->x_n = 1;
x->x_zerodel = 0;
sigdelread_float(x, f);
outlet_new(&x->x_obj, &s_signal);
return (x);
}
static void sigdelread_float(t_sigdelread *x, t_float f)
{
int samps;
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_deltime = f;
if (delwriter)
{
int delsize = delwriter->x_cspace.c_n;
x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime)
+ x->x_n - x->x_zerodel;
if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n;
else if (x->x_delsamps > delwriter->x_cspace.c_n - DEFDELVS)
x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS;
}
}
static t_int *sigdelread_perform(t_int *w)
{
t_float *out = (t_float *)(w[1]);
t_delwritectl *c = (t_delwritectl *)(w[2]);
int delsamps = *(int *)(w[3]);
int n = (int)(w[4]);
int phase = c->c_phase - delsamps, nsamps = c->c_n;
float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS);
if (phase < 0) phase += nsamps;
bp = vp + phase;
while (n--)
{
*out++ = *bp++;
if (bp == ep) bp -= nsamps;
}
return (w+5);
}
static void sigdelread_dsp(t_sigdelread *x, t_signal **sp)
{
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_sr = sp[0]->s_sr * 0.001;
x->x_n = sp[0]->s_n;
if (delwriter)
{
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
sigdelread_float(x, x->x_deltime);
dsp_add(sigdelread_perform, 4,
sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n);
}
else if (*x->x_sym->s_name)
error("delread~: %s: no such delwrite~",x->x_sym->s_name);
}
static void sigdelread_setup(void)
{
sigdelread_class = class_new(gensym("delread~"),
(t_newmethod)sigdelread_new, 0,
sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0);
class_addmethod(sigdelread_class, (t_method)sigdelread_dsp,
gensym("dsp"), 0);
class_addfloat(sigdelread_class, (t_method)sigdelread_float);
}
/* ----------------------------- vd~ ----------------------------- */
static t_class *sigvd_class;
typedef struct _sigvd
{
t_object x_obj;
t_symbol *x_sym;
t_float x_sr; /* samples per msec */
int x_zerodel; /* 0 or vecsize depending on read/write order */
float x_f;
} t_sigvd;
static void *sigvd_new(t_symbol *s)
{
t_sigvd *x = (t_sigvd *)pd_new(sigvd_class);
if (!*s->s_name) s = gensym("vd~");
x->x_sym = s;
x->x_sr = 1;
x->x_zerodel = 0;
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
static t_int *sigvd_perform(t_int *w)
{
t_float *in = (t_float *)(w[1]);
t_float *out = (t_float *)(w[2]);
t_delwritectl *ctl = (t_delwritectl *)(w[3]);
t_sigvd *x = (t_sigvd *)(w[4]);
int n = (int)(w[5]);
int nsamps = ctl->c_n;
float limit = nsamps - n - 1;
float fn = n-1;
float *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase;
float zerodel = x->x_zerodel;
while (n--)
{
float delsamps = x->x_sr * *in++ - zerodel, frac;
int idelsamps;
float a, b, c, d, cminusb;
if (delsamps < 1.00001f) delsamps = 1.00001f;
if (delsamps > limit) delsamps = limit;
delsamps += fn;
fn = fn - 1.0f;
idelsamps = delsamps;
frac = delsamps - (float)idelsamps;
bp = wp - idelsamps;
if (bp < vp + 4) bp += nsamps;
d = bp[-3];
c = bp[-2];
b = bp[-1];
a = bp[0];
cminusb = c-b;
*out++ = b + frac * (
cminusb - 0.1666667f * (1.-frac) * (
(d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
)
);
}
return (w+6);
}
static void sigvd_dsp(t_sigvd *x, t_signal **sp)
{
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_sr = sp[0]->s_sr * 0.001;
if (delwriter)
{
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
dsp_add(sigvd_perform, 5,
sp[0]->s_vec, sp[1]->s_vec,
&delwriter->x_cspace, x, sp[0]->s_n);
}
else error("vd~: %s: no such delwrite~",x->x_sym->s_name);
}
static void sigvd_setup(void)
{
sigvd_class = class_new(gensym("vd~"), (t_newmethod)sigvd_new, 0,
sizeof(t_sigvd), 0, A_DEFSYM, 0);
class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), 0);
CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f);
}
/* ----------------------- global setup routine ---------------- */
void d_delay_setup(void)
{
sigdelwrite_setup();
sigdelread_setup();
sigvd_setup();
}

View file

@ -1,548 +0,0 @@
/* 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. */
/* "filters", both linear and nonlinear.
*/
#include "m_pd.h"
#include <math.h>
/* ---------------- hip~ - 1-pole 1-zero hipass filter. ----------------- */
typedef struct hipctl
{
float c_x;
float c_coef;
} t_hipctl;
typedef struct sighip
{
t_object x_obj;
float x_sr;
float x_hz;
t_hipctl x_cspace;
t_hipctl *x_ctl;
float x_f;
} t_sighip;
t_class *sighip_class;
static void sighip_ft1(t_sighip *x, t_floatarg f);
static void *sighip_new(t_floatarg f)
{
t_sighip *x = (t_sighip *)pd_new(sighip_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_sr = 44100;
x->x_ctl = &x->x_cspace;
x->x_cspace.c_x = 0;
sighip_ft1(x, f);
x->x_f = 0;
return (x);
}
static void sighip_ft1(t_sighip *x, t_floatarg f)
{
if (f < 0) f = 0;
x->x_hz = f;
x->x_ctl->c_coef = 1 - f * (2 * 3.14159) / x->x_sr;
if (x->x_ctl->c_coef < 0)
x->x_ctl->c_coef = 0;
else if (x->x_ctl->c_coef > 1)
x->x_ctl->c_coef = 1;
}
static t_int *sighip_perform(t_int *w)
{
float *in = (float *)(w[1]);
float *out = (float *)(w[2]);
t_hipctl *c = (t_hipctl *)(w[3]);
int n = (t_int)(w[4]);
int i;
float last = c->c_x;
float coef = c->c_coef;
if (coef < 1)
{
for (i = 0; i < n; i++)
{
float new = *in++ + coef * last;
*out++ = new - last;
last = new;
}
if (PD_BIGORSMALL(last))
last = 0;
c->c_x = last;
}
else
{
for (i = 0; i < n; i++)
*out++ = *in++;
c->c_x = 0;
}
return (w+5);
}
static void sighip_dsp(t_sighip *x, t_signal **sp)
{
x->x_sr = sp[0]->s_sr;
sighip_ft1(x, x->x_hz);
dsp_add(sighip_perform, 4,
sp[0]->s_vec, sp[1]->s_vec,
x->x_ctl, sp[0]->s_n);
}
static void sighip_clear(t_sighip *x, t_floatarg q)
{
x->x_cspace.c_x = 0;
}
void sighip_setup(void)
{
sighip_class = class_new(gensym("hip~"), (t_newmethod)sighip_new, 0,
sizeof(t_sighip), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sighip_class, t_sighip, x_f);
class_addmethod(sighip_class, (t_method)sighip_dsp, gensym("dsp"), 0);
class_addmethod(sighip_class, (t_method)sighip_ft1,
gensym("ft1"), A_FLOAT, 0);
class_addmethod(sighip_class, (t_method)sighip_clear, gensym("clear"), 0);
}
/* ---------------- lop~ - 1-pole lopass filter. ----------------- */
typedef struct lopctl
{
float c_x;
float c_coef;
} t_lopctl;
typedef struct siglop
{
t_object x_obj;
float x_sr;
float x_hz;
t_lopctl x_cspace;
t_lopctl *x_ctl;
float x_f;
} t_siglop;
t_class *siglop_class;
static void siglop_ft1(t_siglop *x, t_floatarg f);
static void *siglop_new(t_floatarg f)
{
t_siglop *x = (t_siglop *)pd_new(siglop_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_sr = 44100;
x->x_ctl = &x->x_cspace;
x->x_cspace.c_x = 0;
siglop_ft1(x, f);
x->x_f = 0;
return (x);
}
static void siglop_ft1(t_siglop *x, t_floatarg f)
{
if (f < 0) f = 0;
x->x_hz = f;
x->x_ctl->c_coef = f * (2 * 3.14159) / x->x_sr;
if (x->x_ctl->c_coef > 1)
x->x_ctl->c_coef = 1;
else if (x->x_ctl->c_coef < 0)
x->x_ctl->c_coef = 0;
}
static void siglop_clear(t_siglop *x, t_floatarg q)
{
x->x_cspace.c_x = 0;
}
static t_int *siglop_perform(t_int *w)
{
float *in = (float *)(w[1]);
float *out = (float *)(w[2]);
t_lopctl *c = (t_lopctl *)(w[3]);
int n = (t_int)(w[4]);
int i;
float last = c->c_x;
float coef = c->c_coef;
float feedback = 1 - coef;
for (i = 0; i < n; i++)
last = *out++ = coef * *in++ + feedback * last;
if (PD_BIGORSMALL(last))
last = 0;
c->c_x = last;
return (w+5);
}
static void siglop_dsp(t_siglop *x, t_signal **sp)
{
x->x_sr = sp[0]->s_sr;
siglop_ft1(x, x->x_hz);
dsp_add(siglop_perform, 4,
sp[0]->s_vec, sp[1]->s_vec,
x->x_ctl, sp[0]->s_n);
}
void siglop_setup(void)
{
siglop_class = class_new(gensym("lop~"), (t_newmethod)siglop_new, 0,
sizeof(t_siglop), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(siglop_class, t_siglop, x_f);
class_addmethod(siglop_class, (t_method)siglop_dsp, gensym("dsp"), 0);
class_addmethod(siglop_class, (t_method)siglop_ft1,
gensym("ft1"), A_FLOAT, 0);
class_addmethod(siglop_class, (t_method)siglop_clear, gensym("clear"), 0);
}
/* ---------------- bp~ - 2-pole bandpass filter. ----------------- */
typedef struct bpctl
{
float c_x1;
float c_x2;
float c_coef1;
float c_coef2;
float c_gain;
} t_bpctl;
typedef struct sigbp
{
t_object x_obj;
float x_sr;
float x_freq;
float x_q;
t_bpctl x_cspace;
t_bpctl *x_ctl;
float x_f;
} t_sigbp;
t_class *sigbp_class;
static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q);
static void *sigbp_new(t_floatarg f, t_floatarg q)
{
t_sigbp *x = (t_sigbp *)pd_new(sigbp_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft2"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_sr = 44100;
x->x_ctl = &x->x_cspace;
x->x_cspace.c_x1 = 0;
x->x_cspace.c_x2 = 0;
sigbp_docoef(x, f, q);
x->x_f = 0;
return (x);
}
static float sigbp_qcos(float f)
{
if (f >= -(0.5f*3.14159f) && f <= 0.5f*3.14159f)
{
float g = f*f;
return (((g*g*g * (-1.0f/720.0f) + g*g*(1.0f/24.0f)) - g*0.5) + 1);
}
else return (0);
}
static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q)
{
float r, oneminusr, omega;
if (f < 0.001) f = 10;
if (q < 0) q = 0;
x->x_freq = f;
x->x_q = q;
omega = f * (2.0f * 3.14159f) / x->x_sr;
if (q < 0.001) oneminusr = 1.0f;
else oneminusr = omega/q;
if (oneminusr > 1.0f) oneminusr = 1.0f;
r = 1.0f - oneminusr;
x->x_ctl->c_coef1 = 2.0f * sigbp_qcos(omega) * r;
x->x_ctl->c_coef2 = - r * r;
x->x_ctl->c_gain = 2 * oneminusr * (oneminusr + r * omega);
/* post("r %f, omega %f, coef1 %f, coef2 %f",
r, omega, x->x_ctl->c_coef1, x->x_ctl->c_coef2); */
}
static void sigbp_ft1(t_sigbp *x, t_floatarg f)
{
sigbp_docoef(x, f, x->x_q);
}
static void sigbp_ft2(t_sigbp *x, t_floatarg q)
{
sigbp_docoef(x, x->x_freq, q);
}
static void sigbp_clear(t_sigbp *x, t_floatarg q)
{
x->x_ctl->c_x1 = x->x_ctl->c_x2 = 0;
}
static t_int *sigbp_perform(t_int *w)
{
float *in = (float *)(w[1]);
float *out = (float *)(w[2]);
t_bpctl *c = (t_bpctl *)(w[3]);
int n = (t_int)(w[4]);
int i;
float last = c->c_x1;
float prev = c->c_x2;
float coef1 = c->c_coef1;
float coef2 = c->c_coef2;
float gain = c->c_gain;
for (i = 0; i < n; i++)
{
float output = *in++ + coef1 * last + coef2 * prev;
*out++ = gain * output;
prev = last;
last = output;
}
if (PD_BIGORSMALL(last))
last = 0;
if (PD_BIGORSMALL(prev))
prev = 0;
c->c_x1 = last;
c->c_x2 = prev;
return (w+5);
}
static void sigbp_dsp(t_sigbp *x, t_signal **sp)
{
x->x_sr = sp[0]->s_sr;
sigbp_docoef(x, x->x_freq, x->x_q);
dsp_add(sigbp_perform, 4,
sp[0]->s_vec, sp[1]->s_vec,
x->x_ctl, sp[0]->s_n);
}
void sigbp_setup(void)
{
sigbp_class = class_new(gensym("bp~"), (t_newmethod)sigbp_new, 0,
sizeof(t_sigbp), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigbp_class, t_sigbp, x_f);
class_addmethod(sigbp_class, (t_method)sigbp_dsp, gensym("dsp"), 0);
class_addmethod(sigbp_class, (t_method)sigbp_ft1,
gensym("ft1"), A_FLOAT, 0);
class_addmethod(sigbp_class, (t_method)sigbp_ft2,
gensym("ft2"), A_FLOAT, 0);
class_addmethod(sigbp_class, (t_method)sigbp_clear, gensym("clear"), 0);
}
/* ---------------- biquad~ - raw biquad filter ----------------- */
typedef struct biquadctl
{
float c_x1;
float c_x2;
float c_fb1;
float c_fb2;
float c_ff1;
float c_ff2;
float c_ff3;
} t_biquadctl;
typedef struct sigbiquad
{
t_object x_obj;
float x_f;
t_biquadctl x_cspace;
t_biquadctl *x_ctl;
} t_sigbiquad;
t_class *sigbiquad_class;
static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv);
static void *sigbiquad_new(t_symbol *s, int argc, t_atom *argv)
{
t_sigbiquad *x = (t_sigbiquad *)pd_new(sigbiquad_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_ctl = &x->x_cspace;
x->x_cspace.c_x1 = x->x_cspace.c_x2 = 0;
sigbiquad_list(x, s, argc, argv);
x->x_f = 0;
return (x);
}
static t_int *sigbiquad_perform(t_int *w)
{
float *in = (float *)(w[1]);
float *out = (float *)(w[2]);
t_biquadctl *c = (t_biquadctl *)(w[3]);
int n = (t_int)(w[4]);
int i;
float last = c->c_x1;
float prev = c->c_x2;
float fb1 = c->c_fb1;
float fb2 = c->c_fb2;
float ff1 = c->c_ff1;
float ff2 = c->c_ff2;
float ff3 = c->c_ff3;
for (i = 0; i < n; i++)
{
float output = *in++ + fb1 * last + fb2 * prev;
if (PD_BIGORSMALL(output))
output = 0;
*out++ = ff1 * output + ff2 * last + ff3 * prev;
prev = last;
last = output;
}
c->c_x1 = last;
c->c_x2 = prev;
return (w+5);
}
static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv)
{
float fb1 = atom_getfloatarg(0, argc, argv);
float fb2 = atom_getfloatarg(1, argc, argv);
float ff1 = atom_getfloatarg(2, argc, argv);
float ff2 = atom_getfloatarg(3, argc, argv);
float ff3 = atom_getfloatarg(4, argc, argv);
float discriminant = fb1 * fb1 + 4 * fb2;
t_biquadctl *c = x->x_ctl;
if (discriminant < 0) /* imaginary roots -- resonant filter */
{
/* they're conjugates so we just check that the product
is less than one */
if (fb2 >= -1.0f) goto stable;
}
else /* real roots */
{
/* check that the parabola 1 - fb1 x - fb2 x^2 has a
vertex between -1 and 1, and that it's nonnegative
at both ends, which implies both roots are in [1-,1]. */
if (fb1 <= 2.0f && fb1 >= -2.0f &&
1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
goto stable;
}
/* if unstable, just bash to zero */
fb1 = fb2 = ff1 = ff2 = ff3 = 0;
stable:
c->c_fb1 = fb1;
c->c_fb2 = fb2;
c->c_ff1 = ff1;
c->c_ff2 = ff2;
c->c_ff3 = ff3;
}
static void sigbiquad_set(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv)
{
t_biquadctl *c = x->x_ctl;
c->c_x1 = atom_getfloatarg(0, argc, argv);
c->c_x2 = atom_getfloatarg(1, argc, argv);
}
static void sigbiquad_dsp(t_sigbiquad *x, t_signal **sp)
{
dsp_add(sigbiquad_perform, 4,
sp[0]->s_vec, sp[1]->s_vec,
x->x_ctl, sp[0]->s_n);
}
void sigbiquad_setup(void)
{
sigbiquad_class = class_new(gensym("biquad~"), (t_newmethod)sigbiquad_new,
0, sizeof(t_sigbiquad), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(sigbiquad_class, t_sigbiquad, x_f);
class_addmethod(sigbiquad_class, (t_method)sigbiquad_dsp, gensym("dsp"), 0);
class_addlist(sigbiquad_class, sigbiquad_list);
class_addmethod(sigbiquad_class, (t_method)sigbiquad_set, gensym("set"),
A_GIMME, 0);
class_addmethod(sigbiquad_class, (t_method)sigbiquad_set, gensym("clear"),
A_GIMME, 0);
}
/* ---------------- samphold~ - sample and hold ----------------- */
typedef struct sigsamphold
{
t_object x_obj;
float x_f;
float x_lastin;
float x_lastout;
} t_sigsamphold;
t_class *sigsamphold_class;
static void *sigsamphold_new(void)
{
t_sigsamphold *x = (t_sigsamphold *)pd_new(sigsamphold_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, gensym("signal"));
x->x_lastin = 0;
x->x_lastout = 0;
x->x_f = 0;
return (x);
}
static t_int *sigsamphold_perform(t_int *w)
{
float *in1 = (float *)(w[1]);
float *in2 = (float *)(w[2]);
float *out = (float *)(w[3]);
t_sigsamphold *x = (t_sigsamphold *)(w[4]);
int n = (t_int)(w[5]);
int i;
float lastin = x->x_lastin;
float lastout = x->x_lastout;
for (i = 0; i < n; i++, *in1++)
{
float next = *in2++;
if (next < lastin) lastout = *in1;
*out++ = lastout;
lastin = next;
}
x->x_lastin = lastin;
x->x_lastout = lastout;
return (w+6);
}
static void sigsamphold_dsp(t_sigsamphold *x, t_signal **sp)
{
dsp_add(sigsamphold_perform, 5,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,
x, sp[0]->s_n);
}
static void sigsamphold_reset(t_sigsamphold *x)
{
x->x_lastin = 1e20;
}
static void sigsamphold_set(t_sigsamphold *x, t_float f)
{
x->x_lastout = f;
}
void sigsamphold_setup(void)
{
sigsamphold_class = class_new(gensym("samphold~"),
(t_newmethod)sigsamphold_new, 0, sizeof(t_sigsamphold), 0, 0);
CLASS_MAINSIGNALIN(sigsamphold_class, t_sigsamphold, x_f);
class_addmethod(sigsamphold_class, (t_method)sigsamphold_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(sigsamphold_class, (t_method)sigsamphold_reset,
gensym("reset"), 0);
class_addmethod(sigsamphold_class, (t_method)sigsamphold_dsp,
gensym("dsp"), 0);
}
/* ------------------------ setup routine ------------------------- */
void d_filter_setup(void)
{
sighip_setup();
siglop_setup();
sigbp_setup();
sigbiquad_setup();
sigsamphold_setup();
}

View file

@ -1,573 +0,0 @@
/* Copyright (c) 1997-2001 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* mathematical functions and other transfer functions, including tilde
versions of stuff from x_acoustics.c.
*/
#include "m_pd.h"
#include <math.h>
#define LOGTEN 2.302585092994
/* ------------------------- clip~ -------------------------- */
static t_class *clip_class;
typedef struct _clip
{
t_object x_obj;
float x_f;
t_sample x_lo;
t_sample x_hi;
} t_clip;
static void *clip_new(t_floatarg lo, t_floatarg hi)
{
t_clip *x = (t_clip *)pd_new(clip_class);
x->x_lo = lo;
x->x_hi = hi;
outlet_new(&x->x_obj, gensym("signal"));
floatinlet_new(&x->x_obj, &x->x_lo);
floatinlet_new(&x->x_obj, &x->x_hi);
x->x_f = 0;
return (x);
}
static t_int *clip_perform(t_int *w)
{
t_clip *x = (t_clip *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
float f = *in++;
if (f < x->x_lo) f = x->x_lo;
if (f > x->x_hi) f = x->x_hi;
*out++ = f;
}
return (w+5);
}
static void clip_dsp(t_clip *x, t_signal **sp)
{
dsp_add(clip_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void clip_setup(void)
{
clip_class = class_new(gensym("clip~"), (t_newmethod)clip_new, 0,
sizeof(t_clip), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(clip_class, t_clip, x_f);
class_addmethod(clip_class, (t_method)clip_dsp, gensym("dsp"), 0);
}
/* sigrsqrt - reciprocal square root good to 8 mantissa bits */
#define DUMTAB1SIZE 256
#define DUMTAB2SIZE 1024
static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE];
static void init_rsqrt(void)
{
int i;
for (i = 0; i < DUMTAB1SIZE; i++)
{
float f;
long l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
*(long *)(&f) = l;
rsqrt_exptab[i] = 1./sqrt(f);
}
for (i = 0; i < DUMTAB2SIZE; i++)
{
float f = 1 + (1./DUMTAB2SIZE) * i;
rsqrt_mantissatab[i] = 1./sqrt(f);
}
}
/* these are used in externs like "bonk" */
float q8_rsqrt(float f)
{
long l = *(long *)(&f);
if (f < 0) return (0);
else return (rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff]);
}
float q8_sqrt(float f)
{
long l = *(long *)(&f);
if (f < 0) return (0);
else return (f * rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff]);
}
/* the old names are OK unless we're in IRIX N32 */
#ifndef N32
float qsqrt(float f) {return (q8_sqrt(f)); }
float qrsqrt(float f) {return (q8_rsqrt(f)); }
#endif
typedef struct sigrsqrt
{
t_object x_obj;
float x_f;
} t_sigrsqrt;
static t_class *sigrsqrt_class;
static void *sigrsqrt_new(void)
{
t_sigrsqrt *x = (t_sigrsqrt *)pd_new(sigrsqrt_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *sigrsqrt_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
while (n--)
{
float f = *in;
long l = *(long *)(in++);
if (f < 0) *out++ = 0;
else
{
float g = rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff];
*out++ = 1.5 * g - 0.5 * g * g * g * f;
}
}
return (w + 4);
}
static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp)
{
dsp_add(sigrsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void sigrsqrt_setup(void)
{
init_rsqrt();
sigrsqrt_class = class_new(gensym("rsqrt~"), (t_newmethod)sigrsqrt_new, 0,
sizeof(t_sigrsqrt), 0, 0);
/* an old name for it: */
class_addcreator(sigrsqrt_new, gensym("q8_rsqrt~"), 0);
CLASS_MAINSIGNALIN(sigrsqrt_class, t_sigrsqrt, x_f);
class_addmethod(sigrsqrt_class, (t_method)sigrsqrt_dsp, gensym("dsp"), 0);
}
/* sigsqrt - square root good to 8 mantissa bits */
typedef struct sigsqrt
{
t_object x_obj;
float x_f;
} t_sigsqrt;
static t_class *sigsqrt_class;
static void *sigsqrt_new(void)
{
t_sigsqrt *x = (t_sigsqrt *)pd_new(sigsqrt_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
t_int *sigsqrt_perform(t_int *w) /* not static; also used in d_fft.c */
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
while (n--)
{
float f = *in;
long l = *(long *)(in++);
if (f < 0) *out++ = 0;
else
{
float g = rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff];
*out++ = f * (1.5 * g - 0.5 * g * g * g * f);
}
}
return (w + 4);
}
static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp)
{
dsp_add(sigsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void sigsqrt_setup(void)
{
sigsqrt_class = class_new(gensym("sqrt~"), (t_newmethod)sigsqrt_new, 0,
sizeof(t_sigsqrt), 0, 0);
class_addcreator(sigsqrt_new, gensym("q8_sqrt~"), 0); /* old name */
CLASS_MAINSIGNALIN(sigsqrt_class, t_sigsqrt, x_f);
class_addmethod(sigsqrt_class, (t_method)sigsqrt_dsp, gensym("dsp"), 0);
}
/* ------------------------------ wrap~ -------------------------- */
typedef struct wrap
{
t_object x_obj;
float x_f;
} t_sigwrap;
t_class *sigwrap_class;
static void *sigwrap_new(void)
{
t_sigwrap *x = (t_sigwrap *)pd_new(sigwrap_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *sigwrap_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
while (n--)
{
float f = *in++;
int k = f;
if (f > 0) *out++ = f-k;
else *out++ = f - (k-1);
}
return (w + 4);
}
static void sigwrap_dsp(t_sigwrap *x, t_signal **sp)
{
dsp_add(sigwrap_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void sigwrap_setup(void)
{
sigwrap_class = class_new(gensym("wrap~"), (t_newmethod)sigwrap_new, 0,
sizeof(t_sigwrap), 0, 0);
CLASS_MAINSIGNALIN(sigwrap_class, t_sigwrap, x_f);
class_addmethod(sigwrap_class, (t_method)sigwrap_dsp, gensym("dsp"), 0);
}
/* ------------------------------ mtof_tilde~ -------------------------- */
typedef struct mtof_tilde
{
t_object x_obj;
float x_f;
} t_mtof_tilde;
t_class *mtof_tilde_class;
static void *mtof_tilde_new(void)
{
t_mtof_tilde *x = (t_mtof_tilde *)pd_new(mtof_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *mtof_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; in++, out++)
{
float f = *in;
if (f <= -1500) *out = 0;
else
{
if (f > 1499) f = 1499;
*out = 8.17579891564 * exp(.0577622650 * f);
}
}
return (w + 4);
}
static void mtof_tilde_dsp(t_mtof_tilde *x, t_signal **sp)
{
dsp_add(mtof_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void mtof_tilde_setup(void)
{
mtof_tilde_class = class_new(gensym("mtof~"), (t_newmethod)mtof_tilde_new, 0,
sizeof(t_mtof_tilde), 0, 0);
CLASS_MAINSIGNALIN(mtof_tilde_class, t_mtof_tilde, x_f);
class_addmethod(mtof_tilde_class, (t_method)mtof_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------------ ftom_tilde~ -------------------------- */
typedef struct ftom_tilde
{
t_object x_obj;
float x_f;
} t_ftom_tilde;
t_class *ftom_tilde_class;
static void *ftom_tilde_new(void)
{
t_ftom_tilde *x = (t_ftom_tilde *)pd_new(ftom_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *ftom_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; *in++, out++)
{
float f = *in;
*out = (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500);
}
return (w + 4);
}
static void ftom_tilde_dsp(t_ftom_tilde *x, t_signal **sp)
{
dsp_add(ftom_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void ftom_tilde_setup(void)
{
ftom_tilde_class = class_new(gensym("ftom~"), (t_newmethod)ftom_tilde_new, 0,
sizeof(t_ftom_tilde), 0, 0);
CLASS_MAINSIGNALIN(ftom_tilde_class, t_ftom_tilde, x_f);
class_addmethod(ftom_tilde_class, (t_method)ftom_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------------ dbtorms~ -------------------------- */
typedef struct dbtorms_tilde
{
t_object x_obj;
float x_f;
} t_dbtorms_tilde;
t_class *dbtorms_tilde_class;
static void *dbtorms_tilde_new(void)
{
t_dbtorms_tilde *x = (t_dbtorms_tilde *)pd_new(dbtorms_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *dbtorms_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; in++, out++)
{
float f = *in;
if (f <= 0) *out = 0;
else
{
if (f > 485)
f = 485;
*out = exp((LOGTEN * 0.05) * (f-100.));
}
}
return (w + 4);
}
static void dbtorms_tilde_dsp(t_dbtorms_tilde *x, t_signal **sp)
{
dsp_add(dbtorms_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void dbtorms_tilde_setup(void)
{
dbtorms_tilde_class = class_new(gensym("dbtorms~"), (t_newmethod)dbtorms_tilde_new, 0,
sizeof(t_dbtorms_tilde), 0, 0);
CLASS_MAINSIGNALIN(dbtorms_tilde_class, t_dbtorms_tilde, x_f);
class_addmethod(dbtorms_tilde_class, (t_method)dbtorms_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------------ rmstodb~ -------------------------- */
typedef struct rmstodb_tilde
{
t_object x_obj;
float x_f;
} t_rmstodb_tilde;
t_class *rmstodb_tilde_class;
static void *rmstodb_tilde_new(void)
{
t_rmstodb_tilde *x = (t_rmstodb_tilde *)pd_new(rmstodb_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *rmstodb_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; in++, out++)
{
float f = *in;
if (f <= 0) *out = 0;
else
{
float g = 100 + 20./LOGTEN * log(f);
*out = (g < 0 ? 0 : g);
}
}
return (w + 4);
}
static void rmstodb_tilde_dsp(t_rmstodb_tilde *x, t_signal **sp)
{
dsp_add(rmstodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void rmstodb_tilde_setup(void)
{
rmstodb_tilde_class = class_new(gensym("rmstodb~"), (t_newmethod)rmstodb_tilde_new, 0,
sizeof(t_rmstodb_tilde), 0, 0);
CLASS_MAINSIGNALIN(rmstodb_tilde_class, t_rmstodb_tilde, x_f);
class_addmethod(rmstodb_tilde_class, (t_method)rmstodb_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------------ dbtopow~ -------------------------- */
typedef struct dbtopow_tilde
{
t_object x_obj;
float x_f;
} t_dbtopow_tilde;
t_class *dbtopow_tilde_class;
static void *dbtopow_tilde_new(void)
{
t_dbtopow_tilde *x = (t_dbtopow_tilde *)pd_new(dbtopow_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *dbtopow_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; in++, out++)
{
float f = *in;
if (f <= 0) *out = 0;
else
{
if (f > 870)
f = 870;
*out = exp((LOGTEN * 0.1) * (f-100.));
}
}
return (w + 4);
}
static void dbtopow_tilde_dsp(t_dbtopow_tilde *x, t_signal **sp)
{
dsp_add(dbtopow_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void dbtopow_tilde_setup(void)
{
dbtopow_tilde_class = class_new(gensym("dbtopow~"), (t_newmethod)dbtopow_tilde_new, 0,
sizeof(t_dbtopow_tilde), 0, 0);
CLASS_MAINSIGNALIN(dbtopow_tilde_class, t_dbtopow_tilde, x_f);
class_addmethod(dbtopow_tilde_class, (t_method)dbtopow_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------------ powtodb~ -------------------------- */
typedef struct powtodb_tilde
{
t_object x_obj;
float x_f;
} t_powtodb_tilde;
t_class *powtodb_tilde_class;
static void *powtodb_tilde_new(void)
{
t_powtodb_tilde *x = (t_powtodb_tilde *)pd_new(powtodb_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *powtodb_tilde_perform(t_int *w)
{
float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2);
t_int n = *(t_int *)(w+3);
for (; n--; in++, out++)
{
float f = *in;
if (f <= 0) *out = 0;
else
{
float g = 100 + 10./LOGTEN * log(f);
*out = (g < 0 ? 0 : g);
}
}
return (w + 4);
}
static void powtodb_tilde_dsp(t_powtodb_tilde *x, t_signal **sp)
{
dsp_add(powtodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void powtodb_tilde_setup(void)
{
powtodb_tilde_class = class_new(gensym("powtodb~"), (t_newmethod)powtodb_tilde_new, 0,
sizeof(t_powtodb_tilde), 0, 0);
CLASS_MAINSIGNALIN(powtodb_tilde_class, t_powtodb_tilde, x_f);
class_addmethod(powtodb_tilde_class, (t_method)powtodb_tilde_dsp, gensym("dsp"), 0);
}
/* ------------------------ global setup routine ------------------------- */
void d_math_setup(void)
{
t_symbol *s = gensym("acoustics~.pd");
clip_setup();
sigrsqrt_setup();
sigsqrt_setup();
sigwrap_setup();
mtof_tilde_setup();
ftom_tilde_setup();
dbtorms_tilde_setup();
rmstodb_tilde_setup();
dbtopow_tilde_setup();
powtodb_tilde_setup();
class_sethelpsymbol(mtof_tilde_class, s);
class_sethelpsymbol(ftom_tilde_class, s);
class_sethelpsymbol(dbtorms_tilde_class, s);
class_sethelpsymbol(rmstodb_tilde_class, s);
class_sethelpsymbol(dbtopow_tilde_class, s);
class_sethelpsymbol(powtodb_tilde_class, s);
}

View file

@ -1,535 +0,0 @@
/* 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. */
/* sinusoidal oscillator and table lookup; see also tabosc4~ in d_array.c.
*/
#include "m_pd.h"
#include "math.h"
#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
/* machine-dependent definitions. These ifdefs really
should have been by CPU type and not by operating system! */
#ifdef IRIX
/* big-endian. Most significant byte is at low address in memory */
#define HIOFFSET 0 /* word offset to find MSB */
#define LOWOFFSET 1 /* word offset to find LSB */
#define int32 long /* a data type that has 32 bits */
#else
#ifdef MSW
/* little-endian; most significant byte is at highest address */
#define HIOFFSET 1
#define LOWOFFSET 0
#define int32 long
#else
#ifdef __FreeBSD__
#include <machine/endian.h>
#if BYTE_ORDER == LITTLE_ENDIAN
#define HIOFFSET 1
#define LOWOFFSET 0
#else
#define HIOFFSET 0 /* word offset to find MSB */
#define LOWOFFSET 1 /* word offset to find LSB */
#endif /* BYTE_ORDER */
#include <sys/types.h>
#define int32 int32_t
#endif
#ifdef __linux__
#include <endian.h>
#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)
#error No byte order defined
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define HIOFFSET 1
#define LOWOFFSET 0
#else
#define HIOFFSET 0 /* word offset to find MSB */
#define LOWOFFSET 1 /* word offset to find LSB */
#endif /* __BYTE_ORDER */
#include <sys/types.h>
#define int32 int32_t
#else
#ifdef MACOSX
#define HIOFFSET 0 /* word offset to find MSB */
#define LOWOFFSET 1 /* word offset to find LSB */
#define int32 int /* a data type that has 32 bits */
#endif /* MACOSX */
#endif /* __linux__ */
#endif /* MSW */
#endif /* SGI */
union tabfudge
{
double tf_d;
int32 tf_i[2];
};
/* -------------------------- phasor~ ------------------------------ */
static t_class *phasor_class, *scalarphasor_class;
#if 1 /* in the style of R. Hoeldrich (ICMC 1995 Banff) */
typedef struct _phasor
{
t_object x_obj;
double x_phase;
float x_conv;
float x_f; /* scalar frequency */
} t_phasor;
static void *phasor_new(t_floatarg f)
{
t_phasor *x = (t_phasor *)pd_new(phasor_class);
x->x_f = f;
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_phase = 0;
x->x_conv = 0;
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}
static t_int *phasor_perform(t_int *w)
{
t_phasor *x = (t_phasor *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
double dphase = x->x_phase + UNITBIT32;
union tabfudge tf;
int normhipart;
float conv = x->x_conv;
tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
tf.tf_d = dphase;
while (n--)
{
tf.tf_i[HIOFFSET] = normhipart;
dphase += *in++ * conv;
*out++ = tf.tf_d - UNITBIT32;
tf.tf_d = dphase;
}
tf.tf_i[HIOFFSET] = normhipart;
x->x_phase = tf.tf_d - UNITBIT32;
return (w+5);
}
static void phasor_dsp(t_phasor *x, t_signal **sp)
{
x->x_conv = 1./sp[0]->s_sr;
dsp_add(phasor_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void phasor_ft1(t_phasor *x, t_float f)
{
x->x_phase = f;
}
static void phasor_setup(void)
{
phasor_class = class_new(gensym("phasor~"), (t_newmethod)phasor_new, 0,
sizeof(t_phasor), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(phasor_class, t_phasor, x_f);
class_addmethod(phasor_class, (t_method)phasor_dsp, gensym("dsp"), 0);
class_addmethod(phasor_class, (t_method)phasor_ft1,
gensym("ft1"), A_FLOAT, 0);
}
#endif /* Hoeldrich version */
/* ------------------------ cos~ ----------------------------- */
float *cos_table;
static t_class *cos_class;
typedef struct _cos
{
t_object x_obj;
float x_f;
} t_cos;
static void *cos_new(void)
{
t_cos *x = (t_cos *)pd_new(cos_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}
static t_int *cos_perform(t_int *w)
{
t_float *in = (t_float *)(w[1]);
t_float *out = (t_float *)(w[2]);
int n = (int)(w[3]);
float *tab = cos_table, *addr, f1, f2, frac;
double dphase;
int normhipart;
union tabfudge tf;
tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
#if 0 /* this is the readable version of the code. */
while (n--)
{
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
tf.tf_d = dphase;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
}
#endif
#if 1 /* this is the same, unwrapped by hand. */
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
tf.tf_d = dphase;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
while (--n)
{
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
frac = tf.tf_d - UNITBIT32;
tf.tf_d = dphase;
f1 = addr[0];
f2 = addr[1];
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
*out++ = f1 + frac * (f2 - f1);
tf.tf_i[HIOFFSET] = normhipart;
}
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
#endif
return (w+4);
}
static void cos_dsp(t_cos *x, t_signal **sp)
{
dsp_add(cos_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void cos_maketable(void)
{
int i;
float *fp, phase, phsinc = (2. * 3.14159) / COSTABSIZE;
union tabfudge tf;
if (cos_table) return;
cos_table = (float *)getbytes(sizeof(float) * (COSTABSIZE+1));
for (i = COSTABSIZE + 1, fp = cos_table, phase = 0; i--;
fp++, phase += phsinc)
*fp = cos(phase);
/* here we check at startup whether the byte alignment
is as we declared it. If not, the code has to be
recompiled the other way. */
tf.tf_d = UNITBIT32 + 0.5;
if ((unsigned)tf.tf_i[LOWOFFSET] != 0x80000000)
bug("cos~: unexpected machine alignment");
}
static void cos_setup(void)
{
cos_class = class_new(gensym("cos~"), (t_newmethod)cos_new, 0,
sizeof(t_cos), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(cos_class, t_cos, x_f);
class_addmethod(cos_class, (t_method)cos_dsp, gensym("dsp"), 0);
cos_maketable();
}
/* ------------------------ osc~ ----------------------------- */
static t_class *osc_class, *scalarosc_class;
typedef struct _osc
{
t_object x_obj;
double x_phase;
float x_conv;
float x_f; /* frequency if scalar */
} t_osc;
static void *osc_new(t_floatarg f)
{
t_osc *x = (t_osc *)pd_new(osc_class);
x->x_f = f;
outlet_new(&x->x_obj, gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_phase = 0;
x->x_conv = 0;
return (x);
}
static t_int *osc_perform(t_int *w)
{
t_osc *x = (t_osc *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
float *tab = cos_table, *addr, f1, f2, frac;
double dphase = x->x_phase + UNITBIT32;
int normhipart;
union tabfudge tf;
float conv = x->x_conv;
tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
#if 0
while (n--)
{
tf.tf_d = dphase;
dphase += *in++ * conv;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
}
#endif
#if 1
tf.tf_d = dphase;
dphase += *in++ * conv;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
while (--n)
{
tf.tf_d = dphase;
f1 = addr[0];
dphase += *in++ * conv;
f2 = addr[1];
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
*out++ = f1 + frac * (f2 - f1);
frac = tf.tf_d - UNITBIT32;
}
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
#endif
tf.tf_d = UNITBIT32 * COSTABSIZE;
normhipart = tf.tf_i[HIOFFSET];
tf.tf_d = dphase + (UNITBIT32 * COSTABSIZE - UNITBIT32);
tf.tf_i[HIOFFSET] = normhipart;
x->x_phase = tf.tf_d - UNITBIT32 * COSTABSIZE;
return (w+5);
}
static void osc_dsp(t_osc *x, t_signal **sp)
{
x->x_conv = COSTABSIZE/sp[0]->s_sr;
dsp_add(osc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void osc_ft1(t_osc *x, t_float f)
{
x->x_phase = COSTABSIZE * f;
}
static void osc_setup(void)
{
osc_class = class_new(gensym("osc~"), (t_newmethod)osc_new, 0,
sizeof(t_osc), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(osc_class, t_osc, x_f);
class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 0);
class_addmethod(osc_class, (t_method)osc_ft1, gensym("ft1"), A_FLOAT, 0);
cos_maketable();
}
/* ---------------- vcf~ - 2-pole bandpass filter. ----------------- */
typedef struct vcfctl
{
float c_re;
float c_im;
float c_q;
float c_isr;
} t_vcfctl;
typedef struct sigvcf
{
t_object x_obj;
t_vcfctl x_cspace;
t_vcfctl *x_ctl;
float x_f;
} t_sigvcf;
t_class *sigvcf_class;
static void *sigvcf_new(t_floatarg q)
{
t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_ctl = &x->x_cspace;
x->x_cspace.c_re = 0;
x->x_cspace.c_im = 0;
x->x_cspace.c_q = q;
x->x_cspace.c_isr = 0;
x->x_f = 0;
return (x);
}
static void sigvcf_ft1(t_sigvcf *x, t_floatarg f)
{
x->x_ctl->c_q = (f > 0 ? f : 0.f);
}
static t_int *sigvcf_perform(t_int *w)
{
float *in1 = (float *)(w[1]);
float *in2 = (float *)(w[2]);
float *out1 = (float *)(w[3]);
float *out2 = (float *)(w[4]);
t_vcfctl *c = (t_vcfctl *)(w[5]);
int n = (t_int)(w[6]);
int i;
float re = c->c_re, re2;
float im = c->c_im;
float q = c->c_q;
float qinv = (q > 0? 1.0f/q : 0);
float ampcorrect = 2.0f - 2.0f / (q + 2.0f);
float isr = c->c_isr;
float coefr, coefi;
float *tab = cos_table, *addr, f1, f2, frac;
double dphase;
int normhipart, tabindex;
union tabfudge tf;
tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
for (i = 0; i < n; i++)
{
float cf, cfindx, r, oneminusr;
cf = *in2++ * isr;
if (cf < 0) cf = 0;
cfindx = cf * (float)(COSTABSIZE/6.28318f);
r = (qinv > 0 ? 1 - cf * qinv : 0);
if (r < 0) r = 0;
oneminusr = 1.0f - r;
dphase = ((double)(cfindx)) + UNITBIT32;
tf.tf_d = dphase;
tabindex = tf.tf_i[HIOFFSET] & (COSTABSIZE-1);
addr = tab + tabindex;
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
coefr = r * (f1 + frac * (f2 - f1));
addr = tab + ((tabindex - (COSTABSIZE/4)) & (COSTABSIZE-1));
f1 = addr[0];
f2 = addr[1];
coefi = r * (f1 + frac * (f2 - f1));
f1 = *in1++;
re2 = re;
*out1++ = re = ampcorrect * oneminusr * f1
+ coefr * re2 - coefi * im;
*out2++ = im = coefi * re2 + coefr * im;
}
if (PD_BIGORSMALL(re))
re = 0;
if (PD_BIGORSMALL(im))
im = 0;
c->c_re = re;
c->c_im = im;
return (w+7);
}
static void sigvcf_dsp(t_sigvcf *x, t_signal **sp)
{
x->x_ctl->c_isr = 6.28318f/sp[0]->s_sr;
dsp_add(sigvcf_perform, 6,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
x->x_ctl, sp[0]->s_n);
}
void sigvcf_setup(void)
{
sigvcf_class = class_new(gensym("vcf~"), (t_newmethod)sigvcf_new, 0,
sizeof(t_sigvcf), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, x_f);
class_addmethod(sigvcf_class, (t_method)sigvcf_dsp, gensym("dsp"), 0);
class_addmethod(sigvcf_class, (t_method)sigvcf_ft1,
gensym("ft1"), A_FLOAT, 0);
}
/* -------------------------- noise~ ------------------------------ */
static t_class *noise_class;
typedef struct _noise
{
t_object x_obj;
int x_val;
} t_noise;
static void *noise_new(void)
{
t_noise *x = (t_noise *)pd_new(noise_class);
static int init = 307;
x->x_val = (init *= 1319);
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}
static t_int *noise_perform(t_int *w)
{
t_float *out = (t_float *)(w[1]);
int *vp = (int *)(w[2]);
int n = (int)(w[3]);
int val = *vp;
while (n--)
{
*out++ = ((float)((val & 0x7fffffff) - 0x40000000)) *
(float)(1.0 / 0x40000000);
val = val * 435898247 + 382842987;
}
*vp = val;
return (w+4);
}
static void noise_dsp(t_noise *x, t_signal **sp)
{
dsp_add(noise_perform, 3, sp[0]->s_vec, &x->x_val, sp[0]->s_n);
}
static void noise_setup(void)
{
noise_class = class_new(gensym("noise~"), (t_newmethod)noise_new, 0,
sizeof(t_noise), 0, 0);
class_addmethod(noise_class, (t_method)noise_dsp, gensym("dsp"), 0);
}
/* ----------------------- global setup routine ---------------- */
void d_osc_setup(void)
{
phasor_setup();
cos_setup();
osc_setup();
sigvcf_setup();
noise_setup();
}

View file

@ -1,9 +0,0 @@
#N canvas 0 0 236 296 10;
#X obj 79 77 gcanvas 80 80 0 0;
#X floatatom 42 209 5 0 0 0 - - -;
#X floatatom 107 205 5 0 0 0 - - -;
#X floatatom 149 210 5 0 0 0 - - -;
#X connect 0 0 1 0;
#X connect 0 1 2 0;
#X connect 0 2 3 0;

View file

@ -1,176 +0,0 @@
PREFIX = /usr/
EXT = pd_linux
# pd specific
VPATH = ../obj:./
OBJ_DIR = ../obj
BIN_DIR = ../bin
BROOT=/usr
X11LIB = $(BROOT)/X11R6/lib
DEFINES = -DPD -DUNIX
pd-gui_INCLUDES = -I$(BROOT)/include/tcl8.4 -I$(BROOT)/X11R6/include
pd-gui_LIBS = -ltk8.4 -ltcl8.4 -lX11 -ldl
pd-gui_LDFLAGS = -L$(X11LIB)
pd-gui_DEFINES = $(DEFINES)
pd_LIBS = -lm -lpthread -ldl
pd_LDFLAGS = -Wl,-export-dynamic
pd_DEFINES = $(DEFINES) -DINSTALL_PREFIX=\"$(PREFIX)\" \
-DFIXEDPOINT -DUSEAPI_OSS -DDL_OPEN
extra_DEFINES = $(DEFINES) -DFIXEDPOINT
extra_INCLUDES = -I../src
extra_LDFLAGS = -shared
# IPOD toolchain
ifeq ($(CC), arm-elf-gcc)
pd_LDFLAGS += -elf2flt
pd_LIBS = -lm -lpthread
pd_DEFINES = $(DEFINES) -DINSTALL_PREFIX=\"$(PREFIX)\" \
-DFIXEDPOINT -DUSEAPI_OSS -D__linux__ -Dfork=getpid
extra_DEFINES += -D__linux__ -Dfork=getpid
endif
# BLACKFIN toolchain
ifeq ($(CC), bfin-uclinux-gcc)
pd_LIBS = -lm -lpthread
pd_DEFINES = $(DEFINES) -DINSTALL_PREFIX=\"$(PREFIX)\" \
-DFIXEDPOINT -DUSEAPI_OSS -D__linux__
extra_DEFINES += -D__linux__
endif
# the sources
pd_SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
d_ugen.c d_arithmetic.c d_dac.c d_misc.c \
d_fft.c d_mayer_fft.c d_fftroutine.c d_global.c \
d_resample.c d_ctl.c d_soundfile.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c \
s_midi_oss.c s_audio_oss.c
pd_SRC += d_imayer_fft.c m_fixed.c
pd_OBJ = $(pd_SRC:.c=.o)
pd-gui_SRC = t_main.c t_tkcmd.c
pd-gui_OBJ = $(pd-gui_SRC:.c=.o)
extra_SRC = $(shell ls ../intern/*.c) $(shell ls ../extra/*.c)
extra_OBJ = $(extra_SRC:.c=.o)
extra_EXT = $(extra_SRC:.c=.pd_linux)
#
# ------------------ targets ------------------------------------
#
all: $(BIN_DIR)/pd \
$(BIN_DIR)/pd-gui \
$(BIN_DIR)/pd-watchdog \
$(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive \
$(BIN_DIR)/pd.tk \
extra
pd: $(BIN_DIR)/pd
pd-gui: $(BIN_DIR)/pd-gui
pd-watchdog: $(BIN_DIR)/pd-watchdog
static:
make pd_SRC="$(pd_SRC) $(extra_SRC)" DEFINES="-DPD -DUNIX -DSTATIC" \
pd pd-gui pd-watchdog $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive $(BIN_DIR)/pd.tk
extra: $(extra_EXT)
ipod:
make CC=arm-elf-gcc static
blackfin:
make CC=bfin-uclinux-gcc static
$(pd_OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(pd_DEFINES) $(pd_INCLUDES) -c -o $(OBJ_DIR)/$@ $+
$(pd-gui_OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(pd-gui_DEFINES) $(pd-gui_INCLUDES) -c -o $(OBJ_DIR)/$@ $+
$(extra_OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(extra_DEFINES) $(extra_INCLUDES) -c -o $@ $*.c
$(extra_EXT) : %.$(EXT) : %.o
$(CC) -o $@ $(extra_LDFLAGS) $+
$(BIN_DIR)/pd-watchdog: s_watchdog.c
$(CC) $(CFLAGS) $(DEFINES) -o $@ s_watchdog.c
$(BIN_DIR)/pdsend: u_pdsend.c
$(CC) $(CFLAGS) $(DEFINES) -o $@ u_pdsend.c
$(BIN_DIR)/pdreceive: u_pdreceive.c
$(CC) $(CFLAGS) $(DEFINES) -o $@ u_pdreceive.c
$(BIN_DIR)/pd: $(pd_OBJ)
cd ../obj; $(CC) $(pd_LDFLAGS) -o $@ $(pd_OBJ) $(pd_LIBS)
$(BIN_DIR)/pd-gui: $(pd-gui_OBJ)
cd ../obj; $(CC) -o $@ $(pd-gui_OBJ) $(pd-gui_LDFLAGS) $(pd-gui_LIBS)
$(BIN_DIR)/pd.tk: u_main.tk
echo set pd_nt 0 > $(BIN_DIR)/pd.tk
grep -v "set pd_nt" < u_main.tk >> $@
INSTDIR = $(DESTDIR)/$(PREFIX)
install: all
# Create the directory structure
install -d $(INSTDIR)/lib/pd/bin
install -d $(INSTDIR)/lib/pd/extra
install -d $(INSTDIR)/lib/pd/intern
install -d $(INSTDIR)/lib/pd/doc
install -d $(INSTDIR)/bin
install -d $(INSTDIR)/include
install $(BIN_DIR)/pd-gui $(INSTDIR)/lib/pd/bin/
install $(BIN_DIR)/pd-watchdog $(INSTDIR)/lib/pd/bin/
install -m 644 $(BIN_DIR)/pd.tk $(INSTDIR)/lib/pd/bin/
install -m 755 $(BIN_DIR)/pd $(INSTDIR)/bin/
install -m 755 $(BIN_DIR)/pdsend $(INSTDIR)/bin/pdsend
install -m 755 $(BIN_DIR)/pdreceive $(INSTDIR)/bin/pdreceive
cp -r ../doc/7.stuff $(INSTDIR)/lib/pd/doc
cp -r ../doc/5.reference $(INSTDIR)/lib/pd/doc
install -m 644 m_pd.h $(INSTDIR)/include/m_pd.h
# Install the externals if possible
cp ../extra/*.pd_linux $(INSTDIR)/lib/pd/extra
cp ../intern/*.pd_linux $(INSTDIR)/lib/pd/intern
# Install the ICON and desktop file
install -d $(INSTDIR)/share/pixmaps
install -d $(INSTDIR)/share/applications
cp ../ipkg/pd-icon.png $(INSTDIR)/share/pixmaps
cp ../ipkg/pd.desktop $(INSTDIR)/share/applications/
clean:
-rm -f `find ../extra/ -name "*.pd_*"`
-rm -f tags
-rm -f ../obj/* $(BIN_DIR)/* ../extra/*.{o,$(EXT)} ../intern/*.{o,$(EXT)}
-rm -f *~
-rm -f $(BIN_DIR)/pdsend $(BIN_DIR)/pdreceive

View file

@ -1,946 +0,0 @@
/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* this file inputs and outputs audio using the ALSA API available on linux. */
#include <alsa/asoundlib.h>
#include "m_pd.h"
#include "s_stuff.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mman.h>
typedef int16_t t_alsa_sample16;
typedef int32_t t_alsa_sample32;
#define ALSA_SAMPLEWIDTH_16 sizeof(t_alsa_sample16)
#define ALSA_SAMPLEWIDTH_32 sizeof(t_alsa_sample32)
#define ALSA_XFERSIZE16 (signed int)(sizeof(t_alsa_sample16) * DEFDACBLKSIZE)
#define ALSA_XFERSIZE32 (signed int)(sizeof(t_alsa_sample32) * DEFDACBLKSIZE)
#define ALSA_MAXDEV 1
#define ALSA_JITTER 1024
#define ALSA_EXTRABUFFER 2048
#define ALSA_DEFFRAGSIZE 64
#define ALSA_DEFNFRAG 12
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif
#if (SND_LIB_MAJOR < 1)
#define ALSAAPI9
#endif
typedef struct _alsa_dev
{
snd_pcm_t *inhandle;
snd_pcm_t *outhandle;
int innoninterleave; /* true if we're set for noninterleaved read */
int outnoninterleave; /* same for write */
} t_alsa_dev;
t_alsa_dev alsa_device;
static void *alsa_snd_buf = 0;
static void **alsa_buf_ptrs;
static int alsa_samplewidth;
static snd_pcm_status_t* in_status;
static snd_pcm_status_t* out_status;
static int alsa_mode;
static int alsa_buf_samps; /* believed actual ALSA bufsize in sample frames */
static int alsa_inchannels;
static int alsa_outchannels;
/* Defines */
#define DEBUG(x) x
#define DEBUG2(x) {x;}
static void alsa_checkiosync( void);
static void alsa_numbertoname(int devno, char *devname, int nchar);
/* don't assume we can turn all 31 bits when doing float-to-fix;
otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
#define FMAX 0x7ffff000
#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
/* support for ALSA pcmv2 api by Karl MacMillan<karlmac@peabody.jhu.edu> */
static void check_error(int err, const char *why)
{
if (err < 0)
fprintf(stderr, "%s: %s\n", why, snd_strerror(err));
}
/* was: alsa_open_audio(int wantinchans, int wantoutchans, int srate) */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
int *choutdev, int rate)
{
int err, inchans = 0, outchans = 0, subunitdir;
char devname[512];
snd_pcm_hw_params_t* hw_params;
snd_pcm_sw_params_t* sw_params;
snd_output_t* out;
int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE);
int nfrags, i;
short* tmp_buf;
unsigned int tmp_uint;
snd_pcm_uframes_t tmp_snd_pcm_uframes;
int wantinchans, wantoutchans, devno;
if (naudioindev >= 2 || naudiooutdev >= 2)
post("alsa: only one input and output device allowed (extras ignored");
if (naudioindev >= 1 && naudiooutdev >= 1 &&
audioindev[0] != audiooutdev[0])
post("alsa: changing output device to agree with input device");
if (nchindev)
wantinchans = chindev[0];
else wantinchans = (naudioindev ? 2 : 0);
if (nchoutdev)
wantoutchans = choutdev[0];
else wantoutchans = (naudiooutdev ? 2 : 0);
devno = (naudioindev > 0 ? audioindev[0] :
(naudiooutdev > 0 ? audiooutdev[0] : 0));
alsa_numbertoname(devno, devname, 512);
if (sys_verbose)
post("device name %s; channels in %d, out %d", devname, wantinchans,
wantoutchans);
nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size);
/* save our belief as to ALSA's buffer size for later */
alsa_buf_samps = nfrags * frag_size;
if (sys_verbose)
post("audio buffer set to %d", (int)(0.001 * sys_schedadvance));
alsa_device.innoninterleave = alsa_device.outnoninterleave = 0;
if (wantinchans)
{
err = snd_pcm_open(&alsa_device.inhandle, devname,
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
check_error(err, "snd_pcm_open (input)");
if (err < 0)
inchans = 0;
else
{
inchans = wantinchans;
snd_pcm_nonblock(alsa_device.inhandle, 1);
}
}
if (wantoutchans)
{
err = snd_pcm_open(&alsa_device.outhandle, devname,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
check_error(err, "snd_pcm_open (output)");
if (err < 0)
outchans = 0;
else
{
outchans = wantoutchans;
snd_pcm_nonblock(alsa_device.outhandle, 1);
}
}
if (inchans)
{
if (sys_verbose)
post("opening sound input...");
err = snd_pcm_hw_params_malloc(&hw_params);
check_error(err, "snd_pcm_hw_params_malloc (input)");
// get the default params
err = snd_pcm_hw_params_any(alsa_device.inhandle, hw_params);
check_error(err, "snd_pcm_hw_params_any (input)");
/* try to set interleaved access */
err = snd_pcm_hw_params_set_access(alsa_device.inhandle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
{
/* OK, so try non-interleaved */
err = snd_pcm_hw_params_set_access(alsa_device.inhandle,
hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
if (err >= 0)
{
post("using non-interleaved audio input");
alsa_device.innoninterleave = 1;
}
}
check_error(err, "snd_pcm_hw_params_set_access (input)");
// Try to set 32 bit format first
err = snd_pcm_hw_params_set_format(alsa_device.inhandle, hw_params,
SND_PCM_FORMAT_S32);
if (err < 0)
{
/* fprintf(stderr,
"PD-ALSA: 32 bit format not available - using 16\n"); */
err = snd_pcm_hw_params_set_format(alsa_device.inhandle, hw_params,
SND_PCM_FORMAT_S16);
check_error(err, "snd_pcm_hw_params_set_format (input)");
alsa_samplewidth = 2;
}
else
{
alsa_samplewidth = 4;
}
post("Sample width set to %d bytes", alsa_samplewidth);
// set the subformat
err = snd_pcm_hw_params_set_subformat(alsa_device.inhandle, hw_params,
SND_PCM_SUBFORMAT_STD);
check_error(err, "snd_pcm_hw_params_set_subformat (input)");
// set the number of channels
tmp_uint = inchans;
err = snd_pcm_hw_params_set_channels_min(alsa_device.inhandle,
hw_params, &tmp_uint);
check_error(err, "snd_pcm_hw_params_set_channels (input)");
if (tmp_uint != (unsigned)inchans)
post("ALSA: set input channels to %d", tmp_uint);
inchans = tmp_uint;
// set the sampling rate
err = snd_pcm_hw_params_set_rate_min(alsa_device.inhandle, hw_params,
&rate, 0);
check_error(err, "snd_pcm_hw_params_set_rate_min (input)");
#if 0
err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
post("input sample rate %d", err);
#endif
// set the period - ie frag size
// post("fragsize a %d", frag_size);
/* LATER try this to get a recommended period size...
right now, it trips an assertion failure in ALSA lib */
#if 0
post("input period was %d, min %d, max %d\n",
snd_pcm_hw_params_get_period_size(hw_params, 0),
snd_pcm_hw_params_get_period_size_min(hw_params, 0),
snd_pcm_hw_params_get_period_size_max(hw_params, 0));
#endif
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_period_size_near(alsa_device.inhandle,
hw_params,
(snd_pcm_uframes_t)
frag_size, 0);
#else
tmp_snd_pcm_uframes = frag_size;
err = snd_pcm_hw_params_set_period_size_near(alsa_device.inhandle,
hw_params, &tmp_snd_pcm_uframes, 0);
#endif
check_error(err, "snd_pcm_hw_params_set_period_size_near (input)");
// post("fragsize b %d", frag_size);
// set the number of periods - ie numfrags
// post("nfrags a %d", nfrags);
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_periods_near(alsa_device.inhandle,
hw_params, nfrags, 0);
#else
tmp_uint = nfrags;
err = snd_pcm_hw_params_set_periods_near(alsa_device.inhandle,
hw_params, &tmp_uint, 0);
#endif
check_error(err, "snd_pcm_hw_params_set_periods_near (input)");
// set the buffer size
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_buffer_size_near(alsa_device.inhandle,
hw_params, nfrags * frag_size);
#else
tmp_snd_pcm_uframes = nfrags * frag_size;
err = snd_pcm_hw_params_set_buffer_size_near(alsa_device.inhandle,
hw_params, &tmp_snd_pcm_uframes);
#endif
check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)");
err = snd_pcm_hw_params(alsa_device.inhandle, hw_params);
check_error(err, "snd_pcm_hw_params (input)");
snd_pcm_hw_params_free(hw_params);
err = snd_pcm_sw_params_malloc(&sw_params);
check_error(err, "snd_pcm_sw_params_malloc (input)");
err = snd_pcm_sw_params_current(alsa_device.inhandle, sw_params);
check_error(err, "snd_pcm_sw_params_current (input)");
err = snd_pcm_sw_params_set_start_threshold(alsa_device.inhandle,
sw_params, nfrags * frag_size);
check_error(err, "snd_pcm_sw_params_set_start_threshold (input)");
err = snd_pcm_sw_params_set_stop_threshold(alsa_device.inhandle,
sw_params, 0x7fffffff);
check_error(err, "snd_pcm_sw_params_set_stop_threshold (input)");
err = snd_pcm_sw_params_set_avail_min(alsa_device.inhandle, sw_params,
frag_size);
check_error(err, "snd_pcm_sw_params_set_avail_min (input)");
err = snd_pcm_sw_params(alsa_device.inhandle, sw_params);
check_error(err, "snd_pcm_sw_params (input)");
snd_pcm_sw_params_free(sw_params);
snd_output_stdio_attach(&out, stderr, 0);
#if 0
if (sys_verbose)
{
snd_pcm_dump_hw_setup(alsa_device.inhandle, out);
snd_pcm_dump_sw_setup(alsa_device.inhandle, out);
}
#endif
}
if (outchans)
{
int foo;
if (sys_verbose)
post("opening sound output...");
err = snd_pcm_hw_params_malloc(&hw_params);
check_error(err, "snd_pcm_sw_params (output)");
// get the default params
err = snd_pcm_hw_params_any(alsa_device.outhandle, hw_params);
check_error(err, "snd_pcm_hw_params_any (output)");
// set interleaved access - FIXME deal with other access types
err = snd_pcm_hw_params_set_access(alsa_device.outhandle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED);
check_error(err, "snd_pcm_hw_params_set_access (output)");
/* try to set interleaved access */
err = snd_pcm_hw_params_set_access(alsa_device.outhandle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
{
/* OK, so try non-interleaved */
err = snd_pcm_hw_params_set_access(alsa_device.outhandle,
hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
if (err >= 0)
{
post("using non-interleaved audio");
alsa_device.outnoninterleave = 1;
}
}
check_error(err, "snd_pcm_hw_params_set_access (output)");
// Try to set 32 bit format first
err = snd_pcm_hw_params_set_format(alsa_device.outhandle, hw_params,
SND_PCM_FORMAT_S32);
if (err < 0)
{
err = snd_pcm_hw_params_set_format(alsa_device.outhandle,
hw_params,SND_PCM_FORMAT_S16);
check_error(err, "snd_pcm_hw_params_set_format (output)");
/* fprintf(stderr,
"PD-ALSA: 32 bit format not available - using 16\n"); */
alsa_samplewidth = 2;
}
else
{
alsa_samplewidth = 4;
}
// set the subformat
err = snd_pcm_hw_params_set_subformat(alsa_device.outhandle, hw_params,
SND_PCM_SUBFORMAT_STD);
check_error(err, "snd_pcm_hw_params_set_subformat (output)");
// set the number of channels
tmp_uint = outchans;
err = snd_pcm_hw_params_set_channels_min(alsa_device.outhandle,
hw_params, &tmp_uint);
check_error(err, "snd_pcm_hw_params_set_channels (output)");
if (tmp_uint != (unsigned)outchans)
post("alsa: set output channels to %d", tmp_uint);
outchans = tmp_uint;
// set the sampling rate
err = snd_pcm_hw_params_set_rate_min(alsa_device.outhandle, hw_params,
&rate, 0);
check_error(err, "snd_pcm_hw_params_set_rate_min (output)");
#if 0
err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
post("output sample rate %d", err);
#endif
// set the period - ie frag size
#if 0
post("output period was %d, min %d, max %d\n",
snd_pcm_hw_params_get_period_size(hw_params, 0),
snd_pcm_hw_params_get_period_size_min(hw_params, 0),
snd_pcm_hw_params_get_period_size_max(hw_params, 0));
#endif
// post("fragsize c %d", frag_size);
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_period_size_near(alsa_device.outhandle,
hw_params,
(snd_pcm_uframes_t)
frag_size, 0);
#else
tmp_snd_pcm_uframes = frag_size;
err = snd_pcm_hw_params_set_period_size_near(alsa_device.outhandle,
hw_params, &tmp_snd_pcm_uframes, 0);
#endif
// post("fragsize d %d", frag_size);
check_error(err, "snd_pcm_hw_params_set_period_size_near (output)");
// set the number of periods - ie numfrags
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_periods_near(alsa_device.outhandle,
hw_params, nfrags, 0);
#else
tmp_uint = nfrags;
err = snd_pcm_hw_params_set_periods_near(alsa_device.outhandle,
hw_params, &tmp_uint, 0);
#endif
check_error(err, "snd_pcm_hw_params_set_periods_near (output)");
// set the buffer size
#ifdef ALSAAPI9
err = snd_pcm_hw_params_set_buffer_size_near(alsa_device.outhandle,
hw_params, nfrags * frag_size);
#else
tmp_snd_pcm_uframes = nfrags * frag_size;
err = snd_pcm_hw_params_set_buffer_size_near(alsa_device.outhandle,
hw_params, &tmp_snd_pcm_uframes);
#endif
check_error(err, "snd_pcm_hw_params_set_buffer_size_near (output)");
err = snd_pcm_hw_params(alsa_device.outhandle, hw_params);
check_error(err, "snd_pcm_hw_params (output)");
snd_pcm_hw_params_free(hw_params);
err = snd_pcm_sw_params_malloc(&sw_params);
check_error(err, "snd_pcm_sw_params_malloc (output)");
err = snd_pcm_sw_params_current(alsa_device.outhandle, sw_params);
check_error(err, "snd_pcm_sw_params_current (output)");
err = snd_pcm_sw_params_set_start_threshold(alsa_device.outhandle,
sw_params, nfrags * frag_size);
check_error(err, "snd_pcm_sw_params_set_start_threshold (output)");
err = snd_pcm_sw_params_set_stop_threshold(alsa_device.outhandle,
sw_params, 0x7fffffff);
check_error(err, "snd_pcm_sw_params_set_stop_threshold (output)");
err = snd_pcm_sw_params_set_avail_min(alsa_device.outhandle, sw_params,
frag_size);
check_error(err, "snd_pcm_sw_params_set_avail_min (output)");
err = snd_pcm_sw_params(alsa_device.outhandle, sw_params);
check_error(err, "snd_pcm_sw_params (output)");
snd_pcm_sw_params_free(sw_params);
snd_output_stdio_attach(&out, stderr, 0);
#if 0
if (sys_verbose)
{
snd_pcm_dump_hw_setup(alsa_device.outhandle, out);
snd_pcm_dump_sw_setup(alsa_device.outhandle, out);
}
#endif
}
if (inchans)
snd_pcm_prepare(alsa_device.inhandle);
if (outchans)
snd_pcm_prepare(alsa_device.outhandle);
// if duplex we can link the channels so they start together
if (inchans && outchans)
snd_pcm_link(alsa_device.inhandle, alsa_device.outhandle);
// set up the status variables
err = snd_pcm_status_malloc(&in_status);
check_error(err, "snd_pcm_status_malloc");
err = snd_pcm_status_malloc(&out_status);
check_error(err, "snd_pcm_status_malloc");
// set up the buffer
if (alsa_snd_buf)
free(alsa_snd_buf);
alsa_snd_buf = (void *)malloc(
sizeof(char) * alsa_samplewidth * DEFDACBLKSIZE *
(outchans > inchans ? outchans : inchans));
memset(alsa_snd_buf, 0, sizeof(char) * alsa_samplewidth * DEFDACBLKSIZE *
(outchans > inchans ? outchans : inchans));
/* make an array of pointers too in case we need them */
if (alsa_buf_ptrs)
free(alsa_buf_ptrs);
alsa_buf_ptrs = (void **)malloc(
sizeof(void *) * (outchans > inchans ? outchans : inchans));
for (i = 0; i < (outchans > inchans ? outchans : inchans); i++)
alsa_buf_ptrs[i] = (t_alsa_sample32 *)alsa_snd_buf + i * DEFDACBLKSIZE;
// fill the buffer with silence
if (outchans)
{
i = (frag_size * nfrags)/DEFDACBLKSIZE + 1;
while (i--)
{
if (alsa_device.outnoninterleave)
snd_pcm_writen(alsa_device.outhandle, alsa_buf_ptrs,
DEFDACBLKSIZE);
else snd_pcm_writei(alsa_device.outhandle, alsa_snd_buf,
DEFDACBLKSIZE);
}
/* confused about this: */
/* if ((err = snd_pcm_start(alsa_device.outhandle) < 0))
check_error(err, "output start failed\n"); */
}
else if (inchans)
{
if (snd_pcm_start(alsa_device.inhandle) < 0)
check_error(err, "input start failed\n");
}
alsa_outchannels = outchans;
alsa_inchannels = inchans;
return (!(inchans || outchans));
}
void alsa_close_audio(void)
{
int err;
if (alsa_inchannels)
{
err = snd_pcm_close(alsa_device.inhandle);
check_error(err, "snd_pcm_close (input)");
}
if (alsa_outchannels)
{
err = snd_pcm_close(alsa_device.outhandle);
check_error(err, "snd_pcm_close (output)");
}
}
// #define DEBUG_ALSA_XFER
int alsa_send_dacs(void)
{
static int16_t *sp;
static int xferno = 0;
static int callno = 0;
static double timenow;
double timelast;
t_sample *fp, *fp1, *fp2;
int i, j, k, err, devno = 0;
int inputcount = 0, outputcount = 0, inputlate = 0, outputlate = 0;
int result;
int inchannels = (sys_inchannels > alsa_inchannels ?
alsa_inchannels : sys_inchannels);
int outchannels = (sys_outchannels > alsa_outchannels ?
alsa_outchannels : sys_outchannels);
unsigned int intransfersize = DEFDACBLKSIZE;
unsigned int outtransfersize = DEFDACBLKSIZE;
// get the status
if (!inchannels && !outchannels)
{
return SENDDACS_NO;
}
timelast = timenow;
timenow = sys_getrealtime();
#ifdef DEBUG_ALSA_XFER
if (timenow - timelast > 0.050)
fprintf(stderr, "(%d)",
(int)(1000 * (timenow - timelast))), fflush(stderr);
#endif
callno++;
alsa_checkiosync(); /* check I/O are in sync and data not late */
if (alsa_inchannels)
{
snd_pcm_status(alsa_device.inhandle, in_status);
if (snd_pcm_status_get_avail(in_status) < intransfersize)
return SENDDACS_NO;
}
if (alsa_outchannels)
{
snd_pcm_status(alsa_device.outhandle, out_status);
if (snd_pcm_status_get_avail(out_status) < outtransfersize)
return SENDDACS_NO;
}
/* do output */
if (alsa_outchannels)
{
fp = sys_soundout;
if (alsa_samplewidth == 4)
{
if (alsa_device.outnoninterleave)
{
int n = outchannels * DEFDACBLKSIZE;
for (i = 0, fp1 = fp; i < n; i++)
{
float s1 = *fp1 * INT32_MAX;
((t_alsa_sample32 *)alsa_snd_buf)[i] = CLIP32(s1);
}
n = alsa_outchannels * DEFDACBLKSIZE;
for (; i < n; i++)
((t_alsa_sample32 *)alsa_snd_buf)[i] = 0;
}
else
{
for (i = 0, fp1 = fp; i < outchannels; i++,
fp1 += DEFDACBLKSIZE)
{
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += alsa_outchannels, fp2++)
{
float s1 = *fp2 * INT32_MAX;
((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1);
}
}
}
}
else
{
for (i = 0, fp1 = fp; i < outchannels; i++, fp1 += DEFDACBLKSIZE)
{
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += alsa_outchannels, fp2++)
{
int s = *fp2 * 32767.;
if (s > 32767)
s = 32767;
else if (s < -32767)
s = -32767;
((t_alsa_sample16 *)alsa_snd_buf)[j] = s;
}
}
}
if (alsa_device.outnoninterleave)
result = snd_pcm_writen(alsa_device.outhandle, alsa_buf_ptrs,
outtransfersize);
else result = snd_pcm_writei(alsa_device.outhandle, alsa_snd_buf,
outtransfersize);
if (result != (int)outtransfersize)
{
#ifdef DEBUG_ALSA_XFER
if (result >= 0 || errno == EAGAIN)
fprintf(stderr, "ALSA: write returned %d of %d\n",
result, outtransfersize);
else fprintf(stderr, "ALSA: write: %s\n",
snd_strerror(errno));
fprintf(stderr,
"inputcount %d, outputcount %d, outbufsize %d\n",
inputcount, outputcount,
(ALSA_EXTRABUFFER + sys_advance_samples)
* alsa_samplewidth * outchannels);
#endif
sys_log_error(ERR_DACSLEPT);
return (SENDDACS_NO);
}
/* zero out the output buffer */
memset(sys_soundout, 0, DEFDACBLKSIZE * sizeof(*sys_soundout) *
sys_outchannels);
if (sys_getrealtime() - timenow > 0.002)
{
#ifdef DEBUG_ALSA_XFER
fprintf(stderr, "output %d took %d msec\n",
callno, (int)(1000 * (timenow - timelast))), fflush(stderr);
#endif
timenow = sys_getrealtime();
sys_log_error(ERR_DACSLEPT);
}
}
/* do input */
if (alsa_inchannels)
{
if (alsa_device.innoninterleave)
result = snd_pcm_readn(alsa_device.inhandle, alsa_buf_ptrs,
intransfersize);
else result = snd_pcm_readi(alsa_device.inhandle, alsa_snd_buf,
intransfersize);
if (result < (int)intransfersize)
{
#ifdef DEBUG_ALSA_XFER
if (result < 0)
fprintf(stderr,
"snd_pcm_read %d %d: %s\n",
callno, xferno, snd_strerror(errno));
else fprintf(stderr,
"snd_pcm_read %d %d returned only %d\n",
callno, xferno, result);
fprintf(stderr,
"inputcount %d, outputcount %d, inbufsize %d\n",
inputcount, outputcount,
(ALSA_EXTRABUFFER + sys_advance_samples)
* alsa_samplewidth * inchannels);
#endif
sys_log_error(ERR_ADCSLEPT);
return (SENDDACS_NO);
}
fp = sys_soundin;
if (alsa_samplewidth == 4)
{
if (alsa_device.innoninterleave)
{
int n = inchannels * DEFDACBLKSIZE;
for (i = 0, fp1 = fp; i < n; i++)
*fp1 = (float) ((t_alsa_sample32 *)alsa_snd_buf)[i]
* (1./ INT32_MAX);
}
else
{
for (i = 0, fp1 = fp; i < inchannels;
i++, fp1 += DEFDACBLKSIZE)
{
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += alsa_inchannels, fp2++)
*fp2 = (float) ((t_alsa_sample32 *)alsa_snd_buf)[j]
* (1./ INT32_MAX);
}
}
}
else
{
for (i = 0, fp1 = fp; i < inchannels; i++, fp1 += DEFDACBLKSIZE)
{
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += alsa_inchannels, fp2++)
*fp2 = (float) ((t_alsa_sample16 *)alsa_snd_buf)[j]
* 3.051850e-05;
}
}
}
xferno++;
if (sys_getrealtime() - timenow > 0.002)
{
#ifdef DEBUG_ALSA_XFER
fprintf(stderr, "routine took %d msec\n",
(int)(1000 * (sys_getrealtime() - timenow)));
#endif
sys_log_error(ERR_ADCSLEPT);
}
return SENDDACS_YES;
}
void alsa_printstate( void)
{
int i, result;
snd_pcm_sframes_t indelay, outdelay;
if (sys_audioapi != API_ALSA)
{
error("restart-audio: implemented for ALSA only.");
return;
}
if (sys_inchannels)
{
result = snd_pcm_delay(alsa_device.inhandle, &indelay);
if (result < 0)
post("snd_pcm_delay 1 failed");
else post("in delay %d", indelay);
}
if (sys_outchannels)
{
result = snd_pcm_delay(alsa_device.outhandle, &outdelay);
if (result < 0)
post("snd_pcm_delay 2 failed");
else post("out delay %d", outdelay);
}
post("sum %d (%d mod 64)\n", indelay + outdelay, (indelay+outdelay)%64);
post("buf samples %d", alsa_buf_samps);
}
void alsa_resync( void)
{
int i, result;
if (sys_audioapi != API_ALSA)
{
error("restart-audio: implemented for ALSA only.");
return;
}
memset(alsa_snd_buf, 0,
sizeof(char) * alsa_samplewidth * DEFDACBLKSIZE * sys_outchannels);
for (i = 0; i < 1000000; i++)
{
if (alsa_device.outnoninterleave)
result = snd_pcm_writen(alsa_device.outhandle, alsa_buf_ptrs,
DEFDACBLKSIZE);
else result = snd_pcm_writei(alsa_device.outhandle, alsa_snd_buf,
DEFDACBLKSIZE);
if (result != (int)DEFDACBLKSIZE)
break;
}
post("%d written", i);
}
void alsa_putzeros(int n)
{
int i, result;
memset(alsa_snd_buf, 0,
sizeof(char) * alsa_samplewidth * DEFDACBLKSIZE * alsa_outchannels);
for (i = 0; i < n; i++)
{
if (alsa_device.outnoninterleave)
result = snd_pcm_writen(alsa_device.outhandle, alsa_buf_ptrs,
DEFDACBLKSIZE);
else result = snd_pcm_writei(alsa_device.outhandle, alsa_snd_buf,
DEFDACBLKSIZE);
#if 0
if (result != DEFDACBLKSIZE)
post("result %d", result);
#endif
}
/* post ("putzeros %d", n); */
}
void alsa_getzeros(int n)
{
int i, result;
for (i = 0; i < n; i++)
{
result = snd_pcm_readi(alsa_device.inhandle, alsa_snd_buf,
DEFDACBLKSIZE);
#if 0
if (result != DEFDACBLKSIZE)
post("result %d", result);
#endif
}
/* post ("getzeros %d", n); */
}
/* call this only if both input and output are open */
static void alsa_checkiosync( void)
{
int i, result, checkit = 1, giveup = 1000, alreadylogged = 0;
snd_pcm_sframes_t indelay, outdelay, defect;
if (!(alsa_outchannels && alsa_inchannels))
return;
while (checkit)
{
checkit = 0;
if (giveup-- <= 0)
return;
result = snd_pcm_delay(alsa_device.outhandle, &outdelay);
if (result < 0)
{
post("output snd_pcm_delay failed: %s", snd_strerror(result));
if (snd_pcm_status(alsa_device.outhandle, out_status) < 0)
post("output snd_pcm_status failed");
else post("astate %d",
snd_pcm_status_get_state(out_status));
return;
}
if (outdelay < 0)
sys_log_error(ERR_DATALATE), alreadylogged = 1;
if (sys_inchannels)
{
result = snd_pcm_delay(alsa_device.inhandle, &indelay);
if (result < 0)
{
post("input snd_pcm_delay failed");
return;
}
defect = indelay + outdelay - alsa_buf_samps;
if (defect < -(3 * DEFDACBLKSIZE / 2) )
{
checkit = 1;
alsa_putzeros(1);
if (!alreadylogged)
sys_log_error(ERR_RESYNC), alreadylogged = 1;
}
else if (defect > 0)
{
checkit = 1;
alsa_getzeros(1);
if (!alreadylogged)
sys_log_error(ERR_RESYNC), alreadylogged = 1;
}
/* if (alreadylogged)
post("in %d out %d defect %d", indelay, outdelay, defect); */
}
}
}
static int alsa_nnames = 0;
static char **alsa_names = 0;
void alsa_adddev(char *name)
{
if (alsa_nnames)
alsa_names = (char **)t_resizebytes(alsa_names,
alsa_nnames * sizeof(char *),
(alsa_nnames+1) * sizeof(char *));
else alsa_names = (char **)t_getbytes(sizeof(char *));
alsa_names[alsa_nnames] = gensym(name)->s_name;
alsa_nnames++;
}
static void alsa_numbertoname(int devno, char *devname, int nchar)
{
int ndev = 0, cardno = -1;
while (!snd_card_next(&cardno) && cardno >= 0)
ndev++;
if (devno < 2*ndev)
{
if (devno & 1)
snprintf(devname, nchar, "plughw:%d", devno/2);
else snprintf(devname, nchar, "hw:%d", devno/2);
}
else if (devno <2*ndev + alsa_nnames)
snprintf(devname, nchar, "%s", alsa_names[devno - 2*ndev]);
else snprintf(devname, nchar, "???");
}
/* For each hardware card found, we list two devices, the "hard" and
"plug" one. The card scan is derived from portaudio code. */
void alsa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int ndev = 0, cardno = -1, i, j;
*canmulti = 0; /* only one device; must be the same for input&output */
while (!snd_card_next(&cardno) && cardno >= 0)
{
snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
char devname[80];
const char *desc;
if (2 * ndev + 2 > maxndev)
break;
/* apparently, "cardno" is just a counter; but check that here */
if (ndev != cardno)
fprintf(stderr, "oops: ALSA cards not reported in order?\n");
sprintf(devname, "hw:%d", cardno );
/* fprintf(stderr, "\ntry %s...\n", devname); */
if (snd_ctl_open(&ctl, devname, 0) >= 0)
{
snd_ctl_card_info_malloc(&info);
snd_ctl_card_info(ctl, info);
desc = snd_ctl_card_info_get_name(info);
snd_ctl_card_info_free(info);
}
else
{
fprintf(stderr, "ALSA card scan error\n");
desc = "???";
}
/* fprintf(stderr, "name: %s\n", snd_ctl_card_info_get_name(info)); */
sprintf(indevlist + 2*ndev * devdescsize, "%s (hardware)", desc);
sprintf(indevlist + (2*ndev + 1) * devdescsize, "%s (plug-in)", desc);
sprintf(outdevlist + 2*ndev * devdescsize, "%s (hardware)", desc);
sprintf(outdevlist + (2*ndev + 1) * devdescsize, "%s (plug-in)", desc);
ndev++;
}
for (i = 0, j = 2*ndev; i < alsa_nnames; i++, j++)
{
if (j >= maxndev)
break;
snprintf(indevlist + j * devdescsize, devdescsize, "%s",
alsa_names[i]);
}
*nindevs = *noutdevs = j;
}

View file

@ -1,795 +0,0 @@
/* 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. */
/* modified 2/98 by Winfried Ritsch to deal with up to 4 synchronized
"wave" devices, which is how ADAT boards appear to the WAVE API. */
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <windows.h>
#include <MMSYSTEM.H>
/* ------------------------- audio -------------------------- */
static void nt_close_midiin(void);
static void nt_noresync( void);
static void postflags(void);
#define NAPORTS 16 /* wini hack for multiple ADDA devices */
#define CHANNELS_PER_DEVICE 2
#define DEFAULTCHANS 2
#define DEFAULTSRATE 44100
#define SAMPSIZE 2
int nt_realdacblksize;
#define DEFREALDACBLKSIZE (4 * DEFDACBLKSIZE) /* larger underlying bufsize */
#define MAXBUFFER 100 /* number of buffers in use at maximum advance */
#define DEFBUFFER 30 /* default is about 30x6 = 180 msec! */
static int nt_naudiobuffer = DEFBUFFER;
float sys_dacsr = DEFAULTSRATE;
static int nt_whichapi = API_MMIO;
static int nt_meters; /* true if we're metering */
static float nt_inmax; /* max input amplitude */
static float nt_outmax; /* max output amplitude */
static int nt_nwavein, nt_nwaveout; /* number of WAVE devices in and out */
typedef struct _sbuf
{
HANDLE hData;
HPSTR lpData; // pointer to waveform data memory
HANDLE hWaveHdr;
WAVEHDR *lpWaveHdr; // pointer to header structure
} t_sbuf;
t_sbuf ntsnd_outvec[NAPORTS][MAXBUFFER]; /* circular buffer array */
HWAVEOUT ntsnd_outdev[NAPORTS]; /* output device */
static int ntsnd_outphase[NAPORTS]; /* index of next buffer to send */
t_sbuf ntsnd_invec[NAPORTS][MAXBUFFER]; /* circular buffer array */
HWAVEIN ntsnd_indev[NAPORTS]; /* input device */
static int ntsnd_inphase[NAPORTS]; /* index of next buffer to read */
static void nt_waveinerror(char *s, int err)
{
char t[256];
waveInGetErrorText(err, t, 256);
fprintf(stderr, s, t);
}
static void nt_waveouterror(char *s, int err)
{
char t[256];
waveOutGetErrorText(err, t, 256);
fprintf(stderr, s, t);
}
static void wave_prep(t_sbuf *bp, int setdone)
{
WAVEHDR *wh;
short *sp;
int i;
/*
* Allocate and lock memory for the waveform data. The memory
* for waveform data must be globally allocated with
* GMEM_MOVEABLE and GMEM_SHARE flags.
*/
if (!(bp->hData =
GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
(DWORD) (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize))))
printf("alloc 1 failed\n");
if (!(bp->lpData =
(HPSTR) GlobalLock(bp->hData)))
printf("lock 1 failed\n");
/* Allocate and lock memory for the header. */
if (!(bp->hWaveHdr =
GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR))))
printf("alloc 2 failed\n");
if (!(wh = bp->lpWaveHdr =
(WAVEHDR *) GlobalLock(bp->hWaveHdr)))
printf("lock 2 failed\n");
for (i = CHANNELS_PER_DEVICE * nt_realdacblksize,
sp = (short *)bp->lpData; i--; )
*sp++ = 0;
wh->lpData = bp->lpData;
wh->dwBufferLength = (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize);
wh->dwFlags = 0;
wh->dwLoops = 0L;
wh->lpNext = 0;
wh->reserved = 0;
/* optionally (for writing) set DONE flag as if we had queued them */
if (setdone)
wh->dwFlags = WHDR_DONE;
}
static UINT nt_whichdac = WAVE_MAPPER, nt_whichadc = WAVE_MAPPER;
int mmio_do_open_audio(void)
{
PCMWAVEFORMAT form;
int i, j;
UINT mmresult;
int nad, nda;
static int naudioprepped = 0, nindevsprepped = 0, noutdevsprepped = 0;
if (sys_verbose)
post("%d devices in, %d devices out",
nt_nwavein, nt_nwaveout);
form.wf.wFormatTag = WAVE_FORMAT_PCM;
form.wf.nChannels = CHANNELS_PER_DEVICE;
form.wf.nSamplesPerSec = sys_dacsr;
form.wf.nAvgBytesPerSec = sys_dacsr * (CHANNELS_PER_DEVICE * SAMPSIZE);
form.wf.nBlockAlign = CHANNELS_PER_DEVICE * SAMPSIZE;
form.wBitsPerSample = 8 * SAMPSIZE;
if (nt_nwavein <= 1 && nt_nwaveout <= 1)
nt_noresync();
if (nindevsprepped < nt_nwavein)
{
for (i = nindevsprepped; i < nt_nwavein; i++)
for (j = 0; j < naudioprepped; j++)
wave_prep(&ntsnd_invec[i][j], 0);
nindevsprepped = nt_nwavein;
}
if (noutdevsprepped < nt_nwaveout)
{
for (i = noutdevsprepped; i < nt_nwaveout; i++)
for (j = 0; j < naudioprepped; j++)
wave_prep(&ntsnd_outvec[i][j], 1);
noutdevsprepped = nt_nwaveout;
}
if (naudioprepped < nt_naudiobuffer)
{
for (j = naudioprepped; j < nt_naudiobuffer; j++)
{
for (i = 0; i < nt_nwavein; i++)
wave_prep(&ntsnd_invec[i][j], 0);
for (i = 0; i < nt_nwaveout; i++)
wave_prep(&ntsnd_outvec[i][j], 1);
}
naudioprepped = nt_naudiobuffer;
}
for (nad=0; nad < nt_nwavein; nad++)
{
/* Open waveform device(s), sucessively numbered, for input */
mmresult = waveInOpen(&ntsnd_indev[nad], nt_whichadc+nad,
(WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);
if (sys_verbose)
printf("opened adc device %d with return %d\n",
nt_whichadc+nad,mmresult);
if (mmresult != MMSYSERR_NOERROR)
{
nt_waveinerror("waveInOpen: %s\n", mmresult);
nt_nwavein = nad; /* nt_nwavein = 0 wini */
}
else
{
for (i = 0; i < nt_naudiobuffer; i++)
{
mmresult = waveInPrepareHeader(ntsnd_indev[nad],
ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveinprepareheader: %s\n", mmresult);
mmresult = waveInAddBuffer(ntsnd_indev[nad],
ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
}
}
}
/* quickly start them all together */
for (nad = 0; nad < nt_nwavein; nad++)
waveInStart(ntsnd_indev[nad]);
for (nda = 0; nda < nt_nwaveout; nda++)
{
/* Open a waveform device for output in sucessiv device numbering*/
mmresult = waveOutOpen(&ntsnd_outdev[nda], nt_whichdac + nda,
(WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);
if (sys_verbose)
fprintf(stderr,"opened dac device %d, with return %d\n",
nt_whichdac +nda, mmresult);
if (mmresult != MMSYSERR_NOERROR)
{
fprintf(stderr,"Wave out open device %d + %d\n",nt_whichdac,nda);
nt_waveouterror("waveOutOpen device: %s\n", mmresult);
nt_nwaveout = nda;
}
}
return (0);
}
void mmio_close_audio( void)
{
int errcode;
int nda, nad;
if (sys_verbose)
post("closing audio...");
for (nda=0; nda < nt_nwaveout; nda++) /*if (nt_nwaveout) wini */
{
errcode = waveOutReset(ntsnd_outdev[nda]);
if (errcode != MMSYSERR_NOERROR)
printf("error resetting output %d: %d\n", nda, errcode);
errcode = waveOutClose(ntsnd_outdev[nda]);
if (errcode != MMSYSERR_NOERROR)
printf("error closing output %d: %d\n",nda , errcode);
}
nt_nwaveout = 0;
for(nad=0; nad < nt_nwavein;nad++) /* if (nt_nwavein) wini */
{
errcode = waveInReset(ntsnd_indev[nad]);
if (errcode != MMSYSERR_NOERROR)
printf("error resetting input: %d\n", errcode);
errcode = waveInClose(ntsnd_indev[nad]);
if (errcode != MMSYSERR_NOERROR)
printf("error closing input: %d\n", errcode);
}
nt_nwavein = 0;
}
#define ADCJITTER 10 /* We tolerate X buffers of jitter by default */
#define DACJITTER 10
static int nt_adcjitterbufsallowed = ADCJITTER;
static int nt_dacjitterbufsallowed = DACJITTER;
/* ------------- MIDI time stamping from audio clock ------------ */
#ifdef MIDI_TIMESTAMP
static double nt_hibuftime;
static double initsystime = -1;
/* call this whenever we reset audio */
static void nt_resetmidisync(void)
{
initsystime = clock_getsystime();
nt_hibuftime = sys_getrealtime();
}
/* call this whenever we're idled waiting for audio to be ready.
The routine maintains a high and low water point for the difference
between real and DAC time. */
static void nt_midisync(void)
{
double jittersec, diff;
if (initsystime == -1) nt_resetmidisync();
jittersec = (nt_dacjitterbufsallowed > nt_adcjitterbufsallowed ?
nt_dacjitterbufsallowed : nt_adcjitterbufsallowed)
* nt_realdacblksize / sys_getsr();
diff = sys_getrealtime() - 0.001 * clock_gettimesince(initsystime);
if (diff > nt_hibuftime) nt_hibuftime = diff;
if (diff < nt_hibuftime - jittersec)
{
post("jitter excess %d %f", dac, diff);
nt_resetmidisync();
}
}
static double nt_midigettimefor(LARGE_INTEGER timestamp)
{
/* this is broken now... used to work when "timestamp" was derived from
QueryPerformanceCounter() instead of the gates approved
timeGetSystemTime() call in the MIDI callback routine below. */
return (nt_tixtotime(timestamp) - nt_hibuftime);
}
#endif /* MIDI_TIMESTAMP */
static int nt_fill = 0;
#define WRAPFWD(x) ((x) >= nt_naudiobuffer ? (x) - nt_naudiobuffer: (x))
#define WRAPBACK(x) ((x) < 0 ? (x) + nt_naudiobuffer: (x))
#define MAXRESYNC 500
#if 0 /* this is used for debugging */
static void nt_printaudiostatus(void)
{
int nad, nda;
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
int firstphasedone = -1, firstphasebusy = -1;
for (count = 0; count < nt_naudiobuffer; count++)
{
int donethis =
(ntsnd_invec[nad][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
int donenext =
(ntsnd_invec[nad][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
if (donethis && !donenext)
{
if (firstphasebusy >= 0) goto multipleadc;
firstphasebusy = count;
}
if (!donethis && donenext)
{
if (firstphasedone >= 0) goto multipleadc;
firstphasedone = count;
}
phase2 = phase3;
phase3 = WRAPFWD(phase2 + 1);
}
post("nad %d phase %d busy %d done %d", nad, phase, firstphasebusy,
firstphasedone);
continue;
multipleadc:
startpost("nad %d phase %d: oops:", nad, phase);
for (count = 0; count < nt_naudiobuffer; count++)
{
char buf[80];
sprintf(buf, " %d",
(ntsnd_invec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
poststring(buf);
}
endpost();
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nad];
int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
int firstphasedone = -1, firstphasebusy = -1;
for (count = 0; count < nt_naudiobuffer; count++)
{
int donethis =
(ntsnd_outvec[nda][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
int donenext =
(ntsnd_outvec[nda][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
if (donethis && !donenext)
{
if (firstphasebusy >= 0) goto multipledac;
firstphasebusy = count;
}
if (!donethis && donenext)
{
if (firstphasedone >= 0) goto multipledac;
firstphasedone = count;
}
phase2 = phase3;
phase3 = WRAPFWD(phase2 + 1);
}
if (firstphasebusy < 0) post("nda %d phase %d all %d",
nda, phase, (ntsnd_outvec[nad][0].lpWaveHdr->dwFlags & WHDR_DONE));
else post("nda %d phase %d busy %d done %d", nda, phase, firstphasebusy,
firstphasedone);
continue;
multipledac:
startpost("nda %d phase %d: oops:", nda, phase);
for (count = 0; count < nt_naudiobuffer; count++)
{
char buf[80];
sprintf(buf, " %d",
(ntsnd_outvec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
poststring(buf);
}
endpost();
}
}
#endif /* 0 */
/* this is a hack to avoid ever resyncing audio pointers in case for whatever
reason the sync testing below gives false positives. */
static int nt_resync_cancelled;
static void nt_noresync( void)
{
nt_resync_cancelled = 1;
}
static void nt_resyncaudio(void)
{
UINT mmresult;
int nad, nda, count;
if (nt_resync_cancelled)
return;
/* for each open input device, eat all buffers which are marked
ready. The next one will thus be "busy". */
post("resyncing audio");
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
for (count = 0; count < MAXRESYNC; count++)
{
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (!(inwavehdr->dwFlags & WHDR_DONE)) break;
if (inwavehdr->dwFlags & WHDR_PREPARED)
waveInUnprepareHeader(ntsnd_indev[nad],
inwavehdr, sizeof(WAVEHDR));
inwavehdr->dwFlags = 0L;
waveInPrepareHeader(ntsnd_indev[nad], inwavehdr, sizeof(WAVEHDR));
mmresult = waveInAddBuffer(ntsnd_indev[nad], inwavehdr,
sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
ntsnd_inphase[nad] = phase = WRAPFWD(phase + 1);
}
if (count == MAXRESYNC) post("resync error 1");
}
/* Each output buffer which is "ready" is filled with zeros and
queued. */
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
for (count = 0; count < MAXRESYNC; count++)
{
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (!(outwavehdr->dwFlags & WHDR_DONE)) break;
if (outwavehdr->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(ntsnd_outdev[nda],
outwavehdr, sizeof(WAVEHDR));
outwavehdr->dwFlags = 0L;
memset((char *)(ntsnd_outvec[nda][phase].lpData),
0, (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize));
waveOutPrepareHeader(ntsnd_outdev[nda], outwavehdr,
sizeof(WAVEHDR));
mmresult = waveOutWrite(ntsnd_outdev[nda], outwavehdr,
sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveouterror("waveOutAddBuffer: %s\n", mmresult);
ntsnd_outphase[nda] = phase = WRAPFWD(phase + 1);
}
if (count == MAXRESYNC) post("resync error 2");
}
#ifdef MIDI_TIMESTAMP
nt_resetmidisync();
#endif
}
#define LATE 0
#define RESYNC 1
#define NOTHING 2
static int nt_errorcount;
static int nt_resynccount;
static double nt_nextreporttime = -1;
void nt_logerror(int which)
{
#if 0
post("error %d %d", count, which);
if (which < NOTHING) nt_errorcount++;
if (which == RESYNC) nt_resynccount++;
if (sys_getrealtime() > nt_nextreporttime)
{
post("%d audio I/O error%s", nt_errorcount,
(nt_errorcount > 1 ? "s" : ""));
if (nt_resynccount) post("DAC/ADC sync error");
nt_errorcount = nt_resynccount = 0;
nt_nextreporttime = sys_getrealtime() - 5;
}
#endif
}
/* system buffer with t_sample types for one tick */
t_sample *sys_soundout;
t_sample *sys_soundin;
float sys_dacsr;
int mmio_send_dacs(void)
{
HMMIO hmmio;
UINT mmresult;
HANDLE hFormat;
int i, j;
short *sp1, *sp2;
float *fp1, *fp2;
int nextfill, doxfer = 0;
int nda, nad;
if (!nt_nwavein && !nt_nwaveout) return (0);
if (nt_meters)
{
int i, n;
float maxsamp;
for (i = 0, n = 2 * nt_nwavein * DEFDACBLKSIZE, maxsamp = nt_inmax;
i < n; i++)
{
float f = sys_soundin[i];
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
nt_inmax = maxsamp;
for (i = 0, n = 2 * nt_nwaveout * DEFDACBLKSIZE, maxsamp = nt_outmax;
i < n; i++)
{
float f = sys_soundout[i];
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
nt_outmax = maxsamp;
}
/* the "fill pointer" nt_fill controls where in the next
I/O buffers we will write and/or read. If it's zero, we
first check whether the buffers are marked "done". */
if (!nt_fill)
{
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (!(inwavehdr->dwFlags & WHDR_DONE)) goto idle;
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr =
ntsnd_outvec[nda][phase].lpWaveHdr;
if (!(outwavehdr->dwFlags & WHDR_DONE)) goto idle;
}
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr =
ntsnd_invec[nad][phase].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_PREPARED)
waveInUnprepareHeader(ntsnd_indev[nad],
inwavehdr, sizeof(WAVEHDR));
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(ntsnd_outdev[nda],
outwavehdr, sizeof(WAVEHDR));
}
}
/* Convert audio output to fixed-point and put it in the output
buffer. */
for (nda = 0, fp1 = sys_soundout; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
for (i = 0, sp1 = (short *)(ntsnd_outvec[nda][phase].lpData) +
CHANNELS_PER_DEVICE * nt_fill;
i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
{
for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
{
int x1 = 32767.f * *fp2;
if (x1 > 32767) x1 = 32767;
else if (x1 < -32767) x1 = -32767;
*sp2 = x1;
}
}
}
memset(sys_soundout, 0,
(DEFDACBLKSIZE *sizeof(t_sample)*CHANNELS_PER_DEVICE)*nt_nwaveout);
/* vice versa for the input buffer */
for (nad = 0, fp1 = sys_soundin; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
for (i = 0, sp1 = (short *)(ntsnd_invec[nad][phase].lpData) +
CHANNELS_PER_DEVICE * nt_fill;
i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
{
for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
{
*fp2 = ((float)(1./32767.)) * (float)(*sp2);
}
}
}
nt_fill = nt_fill + DEFDACBLKSIZE;
if (nt_fill == nt_realdacblksize)
{
nt_fill = 0;
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
HWAVEIN device = ntsnd_indev[nad];
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
waveInPrepareHeader(device, inwavehdr, sizeof(WAVEHDR));
mmresult = waveInAddBuffer(device, inwavehdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
ntsnd_inphase[nad] = WRAPFWD(phase + 1);
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
HWAVEOUT device = ntsnd_outdev[nda];
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
waveOutPrepareHeader(device, outwavehdr, sizeof(WAVEHDR));
mmresult = waveOutWrite(device, outwavehdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveouterror("waveOutWrite: %s\n", mmresult);
ntsnd_outphase[nda] = WRAPFWD(phase + 1);
}
/* check for DAC underflow or ADC overflow. */
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = WRAPBACK(ntsnd_inphase[nad] - 2);
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_DONE) goto late;
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = WRAPBACK(ntsnd_outphase[nda] - 2);
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_DONE) goto late;
}
}
return (1);
late:
nt_logerror(LATE);
nt_resyncaudio();
return (1);
idle:
/* If more than nt_adcjitterbufsallowed ADC buffers are ready
on any input device, resynchronize */
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr =
ntsnd_invec[nad]
[WRAPFWD(phase + nt_adcjitterbufsallowed)].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_DONE)
{
nt_resyncaudio();
return (0);
}
}
/* test dac sync the same way */
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr =
ntsnd_outvec[nda]
[WRAPFWD(phase + nt_dacjitterbufsallowed)].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_DONE)
{
nt_resyncaudio();
return (0);
}
}
#ifdef MIDI_TIMESTAMP
nt_midisync();
#endif
return (0);
}
/* ------------------- public routines -------------------------- */
void mmio_open_audio(int naudioindev, int *audioindev,
int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
int nchoutdev, int *choutdev, int rate) /* IOhannes */
{
int nbuf;
nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE);
nbuf = sys_advance_samples/nt_realdacblksize;
if (nbuf >= MAXBUFFER)
{
fprintf(stderr, "pd: audio buffering maxed out to %d\n",
(int)(MAXBUFFER * ((nt_realdacblksize * 1000.)/44100.)));
nbuf = MAXBUFFER;
}
else if (nbuf < 4) nbuf = 4;
fprintf(stderr, "%d audio buffers\n", nbuf);
nt_naudiobuffer = nbuf;
if (nt_adcjitterbufsallowed > nbuf - 2)
nt_adcjitterbufsallowed = nbuf - 2;
if (nt_dacjitterbufsallowed > nbuf - 2)
nt_dacjitterbufsallowed = nbuf - 2;
nt_nwavein = sys_inchannels / 2;
nt_nwaveout = sys_outchannels / 2;
nt_whichadc = (naudioindev < 1 ?
(nt_nwavein > 1 ? WAVE_MAPPER : -1) : audioindev[0]);
nt_whichdac = (naudiooutdev < 1 ?
(nt_nwaveout > 1 ? WAVE_MAPPER : -1) : audiooutdev[0]);
if (naudiooutdev > 1 || naudioindev > 1)
post("separate audio device choice not supported; using sequential devices.");
mmio_do_open_audio();
}
void mmio_reportidle(void)
{
}
#if 0
/* list the audio and MIDI device names */
void mmio_listdevs(void)
{
UINT wRtn, ndevices;
unsigned int i;
ndevices = waveInGetNumDevs();
for (i = 0; i < ndevices; i++)
{
WAVEINCAPS wicap;
wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap,
sizeof(wicap));
if (wRtn) nt_waveinerror("waveInGetDevCaps: %s\n", wRtn);
else fprintf(stderr,
"audio input device #%d: %s\n", i+1, wicap.szPname);
}
ndevices = waveOutGetNumDevs();
for (i = 0; i < ndevices; i++)
{
WAVEOUTCAPS wocap;
wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap,
sizeof(wocap));
if (wRtn) nt_waveouterror("waveOutGetDevCaps: %s\n", wRtn);
else fprintf(stderr,
"audio output device #%d: %s\n", i+1, wocap.szPname);
}
}
#endif
void mmio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int wRtn, ndev, i;
*canmulti = 2; /* supports multiple devices */
ndev = waveInGetNumDevs();
if (ndev > maxndev)
ndev = maxndev;
*nindevs = ndev;
for (i = 0; i < ndev; i++)
{
WAVEINCAPS wicap;
wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap, sizeof(wicap));
sprintf(indevlist + i * devdescsize, (wRtn ? "???" : wicap.szPname));
}
ndev = waveOutGetNumDevs();
if (ndev > maxndev)
ndev = maxndev;
*noutdevs = ndev;
for (i = 0; i < ndev; i++)
{
WAVEOUTCAPS wocap;
wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap, sizeof(wocap));
sprintf(outdevlist + i * devdescsize, (wRtn ? "???" : wocap.szPname));
}
}

View file

@ -1,845 +0,0 @@
/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* this file inputs and outputs audio using the OSS API available on linux. */
#ifdef USEAPI_OSS
#include <linux/soundcard.h>
#include "m_pd.h"
#include "s_stuff.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mman.h>
/* Defines */
#define DEBUG(x) x
#define DEBUG2(x) {x;}
#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
#define OSS_MAXDEV 4 /* maximum number of input or output devices */
#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
#define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */
#define OSS_DEFAULTCH 2
#define RME_DEFAULTCH 8 /* need this even if RME undefined */
typedef int16_t t_oss_int16;
typedef int32_t t_oss_int32;
#define OSS_MAXSAMPLEWIDTH sizeof(t_oss_int32)
#define OSS_BYTESPERCHAN(width) (DEFDACBLKSIZE * (width))
#define OSS_XFERSAMPS(chans) (DEFDACBLKSIZE* (chans))
#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
/* GLOBALS */
static int linux_meters; /* true if we're metering */
static float linux_inmax; /* max input amplitude */
static float linux_outmax; /* max output amplitude */
static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
/* our device handles */
typedef struct _oss_dev
{
int d_fd;
unsigned int d_space; /* bytes available for writing/reading */
int d_bufsize; /* total buffer size in blocks for this device */
int d_dropcount; /* # of buffers to drop for resync (output only) */
unsigned int d_nchannels; /* number of channels for this device */
unsigned int d_bytespersamp; /* bytes per sample (2 for 16 bit, 4 for 32) */
} t_oss_dev;
static t_oss_dev linux_dacs[OSS_MAXDEV];
static t_oss_dev linux_adcs[OSS_MAXDEV];
static int linux_noutdevs = 0;
static int linux_nindevs = 0;
/* exported variables */
float sys_dacsr;
t_sample *sys_soundout;
t_sample *sys_soundin;
/* OSS-specific private variables */
static int oss_blockmode = 1; /* flag to use "blockmode" */
static int oss_32bit = 0; /* allow 23 bit transfers in OSS */
static char ossdsp[] = "/dev/dsp%d";
/* don't assume we can turn all 31 bits when doing float-to-fix;
otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
#define FMAX 0x7ffff000
#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
/* ------------- private routines for all APIS ------------------- */
static void linux_flush_all_underflows_to_zero(void)
{
/*
TODO: Implement similar thing for linux (GGeiger)
One day we will figure this out, I hope, because it
costs CPU time dearly on Intel - LT
*/
/* union fpc_csr f;
f.fc_word = get_fpc_csr();
f.fc_struct.flush = 1;
set_fpc_csr(f.fc_word);
*/
}
static int oss_ndev = 0;
/* find out how many OSS devices we have. Since this has to
open the devices to find out if they're there, we have
to be called before audio is actually started up. So we
cache the results, which in effect are the number of available
devices. */
void oss_init(void)
{
int fd, i;
static int countedthem = 0;
if (countedthem)
return;
for (i = 0; i < 10; i++)
{
char devname[100];
if (i == 0)
strcpy(devname, "/dev/dsp");
else sprintf(devname, "/dev/dsp%d", i);
if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1)
{
oss_ndev++;
close(fd);
}
else break;
}
countedthem = 1;
}
void oss_set32bit( void)
{
oss_32bit = 1;
}
typedef struct _multidev {
int fd;
int channels;
int format;
} t_multidev;
int oss_reset(int fd) {
int err;
if ((err = ioctl(fd,SNDCTL_DSP_RESET)) < 0)
error("OSS: Could not reset");
return err;
}
/* The AFMT_S32_BLOCKED format is not defined in standard linux kernels
but is proposed by Guenter Geiger to support extending OSS to handle
32 bit sample. This is user in Geiger's OSS driver for RME Hammerfall.
I'm not clear why this isn't called AFMT_S32_[SLN]E... */
#ifndef AFMT_S32_BLOCKED
#define AFMT_S32_BLOCKED 0x0000400
#endif
void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
{ /* IOhannes */
int orig, param, nblk, fd = dev->d_fd, wantformat;
int nchannels = dev->d_nchannels;
int advwas = sys_schedadvance;
audio_buf_info ainfo;
/* IOhannes :
* pd is very likely to crash if different formats are used on
multiple soundcards
*/
/* set resolution - first try 4 byte samples */
if (oss_32bit && (ioctl(fd,SNDCTL_DSP_GETFMTS,&param) >= 0) &&
(param & AFMT_S32_BLOCKED))
{
wantformat = AFMT_S32_BLOCKED;
dev->d_bytespersamp = 4;
}
else
{
wantformat = AFMT_S16_NE;
dev->d_bytespersamp = 2;
}
param = wantformat;
if (sys_verbose)
post("bytes per sample = %d", dev->d_bytespersamp);
if (ioctl(fd, SNDCTL_DSP_SETFMT, &param) == -1)
fprintf(stderr,"OSS: Could not set DSP format\n");
else if (wantformat != param)
fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n",
wantformat, param);
/* sample rate */
orig = param = srate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &param) == -1)
fprintf(stderr,"OSS: Could not set sampling rate for device\n");
else if( orig != param )
fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n",
orig, param );
if (oss_blockmode && !skipblocksize)
{
int fragbytes, logfragsize, nfragment;
/* setting fragment count and size. */
if (!linux_fragsize)
{
linux_fragsize = OSS_DEFFRAGSIZE;
while (linux_fragsize > DEFDACBLKSIZE
&& linux_fragsize * 4 > sys_advance_samples)
linux_fragsize = linux_fragsize/2;
}
/* post("adv_samples %d", sys_advance_samples); */
nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize;
fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels);
logfragsize = ilog2(fragbytes);
if (fragbytes != (1 << logfragsize))
post("warning: OSS takes only power of 2 blocksize; using %d",
(1 << logfragsize)/(dev->d_bytespersamp * nchannels));
if (sys_verbose)
post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes);
param = orig = (nfragment<<16) + logfragsize;
if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, &param) == -1)
error("OSS: Could not set or read fragment size\n");
if (param != orig)
{
nfragment = ((param >> 16) & 0xffff);
logfragsize = (param & 0xffff);
post("warning: actual fragments %d, blocksize %d",
nfragment, (1 << logfragsize));
}
if (sys_verbose)
post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance));
}
if (dac)
{
/* use "free space" to learn the buffer size. Normally you
should set this to your own desired value; but this seems not
to be implemented uniformly across different sound cards. LATER
we should figure out what to do if the requested scheduler advance
is greater than this buffer size; for now, we just print something
out. */
int defect;
if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device failed");
dev->d_bufsize = ainfo.bytes;
defect = sys_advance_samples * (dev->d_bytespersamp * nchannels)
- dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp);
if (defect > 0)
{
if (sys_verbose || defect > (dev->d_bufsize >> 2))
fprintf(stderr,
"OSS: requested audio buffer size %d limited to %d\n",
sys_advance_samples * (dev->d_bytespersamp * nchannels),
dev->d_bufsize);
sys_advance_samples =
(dev->d_bufsize - OSS_XFERSAMPS(nchannels)) /
(dev->d_bytespersamp *nchannels);
}
}
}
static int oss_setchannels(int fd, int wantchannels, char *devname)
{ /* IOhannes */
int param = wantchannels;
while (param>1) {
int save = param;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1) {
error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname);
} else {
if (param == save) return (param);
}
param=save-1;
}
return (0);
}
#define O_AUDIOFLAG 0 /* O_NDELAY */
int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
int noutdev, int *outdev, int nchout, int *chout, int rate)
{ /* IOhannes */
int capabilities = 0;
int inchannels = 0, outchannels = 0;
char devname[20];
int n, i, fd;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
int num_devs = 0;
int wantmore=0;
int spread = 0;
audio_buf_info ainfo;
linux_nindevs = linux_noutdevs = 0;
/* mark input devices unopened */
for (i = 0; i < OSS_MAXDEV; i++)
linux_adcs[i].d_fd = -1;
/* open output devices */
wantmore=0;
if (noutdev < 0 || nindev < 0)
bug("linux_open_audio");
for (n = 0; n < noutdev; n++)
{
int gotchans, j, inindex = -1;
int thisdevice = (outdev[n] >= 0 ? outdev[n] : n-1);
int wantchannels = (nchout>n) ? chout[n] : wantmore;
fd = -1;
if (!wantchannels)
goto end_out_loop;
if (thisdevice > 1)
sprintf(devname, "/dev/dsp%d", thisdevice-1);
else sprintf(devname, "/dev/dsp");
/* search for input request for same device. Succeed only
if the number of channels matches. */
for (j = 0; j < nindev; j++)
if (indev[j] == thisdevice && chin[j] == wantchannels)
inindex = j;
/* if the same device is requested for input and output,
try to open it read/write */
if (inindex >= 0)
{
sys_setalarm(1000000);
if ((fd = open(devname, O_RDWR | O_AUDIOFLAG)) == -1)
{
post("%s (read/write): %s", devname, strerror(errno));
post("(now will try write-only...)");
}
else
{
if (sys_verbose)
post("opened %s for reading and writing\n", devname);
linux_adcs[inindex].d_fd = fd;
}
}
/* if that didn't happen or if it failed, try write-only */
if (fd == -1)
{
sys_setalarm(1000000);
if ((fd = open(devname, O_WRONLY | O_AUDIOFLAG)) == -1)
{
post("%s (writeonly): %s",
devname, strerror(errno));
break;
}
if (sys_verbose)
post("opened %s for writing only\n", devname);
}
if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1)
error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname);
gotchans = oss_setchannels(fd,
(wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
devname);
if (sys_verbose)
post("opened audio output on %s; got %d channels",
devname, gotchans);
if (gotchans < 2)
{
/* can't even do stereo? just give up. */
close(fd);
}
else
{
linux_dacs[linux_noutdevs].d_nchannels = gotchans;
linux_dacs[linux_noutdevs].d_fd = fd;
oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
linux_noutdevs++;
outchannels += gotchans;
if (inindex >= 0)
{
linux_adcs[inindex].d_nchannels = gotchans;
chin[inindex] = gotchans;
}
}
/* LATER think about spreading large numbers of channels over
various dsp's and vice-versa */
wantmore = wantchannels - gotchans;
end_out_loop: ;
}
/* open input devices */
wantmore = 0;
for (n = 0; n < nindev; n++)
{
int gotchans=0;
int thisdevice = (indev[n] >= 0 ? indev[n] : n-1);
int wantchannels = (nchin>n)?chin[n]:wantmore;
int alreadyopened = 0;
if (!wantchannels)
goto end_in_loop;
if (thisdevice > 1)
sprintf(devname, "/dev/dsp%d", thisdevice - 1);
else sprintf(devname, "/dev/dsp");
sys_setalarm(1000000);
/* perhaps it's already open from the above? */
if (linux_dacs[n].d_fd >= 0)
{
fd = linux_dacs[n].d_fd;
alreadyopened = 1;
}
else
{
/* otherwise try to open it here. */
if ((fd = open(devname, O_RDONLY | O_AUDIOFLAG)) == -1)
{
post("%s (readonly): %s", devname, strerror(errno));
goto end_in_loop;
}
if (sys_verbose)
post("opened %s for reading only\n", devname);
}
linux_adcs[linux_nindevs].d_fd = fd;
gotchans = oss_setchannels(fd,
(wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
devname);
if (sys_verbose)
post("opened audio input device %s; got %d channels",
devname, gotchans);
if (gotchans < 1)
{
close(fd);
goto end_in_loop;
}
linux_adcs[linux_nindevs].d_nchannels = gotchans;
oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
inchannels += gotchans;
linux_nindevs++;
wantmore = wantchannels-gotchans;
/* LATER think about spreading large numbers of channels over
various dsp's and vice-versa */
end_in_loop: ;
}
/* We have to do a read to start the engine. This is
necessary because sys_send_dacs waits until the input
buffer is filled and only reads on a filled buffer.
This is good, because it's a way to make sure that we
will not block. But I wonder why we only have to read
from one of the devices and not all of them??? */
if (linux_nindevs)
{
if (sys_verbose)
fprintf(stderr,("OSS: issuing first ADC 'read' ... "));
read(linux_adcs[0].d_fd, buf,
linux_adcs[0].d_bytespersamp *
linux_adcs[0].d_nchannels * DEFDACBLKSIZE);
if (sys_verbose)
fprintf(stderr, "...done.\n");
}
sys_setalarm(0);
return (0);
}
void oss_close_audio( void)
{
int i;
for (i=0;i<linux_nindevs;i++)
close(linux_adcs[i].d_fd);
for (i=0;i<linux_noutdevs;i++)
close(linux_dacs[i].d_fd);
linux_nindevs = linux_noutdevs = 0;
}
static int linux_dacs_write(int fd,void* buf,long bytes)
{
return write(fd, buf, bytes);
}
static int linux_adcs_read(int fd,void* buf,long bytes)
{
return read(fd, buf, bytes);
}
/* query audio devices for "available" data size. */
static void oss_calcspace(void)
{
int dev;
audio_buf_info ainfo;
for (dev=0; dev < linux_noutdevs; dev++)
{
if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
linux_dacs[dev].d_space = ainfo.bytes;
}
for (dev = 0; dev < linux_nindevs; dev++)
{
if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0)
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd);
linux_adcs[dev].d_space = ainfo.bytes;
}
}
void linux_audiostatus(void)
{
int dev;
if (!oss_blockmode)
{
oss_calcspace();
for (dev=0; dev < linux_noutdevs; dev++)
fprintf(stderr, "dac %d space %d\n", dev, linux_dacs[dev].d_space);
for (dev = 0; dev < linux_nindevs; dev++)
fprintf(stderr, "adc %d space %d\n", dev, linux_adcs[dev].d_space);
}
}
/* this call resyncs audio output and input which will cause discontinuities
in audio output and/or input. */
static void oss_doresync( void)
{
int dev, zeroed = 0, wantsize;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
audio_buf_info ainfo;
/* 1. if any input devices are ahead (have more than 1 buffer stored),
drop one or more buffers worth */
for (dev = 0; dev < linux_nindevs; dev++)
{
if (linux_adcs[dev].d_space == 0)
{
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp));
}
else while (linux_adcs[dev].d_space >
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
{
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp));
if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0)
{
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd);
break;
}
linux_adcs[dev].d_space = ainfo.bytes;
}
}
/* 2. if any output devices are behind, feed them zeros to catch them
up */
for (dev = 0; dev < linux_noutdevs; dev++)
{
while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
sys_advance_samples * (linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp))
{
if (!zeroed)
{
unsigned int i;
for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels);
i++)
buf[i] = 0;
zeroed = 1;
}
linux_dacs_write(linux_dacs[dev].d_fd, buf,
OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
linux_dacs[dev].d_bytespersamp));
if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
{
fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
dev, linux_dacs[dev].d_fd);
break;
}
linux_dacs[dev].d_space = ainfo.bytes;
}
}
/* 3. if any DAC devices are too far ahead, plan to drop the
number of frames which will let the others catch up. */
for (dev = 0; dev < linux_noutdevs; dev++)
{
if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
(sys_advance_samples - 1) * linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp)
{
linux_dacs[dev].d_dropcount = sys_advance_samples - 1 -
(linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) /
(linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp) ;
}
else linux_dacs[dev].d_dropcount = 0;
}
}
int oss_send_dacs(void)
{
t_sample *fp1, *fp2;
long fill;
int i, j, dev, rtnval = SENDDACS_YES;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
t_oss_int16 *sp;
t_oss_int32 *lp;
/* the maximum number of samples we should have in the ADC buffer */
int idle = 0;
int thischan;
t_time timeref, timenow;
if (!linux_nindevs && !linux_noutdevs)
return (SENDDACS_NO);
if (!oss_blockmode)
{
/* determine whether we're idle. This is true if either (1)
some input device has less than one buffer to read or (2) some
output device has fewer than (sys_advance_samples) blocks buffered
already. */
oss_calcspace();
for (dev=0; dev < linux_noutdevs; dev++)
if (linux_dacs[dev].d_dropcount ||
(linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space >
sys_advance_samples * linux_dacs[dev].d_bytespersamp *
linux_dacs[dev].d_nchannels))
idle = 1;
for (dev=0; dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space <
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
idle = 1;
}
if (idle && !oss_blockmode)
{
/* sometimes---rarely---when the ADC available-byte-count is
zero, it's genuine, but usually it's because we're so
late that the ADC has overrun its entire kernel buffer. We
distinguish between the two by waiting 2 msec and asking again.
There should be an error flag we could check instead; look for this
someday... */
for (dev = 0;dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space == 0)
{
audio_buf_info ainfo;
sys_microsleep(2000);
oss_calcspace();
if (linux_adcs[dev].d_space != 0) continue;
/* here's the bad case. Give up and resync. */
sys_log_error(ERR_DATALATE);
oss_doresync();
return (SENDDACS_NO);
}
/* check for slippage between devices, either because
data got lost in the driver from a previous late condition, or
because the devices aren't synced. When we're idle, no
input device should have more than one buffer readable and
no output device should have less than sys_advance_samples-1
*/
for (dev=0; dev < linux_noutdevs; dev++)
if (!linux_dacs[dev].d_dropcount &&
(linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space <
(sys_advance_samples - 2) *
(linux_dacs[dev].d_bytespersamp *
linux_dacs[dev].d_nchannels)))
goto badsync;
for (dev=0; dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space > 3 *
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
goto badsync;
/* return zero to tell the scheduler we're idle. */
return (SENDDACS_NO);
badsync:
sys_log_error(ERR_RESYNC);
oss_doresync();
return (SENDDACS_NO);
}
/* do output */
timeref = sys_getrealtime();
for (dev=0, thischan = 0; dev < linux_noutdevs; dev++)
{
int nchannels = linux_dacs[dev].d_nchannels;
if (linux_dacs[dev].d_dropcount)
linux_dacs[dev].d_dropcount--;
else
{
if (linux_dacs[dev].d_bytespersamp == 4)
{
for (i = DEFDACBLKSIZE * nchannels, fp1 = sys_soundout +
DEFDACBLKSIZE*thischan,
lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
{
t_sample f = SCALE32(*fp1);
*lp = (f >= 2147483647 ? 2147483647 :
(f < -2147483647 ? -2147483647 : f));
}
}
else
{
for (i = DEFDACBLKSIZE, fp1 = sys_soundout +
DEFDACBLKSIZE*thischan,
sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
{
for (j=0, fp2 = fp1; j<nchannels; j++, fp2 += DEFDACBLKSIZE)
{
int s = SCALE16(*fp2);
if (s > 32767) s = 32767;
else if (s < -32767) s = -32767;
sp[j] = s;
}
}
}
#if 0
#define PR_S "%8d"
{
int nm = 64;
int* sp1 = buf;
post("dac:");
while (nm > 0)
{
post(PR_S PR_S PR_S PR_S PR_S PR_S PR_S PR_S,
sp1[0], sp1[1], sp1[2], sp1[3], sp1[4], sp1[5], sp1[6], sp1[7]);
nm -= 8;
sp1 += 8;
}
}
#endif
linux_dacs_write(linux_dacs[dev].d_fd, buf,
OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp));
#if 0
if ((timenow = sys_getrealtime()) - timeref > 200)
{
post("dacslept %d",sys_getrealtime() - timeref);
if (!oss_blockmode)
sys_log_error(ERR_DACSLEPT);
else rtnval = SENDDACS_SLEPT;
}
#endif
timeref = timenow;
}
thischan += nchannels;
}
memset(sys_soundout, 0,
sys_outchannels * (sizeof(float) * DEFDACBLKSIZE));
/* do input */
for (dev = 0, thischan = 0; dev < linux_nindevs; dev++)
{
int nchannels = linux_adcs[dev].d_nchannels;
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp));
#if 0
if ((timenow = sys_getrealtime()) - timeref > 200)
{
if (!oss_blockmode)
sys_log_error(ERR_ADCSLEPT);
else
rtnval = SENDDACS_SLEPT;
}
#endif
timeref = timenow;
if (linux_adcs[dev].d_bytespersamp == 4)
{
for (i = DEFDACBLKSIZE*nchannels,
fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
{
*fp1 = ((t_sample)(*lp))*(t_sample)(1./2147483648.);
}
}
else
{
for (i = DEFDACBLKSIZE,fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
{
for (j=0;j<sys_inchannels;j++)
fp1[j*DEFDACBLKSIZE] = INVSCALE16(sp[j]);
}
}
thischan += nchannels;
}
if (thischan != sys_inchannels)
bug("inchannels");
return (rtnval);
}
void oss_listdevs( void)
{
post("device listing not implemented in OSS yet\n");
}
void oss_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, ndev;
*canmulti = 2; /* supports multiple devices */
if ((ndev = oss_ndev) > maxndev)
ndev = maxndev;
for (i = 0; i < ndev; i++)
{
sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1);
sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1);
}
*nindevs = *noutdevs = ndev;
}
#endif

View file

@ -1,293 +0,0 @@
/* Copyright (c) 2001 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* this file calls Ross Bencina's and Phil Burk's Portaudio package. It's
the main way in for Mac OS and, with Michael Casey's help, also into
ASIO in Windows. */
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"
#include "pablio_pd.h"
/* LATER try to figure out how to handle default devices in portaudio;
the way s_audio.c handles them isn't going to work here. */
#if defined(MACOSX) || defined(MSW)
#define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
#define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
#endif
/* public interface declared in m_imp.h */
/* implementation */
static PABLIO_Stream *pa_stream;
static int pa_inchans, pa_outchans;
static float *pa_soundin, *pa_soundout;
#define MAX_PA_CHANS 32
#define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
t_sample *soundout, int framesperbuf, int nbuffers,
int indeviceno, int outdeviceno)
{
PaError err;
static int initialized;
int j, devno, pa_indev = 0, pa_outdev = 0;
if (!initialized)
{
/* Initialize PortAudio */
int err = Pa_Initialize();
if ( err != paNoError )
{
fprintf( stderr,
"Error number %d occured initializing portaudio\n",
err);
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return (1);
}
initialized = 1;
}
/* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
if (inchans != 0 && outchans != 0 && inchans != outchans)
error("portaudio: number of input and output channels must match");
if (inchans > MAX_PA_CHANS)
{
post("input channels reduced to maximum %d", MAX_PA_CHANS);
inchans = MAX_PA_CHANS;
}
if (outchans > MAX_PA_CHANS)
{
post("output channels reduced to maximum %d", MAX_PA_CHANS);
outchans = MAX_PA_CHANS;
}
if (inchans > 0)
{
for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
{
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->maxInputChannels > 0)
{
if (devno == indeviceno)
{
pa_indev = j;
break;
}
devno++;
}
}
}
if (outchans > 0)
{
for (j = 0, devno = 0; j < Pa_CountDevices(); j++)
{
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->maxOutputChannels > 0)
{
if (devno == outdeviceno)
{
pa_outdev = j;
break;
}
devno++;
}
}
}
if (sys_verbose)
{
post("input device %d, channels %d", pa_indev, inchans);
post("output device %d, channels %d", pa_outdev, outchans);
post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
}
if (inchans && outchans)
err = OpenAudioStream( &pa_stream, rate, paFloat32,
PABLIO_READ_WRITE, inchans, framesperbuf, nbuffers,
pa_indev, pa_outdev);
else if (inchans)
err = OpenAudioStream( &pa_stream, rate, paFloat32,
PABLIO_READ, inchans, framesperbuf, nbuffers,
pa_indev, pa_outdev);
else if (outchans)
err = OpenAudioStream( &pa_stream, rate, paFloat32,
PABLIO_WRITE, outchans, framesperbuf, nbuffers,
pa_indev, pa_outdev);
else err = 0;
if ( err != paNoError )
{
fprintf( stderr, "Error number %d occured opening portaudio stream\n",
err);
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
Pa_Terminate();
sys_inchannels = sys_outchannels = 0;
return (1);
}
else if (sys_verbose)
post("... opened OK.");
pa_inchans = inchans;
pa_outchans = outchans;
pa_soundin = soundin;
pa_soundout = soundout;
return (0);
}
void pa_close_audio( void)
{
if (pa_inchans || pa_outchans)
CloseAudioStream( pa_stream );
pa_inchans = pa_outchans = 0;
}
int pa_send_dacs(void)
{
float samples[MAX_SAMPLES_PER_FRAME], *fp1, *fp2;
int i, j;
double timebefore;
timebefore = sys_getrealtime();
if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
(pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
{
if (pa_inchans && pa_outchans)
{
int synced = 0;
while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
{
for (j = 0; j < pa_outchans; j++)
for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
fp2 += pa_outchans)
{
*fp2 = 0;
}
synced = 1;
WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
}
while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
{
synced = 1;
ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
}
/* if (synced)
post("sync"); */
}
return (SENDDACS_NO);
}
if (pa_inchans)
{
ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
fp2 += pa_inchans)
{
fp1[i] = *fp2;
}
}
#if 0
{
static int nread;
if (nread == 0)
{
post("it's %f %f %f %f",
pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
nread = 1000;
}
nread--;
}
#endif
if (pa_outchans)
{
for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
fp1 += DEFDACBLKSIZE)
for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
fp2 += pa_outchans)
{
*fp2 = fp1[i];
fp1[i] = 0;
}
WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
}
if (sys_getrealtime() > timebefore + 0.002)
{
/* post("slept"); */
return (SENDDACS_SLEPT);
}
else return (SENDDACS_YES);
}
void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
{
int i,j;
int numDevices;
const PaDeviceInfo *pdi;
PaError err;
Pa_Initialize();
numDevices = Pa_CountDevices();
if( numDevices < 0 )
{
fprintf(stderr, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
err = numDevices;
goto error;
}
fprintf(stderr, "Audio Devices:\n");
for( i=0; i<numDevices; i++ )
{
pdi = Pa_GetDeviceInfo( i );
fprintf(stderr, "device %d:", i+1 );
fprintf(stderr, " %s;", pdi->name );
fprintf(stderr, "%d inputs, ", pdi->maxInputChannels );
fprintf(stderr, "%d outputs", pdi->maxOutputChannels );
if ( i == Pa_GetDefaultInputDevice() )
fprintf(stderr, " (Default Input)");
if ( i == Pa_GetDefaultOutputDevice() )
fprintf(stderr, " (Default Output)");
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
return;
error:
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
}
/* scanning for devices */
void pa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, nin = 0, nout = 0, ndev;
*canmulti = 1; /* one dev each for input and output */
Pa_Initialize();
ndev = Pa_CountDevices();
for (i = 0; i < ndev; i++)
{
const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
if (pdi->maxInputChannels > 0 && nin < maxndev)
{
strcpy(indevlist + nin * devdescsize, pdi->name);
nin++;
}
if (pdi->maxOutputChannels > 0 && nout < maxndev)
{
strcpy(outdevlist + nout * devdescsize, pdi->name);
nout++;
}
}
*nindevs = nin;
*noutdevs = nout;
}

View file

@ -1,52 +0,0 @@
/* In MSW, this is all there is to pd; the rest sits in a "pdlib" dll so
that externs can link back to functions defined in pd. */
#include <stdio.h>
int sys_main(int argc, char **argv);
/* WINBASEAPI PVOID WINAPI AddVectoredExceptionHandler(
ULONG FirstHandler,
PVECTORED_EXCEPTION_HANDLER VectoredHandler ); */
#ifdef MSW
#if 0
#incldue "winbase.h"
LONG NTAPI VectoredExceptionHandler(void *PEXCEPTION_POINTERS)
{
fprintf(stderr, "caught exception\n");
return(EXCEPTION_CONTINUE_SEARCH);
}
int main(int argc, char **argv)
{
printf("Pd entry point\n");
AddVectoredExceptionHandler(
ULONG FirstHandler,
PVECTORED_EXCEPTION_HANDLER VectoredHandler );
#endif
#if 1
int main(int argc, char **argv)
{
__try
{
sys_main(argc, argv);
}
__finally
{
printf("caught an exception; stopping\n");
}
}
#endif
#else /* not MSW */
int main(int argc, char **argv)
{
return (sys_main(argc, argv));
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,839 +0,0 @@
/* Copyright (c) 1997-1999 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* IOhannes :
* hacked the code to add advanced multidevice-support
* 1311:forum::für::umläute:2001
*/
char pd_version[] = "Pd version 0.37.4\n";
char pd_compiletime[] = __TIME__;
char pd_compiledate[] = __DATE__;
#include "m_pd.h"
#include "m_imp.h"
#include "s_stuff.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#ifdef UNIX
#include <unistd.h>
#endif
#ifdef MSW
#include <io.h>
#include <windows.h>
#include <winbase.h>
#endif
void pd_init(void);
int sys_argparse(int argc, char **argv);
void sys_findprogdir(char *progname);
int sys_startgui(const char *guipath);
int sys_rcfile(void);
int m_scheduler(void);
void sys_addhelppath(char *p);
void alsa_adddev(char *name);
int sys_debuglevel;
int sys_verbose;
int sys_noloadbang;
int sys_nogui;
int sys_stdin = 0;
char *sys_guicmd;
t_symbol *sys_libdir;
static t_symbol *sys_guidir;
static t_namelist *sys_externlist;
static t_namelist *sys_openlist;
static t_namelist *sys_messagelist;
static int sys_version;
int sys_oldtclversion; /* hack to warn g_rtext.c about old text sel */
int sys_nmidiout = 1;
#ifdef MSW
int sys_nmidiin = 0;
#else
int sys_nmidiin = 1;
#endif
int sys_midiindevlist[MAXMIDIINDEV] = {1};
int sys_midioutdevlist[MAXMIDIOUTDEV] = {1};
static int sys_main_srate = DEFAULTSRATE;
static int sys_main_advance = DEFAULTADVANCE;
/* IOhannes { */
/* here the "-1" counts signify that the corresponding vector hasn't been
specified in command line arguments; sys_open_audio will detect this
and fill things in. */
int sys_nsoundin = -1;
int sys_nsoundout = -1;
int sys_soundindevlist[MAXAUDIOINDEV];
int sys_soundoutdevlist[MAXAUDIOOUTDEV];
int sys_nchin = -1;
int sys_nchout = -1;
int sys_chinlist[MAXAUDIOINDEV];
int sys_choutlist[MAXAUDIOOUTDEV];
/* } IOhannes */
typedef struct _fontinfo
{
int fi_fontsize;
int fi_maxwidth;
int fi_maxheight;
int fi_hostfontsize;
int fi_width;
int fi_height;
} t_fontinfo;
/* these give the nominal point size and maximum height of the characters
in the six fonts. */
static t_fontinfo sys_fontlist[] = {
{8, 5, 9, 0, 0, 0}, {10, 7, 13, 0, 0, 0}, {12, 9, 16, 0, 0, 0},
{16, 10, 20, 0, 0, 0}, {24, 15, 25, 0, 0, 0}, {36, 25, 45, 0, 0, 0}};
#define NFONT (sizeof(sys_fontlist)/sizeof(*sys_fontlist))
/* here are the actual font size structs on msp's systems:
MSW:
font 8 5 9 8 5 11
font 10 7 13 10 6 13
font 12 9 16 14 8 16
font 16 10 20 16 10 18
font 24 15 25 16 10 18
font 36 25 42 36 22 41
linux:
font 8 5 9 8 5 9
font 10 7 13 12 7 13
font 12 9 16 14 9 15
font 16 10 20 16 10 19
font 24 15 25 24 15 24
font 36 25 42 36 22 41
*/
static t_fontinfo *sys_findfont(int fontsize)
{
unsigned int i;
t_fontinfo *fi;
for (i = 0, fi = sys_fontlist; i < (NFONT-1); i++, fi++)
if (fontsize < fi[1].fi_fontsize) return (fi);
return (sys_fontlist + (NFONT-1));
}
int sys_nearestfontsize(int fontsize)
{
return (sys_findfont(fontsize)->fi_fontsize);
}
int sys_hostfontsize(int fontsize)
{
return (sys_findfont(fontsize)->fi_hostfontsize);
}
int sys_fontwidth(int fontsize)
{
return (sys_findfont(fontsize)->fi_width);
}
int sys_fontheight(int fontsize)
{
return (sys_findfont(fontsize)->fi_height);
}
int sys_defaultfont;
#ifdef MSW
#define DEFAULTFONT 12
#else
#define DEFAULTFONT 10
#endif
static void openit(const char *dirname, const char *filename)
{
char dirbuf[MAXPDSTRING], *nameptr;
int fd = open_via_path(dirname, filename, "", dirbuf, &nameptr,
MAXPDSTRING, 0);
if (fd)
{
close (fd);
glob_evalfile(0, gensym(nameptr), gensym(dirbuf));
}
else
error("%s: can't open", filename);
}
#define NHOSTFONT 7
/* this is called from the gui process. The first argument is the cwd, and
succeeding args give the widths and heights of known fonts. We wait until
these are known to open files and send messages specified on the command line.
We ask the GUI to specify the "cwd" in case we don't have a local OS to get it
from; for instance we could be some kind of RT embedded system. However, to
really make this make sense we would have to implement
open(), read(), etc, calls to be served somehow from the GUI too. */
void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
{
char *cwd = atom_getsymbolarg(0, argc, argv)->s_name;
t_namelist *nl;
unsigned int i, j;
if (argc != 2 + 3 * NHOSTFONT) bug("glob_initfromgui");
for (i = 0; i < NFONT; i++)
{
int wantheight = sys_fontlist[i].fi_maxheight;
for (j = 0; j < NHOSTFONT-1; j++)
{
if (atom_getintarg(3 * (j + 1) + 3, argc, argv) > wantheight)
break;
}
/* j is now the "real" font index for the desired font index i. */
sys_fontlist[i].fi_hostfontsize = atom_getintarg(3 * j + 1, argc, argv);
sys_fontlist[i].fi_width = atom_getintarg(3 * j + 2, argc, argv);
sys_fontlist[i].fi_height = atom_getintarg(3 * j + 3, argc, argv);
}
#if 0
for (i = 0; i < 6; i++)
fprintf(stderr, "font %d %d %d %d %d\n",
sys_fontlist[i].fi_fontsize,
sys_fontlist[i].fi_maxheight,
sys_fontlist[i].fi_hostfontsize,
sys_fontlist[i].fi_width,
sys_fontlist[i].fi_height);
#endif
/* load dynamic libraries specified with "-lib" args */
for (nl = sys_externlist; nl; nl = nl->nl_next)
if (!sys_load_lib(cwd, nl->nl_string))
post("%s: can't load library", nl->nl_string);
namelist_free(sys_externlist);
sys_externlist = 0;
/* open patches specifies with "-open" args */
for (nl = sys_openlist; nl; nl = nl->nl_next)
openit(cwd, nl->nl_string);
namelist_free(sys_openlist);
sys_openlist = 0;
/* send messages specified with "-send" args */
for (nl = sys_messagelist; nl; nl = nl->nl_next)
{
t_binbuf *b = binbuf_new();
binbuf_text(b, nl->nl_string, strlen(nl->nl_string));
binbuf_eval(b, 0, 0, 0);
binbuf_free(b);
}
namelist_free(sys_messagelist);
sys_messagelist = 0;
sys_oldtclversion = atom_getfloatarg(1 + 3 * NHOSTFONT, argc, argv);
}
static void sys_afterargparse(void);
/* this is called from main() in s_entry.c */
int sys_main(int argc, char **argv)
{
#ifdef PD_DEBUG
fprintf(stderr, "Pd: COMPILED FOR DEBUGGING\n");
#endif
pd_init();
sys_findprogdir(argv[0]); /* set sys_progname, guipath */
#ifdef UNIX
sys_rcfile(); /* parse the startup file */
#endif
if (sys_argparse(argc, argv)) /* parse cmd line */
return (1);
sys_afterargparse(); /* post-argparse settings */
if (sys_verbose || sys_version) fprintf(stderr, "%scompiled %s %s\n",
pd_version, pd_compiletime, pd_compiledate);
if (sys_version) /* if we were just asked our version, exit here. */
return (0);
if (sys_startgui(sys_guidir->s_name)) /* start the gui */
return(1);
/* open audio and MIDI */
sys_open_midi(sys_nmidiin, sys_midiindevlist,
sys_nmidiout, sys_midioutdevlist);
sys_open_audio(sys_nsoundin, sys_soundindevlist, sys_nchin, sys_chinlist,
sys_nsoundout, sys_soundoutdevlist, sys_nchout, sys_choutlist,
sys_main_srate, sys_main_advance, 1);
/* run scheduler until it quits */
return (m_scheduler_pda());
return (m_scheduler());
}
static char *(usagemessage[]) = {
"usage: pd [-flags] [file]...\n",
"\naudio configuration flags:\n",
"-r <n> -- specify sample rate\n",
"-audioindev ... -- audio in devices; e.g., \"1,3\" for first and third\n",
"-audiooutdev ... -- audio out devices (same)\n",
"-audiodev ... -- specify input and output together\n",
"-inchannels ... -- audio input channels (by device, like \"2\" or \"16,8\")\n",
"-outchannels ... -- number of audio out channels (same)\n",
"-channels ... -- specify both input and output channels\n",
"-audiobuf <n> -- specify size of audio buffer in msec\n",
"-blocksize <n> -- specify audio I/O block size in sample frames\n",
"-sleepgrain <n> -- specify number of milliseconds to sleep when idle\n",
"-nodac -- suppress audio output\n",
"-noadc -- suppress audio input\n",
"-noaudio -- suppress audio input and output (-nosound is synonym) \n",
"-listdev -- list audio and MIDI devices\n",
#ifdef USEAPI_OSS
"-oss -- use OSS audio API\n",
"-32bit ----- allow 32 bit OSS audio (for RME Hammerfall)\n",
#endif
#ifdef USEAPI_ALSA
"-alsa -- use ALSA audio API\n",
"-alsaadd <name> -- add an ALSA device name to list\n",
"-alsadev <n> ----- obsolete: use -audiodev\n",
#endif
#ifdef USEAPI_JACK
"-jack -- use JACK audio API\n",
#endif
#ifdef USEAPI_PORTAUDIO
#ifdef MSW
"-asio -- use ASIO audio driver (via Portaudio)\n",
"-pa -- synonym for -asio\n",
#else
"-pa -- use Portaudio API\n",
#endif
#endif
#ifdef USEAPI_MMIO
"-mmio -- use MMIO audio API (default for Windows)\n",
#endif
" (default audio API for this platform: ", API_DEFSTRING, ")\n\n",
"\nMIDI configuration flags:\n",
"-midiindev ... -- midi in device list; e.g., \"1,3\" for first and third\n",
"-midioutdev ... -- midi out device list, same format\n",
"-mididev ... -- specify -midioutdev and -midiindev together\n",
"-nomidiin -- suppress MIDI input\n",
"-nomidiout -- suppress MIDI output\n",
"-nomidi -- suppress MIDI input and output\n",
"\nother flags:\n",
"-path <path> -- add to file search path\n",
"-helppath <path> -- add to help file search path\n",
"-open <file> -- open file(s) on startup\n",
"-lib <file> -- load object library(s)\n",
"-font <n> -- specify default font size in points\n",
"-verbose -- extra printout on startup and when searching for files\n",
"-version -- don't run Pd; just print out which version it is \n",
"-d <n> -- specify debug level\n",
"-noloadbang -- suppress all loadbangs\n",
"-nogui -- suppress starting the GUI\n",
"-stdin -- scan stdin for keypresses\n",
"-guicmd \"cmd...\" -- substitute another GUI program (e.g., rsh)\n",
"-send \"msg...\" -- send a message at startup (after patches are loaded)\n",
#ifdef UNIX
"-rt or -realtime -- use real-time priority\n",
"-nrt -- don't use real-time priority\n",
#endif
};
static void sys_parsedevlist(int *np, int *vecp, int max, char *str)
{
int n = 0;
while (n < max)
{
if (!*str) break;
else
{
char *endp;
vecp[n] = strtol(str, &endp, 10);
if (endp == str)
break;
n++;
if (!endp)
break;
str = endp + 1;
}
}
*np = n;
}
static int sys_getmultidevchannels(int n, int *devlist)
{
int sum = 0;
if (n<0)return(-1);
if (n==0)return 0;
while(n--)sum+=*devlist++;
return sum;
}
/* this routine tries to figure out where to find the auxilliary files
Pd will need to run. This is either done by looking at the command line
invokation for Pd, or if that fails, by consulting the variable
INSTALL_PREFIX. In MSW, we don't try to use INSTALL_PREFIX. */
void sys_findprogdir(char *progname)
{
char sbuf[MAXPDSTRING], sbuf2[MAXPDSTRING], *sp;
char *lastslash;
#ifdef UNIX
struct stat statbuf;
#endif
/* find out by what string Pd was invoked; put answer in "sbuf". */
#ifdef MSW
GetModuleFileName(NULL, sbuf2, sizeof(sbuf2));
sbuf2[MAXPDSTRING-1] = 0;
sys_unbashfilename(sbuf2, sbuf);
#endif /* MSW */
#ifdef UNIX
strncpy(sbuf, progname, MAXPDSTRING);
sbuf[MAXPDSTRING-1] = 0;
#endif
lastslash = strrchr(sbuf, '/');
if (lastslash)
{
/* bash last slash to zero so that sbuf is directory pd was in,
e.g., ~/pd/bin */
*lastslash = 0;
/* go back to the parent from there, e.g., ~/pd */
lastslash = strrchr(sbuf, '/');
if (lastslash)
{
strncpy(sbuf2, sbuf, lastslash-sbuf);
sbuf2[lastslash-sbuf] = 0;
}
else strcpy(sbuf2, "..");
}
else
{
/* no slashes found. Try INSTALL_PREFIX. */
#ifdef INSTALL_PREFIX
strcpy(sbuf2, INSTALL_PREFIX);
#else
strcpy(sbuf2, ".");
#endif
}
/* now we believe sbuf2 holds the parent directory of the directory
pd was found in. We now want to infer the "lib" directory and the
"gui" directory. In "simple" UNIX installations, the layout is
.../bin/pd
.../bin/pd-gui
.../doc
and in "complicated" UNIX installations, it's:
.../bin/pd
.../lib/pd/bin/pd-gui
.../lib/pd/doc
To decide which, we stat .../lib/pd; if that exists, we assume it's
the complicated layout. In MSW, it's the "simple" layout, but
the gui program is straight wish80:
.../bin/pd
.../bin/wish80.exe
.../doc
*/
#ifdef UNIX
strncpy(sbuf, sbuf2, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/lib/pd");
if (stat(sbuf, &statbuf) >= 0)
{
/* complicated layout: lib dir is the one we just stat-ed above */
sys_libdir = gensym(sbuf);
/* gui lives in .../lib/pd/bin */
strncpy(sbuf, sbuf2, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/lib/pd/bin");
sys_guidir = gensym(sbuf);
}
else
{
/* simple layout: lib dir is the parent */
sys_libdir = gensym(sbuf2);
/* gui lives in .../bin */
strncpy(sbuf, sbuf2, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/bin");
sys_guidir = gensym(sbuf);
}
#endif
#ifdef MSW
sys_libdir = gensym(sbuf2);
sys_guidir = &s_; /* in MSW the guipath just depends on the libdir */
#endif
}
#ifdef MSW
static int sys_mmio = 1;
#else
static int sys_mmio = 0;
#endif
int sys_argparse(int argc, char **argv)
{
char sbuf[MAXPDSTRING];
int i;
argc--; argv++;
while ((argc > 0) && **argv == '-')
{
if (!strcmp(*argv, "-r") && argc > 1 &&
sscanf(argv[1], "%d", &sys_main_srate) >= 1)
{
argc -= 2;
argv += 2;
}
else if (!strcmp(*argv, "-inchannels"))
{ /* IOhannes */
sys_parsedevlist(&sys_nchin,
sys_chinlist, MAXAUDIOINDEV, argv[1]);
if (!sys_nchin)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-outchannels"))
{ /* IOhannes */
sys_parsedevlist(&sys_nchout, sys_choutlist,
MAXAUDIOOUTDEV, argv[1]);
if (!sys_nchout)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-channels"))
{
sys_parsedevlist(&sys_nchin, sys_chinlist,MAXAUDIOINDEV,
argv[1]);
sys_parsedevlist(&sys_nchout, sys_choutlist,MAXAUDIOOUTDEV,
argv[1]);
if (!sys_nchout)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-soundbuf") || !strcmp(*argv, "-audiobuf"))
{
sys_main_advance = atoi(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-blocksize"))
{
sys_setblocksize(atoi(argv[1]));
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-sleepgrain"))
{
sys_sleepgrain = 1000 * atoi(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-nodac"))
{ /* IOhannes */
sys_nsoundout=0;
sys_nchout = 0;
argc--; argv++;
}
else if (!strcmp(*argv, "-noadc"))
{ /* IOhannes */
sys_nsoundin=0;
sys_nchin = 0;
argc--; argv++;
}
else if (!strcmp(*argv, "-nosound") || !strcmp(*argv, "-noaudio"))
{ /* IOhannes */
sys_nsoundin=sys_nsoundout = 0;
sys_nchin = sys_nchout = 0;
argc--; argv++;
}
#ifdef USEAPI_OSS
else if (!strcmp(*argv, "-oss"))
{
sys_set_audio_api(API_OSS);
argc--; argv++;
}
else if (!strcmp(*argv, "-32bit"))
{
sys_set_audio_api(API_OSS);
oss_set32bit();
argc--; argv++;
}
#endif
#ifdef USEAPI_ALSA
else if (!strcmp(*argv, "-alsa"))
{
sys_set_audio_api(API_ALSA);
argc--; argv++;
}
else if (!strcmp(*argv, "-alsaadd"))
{
if (argc > 1)
alsa_adddev(argv[1]);
else goto usage;
argc -= 2; argv +=2;
}
/* obsolete flag for setting ALSA device number or name */
else if (!strcmp(*argv, "-alsadev"))
{
int devno = 0;
if (argv[1][0] >= '1' && argv[1][0] <= '9')
devno = 1 + 2 * (atoi(argv[1]) - 1);
else if (!strncmp(argv[1], "hw:", 3))
devno = 1 + 2 * atoi(argv[1]+3);
else if (!strncmp(argv[1], "plughw:", 7))
devno = 2 + 2 * atoi(argv[1]+7);
else goto usage;
sys_nsoundin = sys_nsoundout = 1;
sys_soundindevlist[0] = sys_soundoutdevlist[0] = devno;
sys_set_audio_api(API_ALSA);
argc -= 2; argv +=2;
}
#endif
#ifdef USEAPI_JACK
else if (!strcmp(*argv, "-jack"))
{
sys_set_audio_api(API_JACK);
argc--; argv++;
}
#endif
#ifdef USEAPI_PORTAUDIO
else if (!strcmp(*argv, "-pa") || !strcmp(*argv, "-portaudio")
#ifdef MSW
|| !strcmp(*argv, "-asio")
#endif
)
{
sys_set_audio_api(API_PORTAUDIO);
sys_mmio = 0;
argc--; argv++;
}
#endif
#ifdef USEAPI_MMIO
else if (!strcmp(*argv, "-mmio"))
{
sys_set_audio_api(API_MMIO);
sys_mmio = 1;
argc--; argv++;
}
#endif
else if (!strcmp(*argv, "-nomidiin"))
{
sys_nmidiin = 0;
argc--; argv++;
}
else if (!strcmp(*argv, "-nomidiout"))
{
sys_nmidiout = 0;
argc--; argv++;
}
else if (!strcmp(*argv, "-nomidi"))
{
sys_nmidiin = sys_nmidiout = 0;
argc--; argv++;
}
else if (!strcmp(*argv, "-midiindev"))
{
sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV,
argv[1]);
if (!sys_nmidiin)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-midioutdev"))
{
sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV,
argv[1]);
if (!sys_nmidiout)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-mididev"))
{
sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV,
argv[1]);
sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV,
argv[1]);
if (!sys_nmidiout)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-path"))
{
sys_addpath(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-helppath"))
{
sys_addhelppath(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-open") && argc > 1)
{
sys_openlist = namelist_append(sys_openlist, argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-lib") && argc > 1)
{
sys_externlist = namelist_append(sys_externlist, argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-font") && argc > 1)
{
sys_defaultfont = sys_nearestfontsize(atoi(argv[1]));
argc -= 2;
argv += 2;
}
else if (!strcmp(*argv, "-verbose"))
{
sys_verbose = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-version"))
{
sys_version = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-d") && argc > 1 &&
sscanf(argv[1], "%d", &sys_debuglevel) >= 1)
{
argc -= 2;
argv += 2;
}
else if (!strcmp(*argv, "-noloadbang"))
{
sys_noloadbang = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-nogui"))
{
sys_nogui = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-stdin"))
{
sys_stdin = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-guicmd") && argc > 1)
{
sys_guicmd = argv[1];
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-send") && argc > 1)
{
sys_messagelist = namelist_append(sys_messagelist, argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-listdev"))
{
sys_listdevs();
argc--; argv++;
}
#ifdef UNIX
else if (!strcmp(*argv, "-rt") || !strcmp(*argv, "-realtime"))
{
sys_hipriority = 1;
argc--; argv++;
}
else if (!strcmp(*argv, "-nrt"))
{
sys_hipriority = 0;
argc--; argv++;
}
#endif
else if (!strcmp(*argv, "-soundindev") ||
!strcmp(*argv, "-audioindev"))
{ /* IOhannes */
sys_parsedevlist(&sys_nsoundin, sys_soundindevlist,
MAXAUDIOINDEV, argv[1]);
if (!sys_nsoundin)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-soundoutdev") ||
!strcmp(*argv, "-audiooutdev"))
{ /* IOhannes */
sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist,
MAXAUDIOOUTDEV, argv[1]);
if (!sys_nsoundout)
goto usage;
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-sounddev") || !strcmp(*argv, "-audiodev"))
{
sys_parsedevlist(&sys_nsoundin, sys_soundindevlist,
MAXAUDIOINDEV, argv[1]);
sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist,
MAXAUDIOOUTDEV, argv[1]);
if (!sys_nsoundout)
goto usage;
argc -= 2; argv += 2;
}
else
{
unsigned int i;
usage:
for (i = 0; i < sizeof(usagemessage)/sizeof(*usagemessage); i++)
fprintf(stderr, "%s", usagemessage[i]);
return (1);
}
}
if (!sys_defaultfont)
sys_defaultfont = DEFAULTFONT;
for (; argc > 0; argc--, argv++)
sys_openlist = namelist_append(sys_openlist, *argv);
return (0);
}
int sys_getblksize(void)
{
return (DEFDACBLKSIZE);
}
/* stuff to do, once, after calling sys_argparse() -- which may itself
be called twice because of the .pdrc hack. */
static void sys_afterargparse(void)
{
char sbuf[MAXPDSTRING];
int i;
/* add "extra" library to path */
strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/extra");
sys_addpath(sbuf);
strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/intern");
sys_addpath(sbuf);
/* add "doc/5.reference" library to helppath */
strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30);
sbuf[MAXPDSTRING-30] = 0;
strcat(sbuf, "/doc/5.reference");
sys_addhelppath(sbuf);
/* correct to make audio and MIDI device lists zero based. On
MMIO, however, "1" really means the second device (the first one
is "mapper" which is was not included when the command args were
set up, so we leave it that way for compatibility. */
if (!sys_mmio)
{
for (i = 0; i < sys_nsoundin; i++)
sys_soundindevlist[i]--;
for (i = 0; i < sys_nsoundout; i++)
sys_soundoutdevlist[i]--;
}
for (i = 0; i < sys_nmidiin; i++)
sys_midiindevlist[i]--;
for (i = 0; i < sys_nmidiout; i++)
sys_midioutdevlist[i]--;
}
static void sys_addreferencepath(void)
{
char sbuf[MAXPDSTRING];
}

View file

@ -1,642 +0,0 @@
/* Copyright (c) 1997-1999 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* Clock functions (which should move, but where?) and MIDI queueing */
#include "m_pd.h"
#include "s_stuff.h"
#include "m_imp.h"
#ifdef UNIX
#include <unistd.h>
#include <sys/time.h>
#ifdef HAVE_BSTRING_H
#include <bstring.h>
#endif
#endif
#ifdef MSW
#include <winsock.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <wtypes.h>
#endif
#include <string.h>
#include <stdio.h>
#include <signal.h>
typedef struct _midiqelem
{
double q_time;
int q_portno;
unsigned char q_onebyte;
unsigned char q_byte1;
unsigned char q_byte2;
unsigned char q_byte3;
} t_midiqelem;
#define MIDIQSIZE 1024
t_midiqelem midi_outqueue[MIDIQSIZE];
int midi_outhead, midi_outtail;
t_midiqelem midi_inqueue[MIDIQSIZE];
int midi_inhead, midi_intail;
static double sys_midiinittime;
/* this is our current estimate for at what "system" real time the
current logical time's output should occur. */
static double sys_dactimeminusrealtime;
/* same for input, should be schduler advance earlier. */
static double sys_adctimeminusrealtime;
static double sys_newdactimeminusrealtime = -1e20;
static double sys_newadctimeminusrealtime = -1e20;
static double sys_whenupdate;
void sys_initmidiqueue( void)
{
sys_midiinittime = clock_getlogicaltime();
sys_dactimeminusrealtime = sys_adctimeminusrealtime = 0;
}
/* this is called from the OS dependent code from time to time when we
think we know the delay (outbuftime) in seconds, at which the last-output
audio sample will go out the door. */
void sys_setmiditimediff(double inbuftime, double outbuftime)
{
double dactimeminusrealtime =
.001 * clock_gettimesince(sys_midiinittime)
- outbuftime - sys_getrealtime();
double adctimeminusrealtime =
.001 * clock_gettimesince(sys_midiinittime)
+ inbuftime - sys_getrealtime();
if (dactimeminusrealtime > sys_newdactimeminusrealtime)
sys_newdactimeminusrealtime = dactimeminusrealtime;
if (adctimeminusrealtime > sys_newadctimeminusrealtime)
sys_newadctimeminusrealtime = adctimeminusrealtime;
if (sys_getrealtime() > sys_whenupdate)
{
sys_dactimeminusrealtime = sys_newdactimeminusrealtime;
sys_adctimeminusrealtime = sys_newadctimeminusrealtime;
sys_newdactimeminusrealtime = -1e20;
sys_newadctimeminusrealtime = -1e20;
sys_whenupdate = sys_getrealtime() + 1;
}
}
/* return the logical time of the DAC sample we believe is currently
going out, based on how much "system time" has elapsed since the
last time sys_setmiditimediff got called. */
static double sys_getmidioutrealtime( void)
{
return (sys_getrealtime() + sys_dactimeminusrealtime);
}
static double sys_getmidiinrealtime( void)
{
return (sys_getrealtime() + sys_adctimeminusrealtime);
}
static void sys_putnext( void)
{
int portno = midi_outqueue[midi_outtail].q_portno;
if (midi_outqueue[midi_outtail].q_onebyte)
sys_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1);
else sys_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1,
midi_outqueue[midi_outtail].q_byte2,
midi_outqueue[midi_outtail].q_byte3);
midi_outtail = (midi_outtail + 1 == MIDIQSIZE ? 0 : midi_outtail + 1);
}
/* #define TEST_DEJITTER */
void sys_pollmidioutqueue( void)
{
#ifdef TEST_DEJITTER
static int db = 0;
#endif
double midirealtime = sys_getmidioutrealtime();
#ifdef TEST_DEJITTER
if (midi_outhead == midi_outtail)
db = 0;
#endif
while (midi_outhead != midi_outtail)
{
#ifdef TEST_DEJITTER
if (!db)
{
post("out: del %f, midiRT %f logicaltime %f, RT %f dacminusRT %f",
(midi_outqueue[midi_outtail].q_time - midirealtime),
midirealtime, .001 * clock_gettimesince(sys_midiinittime),
sys_getrealtime(), sys_dactimeminusrealtime);
db = 1;
}
#endif
if (midi_outqueue[midi_outtail].q_time <= midirealtime)
sys_putnext();
else break;
}
}
static void sys_queuemidimess(int portno, int onebyte, int a, int b, int c)
{
t_midiqelem *midiqelem;
int newhead = midi_outhead +1;
if (newhead == MIDIQSIZE)
newhead = 0;
/* if FIFO is full flush an element to make room */
if (newhead == midi_outtail)
sys_putnext();
midi_outqueue[midi_outhead].q_portno = portno;
midi_outqueue[midi_outhead].q_onebyte = onebyte;
midi_outqueue[midi_outhead].q_byte1 = a;
midi_outqueue[midi_outhead].q_byte2 = b;
midi_outqueue[midi_outhead].q_byte3 = c;
midi_outqueue[midi_outhead].q_time =
.001 * clock_gettimesince(sys_midiinittime);
midi_outhead = newhead;
sys_pollmidioutqueue();
}
#define MIDI_NOTEON 144
#define MIDI_POLYAFTERTOUCH 160
#define MIDI_CONTROLCHANGE 176
#define MIDI_PROGRAMCHANGE 192
#define MIDI_AFTERTOUCH 208
#define MIDI_PITCHBEND 224
void outmidi_noteon(int portno, int channel, int pitch, int velo)
{
if (pitch < 0) pitch = 0;
else if (pitch > 127) pitch = 127;
if (velo < 0) velo = 0;
else if (velo > 127) velo = 127;
sys_queuemidimess(portno, 0, MIDI_NOTEON + (channel & 0xf), pitch, velo);
}
void outmidi_controlchange(int portno, int channel, int ctl, int value)
{
if (ctl < 0) ctl = 0;
else if (ctl > 127) ctl = 127;
if (value < 0) value = 0;
else if (value > 127) value = 127;
sys_queuemidimess(portno, 0, MIDI_CONTROLCHANGE + (channel & 0xf),
ctl, value);
}
void outmidi_programchange(int portno, int channel, int value)
{
if (value < 0) value = 0;
else if (value > 127) value = 127;
sys_queuemidimess(portno, 0,
MIDI_PROGRAMCHANGE + (channel & 0xf), value, 0);
}
void outmidi_pitchbend(int portno, int channel, int value)
{
if (value < 0) value = 0;
else if (value > 16383) value = 16383;
sys_queuemidimess(portno, 0, MIDI_PITCHBEND + (channel & 0xf),
(value & 127), ((value>>7) & 127));
}
void outmidi_aftertouch(int portno, int channel, int value)
{
if (value < 0) value = 0;
else if (value > 127) value = 127;
sys_queuemidimess(portno, 0, MIDI_AFTERTOUCH + (channel & 0xf), value, 0);
}
void outmidi_polyaftertouch(int portno, int channel, int pitch, int value)
{
if (pitch < 0) pitch = 0;
else if (pitch > 127) pitch = 127;
if (value < 0) value = 0;
else if (value > 127) value = 127;
sys_queuemidimess(portno, 0, MIDI_POLYAFTERTOUCH + (channel & 0xf),
pitch, value);
}
void outmidi_mclk(int portno)
{
sys_queuemidimess(portno, 1, 0xf8, 0,0);
}
/* ------------------------- MIDI input queue handling ------------------ */
typedef struct midiparser
{
int mp_status;
int mp_gotbyte1;
int mp_byte1;
} t_midiparser;
#define MIDINOTEOFF 0x80 /* 2 following 'data bytes' */
#define MIDINOTEON 0x90 /* 2 */
#define MIDIPOLYTOUCH 0xa0 /* 2 */
#define MIDICONTROLCHANGE 0xb0 /* 2 */
#define MIDIPROGRAMCHANGE 0xc0 /* 1 */
#define MIDICHANNELTOUCH 0xd0 /* 1 */
#define MIDIPITCHBEND 0xe0 /* 2 */
#define MIDISTARTSYSEX 0xf0 /* (until F7) */
#define MIDITIMECODE 0xf1 /* 1 */
#define MIDISONGPOS 0xf2 /* 2 */
#define MIDISONGSELECT 0xf3 /* 1 */
#define MIDIRESERVED1 0xf4 /* ? */
#define MIDIRESERVED2 0xf5 /* ? */
#define MIDITUNEREQUEST 0xf6 /* 0 */
#define MIDIENDSYSEX 0xf7 /* 0 */
#define MIDICLOCK 0xf8 /* 0 */
#define MIDITICK 0xf9 /* 0 */
#define MIDISTART 0xfa /* 0 */
#define MIDICONT 0xfb /* 0 */
#define MIDISTOP 0xfc /* 0 */
#define MIDIACTIVESENSE 0xfe /* 0 */
#define MIDIRESET 0xff /* 0 */
/* functions in x_midi.c */
void inmidi_realtimein(int portno, int cmd);
void inmidi_byte(int portno, int byte);
void inmidi_sysex(int portno, int byte);
void inmidi_noteon(int portno, int channel, int pitch, int velo);
void inmidi_controlchange(int portno, int channel, int ctlnumber, int value);
void inmidi_programchange(int portno, int channel, int value);
void inmidi_pitchbend(int portno, int channel, int value);
void inmidi_aftertouch(int portno, int channel, int value);
void inmidi_polyaftertouch(int portno, int channel, int pitch, int value);
static void sys_dispatchnextmidiin( void)
{
static t_midiparser parser[MAXMIDIINDEV], *parserp;
int portno = midi_inqueue[midi_intail].q_portno,
byte = midi_inqueue[midi_intail].q_byte1;
if (!midi_inqueue[midi_intail].q_onebyte)
bug("sys_dispatchnextmidiin");
if (portno < 0 || portno >= MAXMIDIINDEV)
bug("sys_dispatchnextmidiin 2");
parserp = parser + portno;
outlet_setstacklim();
if (byte >= 0xf8)
inmidi_realtimein(portno, byte);
else
{
inmidi_byte(portno, byte);
if (byte & 0x80)
{
if (byte == MIDITUNEREQUEST || byte == MIDIRESERVED1 ||
byte == MIDIRESERVED2)
parserp->mp_status = 0;
else if (byte == MIDISTARTSYSEX)
{
inmidi_sysex(portno, byte);
parserp->mp_status = byte;
}
else if (byte == MIDIENDSYSEX)
{
inmidi_sysex(portno, byte);
parserp->mp_status = 0;
}
else
{
parserp->mp_status = byte;
}
parserp->mp_gotbyte1 = 0;
}
else
{
int cmd = (parserp->mp_status >= 0xf0 ? parserp->mp_status :
(parserp->mp_status & 0xf0));
int chan = (parserp->mp_status & 0xf);
int byte1 = parserp->mp_byte1, gotbyte1 = parserp->mp_gotbyte1;
switch (cmd)
{
case MIDINOTEOFF:
if (gotbyte1)
inmidi_noteon(portno, chan, byte1, 0),
parserp->mp_gotbyte1 = 0;
else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
break;
case MIDINOTEON:
if (gotbyte1)
inmidi_noteon(portno, chan, byte1, byte),
parserp->mp_gotbyte1 = 0;
else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
break;
case MIDIPOLYTOUCH:
if (gotbyte1)
inmidi_polyaftertouch(portno, chan, byte1, byte),
parserp->mp_gotbyte1 = 0;
else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
break;
case MIDICONTROLCHANGE:
if (gotbyte1)
inmidi_controlchange(portno, chan, byte1, byte),
parserp->mp_gotbyte1 = 0;
else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
break;
case MIDIPROGRAMCHANGE:
inmidi_programchange(portno, chan, byte);
break;
case MIDICHANNELTOUCH:
inmidi_aftertouch(portno, chan, byte);
break;
case MIDIPITCHBEND:
if (gotbyte1)
inmidi_pitchbend(portno, chan, ((byte << 7) + byte1)),
parserp->mp_gotbyte1 = 0;
else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
break;
case MIDISTARTSYSEX:
inmidi_sysex(portno, byte);
break;
/* other kinds of messages are just dropped here. We'll
need another status byte before we start letting MIDI in
again (no running status across "system" messages). */
case MIDITIMECODE: /* 1 data byte*/
break;
case MIDISONGPOS: /* 2 */
break;
case MIDISONGSELECT: /* 1 */
break;
}
}
}
midi_intail = (midi_intail + 1 == MIDIQSIZE ? 0 : midi_intail + 1);
}
void sys_pollmidiinqueue( void)
{
#ifdef TEST_DEJITTER
static int db = 0;
#endif
double logicaltime = .001 * clock_gettimesince(sys_midiinittime);
#ifdef TEST_DEJITTER
if (midi_inhead == midi_intail)
db = 0;
#endif
while (midi_inhead != midi_intail)
{
#ifdef TEST_DEJITTER
if (!db)
{
post("in del %f, logicaltime %f, RT %f adcminusRT %f",
(midi_inqueue[midi_intail].q_time - logicaltime),
logicaltime, sys_getrealtime(), sys_adctimeminusrealtime);
db = 1;
}
#endif
#if 0
if (midi_inqueue[midi_intail].q_time <= logicaltime - 0.007)
post("late %f",
1000 * (logicaltime - midi_inqueue[midi_intail].q_time));
#endif
if (midi_inqueue[midi_intail].q_time <= logicaltime)
{
#if 0
post("diff %f",
1000* (logicaltime - midi_inqueue[midi_intail].q_time));
#endif
sys_dispatchnextmidiin();
}
else break;
}
}
/* this should be called from the system dependent MIDI code when a byte
comes in, as a result of our calling sys_poll_midi. We stick it on a
timetag queue and dispatch it at the appropriate logical time. */
void sys_midibytein(int portno, int byte)
{
static int warned = 0;
t_midiqelem *midiqelem;
int newhead = midi_inhead +1;
if (newhead == MIDIQSIZE)
newhead = 0;
/* if FIFO is full flush an element to make room */
if (newhead == midi_intail)
{
if (!warned)
{
post("warning: MIDI timing FIFO overflowed");
warned = 1;
}
sys_dispatchnextmidiin();
}
midi_inqueue[midi_inhead].q_portno = portno;
midi_inqueue[midi_inhead].q_onebyte = 1;
midi_inqueue[midi_inhead].q_byte1 = byte;
midi_inqueue[midi_inhead].q_time = sys_getmidiinrealtime();
midi_inhead = newhead;
sys_pollmidiinqueue();
}
void sys_pollmidiqueue( void)
{
#if 0
static double lasttime;
double newtime = sys_getrealtime();
if (newtime - lasttime > 0.007)
post("delay %d", (int)(1000 * (newtime - lasttime)));
lasttime = newtime;
#endif
sys_poll_midi(); /* OS dependent poll for MIDI input */
sys_pollmidioutqueue();
sys_pollmidiinqueue();
}
/******************** dialog window and device listing ********************/
#ifdef USEAPI_OSS
void midi_oss_init( void);
#endif
/* last requested parameters */
static int midi_nmidiindev;
static int midi_midiindev[MAXMIDIINDEV];
static int midi_nmidioutdev;
static int midi_midioutdev[MAXMIDIOUTDEV];
static void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
int *pnmidioutdev, int *pmidioutdev)
{
int i;
*pnmidiindev = midi_nmidiindev;
for (i = 0; i < MAXMIDIINDEV; i++)
pmidiindev[i] = midi_midiindev[i];
*pnmidioutdev = midi_nmidioutdev;
for (i = 0; i < MAXMIDIOUTDEV; i++)
pmidioutdev[i] = midi_midioutdev[i];
}
static void sys_save_midi_params(
int nmidiindev, int *midiindev,
int nmidioutdev, int *midioutdev)
{
int i;
midi_nmidiindev = nmidiindev;
for (i = 0; i < MAXMIDIINDEV; i++)
midi_midiindev[i] = midiindev[i];
midi_nmidioutdev = nmidioutdev;
for (i = 0; i < MAXMIDIOUTDEV; i++)
midi_midioutdev[i] = midioutdev[i];
}
void sys_open_midi(int nmidiindev, int *midiindev,
int nmidioutdev, int *midioutdev)
{
#ifdef USEAPI_OSS
midi_oss_init();
#endif
sys_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev);
sys_save_midi_params(nmidiindev, midiindev,
nmidioutdev, midioutdev);
}
/* open midi using whatever parameters were last used */
void sys_reopen_midi( void)
{
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev);
}
#define MAXNDEV 20
#define DEVDESCSIZE 80
#ifdef MSW
#define DEVONSET 0 /* microsoft device list starts at 0 (the "mapper"). */
#else /* (see also MSW ifdef in sys_parsedevlist(), s_main.c) */
#define DEVONSET 1 /* To agree with command line flags, normally start at 1 */
#endif
void sys_listmididevs(void )
{
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, i;
midi_getdevs(indevlist, &nindevs, outdevlist, &noutdevs,
MAXNDEV, DEVDESCSIZE);
if (!nindevs)
post("no midi input devices found");
else
{
post("input devices:");
for (i = 0; i < nindevs; i++)
post("%d. %s", i+1, indevlist + i * DEVDESCSIZE);
}
if (!noutdevs)
post("no midi output devices found");
else
{
post("output devices:");
for (i = 0; i < noutdevs; i++)
post("%d. %s", i+DEVONSET, outdevlist + i * DEVDESCSIZE);
}
}
extern t_class *glob_pdobject;
/* start an midi settings dialog window */
void glob_midi_properties(t_pd *dummy, t_floatarg flongform)
{
char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
/* these are the devices you're using: */
int nindev, midiindev[MAXMIDIINDEV];
int noutdev, midioutdev[MAXMIDIOUTDEV];
int midiindev1, midiindev2, midiindev3, midiindev4,
midioutdev1, midioutdev2, midioutdev3, midioutdev4;
/* these are all the devices on your system: */
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, i;
char indevliststring[MAXNDEV*(DEVDESCSIZE+4)+80],
outdevliststring[MAXNDEV*(DEVDESCSIZE+4)+80];
midi_getdevs(indevlist, &nindevs, outdevlist, &noutdevs,
MAXNDEV, DEVDESCSIZE);
strcpy(indevliststring, "{ {none} ");
for (i = 0; i < nindevs; i++)
{
strcat(indevliststring, "\"");
strcat(indevliststring, indevlist + i * DEVDESCSIZE);
strcat(indevliststring, "\" ");
}
strcat(indevliststring, "}");
strcpy(outdevliststring, "{ {none} ");
for (i = 0; i < noutdevs; i++)
{
strcat(outdevliststring, "\"");
strcat(outdevliststring, outdevlist + i * DEVDESCSIZE);
strcat(outdevliststring, "\" ");
}
strcat(outdevliststring, "}");
sys_get_midi_params(&nindev, midiindev, &noutdev, midioutdev);
if (nindev > 1 || noutdev > 1)
flongform = 1;
midiindev1 = (nindev > 0 && midiindev[0]>= 0 ? midiindev[0]+1 : 0);
midiindev2 = (nindev > 1 && midiindev[1]>= 0 ? midiindev[1]+1 : 0);
midiindev3 = (nindev > 2 && midiindev[2]>= 0 ? midiindev[2]+1 : 0);
midiindev4 = (nindev > 3 && midiindev[3]>= 0 ? midiindev[3]+1 : 0);
midioutdev1 = (noutdev > 0 && midioutdev[0]>=0 ? midioutdev[0]+1 : 0);
midioutdev2 = (noutdev > 1 && midioutdev[1]>=0 ? midioutdev[1]+1 : 0);
midioutdev3 = (noutdev > 2 && midioutdev[2]>=0 ? midioutdev[2]+1 : 0);
midioutdev4 = (noutdev > 3 && midioutdev[3]>=0 ? midioutdev[3]+1 : 0);
sprintf(buf,
"pdtk_midi_dialog %%s \
%s %d %d %d %d %s %d %d %d %d \
%d\n",
indevliststring,
midiindev1, midiindev2, midiindev3, midiindev4,
outdevliststring,
midioutdev1, midioutdev2, midioutdev3, midioutdev4,
(flongform != 0));
gfxstub_deleteforkey(0);
gfxstub_new(&glob_pdobject, glob_midi_properties, buf);
}
/* new values from dialog window */
void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
{
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
int i, nindev, noutdev;
int newmidiindev[4], newmidioutdev[4];
for (i = 0; i < 4; i++)
{
newmidiindev[i] = atom_getintarg(i, argc, argv);
newmidioutdev[i] = atom_getintarg(i+4, argc, argv);
}
for (i = 0, nindev = 0; i < 4; i++)
{
if (newmidiindev[i] > 0)
{
newmidiindev[nindev] = newmidiindev[i]-1;
nindev++;
}
}
for (i = 0, noutdev = 0; i < 4; i++)
{
if (newmidioutdev[i] > 0)
{
newmidioutdev[noutdev] = newmidioutdev[i]-1;
noutdev++;
}
}
sys_close_midi();
sys_open_midi(nindev, newmidiindev, noutdev, newmidioutdev);
}

View file

@ -1,360 +0,0 @@
/* Copyright (c) 1997-1999 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* MIDI I/O for Linux using OSS */
#include <stdio.h>
#ifdef UNIX
#include <unistd.h>
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "m_pd.h"
#include "s_stuff.h"
static int oss_nmidiin;
static int oss_midiinfd[MAXMIDIINDEV];
static int oss_nmidiout;
static int oss_midioutfd[MAXMIDIOUTDEV];
static void oss_midiout(int fd, int n)
{
char b = n;
if ((write(fd, (char *) &b, 1)) != 1)
perror("midi write");
}
#define O_MIDIFLAG O_NDELAY
void sys_do_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec)
{
int i;
for (i = 0; i < nmidiout; i++)
oss_midioutfd[i] = -1;
for (i = 0, oss_nmidiin = 0; i < nmidiin; i++)
{
int fd = -1, j, outdevindex = -1;
char namebuf[80];
int devno = midiinvec[i];
for (j = 0; j < nmidiout; j++)
if (midioutvec[j] == midiinvec[i])
outdevindex = j;
/* try to open the device for read/write. */
if (devno == 0 && fd < 0 && outdevindex >= 0)
{
sys_setalarm(1000000);
fd = open("/dev/midi", O_RDWR | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr,
"device 1: tried /dev/midi READ/WRITE; returned %d\n", fd);
if (outdevindex >= 0 && fd >= 0)
oss_midioutfd[outdevindex] = fd;
}
if (fd < 0 && outdevindex >= 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%2.2d", devno);
fd = open(namebuf, O_RDWR | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr,
"device %d: tried %s READ/WRITE; returned %d\n",
devno, namebuf, fd);
if (outdevindex >= 0 && fd >= 0)
oss_midioutfd[outdevindex] = fd;
}
if (fd < 0 && outdevindex >= 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%d", devno);
fd = open(namebuf, O_RDWR | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr, "device %d: tried %s READ/WRITE; returned %d\n",
devno, namebuf, fd);
if (outdevindex >= 0 && fd >= 0)
oss_midioutfd[outdevindex] = fd;
}
if (devno == 1 && fd < 0)
{
sys_setalarm(1000000);
fd = open("/dev/midi", O_RDONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr,
"device 1: tried /dev/midi READONLY; returned %d\n", fd);
}
if (fd < 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%2.2d", devno);
fd = open(namebuf, O_RDONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr, "device %d: tried %s READONLY; returned %d\n",
devno, namebuf, fd);
}
if (fd < 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%d", devno);
fd = open(namebuf, O_RDONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr, "device %d: tried %s READONLY; returned %d\n",
devno, namebuf, fd);
}
if (fd >= 0)
oss_midiinfd[oss_nmidiin++] = fd;
else post("couldn't open MIDI input device %d", devno);
}
for (i = 0, oss_nmidiout = 0; i < nmidiout; i++)
{
int fd = oss_midioutfd[i];
char namebuf[80];
int devno = midioutvec[i];
if (devno == 1 && fd < 0)
{
sys_setalarm(1000000);
fd = open("/dev/midi", O_WRONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr,
"device 1: tried /dev/midi WRITEONLY; returned %d\n", fd);
}
if (fd < 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%2.2d", devno);
fd = open(namebuf, O_WRONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n",
devno, namebuf, fd);
}
if (fd < 0)
{
sys_setalarm(1000000);
sprintf(namebuf, "/dev/midi%d", devno);
fd = open(namebuf, O_WRONLY | O_MIDIFLAG);
if (sys_verbose)
fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n",
devno, namebuf, fd);
}
if (fd >= 0)
oss_midioutfd[oss_nmidiout++] = fd;
else post("couldn't open MIDI output device %d", devno);
}
if (oss_nmidiin < nmidiin || oss_nmidiout < nmidiout || sys_verbose)
post("opened %d MIDI input device(s) and %d MIDI output device(s).",
oss_nmidiin, oss_nmidiout);
sys_setalarm(0);
}
#define md_msglen(x) (((x)<0xC0)?2:((x)<0xE0)?1:((x)<0xF0)?2:\
((x)==0xF2)?2:((x)<0xF4)?1:0)
void sys_putmidimess(int portno, int a, int b, int c)
{
if (portno >= 0 && portno < oss_nmidiout)
{
switch (md_msglen(a))
{
case 2:
oss_midiout(oss_midioutfd[portno],a);
oss_midiout(oss_midioutfd[portno],b);
oss_midiout(oss_midioutfd[portno],c);
return;
case 1:
oss_midiout(oss_midioutfd[portno],a);
oss_midiout(oss_midioutfd[portno],b);
return;
case 0:
oss_midiout(oss_midioutfd[portno],a);
return;
};
}
}
void sys_putmidibyte(int portno, int byte)
{
if (portno >= 0 && portno < oss_nmidiout)
oss_midiout(oss_midioutfd[portno], byte);
}
#if 0 /* this is the "select" version which doesn't work with OSS
driver for emu10k1 (it doesn't implement select.) */
void sys_poll_midi(void)
{
int i, throttle = 100;
struct timeval timout;
int did = 1, maxfd = 0;
while (did)
{
fd_set readset, writeset, exceptset;
did = 0;
if (throttle-- < 0)
break;
timout.tv_sec = 0;
timout.tv_usec = 0;
FD_ZERO(&writeset);
FD_ZERO(&readset);
FD_ZERO(&exceptset);
for (i = 0; i < oss_nmidiin; i++)
{
if (oss_midiinfd[i] > maxfd)
maxfd = oss_midiinfd[i];
FD_SET(oss_midiinfd[i], &readset);
}
select(maxfd+1, &readset, &writeset, &exceptset, &timout);
for (i = 0; i < oss_nmidiin; i++)
if (FD_ISSET(oss_midiinfd[i], &readset))
{
char c;
int ret = read(oss_midiinfd[i], &c, 1);
if (ret <= 0)
fprintf(stderr, "Midi read error\n");
else sys_midibytein(i, (c & 0xff));
did = 1;
}
}
}
#else
/* this version uses the asynchronous "read()" ... */
void sys_poll_midi(void)
{
int i, throttle = 100;
struct timeval timout;
int did = 1, maxfd = 0;
while (did)
{
fd_set readset, writeset, exceptset;
did = 0;
if (throttle-- < 0)
break;
for (i = 0; i < oss_nmidiin; i++)
{
char c;
int ret = read(oss_midiinfd[i], &c, 1);
if (ret < 0)
{
if (errno != EAGAIN)
perror("MIDI");
}
else if (ret != 0)
{
sys_midibytein(i, (c & 0xff));
did = 1;
}
}
}
}
#endif
void sys_close_midi()
{
int i;
for (i = 0; i < oss_nmidiin; i++)
close(oss_midiinfd[i]);
for (i = 0; i < oss_nmidiout; i++)
close(oss_midioutfd[i]);
oss_nmidiin = oss_nmidiout = 0;
}
#define NSEARCH 10
static int oss_nmidiindevs, oss_nmidioutdevs, oss_initted;
void midi_oss_init(void)
{
int i;
if (oss_initted)
return;
oss_initted = 1;
for (i = 0; i < NSEARCH; i++)
{
int fd;
char namebuf[80];
oss_nmidiindevs = i;
/* try to open the device for reading */
if (i == 0)
{
fd = open("/dev/midi", O_RDONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
}
sprintf(namebuf, "/dev/midi%2.2d", i);
fd = open(namebuf, O_RDONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
sprintf(namebuf, "/dev/midi%d", i);
fd = open(namebuf, O_RDONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
break;
}
for (i = 0; i < NSEARCH; i++)
{
int fd;
char namebuf[80];
oss_nmidioutdevs = i;
/* try to open the device for writing */
if (i == 0)
{
fd = open("/dev/midi", O_WRONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
}
sprintf(namebuf, "/dev/midi%2.2d", i);
fd = open(namebuf, O_WRONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
sprintf(namebuf, "/dev/midi%d", i);
fd = open(namebuf, O_WRONLY | O_NDELAY);
if (fd >= 0)
{
close(fd);
continue;
}
break;
}
}
void midi_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int maxndev, int devdescsize)
{
int i, ndev;
if ((ndev = oss_nmidiindevs) > maxndev)
ndev = maxndev;
for (i = 0; i < ndev; i++)
sprintf(indevlist + i * devdescsize, "OSS MIDI device #%d", i+1);
*nindevs = ndev;
if ((ndev = oss_nmidioutdevs) > maxndev)
ndev = maxndev;
for (i = 0; i < ndev; i++)
sprintf(outdevlist + i * devdescsize, "OSS MIDI device #%d", i+1);
*noutdevs = ndev;
}

View file

@ -1,167 +0,0 @@
/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
this file calls portmidi to do MIDI I/O for MSW and Mac OSX.
*/
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#ifdef UNIX
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "portaudio.h"
#include "portmidi.h"
#include "porttime.h"
#include "pminternal.h"
static PmStream *mac_midiindevlist[MAXMIDIINDEV];
static PmStream *mac_midioutdevlist[MAXMIDIOUTDEV];
static int mac_nmidiindev;
static int mac_nmidioutdev;
void sys_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec)
{
int i = 0;
int n = 0;
PmError err;
Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
mac_nmidiindev = 0;
/* protect the unwary from having MIDI inputs open; they're
bad news if you close Pd's terminal window. see sys_nmidiin
in s_main.c too. */
#ifdef MSW
if (nmidiin)
{
post(
"midi input enabled; warning, don't close the DOS window directly!");
}
else post("not using MIDI input (use 'pd -midiindev 1' to override)");
#endif
for (i = 0; i < nmidiin; i++)
{
if (midiinvec[i] == DEFMIDIDEV)
midiinvec[i] = Pm_GetDefaultInputDeviceID();
err = Pm_OpenInput(&mac_midiindevlist[mac_nmidiindev], midiinvec[i],
NULL, 100, NULL, NULL, NULL);
if (err)
post("could not open midi input device number %d: %s",
midiinvec[i], Pm_GetErrorText(err));
else
{
if (sys_verbose)
post("Midi Input opened.\n");
mac_nmidiindev++;
}
}
mac_nmidioutdev = 0;
for (i = 0; i < nmidiout; i++)
{
if (midioutvec[i] == DEFMIDIDEV)
midioutvec[i] = Pm_GetDefaultOutputDeviceID();
err = Pm_OpenOutput(&mac_midioutdevlist[mac_nmidioutdev], midioutvec[i],
NULL, 0, NULL, NULL, 0);
if (err)
post("could not open midi output device number %d: %s",
midioutvec[i], Pm_GetErrorText(err));
else
{
if (sys_verbose)
post("Midi Output opened.\n");
mac_nmidioutdev++;
}
}
}
void sys_close_midi( void)
{
int i;
for (i = 0; i < mac_nmidiindev; i++)
Pm_Close(mac_midiindevlist[mac_nmidiindev]);
mac_nmidiindev = 0;
for (i = 0; i < mac_nmidioutdev; i++)
Pm_Close(mac_midioutdevlist[mac_nmidioutdev]);
mac_nmidioutdev = 0;
}
void sys_putmidimess(int portno, int a, int b, int c)
{
PmEvent buffer;
fprintf(stderr, "put 1 msg %d %d\n", portno, mac_nmidioutdev);
if (portno >= 0 && portno < mac_nmidioutdev)
{
buffer.message = Pm_Message(a, b, c);
buffer.timestamp = 0;
fprintf(stderr, "put msg\n");
Pm_Write(mac_midioutdevlist[portno], &buffer, 1);
}
}
void sys_putmidibyte(int portno, int byte)
{
post("sorry, no byte-by-byte MIDI output implemented in MAC OSX");
}
void sys_poll_midi(void)
{
int i, nmess;
PmEvent buffer;
for (i = 0; i < mac_nmidiindev; i++)
{
int nmess = Pm_Read(mac_midiindevlist[i], &buffer, 1);
if (nmess > 0)
{
int status = Pm_MessageStatus(buffer.message);
int data1 = Pm_MessageData1(buffer.message);
int data2 = Pm_MessageData2(buffer.message);
int msgtype = (status >> 4) - 8;
switch (msgtype)
{
case 0:
case 1:
case 2:
case 3:
case 6:
sys_midibytein(i, status);
sys_midibytein(i, data1);
sys_midibytein(i, data2);
break;
case 4:
case 5:
sys_midibytein(i, status);
sys_midibytein(i, data1);
break;
case 7:
sys_midibytein(i, status);
break;
}
}
}
}
void sys_listmididevs(void) /* lifted from pa_devs.c in portaudio */
{
int i,j;
for (i = 0; i < Pm_CountDevices(); i++)
{
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
printf("%d: %s, %s", i, info->interf, info->name);
if (info->input) printf(" (input)");
if (info->output) printf(" (output)");
printf("\n");
}
}

View file

@ -1,189 +0,0 @@
/* 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. */
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifdef HAVE_BSTRING_H
#include <bstring.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <dmedia/audio.h>
#include <sys/fpu.h>
#include <dmedia/midi.h>
int mdInit(void); /* prototype was messed up in midi.h */
/* #include "sys/select.h" */
/*
set the special "flush zero" but (FS, bit 24) in the
Control Status Register of the FPU of R4k and beyond
so that the result of any underflowing operation will
be clamped to zero, and no exception of any kind will
be generated on the CPU.
thanks to cpirazzi@cp.esd.sgi.com (Chris Pirazzi).
*/
static void sgi_flush_all_underflows_to_zero(void)
{
union fpc_csr f;
f.fc_word = get_fpc_csr();
f.fc_struct.flush = 1;
set_fpc_csr(f.fc_word);
}
#define NPORT 2
static MDport sgi_inport[NPORT];
static MDport sgi_outport[NPORT];
void sgi_open_midi(int midiin, int midiout)
{
int i;
int sgi_nports = mdInit();
if (sgi_nports < 0) sgi_nports = 0;
else if (sgi_nports > NPORT) sgi_nports = NPORT;
if (sys_verbose)
{
if (!sgi_nports)
{
post("no serial ports are configured for MIDI;");
post("if you want to use MIDI, try exiting Pd, typing");
post("'startmidi -d /dev/ttyd2' to a shell, and restarting Pd.");
}
else if (sgi_nports == 1)
post("Found one MIDI port on %s", mdGetName(0));
else if (sgi_nports == 2)
post("Found MIDI ports on %s and %s",
mdGetName(0), mdGetName(1));
}
if (midiin)
{
for (i = 0; i < sgi_nports; i++)
{
if (!(sgi_inport[i] = mdOpenInPort(mdGetName(i))))
error("MIDI input port %d: open failed", i+1);;
}
}
if (midiout)
{
for (i = 0; i < sgi_nports; i++)
{
if (!(sgi_outport[i] = mdOpenOutPort(mdGetName(i))))
error("MIDI output port %d: open failed", i+1);;
}
}
return;
}
void sys_putmidimess(int portno, int a, int b, int c)
{
MDevent mdv;
if (portno >= NPORT || portno < 0 || !sgi_outport[portno]) return;
mdv.msg[0] = a;
mdv.msg[1] = b;
mdv.msg[2] = c;
mdv.msg[3] = 0;
mdv.sysexmsg = 0;
mdv.stamp = 0;
mdv.msglen = 0;
if (mdSend(sgi_outport[portno], &mdv, 1) < 0)
error("MIDI output error\n");
post("msg out %d %d %d", a, b, c);
}
void sys_putmidibyte(int portno, int foo)
{
error("MIDI raw byte output not available on SGI");
}
void inmidi_noteon(int portno, int channel, int pitch, int velo);
void inmidi_controlchange(int portno, int channel, int ctlnumber, int value);
void inmidi_programchange(int portno, int channel, int value);
void inmidi_pitchbend(int portno, int channel, int value);
void inmidi_aftertouch(int portno, int channel, int value);
void inmidi_polyaftertouch(int portno, int channel, int pitch, int value);
void sys_poll_midi(void)
{
int i;
MDport *mp;
for (i = 0, mp = sgi_inport; i < NPORT; i++, mp++)
{
int ret, status, b1, b2, nfds;
MDevent mdv;
fd_set inports;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (!*mp) continue;
FD_ZERO(&inports);
FD_SET(mdGetFd(*mp), &inports);
if (select(mdGetFd(*mp)+1 , &inports, 0, 0, &timeout) < 0)
perror("midi select");
if (FD_ISSET(mdGetFd(*mp),&inports))
{
if (mdReceive(*mp, &mdv, 1) < 0)
error("failure receiving message\n");
else if (mdv.msg[0] == MD_SYSEX) mdFree(mdv.sysexmsg);
else
{
int status = mdv.msg[0];
int channel = (status & 0xf) + 1;
int b1 = mdv.msg[1];
int b2 = mdv.msg[2];
switch(status & 0xf0)
{
case MD_NOTEOFF:
inmidi_noteon(i, channel, b1, 0);
break;
case MD_NOTEON:
inmidi_noteon(i, channel, b1, b2);
break;
case MD_POLYKEYPRESSURE:
inmidi_polyaftertouch(i, channel, b1, b2);
break;
case MD_CONTROLCHANGE:
inmidi_controlchange(i, channel, b1, b2);
break;
case MD_PITCHBENDCHANGE:
inmidi_pitchbend(i, channel, ((b2 << 7) + b1));
break;
case MD_PROGRAMCHANGE:
inmidi_programchange(i, channel, b1);
break;
case MD_CHANNELPRESSURE:
inmidi_aftertouch(i, channel, b1);
break;
}
}
}
}
}
void sys_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec)
{
sgi_open_midi(nmidiin!=0, nmidiout!=0);
}
void sys_close_midi( void)
{
/* ??? */
}
void sys_set_priority(int foo)
{
fprintf(stderr,
"warning: priority boosting in IRIX not implemented yet\n");
}

View file

@ -1,48 +0,0 @@
/* Copyright (c) 1997-2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* This file is compiled into the separate program, "pd-watchdog," which
tries to prevent Pd from locking up the processor if it's at realtime
priority. Linux only. Invoked from s_inter.c. */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int happy = 1;
while (1)
{
struct timeval timout;
fd_set readset;
if (happy)
{
timout.tv_sec = 5;
timout.tv_usec = 0;
}
else
{
timout.tv_sec = 2;
timout.tv_usec = 0;
}
FD_ZERO(&readset);
FD_SET(0, &readset);
select(1, &readset, 0, 0, &timout);
if (FD_ISSET(0, &readset))
{
char buf[100];
happy = 1;
if (read(0, &buf, 100) <= 0)
return (0);
else continue;
}
happy = 0;
kill(getppid(), SIGHUP);
fprintf(stderr, "watchdog: signaling pd...\n");
}
}

View file

@ -1,121 +0,0 @@
/* 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. */
/* This file should be compared with the corresponding thing in the TK
* distribution whenever updating to newer versions of TCL/TK. */
/*
* Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef MACOSX /* linux and IRIX only; in MACOSX we don't link this in */
#include "tk.h"
#include <stdlib.h>
/*
* The following variable is a special hack that is needed in order for
* Sun shared libraries to be used for Tcl.
*/
extern int matherr(void);
int *tclDummyMathPtr = (int *) matherr;
/*
*----------------------------------------------------------------------
*
* main --
*
* This is the main program for the application.
*
* Results:
* None: Tk_Main never returns here, so this procedure never
* returns either.
*
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
void pdgui_startup(Tcl_Interp *interp);
void pdgui_setname(char *name);
void pdgui_setsock(int port);
void pdgui_sethost(char *name);
int
main(int argc, char **argv)
{
pdgui_setname(argv[0]);
if (argc >= 2)
{
pdgui_setsock(atoi(argv[1]));
argc--; argv++;
argv[0] = "Pd";
}
if (argc >= 2)
{
pdgui_sethost(argv[1]);
argc--; argv++;
argv[0] = "Pd";
}
Tk_Main(argc, argv, Tcl_AppInit);
return 0; /* Needed only to prevent compiler warning. */
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppInit --
*
* This procedure performs application-specific initialization.
* Most applications, especially those that incorporate additional
* packages, will have their own version of this procedure.
* Results:
* Returns a standard Tcl completion code, and leaves an error
* message in interp->result if an error occurs.
*
* Side effects:
* Depends on the startup script.
*
*----------------------------------------------------------------------
*/
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
if (Tk_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
/* setup specific to pd-gui: */
pdgui_startup(interp);
/*
* Specify a user-specific startup file to invoke if the application
* is run interactively. Typically the startup file is "~/.apprc"
* where "app" is the name of the application. If this line is deleted
* then no user-specific startup file will be run under any conditions.
*/
#if 0
tcl_RcFileName = "~/.pdrc";
#endif
return TCL_OK;
}
#endif /* MACOSX */

View file

@ -1,398 +0,0 @@
/* 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. */
#ifdef UNIX /* in unix this only works first; in NT it only works last. */
#include "tk.h"
#endif
#include "t_tk.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#ifdef UNIX
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef HAVE_BSTRING_H
#include <bstring.h>
#endif
#include <sys/time.h>
#include <errno.h>
#endif
#ifdef MSW
#include <winsock.h>
#include <io.h>
#endif
#ifdef MSW
#pragma warning( disable : 4305 ) /* uncast const double to float */
#pragma warning( disable : 4244 ) /* uncast double to float */
#pragma warning( disable : 4101 ) /* unused local variables */
#endif
#ifdef MSW
#include "tk.h"
#endif
void tcl_mess(char *s);
/***************** the socket setup code ********************/
static int portno = 5400;
/* some installations of linux don't know about "localhost" so give
the loopback address; NT, on the other hand, can't understand the
hostname "127.0.0.1". */
char hostname[100] =
#ifdef __linux__
"127.0.0.1";
#else
"localhost";
#endif
void pdgui_setsock(int port)
{
portno = port;
}
void pdgui_sethost(char *name)
{
strncpy(hostname, name, 100);
hostname[99] = 0;
}
static void pdgui_sockerror(char *s)
{
#ifdef MSW
int err = WSAGetLastError();
#endif
#ifdef UNIX
int err = errno;
#endif
fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
tcl_mess("exit\n");
exit(1);
}
static int sockfd;
/* The "pd_suck" command, which polls the socket.
FIXME: if Pd sends something bigger than SOCKSIZE we're in trouble!
This has to be set bigger than any array update message for instance.
*/
#define SOCKSIZE 20000
static char pd_tkbuf[SOCKSIZE+1];
int pd_spillbytes = 0;
static void pd_readsocket(ClientData cd, int mask)
{
int ngot;
fd_set readset, writeset, exceptset;
struct timeval timout;
timout.tv_sec = 0;
timout.tv_usec = 0;
FD_ZERO(&writeset);
FD_ZERO(&readset);
FD_ZERO(&exceptset);
FD_SET(sockfd, &readset);
FD_SET(sockfd, &exceptset);
if (select(sockfd+1, &readset, &writeset, &exceptset, &timout) < 0)
perror("select");
if (FD_ISSET(sockfd, &exceptset) || FD_ISSET(sockfd, &readset))
{
int ret;
ret = recv(sockfd, pd_tkbuf + pd_spillbytes,
SOCKSIZE - pd_spillbytes, 0);
if (ret < 0) pdgui_sockerror("socket receive error");
else if (ret == 0)
{
/* fprintf(stderr, "read %d\n", SOCKSIZE - pd_spillbytes); */
fprintf(stderr, "pd_gui: pd process exited\n");
tcl_mess("exit\n");
}
else
{
char *lastcr = 0, *bp = pd_tkbuf, *ep = bp + (pd_spillbytes + ret);
int brace = 0;
char lastc = 0;
while (bp < ep)
{
char c = *bp;
if (c == '}' && brace) brace--;
else if (c == '{') brace++;
else if (!brace && c == '\n' && lastc != '\\') lastcr = bp;
lastc = c;
bp++;
}
if (lastcr)
{
int xtra = pd_tkbuf + pd_spillbytes + ret - (lastcr+1);
char bashwas = lastcr[1];
lastcr[1] = 0;
tcl_mess(pd_tkbuf);
lastcr[1] = bashwas;
if (xtra)
{
/* fprintf(stderr, "x %d\n", xtra); */
memmove(pd_tkbuf, lastcr+1, xtra);
}
pd_spillbytes = xtra;
}
else
{
pd_spillbytes += ret;
}
}
}
}
#ifndef UNIX
/* if we aren't UNIX, we add a tcl command to poll the
socket for data. */
static int pd_pollsocketCmd(ClientData cd, Tcl_Interp *interp,
int argc, char **argv)
{
pd_readsocket(cd, 0);
return (TCL_OK);
}
#endif
void pdgui_setupsocket(void)
{
struct sockaddr_in server;
struct hostent *hp;
#ifdef UNIX
int retry = 10;
#else
int retry = 1;
#endif
#ifdef MSW
short version = MAKEWORD(2, 0);
WSADATA nobby;
if (WSAStartup(version, &nobby)) pdgui_sockerror("setup");
#endif
/* create a socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) pdgui_sockerror("socket");
/* connect socket using hostname provided in command line */
server.sin_family = AF_INET;
hp = gethostbyname(hostname);
if (hp == 0)
{
fprintf(stderr,
"localhost not found (inet protocol not installed?)\n");
exit(1);
}
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
/* assign client port number */
server.sin_port = htons((unsigned short)portno);
/* try to connect */
while (1)
{
if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) >= 0)
goto gotit;
retry--;
if (retry <= 0)
break;
/* In UNIX there's a race condition; the child won't be
able to connect before the parent (pd) has shed its
setuid-ness. In case this is the problem, sleep and
retry. */
else
{
#ifdef UNIX
fd_set readset, writeset, exceptset;
struct timeval timout;
timout.tv_sec = 0;
timout.tv_usec = 100000;
FD_ZERO(&writeset);
FD_ZERO(&readset);
FD_ZERO(&exceptset);
fprintf(stderr, "retrying connect...\n");
if (select(1, &readset, &writeset, &exceptset, &timout) < 0)
perror("select");
#endif /* UNIX */
}
}
pdgui_sockerror("connecting stream socket");
gotit: ;
#ifdef UNIX
/* in unix we ask TK to call us back. In NT we have to poll. */
Tk_CreateFileHandler(sockfd, TK_READABLE | TK_EXCEPTION,
pd_readsocket, 0);
#endif /* UNIX */
}
/**************************** commands ************************/
static char *pdgui_path;
/* The "pd" command, which cats its args together and throws the result
* at the Pd interpreter.
*/
#define MAXWRITE 1024
static int pdCmd(ClientData cd, Tcl_Interp *interp, int argc, char **argv)
{
if (argc == 2)
{
int n = strlen(argv[1]);
if (send(sockfd, argv[1], n, 0) < n)
{
perror("stdout");
tcl_mess("exit\n");
}
}
else
{
int i;
char buf[MAXWRITE];
buf[0] = 0;
for (i = 1; i < argc; i++)
{
if (strlen(argv[i]) + strlen(buf) + 2 > MAXWRITE)
{
interp->result = "pd: arg list too long";
return (TCL_ERROR);
}
if (i > 1) strcat(buf, " ");
strcat(buf, argv[i]);
}
if (send(sockfd, buf, strlen(buf), 0) < 0)
{
perror("stdout");
tcl_mess("exit\n");
}
}
return (TCL_OK);
}
/*********** "c" level access to tk functions. ******************/
static Tcl_Interp *tk_myinterp;
void tcl_mess(char *s)
{
int result;
result = Tcl_Eval(tk_myinterp, s);
if (result != TCL_OK)
{
if (*tk_myinterp->result) printf("%s\n", tk_myinterp->result);
}
}
/* LATER should do a bounds check -- but how do you get printf to do that? */
void tcl_vmess(char *fmt, ...)
{
int result, i;
char buf[MAXWRITE];
va_list ap;
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
result = Tcl_Eval(tk_myinterp, buf);
if (result != TCL_OK)
{
if (*tk_myinterp->result) printf("%s\n", tk_myinterp->result);
}
va_end(ap);
}
#ifdef UNIX
void pdgui_doevalfile(Tcl_Interp *interp, char *s)
{
char buf[GUISTRING];
sprintf(buf, "set pd_guidir \"%s\"\n", pdgui_path);
tcl_mess(buf);
strcpy(buf, pdgui_path);
strcat(buf, "/bin/");
strcat(buf, s);
if (Tcl_EvalFile(interp, buf) != TCL_OK)
{
char buf2[1000];
sprintf(buf2, "puts [concat tcl: %s: can't open script]\n",
buf);
tcl_mess(buf2);
}
}
void pdgui_evalfile(char *s)
{
pdgui_doevalfile(tk_myinterp, s);
}
#endif
void pdgui_startup(Tcl_Interp *interp)
{
/* save pointer to the main interpreter */
tk_myinterp = interp;
/* add our own TK commands */
Tcl_CreateCommand(interp, "pd", (Tcl_CmdProc*)pdCmd, (ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL);
#ifndef UNIX
Tcl_CreateCommand(interp, "pd_pollsocket",(Tcl_CmdProc*) pd_pollsocketCmd,
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
#endif
pdgui_setupsocket();
/* read in the startup file */
#if !defined(MSW) && !defined(MACOSX)
pdgui_evalfile("pd.tk");
#endif
}
#ifdef UNIX
void pdgui_setname(char *s)
{
char *t;
char *str;
int n;
if (t = strrchr(s, '/')) str = s, n = (t-s) + 1;
else str = "./", n = 2;
if (n > GUISTRING-100) n = GUISTRING-100;
pdgui_path = malloc(n+9);
strncpy(pdgui_path, str, n);
while (strlen(pdgui_path) > 0 && pdgui_path[strlen(pdgui_path)-1] == '/')
pdgui_path[strlen(pdgui_path)-1] = 0;
if (t = strrchr(pdgui_path, '/'))
*t = 0;
}
#endif
int Pdtcl_Init(Tcl_Interp *interp)
{
const char *myvalue = Tcl_GetVar(interp, "argv", 0);
int myportno;
if (myvalue && (myportno = atoi(myvalue)) > 1)
pdgui_setsock(myportno);
tk_myinterp = interp;
pdgui_startup(interp);
interp->result = "loaded pdtcl_init";
return (TCL_OK);
}
int Pdtcl_SafeInit(Tcl_Interp *interp) {
fprintf(stderr, "Pdtcl_Safeinit 51\n");
return (TCL_OK);
}

File diff suppressed because it is too large Load diff

View file

@ -1,326 +0,0 @@
/* Copyright (c) 2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */
/* the "pdreceive" command. This is a standalone program that receives messages
from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to
standard output. */
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#ifdef UNIX
#include <sys/time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SOCKET_ERROR -1
#else
#include <winsock.h>
#endif
typedef struct _fdpoll
{
int fdp_fd;
char *fdp_inbuf;
int fdp_inhead;
int fdp_intail;
int fdp_udp;
} t_fdpoll;
static int nfdpoll;
static t_fdpoll *fdpoll;
static int maxfd;
static int sockfd;
static int protocol;
static void sockerror(char *s);
static void x_closesocket(int fd);
static void dopoll(void);
#define BUFSIZE 4096
int main(int argc, char **argv)
{
int portno;
struct sockaddr_in server;
int nretry = 10;
#ifdef MSW
short version = MAKEWORD(2, 0);
WSADATA nobby;
#endif
if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0)
goto usage;
if (argc >= 3)
{
if (!strcmp(argv[2], "tcp"))
protocol = SOCK_STREAM;
else if (!strcmp(argv[2], "udp"))
protocol = SOCK_DGRAM;
else goto usage;
}
else protocol = SOCK_STREAM;
#ifdef MSW
if (WSAStartup(version, &nobby)) sockerror("WSAstartup");
#endif
sockfd = socket(AF_INET, protocol, 0);
if (sockfd < 0)
{
sockerror("socket()");
exit(1);
}
maxfd = sockfd + 1;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
#ifdef IRIX
/* this seems to work only in IRIX but is unnecessary in
Linux. Not sure what MSW needs in place of this. */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
post("setsockopt failed\n");
#endif
/* assign client port number */
server.sin_port = htons((unsigned short)portno);
/* name the socket */
if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
{
sockerror("bind");
x_closesocket(sockfd);
return (0);
}
if (protocol == SOCK_STREAM)
{
if (listen(sockfd, 5) < 0)
{
sockerror("listen");
x_closesocket(sockfd);
exit(1);
}
}
/* now loop forever selecting on sockets */
while (1)
dopoll();
usage:
fprintf(stderr, "usage: pdreceive <portnumber> [udp|tcp]\n");
fprintf(stderr, "(default is tcp)\n");
exit(1);
}
static void addport(int fd)
{
int nfd = nfdpoll;
t_fdpoll *fp;
fdpoll = (t_fdpoll *)realloc(fdpoll,
(nfdpoll+1) * sizeof(t_fdpoll));
fp = fdpoll + nfdpoll;
fp->fdp_fd = fd;
nfdpoll++;
if (fd >= maxfd) maxfd = fd + 1;
fp->fdp_inhead = fp->fdp_intail = 0;
if (!(fp->fdp_inbuf = malloc(BUFSIZE)))
{
fprintf(stderr, "out of memory");
exit(1);
}
printf("number_connected %d;\n", nfdpoll);
}
static void rmport(t_fdpoll *x)
{
int nfd = nfdpoll;
int i, size = nfdpoll * sizeof(t_fdpoll);
t_fdpoll *fp;
for (i = nfdpoll, fp = fdpoll; i--; fp++)
{
if (fp == x)
{
x_closesocket(fp->fdp_fd);
free(fp->fdp_inbuf);
while (i--)
{
fp[0] = fp[1];
fp++;
}
fdpoll = (t_fdpoll *)realloc(fdpoll,
(nfdpoll-1) * sizeof(t_fdpoll));
nfdpoll--;
printf("number_connected %d;\n", nfdpoll);
return;
}
}
fprintf(stderr, "warning: item removed from poll list but not found");
}
static void doconnect(void)
{
int fd = accept(sockfd, 0, 0);
if (fd < 0)
perror("accept");
else addport(fd);
}
static void udpread(void)
{
char buf[BUFSIZE];
int ret = recv(sockfd, buf, BUFSIZE, 0);
if (ret < 0)
{
sockerror("recv (udp)");
x_closesocket(sockfd);
exit(1);
}
else if (ret > 0)
{
#ifdef UNIX
if (write(1, buf, ret) < ret)
{
perror("write");
exit(1);
}
#else
int j;
for (j = 0; j < ret; j++)
putchar(buf[j]);
#endif
}
}
static int tcpmakeoutput(t_fdpoll *x)
{
char messbuf[BUFSIZE+1], *bp = messbuf;
int indx;
int inhead = x->fdp_inhead;
int intail = x->fdp_intail;
char *inbuf = x->fdp_inbuf;
if (intail == inhead)
return (0);
for (indx = intail; indx != inhead; indx = (indx+1)&(BUFSIZE-1))
{
/* search for a semicolon. */
char c = *bp++ = inbuf[indx];
if (c == ';')
{
intail = (indx+1)&(BUFSIZE-1);
if (inbuf[intail] == '\n')
intail = (intail+1)&(BUFSIZE-1);
*bp++ = '\n';
#ifdef UNIX
write(1, messbuf, bp - messbuf);
#else
{
int j;
for (j = 0; j < bp - messbuf; j++)
putchar(messbuf[j]);
}
#endif
x->fdp_inhead = inhead;
x->fdp_intail = intail;
return (1);
}
}
return (0);
}
static void tcpread(t_fdpoll *x)
{
int readto =
(x->fdp_inhead >= x->fdp_intail ? BUFSIZE : x->fdp_intail-1);
int ret;
/* the input buffer might be full. If so, drop the whole thing */
if (readto == x->fdp_inhead)
{
fprintf(stderr, "pd: dropped message from gui\n");
x->fdp_inhead = x->fdp_intail = 0;
readto = BUFSIZE;
}
else
{
ret = recv(x->fdp_fd, x->fdp_inbuf + x->fdp_inhead,
readto - x->fdp_inhead, 0);
if (ret < 0)
{
sockerror("recv (tcp)");
rmport(x);
}
else if (ret == 0)
rmport(x);
else
{
x->fdp_inhead += ret;
if (x->fdp_inhead >= BUFSIZE)
x->fdp_inhead = 0;
while (tcpmakeoutput(x))
;
}
}
}
static void dopoll(void)
{
int i;
t_fdpoll *fp;
fd_set readset, writeset, exceptset;
FD_ZERO(&writeset);
FD_ZERO(&readset);
FD_ZERO(&exceptset);
FD_SET(sockfd, &readset);
if (protocol == SOCK_STREAM)
{
for (fp = fdpoll, i = nfdpoll; i--; fp++)
FD_SET(fp->fdp_fd, &readset);
}
if (select(maxfd+1, &readset, &writeset, &exceptset, 0) < 0)
{
perror("select");
exit(1);
}
if (protocol == SOCK_STREAM)
{
for (i = 0; i < nfdpoll; i++)
if (FD_ISSET(fdpoll[i].fdp_fd, &readset))
tcpread(&fdpoll[i]);
if (FD_ISSET(sockfd, &readset))
doconnect();
}
else
{
if (FD_ISSET(sockfd, &readset))
udpread();
}
}
static void sockerror(char *s)
{
#ifdef MSW
int err = WSAGetLastError();
if (err == 10054) return;
else if (err == 10044)
{
fprintf(stderr,
"Warning: you might not have TCP/IP \"networking\" turned on\n");
}
#endif
#ifdef UNIX
int err = errno;
#endif
fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
}
static void x_closesocket(int fd)
{
#ifdef UNIX
close(fd);
#endif
#ifdef MSW
closesocket(fd);
#endif
}

View file

@ -1,158 +0,0 @@
/* Copyright (c) 2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */
/* the "pdsend" command. This is a standalone program that forwards messages
from its standard input to Pd via the netsend/netreceive ("FUDI") protocol. */
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#ifdef UNIX
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SOCKET_ERROR -1
#else
#include <winsock.h>
#endif
void sockerror(char *s);
void x_closesocket(int fd);
#define BUFSIZE 4096
int main(int argc, char **argv)
{
int sockfd, portno, protocol;
struct sockaddr_in server;
struct hostent *hp;
char *hostname;
int nretry = 10;
#ifdef MSW
short version = MAKEWORD(2, 0);
WSADATA nobby;
#endif
if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0)
goto usage;
if (argc >= 3)
hostname = argv[2];
else hostname = "127.0.0.1";
if (argc >= 4)
{
if (!strcmp(argv[3], "tcp"))
protocol = SOCK_STREAM;
else if (!strcmp(argv[3], "udp"))
protocol = SOCK_DGRAM;
else goto usage;
}
else protocol = SOCK_STREAM;
#ifdef MSW
if (WSAStartup(version, &nobby)) sockerror("WSAstartup");
#endif
sockfd = socket(AF_INET, protocol, 0);
if (sockfd < 0)
{
sockerror("socket()");
exit(1);
}
/* connect socket using hostname provided in command line */
server.sin_family = AF_INET;
hp = gethostbyname(hostname);
if (hp == 0)
{
fprintf(stderr, "%s: unknown host\n", hostname);
x_closesocket(sockfd);
exit(1);
}
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
/* assign client port number */
server.sin_port = htons((unsigned short)portno);
#if 0 /* try this again for 4.0; this crashed my RH 6.2 machine!) */
/* try to connect. */
for (nretry = 0; nretry < (protocol == SOCK_STREAM ? 10 : 1); nretry++)
{
if (nretry > 0)
{
sleep (nretry < 5 ? 1 : 5);
fprintf(stderr, "retrying...");
}
if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) >= 0)
goto connected;
sockerror("connect");
}
x_closesocket(sockfd);
exit(1);
connected: ;
#else
/* try to connect. */
if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
{
sockerror("connect");
x_closesocket(sockfd);
exit(1);
}
#endif
/* now loop reading stdin and sending it to socket */
while (1)
{
char buf[BUFSIZE], *bp, nsent, nsend;
if (!fgets(buf, BUFSIZE, stdin))
break;
nsend = strlen(buf);
for (bp = buf, nsent = 0; nsent < nsend;)
{
int res = send(sockfd, buf, nsend-nsent, 0);
if (res < 0)
{
sockerror("send");
goto done;
}
nsent += res;
bp += res;
}
}
done:
if (ferror(stdin))
perror("stdin");
exit (0);
usage:
fprintf(stderr, "usage: pdsend <portnumber> [host] [udp|tcp]\n");
fprintf(stderr, "(default is localhost and tcp)\n");
exit(1);
}
void sockerror(char *s)
{
#ifdef MSW
int err = WSAGetLastError();
if (err == 10054) return;
else if (err == 10044)
{
fprintf(stderr,
"Warning: you might not have TCP/IP \"networking\" turned on\n");
}
#endif
#ifdef UNIX
int err = errno;
#endif
fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
}
void x_closesocket(int fd)
{
#ifdef UNIX
close(fd);
#endif
#ifdef MSW
closesocket(fd);
#endif
}

View file

@ -1,378 +0,0 @@
/* Copyright (c) 1997-2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* dialogs. LATER, deal with the situation where the object goes
away before the panel does... */
#include "m_pd.h"
#include <stdio.h>
#include <string.h>
#ifdef UNIX
#include <unistd.h>
#endif
/* --------------------- graphics responder ---------------- */
/* make one of these if you want to put up a dialog window but want to be
protected from getting deleted and then having the dialog call you back. In
this design the calling object doesn't have to keep the address of the dialog
window around; instead we keep a list of all open dialogs. Any object that
might have dialogs, when it is deleted, simply checks down the dialog window
list and breaks off any dialogs that might later have sent messages to it.
Only when the dialog window itself closes do we delete the gfxstub object. */
static t_class *gfxstub_class;
typedef struct _gfxstub
{
t_pd x_pd;
t_pd *x_owner;
void *x_key;
t_symbol *x_sym;
struct _gfxstub *x_next;
} t_gfxstub;
static t_gfxstub *gfxstub_list;
/* create a new one. the "key" is an address by which the owner
will identify it later; if the owner only wants one dialog, this
could just be a pointer to the owner itself. The string "cmd"
is a TK command to create the dialog, with "%s" embedded in
it so we can provide a name by which the GUI can send us back
messages; e.g., "pdtk_canvas_dofont %s 10". */
void gfxstub_new(t_pd *owner, void *key, const char *cmd)
{
char buf[MAXPDSTRING];
char namebuf[80];
t_gfxstub *x;
t_symbol *s;
/* if any exists with matching key, no need to make a
new one; just tell tk to send it front. */
for (x = gfxstub_list; x; x = x->x_next)
{
if (x->x_key == key)
{
sys_vgui("raise .gfxstub%x\n", x);
sys_vgui("focus .gfxstub%x\n", x);
return;
}
}
if (strlen(cmd) + 84 > MAXPDSTRING)
return;
x = (t_gfxstub *)pd_new(gfxstub_class);
sprintf(namebuf, ".gfxstub%x", (t_int)x);
s = gensym(namebuf);
pd_bind(&x->x_pd, s);
x->x_owner = owner;
x->x_sym = s;
x->x_key = key;
x->x_next = gfxstub_list;
gfxstub_list = x;
sprintf(buf, cmd, s->s_name);
sys_gui(buf);
}
static void gfxstub_offlist(t_gfxstub *x)
{
t_gfxstub *y1, *y2;
if (gfxstub_list == x)
gfxstub_list = x->x_next;
else for (y1 = gfxstub_list; y2 = y1->x_next; y1 = y2)
if (y2 == x)
{
y1->x_next = y2->x_next;
break;
}
}
/* if the owner disappears, we still may have to stay around until our
dialog window signs off. Anyway we can now tell the GUI to destroy the
window. */
void gfxstub_deleteforkey(void *key)
{
t_gfxstub *y;
int didit = 1;
while (didit)
{
didit = 0;
for (y = gfxstub_list; y; y = y->x_next)
{
if (y->x_key == key)
{
sys_vgui("destroy .gfxstub%x\n", y);
y->x_owner = 0;
gfxstub_offlist(y);
didit = 1;
break;
}
}
}
}
/* --------- pd messages for gfxstub (these come from the GUI) ---------- */
/* "cancel" to request that we close the dialog window. */
static void gfxstub_cancel(t_gfxstub *x)
{
gfxstub_deleteforkey(x->x_key);
}
/* "signoff" comes from the GUI to say the dialog window closed. */
static void gfxstub_signoff(t_gfxstub *x)
{
gfxstub_offlist(x);
pd_free(&x->x_pd);
}
static t_binbuf *gfxstub_binbuf;
/* a series of "data" messages rebuilds a scalar */
static void gfxstub_data(t_gfxstub *x, t_symbol *s, int argc, t_atom *argv)
{
if (!gfxstub_binbuf)
gfxstub_binbuf = binbuf_new();
binbuf_add(gfxstub_binbuf, argc, argv);
binbuf_addsemi(gfxstub_binbuf);
}
/* the "end" message terminates rebuilding the scalar */
static void gfxstub_end(t_gfxstub *x)
{
canvas_dataproperties((t_canvas *)x->x_owner,
(t_scalar *)x->x_key, gfxstub_binbuf);
binbuf_free(gfxstub_binbuf);
gfxstub_binbuf = 0;
}
/* anything else is a message from the dialog window to the owner;
just forward it. */
static void gfxstub_anything(t_gfxstub *x, t_symbol *s, int argc, t_atom *argv)
{
if (x->x_owner)
pd_typedmess(x->x_owner, s, argc, argv);
}
static void gfxstub_free(t_gfxstub *x)
{
pd_unbind(&x->x_pd, x->x_sym);
}
static void gfxstub_setup(void)
{
gfxstub_class = class_new(gensym("gfxstub"), (t_newmethod)gfxstub_new,
(t_method)gfxstub_free,
sizeof(t_gfxstub), CLASS_PD, 0);
class_addanything(gfxstub_class, gfxstub_anything);
class_addmethod(gfxstub_class, (t_method)gfxstub_signoff,
gensym("signoff"), 0);
class_addmethod(gfxstub_class, (t_method)gfxstub_data,
gensym("data"), A_GIMME, 0);
class_addmethod(gfxstub_class, (t_method)gfxstub_end,
gensym("end"), 0);
class_addmethod(gfxstub_class, (t_method)gfxstub_cancel,
gensym("cancel"), 0);
}
/* -------------------------- openpanel ------------------------------ */
static t_class *openpanel_class;
typedef struct _openpanel
{
t_object x_obj;
t_symbol *x_s;
} t_openpanel;
static void *openpanel_new(void)
{
char buf[50];
t_openpanel *x = (t_openpanel *)pd_new(openpanel_class);
sprintf(buf, "d%x", (t_int)x);
x->x_s = gensym(buf);
pd_bind(&x->x_obj.ob_pd, x->x_s);
outlet_new(&x->x_obj, &s_symbol);
return (x);
}
static void openpanel_bang(t_openpanel *x)
{
sys_vgui("pdtk_openpanel %s\n", x->x_s->s_name);
}
static void openpanel_symbol(t_openpanel *x, t_symbol *s)
{
outlet_symbol(x->x_obj.ob_outlet, s);
}
static void openpanel_free(t_openpanel *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_s);
}
static void openpanel_setup(void)
{
openpanel_class = class_new(gensym("openpanel"),
(t_newmethod)openpanel_new, (t_method)openpanel_free,
sizeof(t_openpanel), 0, A_DEFFLOAT, 0);
class_addbang(openpanel_class, openpanel_bang);
class_addsymbol(openpanel_class, openpanel_symbol);
}
/* -------------------------- savepanel ------------------------------ */
static t_class *savepanel_class;
typedef struct _savepanel
{
t_object x_obj;
t_symbol *x_s;
} t_savepanel;
static void *savepanel_new(void)
{
char buf[50];
t_savepanel *x = (t_savepanel *)pd_new(savepanel_class);
sprintf(buf, "d%x", (t_int)x);
x->x_s = gensym(buf);
pd_bind(&x->x_obj.ob_pd, x->x_s);
outlet_new(&x->x_obj, &s_symbol);
return (x);
}
static void savepanel_bang(t_savepanel *x)
{
sys_vgui("pdtk_savepanel %s\n", x->x_s->s_name);
}
static void savepanel_symbol(t_savepanel *x, t_symbol *s)
{
outlet_symbol(x->x_obj.ob_outlet, s);
}
static void savepanel_free(t_savepanel *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_s);
}
static void savepanel_setup(void)
{
savepanel_class = class_new(gensym("savepanel"),
(t_newmethod)savepanel_new, (t_method)savepanel_free,
sizeof(t_savepanel), 0, A_DEFFLOAT, 0);
class_addbang(savepanel_class, savepanel_bang);
class_addsymbol(savepanel_class, savepanel_symbol);
}
/* ---------------------- key and its relatives ------------------ */
static t_symbol *key_sym, *keyup_sym, *keyname_sym;
static t_class *key_class, *keyup_class, *keyname_class;
typedef struct _key
{
t_object x_obj;
} t_key;
static void *key_new( void)
{
t_key *x = (t_key *)pd_new(key_class);
outlet_new(&x->x_obj, &s_float);
pd_bind(&x->x_obj.ob_pd, key_sym);
return (x);
}
static void key_float(t_key *x, t_floatarg f)
{
outlet_float(x->x_obj.ob_outlet, f);
}
static void key_free(t_key *x)
{
pd_unbind(&x->x_obj.ob_pd, key_sym);
}
typedef struct _keyup
{
t_object x_obj;
} t_keyup;
static void *keyup_new( void)
{
t_keyup *x = (t_keyup *)pd_new(keyup_class);
outlet_new(&x->x_obj, &s_float);
pd_bind(&x->x_obj.ob_pd, keyup_sym);
return (x);
}
static void keyup_float(t_keyup *x, t_floatarg f)
{
outlet_float(x->x_obj.ob_outlet, f);
}
static void keyup_free(t_keyup *x)
{
pd_unbind(&x->x_obj.ob_pd, keyup_sym);
}
typedef struct _keyname
{
t_object x_obj;
t_outlet *x_outlet1;
t_outlet *x_outlet2;
} t_keyname;
static void *keyname_new( void)
{
t_keyname *x = (t_keyname *)pd_new(keyname_class);
x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol);
pd_bind(&x->x_obj.ob_pd, keyname_sym);
return (x);
}
static void keyname_list(t_keyname *x, t_symbol *s, int ac, t_atom *av)
{
outlet_symbol(x->x_outlet2, atom_getsymbolarg(1, ac, av));
outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av));
}
static void keyname_free(t_keyname *x)
{
pd_unbind(&x->x_obj.ob_pd, keyname_sym);
}
static void key_setup(void)
{
key_class = class_new(gensym("key"),
(t_newmethod)key_new, (t_method)key_free,
sizeof(t_key), CLASS_NOINLET, 0);
class_addfloat(key_class, key_float);
key_sym = gensym("#key");
keyup_class = class_new(gensym("keyup"),
(t_newmethod)keyup_new, (t_method)keyup_free,
sizeof(t_keyup), CLASS_NOINLET, 0);
class_addfloat(keyup_class, keyup_float);
keyup_sym = gensym("#keyup");
class_sethelpsymbol(keyup_class, gensym("key"));
keyname_class = class_new(gensym("keyname"),
(t_newmethod)keyname_new, (t_method)keyname_free,
sizeof(t_keyname), CLASS_NOINLET, 0);
class_addlist(keyname_class, keyname_list);
keyname_sym = gensym("#keyname");
class_sethelpsymbol(keyname_class, gensym("key"));
}
/* -------------------------- setup routine ------------------------------ */
void x_gui_setup(void)
{
gfxstub_setup();
openpanel_setup();
savepanel_setup();
key_setup();
}

File diff suppressed because it is too large Load diff

View file

@ -3,12 +3,21 @@ pdbox-net.c
pdbox-func.c
pdbox-gui.c
/*
wfirstfit.c
*/
PDa/src/s_audio_rockbox.c
PDa/src/d_ugen.c
PDa/src/d_arithmetic.c
PDa/src/d_dac.c
PDa/src/d_misc.c
PDa/src/d_fft.c
PDa/src/d_imayer_fft.c
PDa/src/d_mayer_fft.c
PDa/src/d_fftroutine.c
PDa/src/d_global.c
PDa/src/d_resample.c
PDa/src/d_ctl.c
PDa/src/d_soundfile.c
PDa/src/g_canvas.c
PDa/src/g_graph.c
PDa/src/g_text.c
@ -31,57 +40,32 @@ PDa/src/g_toggle.c
PDa/src/g_vdial.c
PDa/src/g_vslider.c
PDa/src/g_vumeter.c
PDa/src/m_pd.c
PDa/src/m_class.c
PDa/src/m_obj.c
PDa/src/m_atom.c
PDa/src/m_memory.c
PDa/src/m_binbuf.c
PDa/src/m_conf.c
PDa/src/m_glob.c
PDa/src/m_sched.c
/* PDa/src/s_main.c Does not compile, system reasons */
/* PDa/src/s_inter.c Does not compile, BSD sockets */
PDa/src/m_fixed.c
PDa/src/s_file.c
PDa/src/s_print.c
PDa/src/s_loader.c
PDa/src/s_path.c
/*
PDa/src/s_entry.c
*/
PDa/src/s_audio.c
/*
PDa/src/s_midi.c
*/
PDa/src/d_ugen.c
PDa/src/d_arithmetic.c
PDa/src/d_dac.c
PDa/src/d_misc.c
PDa/src/d_fft.c
PDa/src/d_mayer_fft.c
PDa/src/d_fftroutine.c
PDa/src/d_global.c
PDa/src/d_resample.c
PDa/src/d_ctl.c
PDa/src/d_soundfile.c
PDa/src/x_arithmetic.c
PDa/src/x_connective.c
PDa/src/x_interface.c
/*
PDa/src/x_midi.c
*/
PDa/src/x_misc.c
PDa/src/x_time.c
PDa/src/x_acoustics.c
PDa/src/x_net.c
PDa/src/x_qlist.c
/*
PDa/src/x_gui.c
*/
PDa/src/d_imayer_fft.c
PDa/src/m_fixed.c
PDa/intern/biquad~.c
PDa/intern/bp~.c
@ -109,9 +93,6 @@ PDa/intern/rsqrt~.c
PDa/intern/samphold~.c
PDa/intern/sfread~.c
PDa/intern/sfwrite~.c
/*
PDa/intern/sig~.c
*/
PDa/intern/snapshot~.c
PDa/intern/sqrt~.c
PDa/intern/tabosc4~.c
@ -130,9 +111,7 @@ PDa/intern/vline~.c
PDa/intern/vsnapshot~.c
PDa/intern/wrap~.c
/* PDa/extra/OSCroute.c */
PDa/extra/bandpass.c
/* PDa/extra/dumpOSC.c Does not compile, file handling stuff */
PDa/extra/equalizer.c
PDa/extra/gcanvas.c
PDa/extra/highpass.c
@ -143,10 +122,4 @@ PDa/extra/lowpass.c
PDa/extra/lowshelf.c
PDa/extra/moog~.c
PDa/extra/notch.c
/* PDa/extra/sendOSC.c Does not compile, file handling stuff */
/*
PDa/extra/shell.c
PDa/extra/slider.c
PDa/extra/sliderh.c
*/
PDa/extra/zerox~.c