This is EnvySimplified.m in view mode; [Download] [Up]
/* This is similar to Envy.m but it makes a number of assumptions about the Application that allow it to be much simpler: It assumes that all parameters will be present in every note and that only noteDurs without noteTags are used (as in software packages such as CSound, C-Music, or MUSIC 5). It also assumes that it will never be necessary to preempt running SynthPatches because the Application will never attempt to play too many simultaneous notes. Keep in mind that a convenient way to insure that parameters are present in every note is to include all parameters in an initial noteUpdate without a noteTag (this noteUpdate is merged into incoming noteDurs by the Music Kit.) The parameters are: amp, ampEnv, ampAtt, ampRel, freq0, freq1, freqEnv, freqAtt, freqRel, bearing See README for details. */ #import <musickit/unitgenerators/unitgenerators.h> #import "EnvySimplified.h" @implementation EnvySimplified static int ampAsymp, freqAsymp, osc, stereoOut, ampPp, freqPp, outPp; +patchTemplateFor:aNote { /* Returns a template describing the UnitGenerators and Patchpoints that comprise the patch. */ static PatchTemplate *theTemplate = nil; if (theTemplate) return theTemplate; theTemplate = [[PatchTemplate alloc] init]; ampAsymp = [theTemplate addUnitGenerator:[AsympUGx class]]; freqAsymp = [theTemplate addUnitGenerator:[AsympUGy class]]; osc = [theTemplate addUnitGenerator:[OscgafiUGxxyy class]]; stereoOut = [theTemplate addUnitGenerator:[Out2sumUGx class]]; ampPp = [theTemplate addPatchpoint:MK_xPatch]; freqPp = [theTemplate addPatchpoint:MK_yPatch]; outPp = ampPp; /* Reuse this patchpoint. */ return theTemplate; } /* Let's define a macro SE ("synth element") to make access more terse: */ #define SE(x) [self synthElementAt:x] - init { /* Sent once when the patch is created. */ [SE(ampAsymp) setOutput:SE(ampPp)]; [SE(freqAsymp) setOutput:SE(freqPp)]; [SE(osc) setAmpInput:SE(ampPp)]; [SE(osc) setIncInput:SE(freqPp)]; [SE(osc) setOutput:SE(outPp)]; [SE(osc) setTable:nil defaultToSineROM:YES]; return self; } - noteOnSelf:aNote { /* Sent when a noteOn is received */ Envelope *ampEnv = [aNote parAsEnvelope:MK_ampEnv]; double amp = [aNote parAsDouble:MK_amp]; double ampAtt = [aNote parAsDouble:MK_ampAtt]; double ampRel = [aNote parAsDouble:MK_ampRel]; Envelope *freqEnv = [aNote parAsEnvelope:MK_freqEnv]; double freq0 = [aNote parAsDouble:MK_freq0]; double freq1 = [aNote freq]; double freqAtt = [aNote parAsDouble:MK_freqAtt]; double freqRel = [aNote parAsDouble:MK_freqRel]; double bearing = [aNote parAsDouble:MK_bearing]; MKUpdateAsymp(SE(ampAsymp), ampEnv, 0.0, amp, ampAtt, ampRel, MK_NODVAL, MK_phraseOn); /* Amplitude envelope */ MKUpdateAsymp(SE(freqAsymp), freqEnv, [SE(osc) incAtFreq:freq0], [SE(osc) incAtFreq:freq1], freqAtt, freqRel, MK_NODVAL, MK_phraseOn); /* Freq env */ [SE(stereoOut) setBearing:bearing]; [SE(stereoOut) setInput:SE(outPp)]; /* Make connection to output */ [synthElements makeObjectsPerform:@selector(run)]; /* Broadcast "run" */ return self; } - (double)noteOffSelf:aNote { /* Sent when a noteOff is received */ [SE(freqAsymp) finish]; /* Signal release portion of freq envelope */ return [SE(ampAsymp) finish]; /* Return amplitude env's time to finish */ } - noteEndSelf { /* Sent when the patch is to go idle (at the end of the ampEnv release). */ [SE(stereoOut) idle]; /* Remove output from sample stream. */ [SE(freqAsymp) abortEnvelope]; /* Abort the freq envelope */ return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.