home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / Reich-o-Matic / Reicher.m < prev    next >
Encoding:
Text File  |  1992-07-31  |  19.4 KB  |  674 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import <objc/Object.h>
  5. #import "Reicher.h"
  6.  
  7. @implementation Reicher:Object
  8.  
  9. #import <appkit/appkit.h>
  10. #import <appkit/Panel.h>    // For the NXAlert panel
  11. #import <soundkit/soundkit.h>
  12. #import <musickit/musickit.h>
  13. #import <musickit/Conductor.h>
  14. #import <musickit/Performer.h>
  15. #import "FluteIns.h"
  16. #import <math.h>
  17. #import "RandomIzer.h"
  18.  
  19. // all the defined values, etc. are in this file
  20. #include "Reichvals.h"
  21.  
  22. static Orchestra *theOrch;
  23. static SynthInstrument *theIns[NUMFLUTES];
  24. static id theRand;
  25. static int going = 0;
  26.  
  27. static Note *theNote[NUMFLUTES];
  28. static Note *theNoteOn[LBREATH*NUMFLUTES][ARRNOTES][NCYCS];
  29. static Note *theNoteOff[LBREATH*NUMFLUTES][ARRNOTES][NCYCS];
  30. static Note *theNoteRun[NUMFLUTES][ARRNOTES][RUNNOTES];
  31. static Note *theNoteUpdate[NUMFLUTES];
  32.  
  33. static int PITCH[ARRNOTES];
  34. static double AMP[ARRNOTES];
  35. static double DUR[ARRNOTES];
  36.  
  37. int perform_switch = 0;
  38. int numflutes = NUMFLUTES;
  39.  
  40. - setup
  41. {
  42.     int MY_outAmp = [[Note class] parName: "MY_outAmp"];
  43.     int MY_dLineLength = [[Note class] parName: "MY_dLineLength"];
  44.     int MY_delay2Length = [[Note class] parName: "MY_delay2Length"];
  45.  
  46.     double D1,D2;
  47.     double panval,pan_incr;
  48.     int j;
  49.     
  50.     if (going == 0) {
  51.         theRand = [RandomIzer new];
  52.         [theRand setit];
  53.         
  54.         theOrch = [Orchestra new];
  55.         if (![theOrch open]) {               
  56.             NXRunAlertPanel("Shoot Fire...", "Can't open the DSP", "darn.", NULL, NULL, "is it clear?");
  57.             exit(1);
  58.             }
  59.                               
  60.         [theOrch setSamplingRate: 22050.0];    
  61.         MKSetDeltaT(.01) ;           
  62.         [Orchestra setFastResponse:YES]; 
  63.         [Orchestra setTimed:NO];
  64.         [Conductor setFinishWhenEmpty:NO];
  65.         [Conductor useSeparateThread:YES];
  66.         [Conductor setThreadPriority:1.0];    
  67.         [theOrch run];                
  68.         [Conductor startPerformance];
  69.             
  70.         [Conductor lockPerformance];
  71.  
  72.         // doesn't matter which notes here, will get updated later
  73.         D1 = MAXLENGTH;
  74.         D2 = MAXD2LENGTH;
  75.  
  76.         panval = -45.0;
  77.         pan_incr = 90.0/(numflutes-1);
  78.         for(j = 0; j < numflutes; j++) {
  79.             theIns[j] = [SynthInstrument new];
  80.             [theIns[j] setSynthPatchClass:[FluteIns class]];   
  81.             [theIns[j] setSynthPatchCount:1];
  82.             theNote[j] = [Note new];
  83.             [theNote[j] setNoteType:MK_noteOn];     
  84.             [theNote[j] setNoteTag:MKNoteTag()];
  85.             [theNote[j] setPar:MK_amp0 toDouble:0.0];                        
  86.             [theNote[j] setPar:MK_amp1 toDouble:0.0];                        
  87.             [theNote[j] setPar:MY_outAmp toDouble:0.3];
  88.             [theNote[j] setPar:MK_bearing toDouble:panval];
  89.             panval += pan_incr;
  90.             [theNote[j] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  91.             [theNote[j] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  92.             [[theIns[j] noteReceiver] receiveNote:theNote[j]];
  93.             }
  94.  
  95.         [Conductor unlockPerformance];
  96.         }
  97.         
  98.     return(self);
  99. }
  100.  
  101. - StartAndStop:sender
  102. {
  103.     int i;
  104.     int MY_outAmp = [[Note class] parName: "MY_outAmp"];
  105.     
  106.     if (going == 0) {
  107.         [self setup];
  108.         switch (perform_switch) {
  109.             case 0:
  110.                 [self doPulsing];
  111.                 break;
  112.             case 1:
  113.                 [self doCanon];
  114.                 break;
  115.             case 2:
  116.                 [self doPhasing];
  117.                 break;
  118.             case 3:
  119.                 [self doInterlock];
  120.                 break;
  121.             }
  122.         going = 1;
  123.         }
  124.     else {
  125.         [Conductor lockPerformance];
  126.         for (i = 0; i < NUMFLUTES; i++) {
  127.             theNoteOff[i][0][0] = [Note new];
  128.             [theNoteOff[i][0][0] setNoteType:MK_noteOff];     
  129.             [theNoteOff[i][0][0] setNoteTag:[theNote[i] noteTag]];
  130.             [theNoteOff[i][0][0] setPar:MK_amp0 toDouble:0.0];                        
  131.             [theNoteOff[i][0][0] setPar:MK_amp1 toDouble:0.0];                        
  132.             [theNoteOff[i][0][0] setPar:MY_outAmp toDouble:0.0];
  133.             [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][0][0]];
  134.             
  135.             [theIns[i] free];
  136.             }
  137.         [Conductor unlockPerformance];
  138.  
  139.         [Conductor finishPerformance];
  140.         
  141.         [theOrch flushTimedMessages];
  142.         [theOrch free];
  143.  
  144.         going = 0;
  145.         }
  146.  
  147.     return(self);
  148. }
  149.  
  150.  
  151. - doPulsing;
  152. {
  153.     int MY_dLineLength = [[Note class] parName: "MY_dLineLength"];
  154.     int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"];
  155.     int MY_delay2Length = [[Note class] parName: "MY_delay2Length"];
  156.     int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"];
  157.     
  158.     double playspeed = 0.23;
  159.     double notedur = 0.17;
  160.     double AMP1,AMP1incr;
  161.     double D1,D2;
  162.     int numpulses,halfway;
  163.     int Reichons[NUMNOTES];
  164.     int i,j;
  165.     int val_int;
  166.     int turnflag;
  167.     double val_double;
  168.     double playtime;
  169.     
  170.             
  171.     [Conductor lockPerformance];         /* Prepare to send MK message */
  172.  
  173.     // choose notes
  174.     // first of all, clear out the placeholder array (for dups)
  175.     for (j = 0; j < NUMNOTES; j++) Reichons[j] = 0;
  176.  
  177.     // now choose a unique note value for each flute
  178.     for(j = 0; j < NUMFLUTES; j++) {
  179.         do {
  180.             val_int = [theRand GetIndex:NUMNOTES-1];
  181.             }
  182.         while (Reichons[val_int] == 1);
  183.         
  184.         Reichons[val_int] = 1;
  185.         
  186.         D1 = Reichnotes[val_int][0];
  187.         D2 = Reichnotes[val_int][1];
  188.  
  189. // set up a Note with this note info and send it out --
  190. // assumption here is that the -play method is queued to be called
  191. // at the correct time to start a new chord
  192.  
  193.         theNoteUpdate[j] = [Note new];
  194.         [theNoteUpdate[j] setNoteType:MK_noteUpdate]; 
  195.         [theNoteUpdate[j] setNoteTag:[theNote[j] noteTag]];
  196.         [theNoteUpdate[j] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  197.         [theNoteUpdate[j] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  198.         [theNoteUpdate[j] setPar:MK_amp1 toDouble:0.0];
  199.         [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteUpdate[j]];
  200.  
  201.         }
  202.  
  203. // at this point, the flutes all are set to the correct note
  204. // now to decide the breath for each flute, and then set up the
  205. // phrase
  206.  
  207.     for (j = 0; j < NUMFLUTES; j++) {
  208.         // choose the number of pulses
  209.         numpulses = [theRand GetIndexRangeHi:LBREATH Lo:SBREATH];
  210.         halfway = numpulses/2;
  211.         turnflag = 0;            
  212.         playtime = playspeed;
  213.         AMP1 = 0.4;
  214.         val_double = [theRand GetNumberRangeHi:0.9 Lo:0.8];
  215.         AMP1incr = (val_double - AMP1)/(double)numpulses;
  216.  
  217.         for (i = 0; i < numpulses; i++) {
  218.             theNoteOn[j][0][0] = [Note new];
  219.             [theNoteOn[j][0][0] setNoteType:MK_noteUpdate]; 
  220.             [theNoteOn[j][0][0] setNoteTag:[theNote[j] noteTag]]; 
  221.             [theNoteOn[j][0][0] setPar:MK_amp1 toDouble:AMP1];
  222.             [theNoteOn[j][0][0] setPar:MY_envelopeSlew toDouble:0.001];        
  223.             [theNoteOn[j][0][0] setPar:MY_noiseVolume toDouble:0.007];
  224.             [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteOn[j][0][0] withDelay:playtime];
  225.  
  226.             theNoteOff[j][0][0] = [Note new];
  227.             [theNoteOff[j][0][0] setNoteType:MK_noteUpdate]; 
  228.             [theNoteOff[j][0][0] setNoteTag:[theNote[j] noteTag]];                         
  229.             [theNoteOff[j][0][0] setPar:MK_amp1 toDouble:0.0];
  230.             [theNoteOff[j][0][0] setPar:MY_envelopeSlew toDouble:1.0];        
  231.             [theNoteOff[j][0][0] setPar:MY_noiseVolume toDouble:0.001];        
  232.             [[theIns[j] noteReceiver] receiveAndFreeNote:theNoteOff[j][0][0] withDelay:playtime+notedur];
  233.             
  234.         playtime = playtime + (playspeed + [theRand GetNumber:0.01]);
  235.         if ((i > halfway) && (turnflag == 0)) {
  236.             AMP1incr *= -1.0;
  237.             turnflag = 1;
  238.             }
  239.         AMP1 = AMP1 + AMP1incr;                
  240.         }
  241.     }
  242.  
  243.     [[Conductor defaultConductor] sel:@selector(doPulsing) to:self withDelay:playtime argCount:0];
  244.                      
  245.     [Conductor unlockPerformance];
  246.  
  247.     return self;
  248. }
  249.  
  250.  
  251. - doCanon
  252. {
  253.     int MY_dLineLength = [[Note class] parName: "MY_dLineLength"];
  254.     int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"];
  255.     int MY_delay2Length = [[Note class] parName: "MY_delay2Length"];
  256.     int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"];
  257.  
  258.     int i,j,k;
  259.     int nrunnotes;
  260.     double D1,D2;
  261.     double playtime,canon_delay;
  262.     static int long_incr;
  263.     static float longdur_mult;
  264.     static int reg_incr, reg_hi, reg_lo;
  265.     static float run_prob, runprob_incr, run_direction;
  266.     static float rest_prob, restprob_incr;
  267.     static float amp_hi, amphi_incr, amp_lo, amplo_incr;
  268.     double noiseval;
  269.             
  270.     [Conductor lockPerformance];
  271.     
  272.     // set up:
  273.     if (going == 0) {            
  274.         // set up some initial flags
  275.         long_incr = LONGSTART;
  276.         longdur_mult = (float)[theRand GetIndexRangeHi:10 Lo:6];
  277.         reg_incr = REGSTART;
  278.         reg_hi = 4;
  279.         reg_lo = 0;
  280.         runprob_incr = RUNPROBINCR;
  281.         run_prob = 0.0;
  282.         run_direction = UP;
  283.         restprob_incr = 0.0 - RESTPROBINCR;
  284.         rest_prob = 0.4;
  285.         amphi_incr = AMPHIINCR;
  286.         amp_hi = 0.8;
  287.         amplo_incr = AMPLOINCR;
  288.         amp_lo = 0.5;
  289.         }
  290.  
  291.         
  292.     // load up the PITCH, AMP, and DUR arrays with values:
  293.     for (j = 0; j < ARRNOTES; j++) {
  294.         // select pitch indices
  295.         if (reg_incr < REGSECTDUR) {
  296.             PITCH[j] = [theRand GetIndexRangeHi:reg_hi Lo:reg_lo];
  297.             if (reg_incr < 0) {
  298.                 reg_incr = REGSTART;
  299.                 if ([theRand GetNumber] < 0.5) {
  300.                     reg_hi = 4;
  301.                     reg_lo = 0;
  302.                     }
  303.                 else {
  304.                     reg_hi = 16;
  305.                     reg_lo = 11;
  306.                     }
  307.                 }
  308.             }
  309.         else {
  310.             PITCH[j] = [theRand GetIndex:16];
  311.             }
  312.         AMP[j] = [theRand GetNumberRangeHi:amp_hi Lo:amp_lo];
  313.         if ([theRand GetNumber] < rest_prob) {
  314.             AMP[j] = 0.0;
  315.             }
  316.         DUR[j] = Beats[ [theRand GetIndex:3] ];
  317.         if (long_incr < LONGSECTDUR) {
  318.             DUR[j] *= longdur_mult;
  319.             if (long_incr < 0) {
  320.                 long_incr = LONGSTART;
  321.                 longdur_mult = (float)[theRand GetIndexRangeHi:10 Lo:6];
  322.                 }
  323.             }
  324.         }
  325.  
  326.     reg_incr--;
  327.     long_incr--;    
  328.     run_prob += runprob_incr;
  329.     if ( (run_prob > 1.0) || (run_prob < 0.0) )
  330.         runprob_incr = 0.0 - runprob_incr;
  331.     rest_prob += restprob_incr;
  332.     if ( (rest_prob > 0.4) || (rest_prob < 0.0) )
  333.         restprob_incr = 0.0 -restprob_incr;
  334.     amp_hi += amphi_incr;
  335.     if ( (amp_hi > 0.95) || (amp_hi < 0.75) )
  336.         amphi_incr = 0.0 - amphi_incr;
  337.     amp_lo += amplo_incr;
  338.     if ( (amp_lo > 0.65) || (amp_lo < 0.4) )
  339.         amplo_incr = 0.0 - amplo_incr;
  340.  
  341.     playtime = 0.0;
  342.     for (j = 0; j < ARRNOTES; j++) {
  343.         // test and possibly do a short run here
  344.         if ( [theRand GetNumber] < run_prob ) {
  345.             // choose the number of notes in the run
  346.             nrunnotes = [theRand GetIndexRangeHi:RUNNOTES Lo:1];
  347.             // choose the run-note duration
  348.             if ( [theRand GetNumber] > 0.9 ) {
  349.                 DUR[j] = SIXTEENTH;
  350.                 }
  351.             else {
  352.                 DUR[j] = EIGHTH;
  353.                 }
  354.  
  355.             // choose the run direction
  356.             if (run_prob < 0.9) {
  357.                 if ( [theRand GetNumber] > 0.5 ) {
  358.                     run_direction = UP;
  359.                     }
  360.                 else {
  361.                     run_direction = DOWN;
  362.                     }
  363.                 }
  364.             else {        // I like the sound of this
  365.                 DUR[j] = SIXTEENTH;
  366.                 nrunnotes = 4;
  367.                 }                            
  368.                     
  369.             // now make the runs!
  370.             for (k = 0; k < nrunnotes; k++) {
  371.                 if (run_direction == UP) {                    
  372.                     if (PITCH[j] > 12) PITCH[j] = [theRand GetIndex:12];
  373.                     D1 = Reichnotes[PITCH[j]+k][0];
  374.                     D2 = Reichnotes[PITCH[j]+k][1];
  375.                     }
  376.                 else {
  377.                     if (PITCH[j] < 5) PITCH[j] = [theRand GetIndexRangeHi:16 Lo:5];
  378.                     D1 = Reichnotes[PITCH[j]-k][0];
  379.                     D2 = Reichnotes[PITCH[j]-k][1];
  380.                     }
  381.                 
  382.                 canon_delay = 0.0;                        
  383.                 for (i = 0; i < NUMFLUTES; i++) {
  384.                     theNoteRun[i][j][k] = [Note new];
  385.                     [theNoteRun[i][j][k] setNoteType:MK_noteUpdate]; 
  386.                     [theNoteRun[i][j][k] setNoteTag:[theNote[i] noteTag]];         
  387.                     [theNoteRun[i][j][k] setPar:MK_amp1 toDouble:AMP[j]];
  388.                     [theNoteRun[i][j][k] setPar:MY_envelopeSlew toDouble:0.001];
  389.                     noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015];        
  390.                     [theNoteRun[i][j][k] setPar:MY_noiseVolume toDouble:noiseval];
  391.                     
  392.                     D1 += [theRand GetPlusMinus:0.0001];    
  393.                     D2 += [theRand GetPlusMinus:0.0001];    
  394.  
  395.                     [theNoteRun[i][j][k] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  396.                     [theNoteRun[i][j][k] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  397.                     [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteRun[i][j][k] withDelay:playtime+canon_delay];
  398.                     canon_delay += (CANONPT + [theRand GetNumber:0.001]);
  399.                     }
  400.                 playtime += DUR[j];
  401.                 }
  402.             }
  403.  
  404.         // play a "normal" note
  405.         else {
  406.             canon_delay = 0.0;
  407.             for (i = 0; i < NUMFLUTES; i++) {
  408.                 theNoteOn[i][j][0] = [Note new];
  409.                 [theNoteOn[i][j][0] setNoteType:MK_noteUpdate]; 
  410.                 [theNoteOn[i][j][0] setNoteTag:[theNote[i] noteTag]];         
  411.                 [theNoteOn[i][j][0] setPar:MK_amp1 toDouble:AMP[j]];
  412.                 [theNoteOn[i][j][0] setPar:MY_envelopeSlew toDouble:0.001];        
  413.                 noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015];        
  414.                 [theNoteOn[i][j][0] setPar:MY_noiseVolume toDouble:noiseval];
  415.  
  416.                 D1 = Reichnotes[PITCH[j]][0];
  417.                 D2 = Reichnotes[PITCH[j]][1];
  418.                     
  419.                 D1 += [theRand GetPlusMinus:0.0001];    
  420.                 D2 += [theRand GetPlusMinus:0.0001];    
  421.  
  422.                 [theNoteOn[i][j][0] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  423.                 [theNoteOn[i][j][0] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  424.                 [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][0] withDelay:playtime+canon_delay];
  425.  
  426.                 theNoteOff[i][j][0] = [Note new];
  427.                 [theNoteOff[i][j][0] setNoteType:MK_noteUpdate]; 
  428.                 [theNoteOff[i][j][0] setNoteTag:[theNote[i] noteTag]];                                     
  429.                 [theNoteOff[i][j][0] setPar:MK_amp1 toDouble:0.0];
  430.                 [theNoteOff[i][j][0] setPar:MY_envelopeSlew toDouble:0.001];        
  431.                 [theNoteOff[i][j][0] setPar:MY_noiseVolume toDouble:0.0];
  432.             
  433.                 [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][0] withDelay:playtime+canon_delay+DUR[j]];
  434.                 canon_delay += (CANONPT + [theRand GetNumber:0.001]);
  435.                 }
  436.             playtime = 0.2 + playtime + (DUR[j] + [theRand GetNumber:0.01]);
  437.             }
  438.         }
  439.  
  440.     [[Conductor defaultConductor] sel:@selector(doCanon) to:self withDelay:playtime argCount:0];
  441.                      
  442.     [Conductor unlockPerformance];
  443.  
  444.     return self;
  445. }
  446.  
  447.  
  448. - doPhasing
  449. {
  450.     int MY_dLineLength = [[Note class] parName: "MY_dLineLength"];
  451.     int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"];
  452.     int MY_delay2Length = [[Note class] parName: "MY_delay2Length"];
  453.     int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"];
  454.  
  455.     double D1,D2;
  456.     int i,j;
  457.     double playtime;
  458.     static double phase_delay;
  459.     static int slurflags[ARRNOTES];
  460.     float noiseval;
  461.  
  462.     [Conductor lockPerformance];
  463.  
  464.     if (going == 0) {            
  465.         // load up the PITCH, AMP, slurflags, and DUR arrays with values:
  466.         for (j = 0; j < ARRNOTES; j++) {
  467.             // select pitch indices from all the notes
  468.             PITCH[j] = [theRand GetIndex:17];
  469.             AMP[j] = [theRand GetNumberRangeHi:0.99 Lo:0.7];
  470.             if (PITCH[j] > 15) {
  471.                 PITCH[j] = 0;
  472.                 AMP[j] = 0.0;
  473.                 }
  474.             DUR[j] = Beats[ [theRand GetIndex:3] ];
  475.             
  476.             slurflags[j] = 0;
  477.             if ( [theRand GetNumber] < SLURPROB) slurflags[j] = 1;
  478.             }
  479.         phase_delay = 0.0;
  480.         }
  481.         
  482.     // queue up the notes for the two flutes
  483.     playtime = 0.0;
  484.     for (j = 0; j < ARRNOTES; j++) {
  485.         for (i = 0; i < numflutes; i++) {
  486.             theNoteOn[i][j][0] = [Note new];
  487.             [theNoteOn[i][j][0] setNoteType:MK_noteUpdate]; 
  488.             [theNoteOn[i][j][0] setNoteTag:[theNote[i] noteTag]];         
  489.             [theNoteOn[i][j][0] setPar:MK_amp1 toDouble:AMP[j]];
  490.             [theNoteOn[i][j][0] setPar:MY_envelopeSlew toDouble:0.001];        
  491.             noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015];        
  492.             [theNoteOn[i][j][0] setPar:MY_noiseVolume toDouble:noiseval];
  493.  
  494.             D1 = Reichnotes[PITCH[j]][0];
  495.             D2 = Reichnotes[PITCH[j]][1];
  496.                     
  497.             D1 += [theRand GetPlusMinus:0.0001];    
  498.             D2 += [theRand GetPlusMinus:0.0001];    
  499.                 
  500.             [theNoteOn[i][j][0] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  501.             [theNoteOn[i][j][0] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  502.             [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][0] withDelay:playtime + ((float)i * phase_delay)];
  503.  
  504.  
  505.             if (slurflags[j] == 0) {
  506.                 theNoteOff[i][j][0] = [Note new];
  507.                 [theNoteOff[i][j][0] setNoteType:MK_noteUpdate]; 
  508.                 [theNoteOff[i][j][0] setNoteTag:[theNote[i] noteTag]];                                     
  509.                 [theNoteOff[i][j][0] setPar:MK_amp1 toDouble:0.0];
  510.                 [theNoteOff[i][j][0] setPar:MY_envelopeSlew toDouble:0.001];        
  511.                 [theNoteOff[i][j][0] setPar:MY_noiseVolume toDouble:0.0];
  512.             
  513.                 [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][0] withDelay:playtime+ ((float)i * phase_delay) + DUR[j]];
  514.                 }
  515.             }
  516.         playtime = 0.2 + playtime + (DUR[j] + [theRand GetNumber:0.01]);
  517.         }
  518.             
  519.     phase_delay += (PHASEINCR + [theRand GetNumber:0.001]);
  520.  
  521.     [[Conductor defaultConductor] sel:@selector(doPhasing) to:self withDelay:playtime argCount:0];
  522.                      
  523.     [Conductor unlockPerformance];
  524.  
  525.     return self;
  526. }
  527.  
  528.  
  529. -doInterlock
  530. {
  531.     int MY_dLineLength = [[Note class] parName: "MY_dLineLength"];
  532.     int MY_noiseVolume = [[Note class] parName: "MY_noiseVolume"];
  533.     int MY_delay2Length = [[Note class] parName: "MY_delay2Length"];
  534.     int MY_envelopeSlew = [[Note class] parName: "MY_envelopeSlew"];
  535.  
  536.     int i,j,k;
  537.     double playtime;
  538.     static int reg_incr, reg_hi, reg_lo;
  539.     static float amp_hi, amphi_incr, amp_lo, amplo_incr;
  540.     float noiseval;
  541.     double D1,D2;
  542.     int cycles;
  543.     float cycle_delay;
  544.  
  545.     [Conductor lockPerformance];
  546.  
  547.     if (going == 0) {
  548.         // set up some initial flags
  549.         reg_incr = REGSTART;
  550.         reg_hi = 4;
  551.         reg_lo = 0;
  552.         amphi_incr = AMPHIINCR;
  553.         amp_hi = 0.8;
  554.         amplo_incr = AMPLOINCR;
  555.         amp_lo = 0.5;
  556.         }
  557.         
  558.     for (i = 0; i < NUMFLUTES; i++) {
  559.         // load up the PITCH, AMP, and DUR arrays with new values:
  560.         for (j = 0; j < CYCARRNOTES; j++) {
  561.             // select pitch indices
  562.             if (reg_incr < REGSECTDUR) {
  563.                 PITCH[j] = [theRand GetIndexRangeHi:reg_hi Lo:reg_lo];
  564.                 if (reg_incr < 0) {
  565.                     reg_incr = REGSTART;
  566.                     if ([theRand GetNumber] < 0.5) {
  567.                         reg_hi = 4;
  568.                         reg_lo = 0;
  569.                         }
  570.                     else {
  571.                         reg_hi = 16;
  572.                         reg_lo = 12;
  573.                         }
  574.                     }
  575.                 }
  576.             else {
  577.                 PITCH[j] = [theRand GetIndex:16];
  578.                 }
  579.             AMP[j] = [theRand GetNumberRangeHi:amp_hi Lo:amp_lo];
  580.             DUR[j] = Beats[ [theRand GetIndex:3] ];
  581.             }
  582.  
  583.         cycles = [theRand GetIndexRangeHi:NCYCS Lo:3];
  584.         cycle_delay = (CYCMEASURE * (float)(i * 4)) + (QUARTER * (float)i);
  585.         for (k = 0; k < cycles; k++) {
  586.             playtime = 0.0;
  587.             for (j = 0; j < CYCARRNOTES; j++) {
  588.                 theNoteOn[i][j][k] = [Note new];
  589.                 [theNoteOn[i][j][k] setNoteType:MK_noteUpdate]; 
  590.                 [theNoteOn[i][j][k] setNoteTag:[theNote[i] noteTag]];         
  591.                    [theNoteOn[i][j][k] setPar:MK_amp1 toDouble:AMP[j]];
  592.                    [theNoteOn[i][j][k] setPar:MY_envelopeSlew toDouble:0.001];        
  593.                 noiseval = [theRand GetNumberRangeHi:0.035 Lo:0.015];        
  594.                    [theNoteOn[i][j][k] setPar:MY_noiseVolume toDouble:noiseval];
  595.  
  596.                 D1 = Reichnotes[PITCH[j]][0];
  597.                 D2 = Reichnotes[PITCH[j]][1];
  598.                     
  599.                 D1 += [theRand GetPlusMinus:0.0001];    
  600.                 D2 += [theRand GetPlusMinus:0.0001];    
  601.                 
  602.                 [theNoteOn[i][j][k] setPar:MY_dLineLength toDouble: (MINLENGTH + (MAXLENGTH - MINLENGTH) * D1)];    
  603.                 [theNoteOn[i][j][k] setPar:MY_delay2Length toDouble: (MAXD2LENGTH * D2)];
  604.                 [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOn[i][j][k] withDelay:playtime+cycle_delay];
  605.  
  606.                 theNoteOff[i][j][k] = [Note new];
  607.                 [theNoteOff[i][j][k] setNoteType:MK_noteUpdate]; 
  608.                 [theNoteOff[i][j][k] setNoteTag:[theNote[i] noteTag]];                                     
  609.                 [theNoteOff[i][j][k] setPar:MK_amp1 toDouble:0.0];
  610.                 [theNoteOff[i][j][k] setPar:MY_envelopeSlew toDouble:0.001];        
  611.                 [theNoteOff[i][j][k] setPar:MY_noiseVolume toDouble:0.0];
  612.            
  613.                 [[theIns[i] noteReceiver] receiveAndFreeNote:theNoteOff[i][j][k] withDelay:playtime+cycle_delay+DUR[j]];
  614.                 playtime = playtime + (DUR[j] + [theRand GetNumber:0.01]);
  615.                 }
  616.                     
  617.             cycle_delay += (CYCMEASURE + [theRand GetNumber:0.001]);
  618.             }
  619.         }                
  620.  
  621.     reg_incr--;
  622.     amp_hi += amphi_incr;
  623.     if ( (amp_hi > 0.95) || (amp_hi < 0.75) )
  624.         amphi_incr = 0.0 - amphi_incr;
  625.     amp_lo += amplo_incr;
  626.     if ( (amp_lo > 0.65) || (amp_lo < 0.4) )
  627.         amplo_incr = 0.0 - amplo_incr;
  628.  
  629.     [[Conductor defaultConductor] sel:@selector(doInterlock) to:self withDelay:(CYCMEASURE * 7) argCount:0];
  630.                      
  631.     [Conductor unlockPerformance];
  632.  
  633.     return self;
  634. }
  635.  
  636.  
  637. - setPulsing:sender
  638. {
  639.     perform_switch = 0;
  640.     numflutes = NUMFLUTES;
  641.     
  642.     return(self);
  643. }
  644.  
  645.  
  646. - setCanon:sender
  647. {
  648.     perform_switch = 1;
  649.     numflutes = NUMFLUTES;
  650.     
  651.     return(self);
  652. }
  653.  
  654.  
  655. - setPhasing:sender
  656. {
  657.     perform_switch = 2;
  658.     numflutes = 2;
  659.     
  660.     return(self);
  661. }
  662.  
  663.  
  664. - setInterlock:sender
  665. {
  666.     perform_switch = 3;
  667.     numflutes = NUMFLUTES;
  668.     
  669.     return(self);
  670. }
  671.  
  672.  
  673. @end
  674.