/********************************************************************** nyx.c Nyx: A very simple external interface to Nyquist Dominic Mazzoni **********************************************************************/ /* system includes */ #include #include #include #include #include #ifndef WIN32 #include #endif /* nyx includes */ #include "nyx.h" /* xlisp includes */ #include "switches.h" #include "xlisp.h" #include "term.h" #include "cext.h" /* nyquist includes */ #include "sound.h" #include "falloc.h" /* nyquist externs */ extern LVAL a_sound; extern snd_list_type zero_snd_list; /* globals */ int nyx_output_pos; int nyx_output_len; char *nyx_output_string; int nyx_expr_pos; int nyx_expr_len; const char *nyx_expr_string; LVAL nyx_result; XLCONTEXT nyx_cntxt; int nyx_parse_error_flag; int nyx_first_time = 1; LVAL nyx_old_obarray; typedef struct nyx_susp_struct { snd_susp_node susp; nyx_audio_callback callback; void *userdata; long len; int channel; } nyx_susp_node, *nyx_susp_type; LVAL copylist(LVAL from) { if (from == NULL) return NULL; return cons(car(from), copylist(cdr(from))); } /* Make a copy of the obarray so that we can erase any changes the user makes to global variables */ void nyx_save_obarray() { LVAL array, obarrayvec; int i; xlsave1(array); array = newvector(HSIZE); obarrayvec = getvalue(obarray); for(i=0; isamples; snd_list->block = out; n = max_sample_block_len; if (susp->susp.current + n > susp->len) n = susp->len - susp->susp.current; err = susp->callback(out_ptr, susp->channel, susp->susp.current, n, susp->userdata); if (err) longjmp(nyx_cntxt.c_jmpbuf, 1); snd_list->block_len = n; susp->susp.current += n; if (n == 0) { /* we didn't read anything, but can't return length zero, so convert snd_list to pointer to zero block */ snd_list_terminate(snd_list); } else if (n < max_sample_block_len) { /* should free susp */ snd_list_unref(snd_list->u.next); /* if something is in buffer, terminate by pointing to zero block */ snd_list->u.next = zero_snd_list; } } void nyx_susp_free(nyx_susp_type susp) { ffree_generic(susp, sizeof(nyx_susp_node), "nyx_susp_free"); } void nyx_susp_print_tree(nyx_susp_type susp, int n) { } void nyx_capture_output(int max_len) { if (nyx_output_string) free(nyx_output_string); nyx_output_string = (char *)malloc(max_len); nyx_output_len = max_len; nyx_output_pos = 0; } void nyx_get_captured_output(int *out_len, const char **out_chars) { *out_len = nyx_output_pos; *out_chars = (const char *)nyx_output_string; nyx_output_pos = 0; } void nyx_set_input_audio(nyx_audio_callback callback, void *userdata, int num_channels, long len, double rate) { sample_type scale_factor = 1.0; time_type t0 = 0.0; nyx_susp_type *susp; sound_type *snd; double stretch_len; LVAL warp; int ch; susp = (nyx_susp_type *)malloc(num_channels * sizeof(nyx_susp_type)); snd = (sound_type *)malloc(num_channels * sizeof(sound_type)); for(ch=0; ch < num_channels; ch++) { falloc_generic(susp[ch], nyx_susp_node, "nyx_set_input_audio"); susp[ch]->callback = callback; susp[ch]->userdata = userdata; susp[ch]->len = len; susp[ch]->channel = ch; susp[ch]->susp.sr = rate; susp[ch]->susp.t0 = t0; susp[ch]->susp.mark = NULL; susp[ch]->susp.print_tree = nyx_susp_print_tree; susp[ch]->susp.current = 0; susp[ch]->susp.fetch = nyx_susp_fetch; susp[ch]->susp.free = nyx_susp_free; susp[ch]->susp.name = "nyx"; snd[ch] = sound_create((snd_susp_type)susp[ch], t0, rate, scale_factor); } /* Bind the sample rate to the "*sound-srate*" global */ setvalue(xlenter("*SOUND-SRATE*"), cvflonum(rate)); /* Bind selection len to "len" global */ setvalue(xlenter("LEN"), cvflonum(len)); if (len > 0) stretch_len = len / rate; else stretch_len = 1.0; /* Set the "*warp*" global based on the length of the audio */ xlprot1(warp); warp = cons(cvflonum(0), /* time offset */ cons(cvflonum(stretch_len), /* time stretch */ cons(NULL, /* cont. time warp */ NULL))); setvalue(xlenter("*WARP*"), warp); xlpop(); if (num_channels > 1) { LVAL array = newvector(num_channels); for(ch=0; chget_next(snd, &cnt); if (block == zero_block || cnt == 0) { result = -1; break; } /* copy the data to a temporary buffer and scale it by the appropriate scale factor */ if (cnt > bufferlen) { if (buffer) free(buffer); buffer = (float *)malloc(cnt * sizeof(float)); bufferlen = cnt; } memcpy(buffer, block->samples, cnt * sizeof(float)); for(i=0; iscale; result = callback(buffer, ch, totals[ch], cnt, userdata); if (result == 0) totals[ch] += cnt; } } finish: if (buffer) free(buffer); free(snds); free(totals); xlend(&nyx_cntxt); } int nyx_get_int() { if (nyx_get_type(nyx_result) != nyx_int) return -1; return getfixnum(nyx_result); } double nyx_get_double() { if (nyx_get_type(nyx_result) != nyx_double) return -1.0; return getflonum(nyx_result); } const char *nyx_get_string() { if (nyx_get_type(nyx_result) != nyx_string) return NULL; return (const char *)getstring(nyx_result); } int nyx_get_num_labels() { LVAL s = nyx_result; int count = 0; if (nyx_get_type(nyx_result) != nyx_labels) return 0; while(s) { count++; s = cdr(s); } return count; } void nyx_get_label(int index, double *time, const char **label) { LVAL s = nyx_result; LVAL t_expr; if (nyx_get_type(nyx_result) != nyx_labels) return; if (index < 0 || index >= nyx_get_num_labels()) return; while(index) { index--; s = cdr(s); } t_expr = car(car(s)); if (floatp(t_expr)) *time = getflonum(t_expr); else if (fixp(t_expr)) *time = (double)getfixnum(t_expr); *label = (const char *)getstring(car(cdr(car(s)))); } const char *nyx_get_error_str() { return NULL; } int ostgetc() { if (nyx_expr_pos < nyx_expr_len) { fflush(stdout); return (nyx_expr_string[nyx_expr_pos++]); } else if (nyx_expr_pos == nyx_expr_len) { /* Add whitespace at the end so that the parser knows that this is the end of the expression */ nyx_expr_pos++; return '\n'; } else return EOF; } /* osinit - initialize */ void osinit(char *banner) { } /* osfinish - clean up before returning to the operating system */ void osfinish(void) { } /* oserror - print an error message */ void oserror(char *msg) { printf("nyx error: %s\n", msg); } long osrand(long n) { return (((int) rand()) % n); } /* osaopen - open an ascii file */ FILE *osaopen(name,mode) char *name,*mode; { FILE *fp; fp = fopen(name,mode); return fp; } /* osbopen - open a binary file */ FILE *osbopen(char *name, char *mode) { char bmode[10]; FILE *fp; strncpy(bmode, mode, 8); strcat(bmode,"b"); fp = fopen(name,bmode); return fp; } /* osclose - close a file */ int osclose(FILE *fp) { return (fclose(fp)); } /* osagetc - get a character from an ascii file */ int osagetc(FILE *fp) { return (getc(fp)); } /* osaputc - put a character to an ascii file */ int osaputc(int ch, FILE *fp) { return (putc(ch,fp)); } extern int dbgflg; /* osbgetc - get a character from a binary file */ /* int osbgetc(fp) FILE *fp; {return (getc(fp));} */ #ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 int osbgetc(FILE *fp) { return (getc(fp)); } #endif /* osbputc - put a character to a binary file */ int osbputc(int ch, FILE *fp) { return (putc(ch,fp)); } /* ostputc - put a character to the terminal */ void ostputc(int ch) { oscheck(); /* check for control characters */ if (nyx_output_pos < nyx_output_len) nyx_output_string[nyx_output_pos++] = (char)ch; else putchar(((char) ch)); } /* osflush - flush the terminal input buffer */ void osflush(void) { } /* oscheck - check for control characters during execution */ void oscheck(void) { /* if they hit control-c: xflush(); xltoplevel(); return; */ } /* xsystem - execute a system command */ #ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 LVAL xsystem() { if (moreargs()) { unsigned char *cmd; cmd = (unsigned char *)getstring(xlgastring()); fprintf(stderr, "Will not execute system command: %s\n", cmd); } return s_true; } #endif /* xsetdir -- set current directory of the process */ LVAL xsetdir() { char *dir = (char *)getstring(xlgastring()); int result; xllastarg(); result = chdir(dir); if (result) { perror("SETDIR"); } return NULL; } /* xgetkey - get a key from the keyboard */ #ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 LVAL xgetkey() {xllastarg(); return (cvfixnum((FIXTYPE)getchar()));} #endif /* ossymbols - enter os specific symbols */ #ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 void ossymbols(void) {} #endif /* xsetupconsole -- used to configure window in Win32 version */ #ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 LVAL xsetupconsole() { return NULL; } #endif /* control-C handling */ void ctcinit() {}