This is ClmCodeGen.m in view mode; [Download] [Up]
/************************************************** * SynthBuilder * Copyright 1993 Nick Porcaro All Rights Reserved **************************************************/ /* * ClmCodeGen.m * Nick Porcaro and Owen Smith Spring/Summer 1993 * * This is the clm related stuff taken out of FakeSynthPatch.m */ #import <stdio.h> #import <stdlib.h> #import <string.h> #import <math.h> #import <appkit/Application.h> #import <appkit/Control.h> #import <appkit/Matrix.h> #import <appkit/Panel.h> #import <appkit/OpenPanel.h> #import <appkit/SavePanel.h> #import "FakeSynthPatch.h" #import "FakePatchPoint.h" #import "FakeUG.h" #import "ClmCodeGen.h" #define MAXMESSAGELENGTH 200 // Added by Owen #define GetNextUG(n) [[[theUG getConnection:n] getFromNode] superview] #define MAXENVSTRING 100 // Added by Owen static BOOL IsInitializeable(char *s); static BOOL MultipleOuts(id theUG); static void DefineBlock(FILE *f, id theUG, id definedList); static void NextCrunch(FILE *f, id theUG, id definedList, int connection); static void PrintCrunch(FILE *f, id theUG, id definedList); static char *ParseEnvString(char *s, double dur); static int GetNumberOfInputs(id theUG); static char TempString[1024]; extern id savePanel; extern id openPanel; extern char *getSavePath(char *banner); extern char *getOpenPath(char *banner); extern char *getAppName(); @implementation ClmCodeGen - init { [super init]; [NXApp loadNibSection:"ClmCodeGen.nib" owner:self withNames:YES]; return self; } - setSP:aSP { theSP = aSP; fakeUGs = [theSP getFakeUGs]; fakePatchPoints = [theSP getFakePatchPoints]; return self; } - displayInspector:sender { [theInspector makeKeyAndOrderFront:self]; return self; } - emitCode:sender { char *file_name; sprintf(TempString, "%s Generate CLM code", getAppName()); if (! (file_name = getSavePath(TempString))) { return self; } [self makeLispCode: file_name samplingRate: [theSamplingRate doubleValue] instrumentName: (char *) [theInstrName stringValue] startTime: [theStartTime doubleValue] duration: [theDuration doubleValue] ]; /* Now do the right thing with the file */ switch ([[patchDest selectedCell] tag]) { case(0): { sprintf(TempString, "open %s", file_name); system(TempString); } case(1): { NXRunAlertPanel(getAppName(), "Paste Board not supported yet", NULL, NULL, NULL); break; } case(2): { sprintf(TempString, "%s %s &", [testerScript stringValue], file_name); printf("Shell command: %s\n", TempString); system(TempString); break; } } return self; } - makeLispCode: (char *) aFileName samplingRate: (double) aSamplingRate instrumentName: (char *) anInstrumentName startTime: (double) aStartTime duration: (double) aDuration { int i; id theUG; char *ug_name, *ug_type; int method_count = 0; int pointCount=0, stickPoint = -1; int envelopes_processed = 0; FILE *f; extern char *getenv(); char *ptr; char *fileName; double samplingRate; char *instrumentName; double startTime; double duration; // isDefined is a list of the names of all the defined multiple-output // synth blocks in the patch for the run-time loop. A better way would be // to tack on another BOOL field to the FakeUG definition, saying whether // or not a particular instance of a FakeUG has been defined or not. id isDefined = [[List alloc] init]; fileName = aFileName; samplingRate = aSamplingRate; instrumentName = anInstrumentName; startTime = aStartTime; duration = aDuration; // Open file f = fopen(fileName, "w"); if (!f) { NXRunAlertPanel("Emit Code", "Can't create file.", NULL, NULL, NULL); return self; } // Get the parameters ptr = (char *) [theSP getName]; if (ptr) { strcpy(instrumentName, ptr); } // Put out file header fprintf(f, ";;; -*- Syntax: Common-Lisp; Package: COMMON-MUSIC; Base: 10; Mode: Lisp -*-\n\n"); fprintf(f, ";;; Instrument: %s; Part: %s\n;;; Created by %s for CLM\n\n", instrumentName, instrumentName, getAppName()); // init stuff fprintf(f, "(in-package 'common-music)\n(in-syntax ':clm)\n\n"); fprintf(f, "(definstrument %s (&key\n", instrumentName); // add params someday? fprintf(f, " (start-time %g)\n", startTime); fprintf(f, " (duration %g)\n", duration); fprintf(f, " (amplitude 0.5))\n\n"); // initialize UGs. beg and end are the start and end time in samples. fprintf(f, " (let* ((beg (floor (* start-time sampling-rate)))\n"); fprintf(f, " (end (+ beg (floor (* duration sampling-rate))))\n"); fprintf(f, " (freq-tweak %g)\n", 8 * atan(1)); // since internal table size is 2Pi? // loop to initialize the actual UGs. Loop goes through all the patchpoints and accesses the UGs through them. // There is definitely a better way, but... for (i=0; i<[fakeUGs count]; i++) { theUG = [fakeUGs objectAt:i]; ug_type = [theUG getGenericTypeString]; if ((ug_type != NULL) && (IsInitializeable(ug_type))) { ug_name = [theUG getName]; fprintf(f, " (%s", ug_name); if (! strcmp(ug_type, "Out2sumUG")) fprintf(f, " (make-locsig))\n"); else if (! strcmp(ug_type, "Out1aUG")) fprintf(f, " (make-locsig :degree -90))\n"); else if (! strcmp(ug_type, "Out1bUG")) fprintf(f, " (make-locsig :degree 90))\n"); else if (! (strcmp(ug_type, "OscgafUG") && strcmp(ug_type, "OscgafiUG"))) { fprintf(f, " (make-oscil :frequency 0.0 :initial-phase 0.0))\n"); } else if (! strcmp(ug_type, "Constantpp")) fprintf(f, " %g)\n", atod([theUG getConstant])); else if (! strcmp(ug_type, "ConstantUG")) fprintf(f, " %g)\n", atod([theUG getArg:0])); else if (! strcmp(ug_type, "DelayUG")) fprintf(f, " (make-delay %d))\n", atoi([theUG getArg:0])); // We should check with Julius about these filters and the "InterpUG". else if (! strcmp(ug_type, "Allpass1UG")) { fprintf(f, " (make-all-pass #| feedback-scaler feedforward-scaler length |#))\n"); } else if (! strcmp(ug_type, "OnepoleUG")) { fprintf(f, " (make-one-pole %g %g))\n", atod([theUG getArg:0]), atod([theUG getArg:1])); } else if (! strcmp(ug_type, "OnezeroUG")) { fprintf(f, " (make-one-zero %g %g))\n", atod([theUG getArg:0]), atod([theUG getArg:1])); } else if (! strcmp(ug_type, "OscgUG")) { fprintf(f, " (make-oscil :frequency %g :initial-phase %g))\n", atod([theUG getArg:1]), atod([theUG getArg:3])); } else if (! strcmp(ug_type, "oscilUG")) { fprintf(f, " (make-oscil :frequency %g :initial-phase %g))\n", atod([theUG getArg:0]), atod([theUG getArg:1])); } else if (! strcmp(ug_type, "ScaleUG")) fprintf(f, " %g)\n", atod([theUG getArg:0])); else if (! strcmp(ug_type, "Scl1add2UG")) fprintf(f, " %g)\n", atod([theUG getArg:0])); else if (! strcmp(ug_type, "Scl2add2UG")) { fprintf(f, "-1 %g)\n (%s-2 %g)\n", atod([theUG getArg:0]), ug_name, atod([theUG getArg:1])); } else if (! strcmp(ug_type, "SnoiseUG")) fprintf(f, " (make-randh))\n"); else if (! strcmp(ug_type, "UnoiseUG")) fprintf(f, " (make-randi))\n"); else if (! strcmp(ug_type, "AsympUG")) { fprintf(f, " (make-env :envelope '%s :start-time start-time :duration duration))\n", ParseEnvString([theUG getArg:4], duration)); } } if ((ug_type != NULL) && (MultipleOuts(theUG) && strcmp(ug_type, "SineROM") && strcmp(ug_type, "Storage"))) { ug_name = [theUG getName]; fprintf(f, " (%s-out 0.0)\n", ug_name); } } fprintf(f, " )\n\n"); // now for the run-time loop fprintf(f, " (set-srate %g)\n", samplingRate); fprintf(f, " (Run\n"); fprintf(f, " (loop for i from beg to end do\n "); for (i=0; i<[fakeUGs count]; i++) { if (! [[fakeUGs objectAt:i] getConnectionName:0]) { DefineBlock(f, [fakeUGs objectAt:i], isDefined); PrintCrunch(f, [fakeUGs objectAt:i], isDefined); } } fprintf(f, "\n )\n )\n (end-run)\n ))\n\n"); // defpart fprintf(f, "(defpart %s (clm-part)\n", instrumentName); fprintf(f, " (name &message start-time duration amplitude)\n"); fprintf(f, " (start-time duration amplitude))\n\n"); // sample score file fprintf(f, "#|\n; Sample score file for instrument %s and part %s\n\n", instrumentName, instrumentName); fprintf(f, "(defscorefile (after '(load :srate %g :channels 2))\n", samplingRate); fprintf(f, " (with-part %s (time 0.0 events 1)))\n", instrumentName); fprintf(f, "|#\n"); fclose(f); return self; } @end static BOOL IsInitializeable(char *s) { // If s is equal to any of these strings, NO is returned. return (strcmp(s, "Add2UG") && strcmp(s, "DswitchUG") && strcmp(s, "DswitchtUG") && strcmp(s, "Mul1add2UG") && strcmp(s, "Mul2UG") && strcmp(s, "SineROM") && strcmp(s, "Storage")); } static BOOL MultipleOuts(id theUG) { // If the UG passed in has more than one output, YES is returned. id theOut; return ((theOut = [theUG getConnection:0]) ? ([[theOut getToNodes] count] > 1) : NO); } static void DefineBlock(FILE *f, id theUG, id definedList) { int i; if (! MultipleOuts(theUG)) { // recurse through all the inputs for (i=1; i <= GetNumberOfInputs(theUG); i++) { DefineBlock(f, GetNextUG(i), definedList); } } else { if (strcmp([theUG getGenericTypeString], "Storage") && strcmp([theUG getGenericTypeString], "SineROM")) { if ([definedList indexOf:theUG] == NX_NOT_IN_LIST) { // add the UG to the list of defined synth blocks [definedList addObject:theUG]; // recurse through all the inputs for (i=1; i <= GetNumberOfInputs(theUG); i++) { DefineBlock(f, GetNextUG(i), definedList); } fprintf(f, "(setf %s-out ", [theUG getName]); PrintCrunch(f, theUG, definedList); fprintf(f, ")\n "); } } } } static void NextCrunch(FILE *f, id theUG, id definedList, int connection) { id nextUG; nextUG = GetNextUG(connection); if (MultipleOuts(nextUG)) { if ([definedList indexOf:nextUG] == NX_NOT_IN_LIST) { fprintf(f, "\n ERROR: No definition for synthblock %s-out\n", [nextUG getName]); } else fprintf(f, "%s-out", [nextUG getName]); } else PrintCrunch(f, nextUG, definedList); } static void PrintCrunch(FILE *f, id theUG, id definedList) { char *type = [theUG getGenericTypeString]; if (! strcmp(type, "Add2UG")) { fprintf(f, "(+ "); NextCrunch(f, theUG, definedList, 1); fprintf(f, " "); NextCrunch(f, theUG, definedList, 2); fprintf(f, ")"); } else if (! strcmp(type, "AsympUG")) { fprintf(f, "(env %s)", [theUG getName]); } else if (! strcmp(type, "Allpass1UG")) { fprintf(f, "(all-pass %s ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ")"); } else if (! (strcmp(type, "ConstantUG") && strcmp(type, "Constantpp"))) { fprintf(f, "%s", [theUG getName]); } else if (! strcmp(type, "DelayUG")) { fprintf(f, "(delay %s ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ")"); } else if (! strcmp(type, "Mul2UG")) { fprintf(f, "(* "); NextCrunch(f, theUG, definedList, 1); fprintf(f, " "); NextCrunch(f, theUG, definedList, 2); fprintf(f, ")"); } else if (! strcmp(type, "OnepoleUG")) { fprintf(f, "(one-pole %s ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ")"); } else if (! strcmp(type, "OnezeroUG")) { fprintf(f, "(one-zero %s ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ")"); } else if (! strcmp(type, "OscgUG")) { fprintf(f, "(oscil %s)", [theUG getName]); } else if (! (strcmp(type, "OscgafUG") && strcmp(type, "OscgafiUG"))) { fprintf(f, "(* "); NextCrunch(f, theUG, definedList, 1); // amp input fprintf(f, " (oscil %s (* freq-tweak ", [theUG getName]); NextCrunch(f, theUG, definedList, 2); // phase inc. input fprintf(f, ")))"); } else if (! (strcmp(type, "Out1aUG") && strcmp(type, "Out1bUG") && strcmp(type, "Out2sumUG"))) { fprintf(f, "(locsig %s i (* amplitude ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, "))"); } else if (! strcmp(type, "Scl1add2UG")) { fprintf(f, "(+ (* %s ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ") "); NextCrunch(f, theUG, definedList, 2); fprintf(f, ")"); } else if (! strcmp(type, "Scl2add2UG")) { fprintf(f, "(+ (* %s-1 ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, ") (* %s-2 ", [theUG getName]); NextCrunch(f, theUG, definedList, 2); fprintf(f, "))"); } else if (! strcmp(type, "SnoiseUG")) { fprintf(f, "(randh %s)", [theUG getName]); } else if (! strcmp(type, "UnoiseUG")) { fprintf(f, "(randi %s)", [theUG getName]); } else if (! strcmp(type, "oscilUG")) { fprintf(f, "(oscil %s (* freq-tweak ", [theUG getName]); NextCrunch(f, theUG, definedList, 1); fprintf(f, "))"); } else fprintf(f, "\n I don't know how to handle this UG yet: %s\n", type); } static char *ParseEnvString(char *s, double dur) { int i, j, bkptnum; BOOL isSticker = NO; char *parsed, *numpair, *final; double *xPts, *yPts; int stickIndex=0, parseLength; double endTime, susTime, newx; for (i=0, bkptnum=0; s[i] != '\0'; i++) { if (s[i] == '|') isSticker = YES; if (s[i] == '(') bkptnum++; } xPts = (double*) malloc(bkptnum*sizeof(double)); yPts = (double*) malloc(bkptnum*sizeof(double)); parsed = (char *) malloc(MAXENVSTRING*sizeof(char)); numpair = (char *) malloc(30*sizeof(char)); for (i=0, j=0; s[i] != '\0'; i++) { if (s[i] == '(') { sscanf(s+i, "(%lf, %lf)", &xPts[j], &yPts[j]); j++; } if (s[i] == '|') stickIndex = j; } endTime = xPts[j-1]; if (! (isSticker && (dur > endTime))) { sprintf(parsed, "("); for (i=0; i < bkptnum; i++) { sprintf(numpair, "%g %g ", xPts[i], yPts[i]); strcat(parsed, numpair); } strcat(parsed, ")"); } else { susTime = dur - endTime; sprintf(parsed, "("); for (i=0; i < stickIndex; i++) { sprintf(numpair, "%g %g ", xPts[i], yPts[i]); strcat(parsed, numpair); } i--; newx = xPts[i] + susTime; sprintf(numpair, "%g %g ", newx, yPts[i]); strcat(parsed, numpair); i++; while (i < bkptnum) { newx = xPts[i] + susTime; sprintf(numpair, "%g %g ", newx, yPts[i]); strcat(parsed, numpair); i++; } strcat(parsed, ")"); } parseLength = strlen(parsed); final = (char *) malloc(parseLength*sizeof(char)); strcpy(final, parsed); free(parsed); free(numpair); return parsed; } static int GetNumberOfInputs(id theUG) { int i; // all inputs start at connection index 1. // if there is no name for the connection, // then the connection does not exist. for (i=1; [theUG getConnectionName:i]; i++); return (i-1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.