This is Reicher.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import <objc/Object.h> #import "Reicher.h" @implementation Reicher:Object #import <appkit/appkit.h> #import <appkit/Panel.h> // For the NXAlert panel #import <soundkit/soundkit.h> #import <musickit/musickit.h> #import <musickit/Conductor.h> #import <musickit/Performer.h> #import "FluteIns.h" #import <math.h> #import "RandomIzer.h" // all the defined values, etc. are in this file #include "Reichvals.h" static Orchestra *theOrch; static SynthInstrument *theIns[NUMFLUTES]; static id theRand; static int going = 0; static Note *theNote[NUMFLUTES]; static Note *theNoteOn[LBREATH*NUMFLUTES][ARRNOTES][NCYCS]; static Note *theNoteOff[LBREATH*NUMFLUTES][ARRNOTES][NCYCS]; static Note *theNoteRun[NUMFLUTES][ARRNOTES][RUNNOTES]; static Note *theNoteUpdate[NUMFLUTES]; static int PITCH[ARRNOTES]; static double AMP[ARRNOTES]; static double DUR[ARRNOTES]; int perform_switch = 0; int numflutes = NUMFLUTES; - setup { int MY_outAmp = [[Note class] parName: "MY_outAmp"]; int MY_dLineLength = [[Note class] parName: "MY_dLineLength"]; int MY_delay2Length = [[Note class] parName: "MY_delay2Length"]; double D1,D2; double panval,pan_incr; int j; if (going == 0) { theRand = [RandomIzer new]; [theRand setit]; theOrch = [Orchestra new]; if (![theOrch open]) { NXRunAlertPanel("Shoot Fire...", "Can't open the DSP", "darn.", NULL, NULL, "is it clear?"); exit(1); } [theOrch setSamplingRate: 22050.0]; MKSetDeltaT(.01) ; [Orchestra setFastResponse:YES]; [Orchestra setTimed:NO]; [Conductor setFinishWhenEmpty:NO]; [Conductor useSeparateThread:YES]; [Conductor setThreadPriority:1.0]; [theOrch run]; [Conductor startPerformance]; [Conductor lockPerformance]; // doesn't matter which notes here, will get updated later D1 = MAXLENGTH; D2 = MAXD2LENGTH; panval = -45.0; pan_incr = 90.0/(numflutes-1); for(j = 0; j < numflutes; j++) { theIns[j] = [SynthInstrument new]; [theIns[j] setSynthPatchClass:[FluteIns class]]; [theIns[j] setSynthPatchCount:1]; theNote[j] = [Note new]; [theNote[j] setNoteType:MK_noteOn]; [theNote[j] setNoteTag:MKNoteTag()]; [theNote[j] setPar:MK_amp0 toDouble:0.0]; [theNote[j] setPar:MK_amp1 toDouble:0.0]; [theNote[j] setPar:MY_outAmp toDouble:0.3]; [theNote[j] setPar:MK_bearing toDouble:panval]; panval += pan_incr; [theNote[j] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNote[j] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [[theIns[j] noteReceiver] receiveNote:theNote[j]]; } [Conductor unlockPerformance]; } return(self); } - StartAndStop:sender { int i; int MY_outAmp = [[Note class] parName: "MY_outAmp"]; if (going == 0) { [self setup]; switch (perform_switch) { case 0: [self doPulsing]; break; case 1: [self doCanon]; break; case 2: [self doPhasing]; break; case 3: [self doInterlock]; break; } going = 1; } else { [Conductor lockPerformance]; for (i = 0; i < NUMFLUTES; i++) { theNoteOff[i][0][0] = [Note new]; [theNoteOff[i][0][0] setNoteType:MK_noteOff]; [theNoteOff[i][0][0] setNoteTag:[theNote[i] noteTag]]; [theNoteOff[i][0][0] setPar:MK_amp0 toDouble:0.0]; [theNoteOff[i][0][0] setPar:MK_amp1 toDouble:0.0]; [theNoteOff[i][0][0] setPar:MY_outAmp toDouble:0.0]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][0][0]]; [theIns[i] free]; } [Conductor unlockPerformance]; [Conductor finishPerformance]; [theOrch flushTimedMessages]; [theOrch free]; going = 0; } return(self); } - doPulsing; { int MY_dLineLength = [[Note class] parName: "MY_dLineLength"]; int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"]; int MY_delay2Length = [[Note class] parName: "MY_delay2Length"]; int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"]; double playspeed = 0.23; double notedur = 0.17; double AMP1,AMP1incr; double D1,D2; int numpulses,halfway; int Reichons[NUMNOTES]; int i,j; int val_int; int turnflag; double val_double; double playtime; [Conductor lockPerformance]; /* Prepare to send MK message */ // choose notes // first of all, clear out the placeholder array (for dups) for (j = 0; j < NUMNOTES; j++) Reichons[j] = 0; // now choose a unique note value for each flute for(j = 0; j < NUMFLUTES; j++) { do { val_int = [theRand GetIndex:NUMNOTES-1]; } while (Reichons[val_int] == 1); Reichons[val_int] = 1; D1 = Reichnotes[val_int][0]; D2 = Reichnotes[val_int][1]; // set up a Note with this note info and send it out -- // assumption here is that the -play method is queued to be called // at the correct time to start a new chord theNoteUpdate[j] = [Note new]; [theNoteUpdate[j] setNoteType:MK_noteUpdate]; [theNoteUpdate[j] setNoteTag:[theNote[j] noteTag]]; [theNoteUpdate[j] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNoteUpdate[j] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [theNoteUpdate[j] setPar:MK_amp1 toDouble:0.0]; [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteUpdate[j]]; } // at this point, the flutes all are set to the correct note // now to decide the breath for each flute, and then set up the // phrase for (j = 0; j < NUMFLUTES; j++) { // choose the number of pulses numpulses = [theRand GetIndexRangeHi:LBREATH Lo:SBREATH]; halfway = numpulses/2; turnflag = 0; playtime = playspeed; AMP1 = 0.4; val_double = [theRand GetNumberRangeHi:0.9 Lo:0.8]; AMP1incr = (val_double - AMP1)/(double)numpulses; for (i = 0; i < numpulses; i++) { theNoteOn[j][0][0] = [Note new]; [theNoteOn[j][0][0] setNoteType:MK_noteUpdate]; [theNoteOn[j][0][0] setNoteTag:[theNote[j] noteTag]]; [theNoteOn[j][0][0] setPar:MK_amp1 toDouble:AMP1]; [theNoteOn[j][0][0] setPar:MY_envelopeSlew toDouble:0.001]; [theNoteOn[j][0][0] setPar:MY_noiseVolume toDouble:0.007]; [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteOn[j][0][0] withDelay:playtime]; theNoteOff[j][0][0] = [Note new]; [theNoteOff[j][0][0] setNoteType:MK_noteUpdate]; [theNoteOff[j][0][0] setNoteTag:[theNote[j] noteTag]]; [theNoteOff[j][0][0] setPar:MK_amp1 toDouble:0.0]; [theNoteOff[j][0][0] setPar:MY_envelopeSlew toDouble:1.0]; [theNoteOff[j][0][0] setPar:MY_noiseVolume toDouble:0.001]; [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteOff[j][0][0] withDelay:playtime+notedur]; playtime = playtime + (playspeed + [theRand GetNumber:0.01]); if ((i > halfway) && (turnflag == 0)) { AMP1incr *= -1.0; turnflag = 1; } AMP1 = AMP1 + AMP1incr; } } [[Conductor defaultConductor] sel:@selector(doPulsing) to:self withDelay:playtime argCount:0]; [Conductor unlockPerformance]; return self; } - doCanon { int MY_dLineLength = [[Note class] parName: "MY_dLineLength"]; int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"]; int MY_delay2Length = [[Note class] parName: "MY_delay2Length"]; int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"]; int i,j,k; int nrunnotes; double D1,D2; double playtime,canon_delay; static int long_incr; static float longdur_mult; static int reg_incr, reg_hi, reg_lo; static float run_prob, runprob_incr, run_direction; static float rest_prob, restprob_incr; static float amp_hi, amphi_incr, amp_lo, amplo_incr; double noiseval; [Conductor lockPerformance]; // set up: if (going == 0) { // set up some initial flags long_incr = LONGSTART; longdur_mult = (float)[theRand GetIndexRangeHi:10 Lo:6]; reg_incr = REGSTART; reg_hi = 4; reg_lo = 0; runprob_incr = RUNPROBINCR; run_prob = 0.0; run_direction = UP; restprob_incr = 0.0 - RESTPROBINCR; rest_prob = 0.4; amphi_incr = AMPHIINCR; amp_hi = 0.8; amplo_incr = AMPLOINCR; amp_lo = 0.5; } // load up the PITCH, AMP, and DUR arrays with values: for (j = 0; j < ARRNOTES; j++) { // select pitch indices if (reg_incr < REGSECTDUR) { PITCH[j] = [theRand GetIndexRangeHi:reg_hi Lo:reg_lo]; if (reg_incr < 0) { reg_incr = REGSTART; if ([theRand GetNumber] < 0.5) { reg_hi = 4; reg_lo = 0; } else { reg_hi = 16; reg_lo = 11; } } } else { PITCH[j] = [theRand GetIndex:16]; } AMP[j] = [theRand GetNumberRangeHi:amp_hi Lo:amp_lo]; if ([theRand GetNumber] < rest_prob) { AMP[j] = 0.0; } DUR[j] = Beats[ [theRand GetIndex:3] ]; if (long_incr < LONGSECTDUR) { DUR[j] *= longdur_mult; if (long_incr < 0) { long_incr = LONGSTART; longdur_mult = (float)[theRand GetIndexRangeHi:10 Lo:6]; } } } reg_incr--; long_incr--; run_prob += runprob_incr; if ( (run_prob > 1.0) || (run_prob < 0.0) ) runprob_incr = 0.0 - runprob_incr; rest_prob += restprob_incr; if ( (rest_prob > 0.4) || (rest_prob < 0.0) ) restprob_incr = 0.0 -restprob_incr; amp_hi += amphi_incr; if ( (amp_hi > 0.95) || (amp_hi < 0.75) ) amphi_incr = 0.0 - amphi_incr; amp_lo += amplo_incr; if ( (amp_lo > 0.65) || (amp_lo < 0.4) ) amplo_incr = 0.0 - amplo_incr; playtime = 0.0; for (j = 0; j < ARRNOTES; j++) { // test and possibly do a short run here if ( [theRand GetNumber] < run_prob ) { // choose the number of notes in the run nrunnotes = [theRand GetIndexRangeHi:RUNNOTES Lo:1]; // choose the run-note duration if ( [theRand GetNumber] > 0.9 ) { DUR[j] = SIXTEENTH; } else { DUR[j] = EIGHTH; } // choose the run direction if (run_prob < 0.9) { if ( [theRand GetNumber] > 0.5 ) { run_direction = UP; } else { run_direction = DOWN; } } else { // I like the sound of this DUR[j] = SIXTEENTH; nrunnotes = 4; } // now make the runs! for (k = 0; k < nrunnotes; k++) { if (run_direction == UP) { if (PITCH[j] > 12) PITCH[j] = [theRand GetIndex:12]; D1 = Reichnotes[PITCH[j]+k][0]; D2 = Reichnotes[PITCH[j]+k][1]; } else { if (PITCH[j] < 5) PITCH[j] = [theRand GetIndexRangeHi:16 Lo:5]; D1 = Reichnotes[PITCH[j]-k][0]; D2 = Reichnotes[PITCH[j]-k][1]; } canon_delay = 0.0; for (i = 0; i < NUMFLUTES; i++) { theNoteRun[i][j][k] = [Note new]; [theNoteRun[i][j][k] setNoteType:MK_noteUpdate]; [theNoteRun[i][j][k] setNoteTag:[theNote[i] noteTag]]; [theNoteRun[i][j][k] setPar:MK_amp1 toDouble:AMP[j]]; [theNoteRun[i][j][k] setPar:MY_envelopeSlew toDouble:0.001]; noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015]; [theNoteRun[i][j][k] setPar:MY_noiseVolume toDouble:noiseval]; D1 += [theRand GetPlusMinus:0.0001]; D2 += [theRand GetPlusMinus:0.0001]; [theNoteRun[i][j][k] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNoteRun[i][j][k] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteRun[i][j][k] withDelay:playtime+canon_delay]; canon_delay += (CANONPT + [theRand GetNumber:0.001]); } playtime += DUR[j]; } } // play a "normal" note else { canon_delay = 0.0; for (i = 0; i < NUMFLUTES; i++) { theNoteOn[i][j][0] = [Note new]; [theNoteOn[i][j][0] setNoteType:MK_noteUpdate]; [theNoteOn[i][j][0] setNoteTag:[theNote[i] noteTag]]; [theNoteOn[i][j][0] setPar:MK_amp1 toDouble:AMP[j]]; [theNoteOn[i][j][0] setPar:MY_envelopeSlew toDouble:0.001]; noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015]; [theNoteOn[i][j][0] setPar:MY_noiseVolume toDouble:noiseval]; D1 = Reichnotes[PITCH[j]][0]; D2 = Reichnotes[PITCH[j]][1]; D1 += [theRand GetPlusMinus:0.0001]; D2 += [theRand GetPlusMinus:0.0001]; [theNoteOn[i][j][0] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNoteOn[i][j][0] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][0] withDelay:playtime+canon_delay]; theNoteOff[i][j][0] = [Note new]; [theNoteOff[i][j][0] setNoteType:MK_noteUpdate]; [theNoteOff[i][j][0] setNoteTag:[theNote[i] noteTag]]; [theNoteOff[i][j][0] setPar:MK_amp1 toDouble:0.0]; [theNoteOff[i][j][0] setPar:MY_envelopeSlew toDouble:0.001]; [theNoteOff[i][j][0] setPar:MY_noiseVolume toDouble:0.0]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][0] withDelay:playtime+canon_delay+DUR[j]]; canon_delay += (CANONPT + [theRand GetNumber:0.001]); } playtime = 0.2 + playtime + (DUR[j] + [theRand GetNumber:0.01]); } } [[Conductor defaultConductor] sel:@selector(doCanon) to:self withDelay:playtime argCount:0]; [Conductor unlockPerformance]; return self; } - doPhasing { int MY_dLineLength = [[Note class] parName: "MY_dLineLength"]; int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"]; int MY_delay2Length = [[Note class] parName: "MY_delay2Length"]; int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"]; double D1,D2; int i,j; double playtime; static double phase_delay; static int slurflags[ARRNOTES]; float noiseval; [Conductor lockPerformance]; if (going == 0) { // load up the PITCH, AMP, slurflags, and DUR arrays with values: for (j = 0; j < ARRNOTES; j++) { // select pitch indices from all the notes PITCH[j] = [theRand GetIndex:17]; AMP[j] = [theRand GetNumberRangeHi:0.99 Lo:0.7]; if (PITCH[j] > 15) { PITCH[j] = 0; AMP[j] = 0.0; } DUR[j] = Beats[ [theRand GetIndex:3] ]; slurflags[j] = 0; if ( [theRand GetNumber] < SLURPROB) slurflags[j] = 1; } phase_delay = 0.0; } // queue up the notes for the two flutes playtime = 0.0; for (j = 0; j < ARRNOTES; j++) { for (i = 0; i < numflutes; i++) { theNoteOn[i][j][0] = [Note new]; [theNoteOn[i][j][0] setNoteType:MK_noteUpdate]; [theNoteOn[i][j][0] setNoteTag:[theNote[i] noteTag]]; [theNoteOn[i][j][0] setPar:MK_amp1 toDouble:AMP[j]]; [theNoteOn[i][j][0] setPar:MY_envelopeSlew toDouble:0.001]; noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015]; [theNoteOn[i][j][0] setPar:MY_noiseVolume toDouble:noiseval]; D1 = Reichnotes[PITCH[j]][0]; D2 = Reichnotes[PITCH[j]][1]; D1 += [theRand GetPlusMinus:0.0001]; D2 += [theRand GetPlusMinus:0.0001]; [theNoteOn[i][j][0] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNoteOn[i][j][0] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][0] withDelay:playtime + ((float)i * phase_delay)]; if (slurflags[j] == 0) { theNoteOff[i][j][0] = [Note new]; [theNoteOff[i][j][0] setNoteType:MK_noteUpdate]; [theNoteOff[i][j][0] setNoteTag:[theNote[i] noteTag]]; [theNoteOff[i][j][0] setPar:MK_amp1 toDouble:0.0]; [theNoteOff[i][j][0] setPar:MY_envelopeSlew toDouble:0.001]; [theNoteOff[i][j][0] setPar:MY_noiseVolume toDouble:0.0]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][0] withDelay:playtime+ ((float)i * phase_delay) + DUR[j]]; } } playtime = 0.2 + playtime + (DUR[j] + [theRand GetNumber:0.01]); } phase_delay += (PHASEINCR + [theRand GetNumber:0.001]); [[Conductor defaultConductor] sel:@selector(doPhasing) to:self withDelay:playtime argCount:0]; [Conductor unlockPerformance]; return self; } -doInterlock { int MY_dLineLength = [[Note class] parName: "MY_dLineLength"]; int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"]; int MY_delay2Length = [[Note class] parName: "MY_delay2Length"]; int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"]; int i,j,k; double playtime; static int reg_incr, reg_hi, reg_lo; static float amp_hi, amphi_incr, amp_lo, amplo_incr; float noiseval; double D1,D2; int cycles; float cycle_delay; [Conductor lockPerformance]; if (going == 0) { // set up some initial flags reg_incr = REGSTART; reg_hi = 4; reg_lo = 0; amphi_incr = AMPHIINCR; amp_hi = 0.8; amplo_incr = AMPLOINCR; amp_lo = 0.5; } for (i = 0; i < NUMFLUTES; i++) { // load up the PITCH, AMP, and DUR arrays with new values: for (j = 0; j < CYCARRNOTES; j++) { // select pitch indices if (reg_incr < REGSECTDUR) { PITCH[j] = [theRand GetIndexRangeHi:reg_hi Lo:reg_lo]; if (reg_incr < 0) { reg_incr = REGSTART; if ([theRand GetNumber] < 0.5) { reg_hi = 4; reg_lo = 0; } else { reg_hi = 16; reg_lo = 12; } } } else { PITCH[j] = [theRand GetIndex:16]; } AMP[j] = [theRand GetNumberRangeHi:amp_hi Lo:amp_lo]; DUR[j] = Beats[ [theRand GetIndex:3] ]; } cycles = [theRand GetIndexRangeHi:NCYCS Lo:3]; cycle_delay = (CYCMEASURE * (float)(i * 4)) + (QUARTER * (float)i); for (k = 0; k < cycles; k++) { playtime = 0.0; for (j = 0; j < CYCARRNOTES; j++) { theNoteOn[i][j][k] = [Note new]; [theNoteOn[i][j][k] setNoteType:MK_noteUpdate]; [theNoteOn[i][j][k] setNoteTag:[theNote[i] noteTag]]; [theNoteOn[i][j][k] setPar:MK_amp1 toDouble:AMP[j]]; [theNoteOn[i][j][k] setPar:MY_envelopeSlew toDouble:0.001]; noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015]; [theNoteOn[i][j][k] setPar:MY_noiseVolume toDouble:noiseval]; D1 = Reichnotes[PITCH[j]][0]; D2 = Reichnotes[PITCH[j]][1]; D1 += [theRand GetPlusMinus:0.0001]; D2 += [theRand GetPlusMinus:0.0001]; [theNoteOn[i][j][k] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)]; [theNoteOn[i][j][k] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][k] withDelay:playtime+cycle_delay]; theNoteOff[i][j][k] = [Note new]; [theNoteOff[i][j][k] setNoteType:MK_noteUpdate]; [theNoteOff[i][j][k] setNoteTag:[theNote[i] noteTag]]; [theNoteOff[i][j][k] setPar:MK_amp1 toDouble:0.0]; [theNoteOff[i][j][k] setPar:MY_envelopeSlew toDouble:0.001]; [theNoteOff[i][j][k] setPar:MY_noiseVolume toDouble:0.0]; [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][k] withDelay:playtime+cycle_delay+DUR[j]]; playtime = playtime + (DUR[j] + [theRand GetNumber:0.01]); } cycle_delay += (CYCMEASURE + [theRand GetNumber:0.001]); } } reg_incr--; amp_hi += amphi_incr; if ( (amp_hi > 0.95) || (amp_hi < 0.75) ) amphi_incr = 0.0 - amphi_incr; amp_lo += amplo_incr; if ( (amp_lo > 0.65) || (amp_lo < 0.4) ) amplo_incr = 0.0 - amplo_incr; [[Conductor defaultConductor] sel:@selector(doInterlock) to:self withDelay:(CYCMEASURE * 7) argCount:0]; [Conductor unlockPerformance]; return self; } - setPulsing:sender { perform_switch = 0; numflutes = NUMFLUTES; return(self); } - setCanon:sender { perform_switch = 1; numflutes = NUMFLUTES; return(self); } - setPhasing:sender { perform_switch = 2; numflutes = 2; return(self); } - setInterlock:sender { perform_switch = 3; numflutes = NUMFLUTES; return(self); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.