Please consider a donation to the Higher Intellect project. See https://preterhuman.net/donate.php or the Donate to Higher Intellect page for more info. |
MT32MusicComponent.c
Jump to navigation
Jump to search
/* File: MT32MusicComponent.c Contains: xxx put contents here xxx Written by: xxx put writers here xxx Copyright: © 1994-1996 by Apple Computer, Inc., all rights reserved. Change History (most recent first): <14> 4/8/96 dvb New Interfaces <13> 9/13/95 JB music dumpfile for new build <12> 8/21/95 dvb new musiccomponent.h stuff <10> 6/12/95 dvb <9+> fine tune the gaps yet again... NAMIDI had it all wrong. <9> 28-4-95 dvb CanDo implemented wrong for subclassed component <8> 14-3-95 dvb gap directive. <7+> delay packet type, set reserved to zero <7> 6-2-95 dvb patch params <6+> patch and timbre params as part of instrument <6> 5-1-95 dvb <5> 14-11-94 dvb upp fixes <4> 24-10-94 dvb minor <3+> make it cleaner for copying and reusing <3> 11-10-94 dvb <2> 10/3/94 JB Dispos... ==> Dispose... */ /* File: MT32MusicComponent.c Written by: dvb Copyright: © 1993-1994 by Apple Computer, Inc., all rights reserved. */ /*----------------------------------- Inclusions -----------------------------------*/ #ifdef MUSICDUMP #ifdef DUMP_USEINCLUDE #include MUSICDUMP #else #pragma load MUSICDUMP #endif #else #include "QTEnv.h" #include "MusicComponent.h" #endif /*----------------------------------- pascal ComponentResult Types -----------------------------------*/ #define kBaseResID 300 #define kSysexTimeGap 15 /* milliseconds midi bus gap after param change */ typedef struct { MusicComponent super; /* the component that does everything we cannot */ MusicComponent self; MusicMIDISendProcPtr midiProc; long midiProcRefCon; } GGlobals; #define MUSIC_BASENAME() MT32 #define MUSIC_GLOBALS() GGlobals *g #include "MusicComponent.k.h" /*----------------------------------- pascal ComponentResult Prototypes -----------------------------------*/ static ComponentFunctionUPP FindRoutine(short selektor); pascal ComponentResult MT32Open (GGlobals *g, ComponentInstance self); pascal ComponentResult MT32Close (GGlobals *g, ComponentInstance self); pascal ComponentResult MT32CanDo (GGlobals *g, short selektor); pascal ComponentResult MT32Version (GGlobals *g); static ComponentResult MT32WriteMIDI(GGlobals *g,int firstByte,...); static ComponentResult SetMT32Parameter(GGlobals *g,long p,short v); /*----------------------------------- The Stuff -----------------------------------*/ #define mt32ParamChannels 0x4000D #define mt32ParamTimbre 0x10000 #define mt32ParamPatch 0x0C000 pascal ComponentResult MT32MusicComponent( ComponentParameters *params, Handle storage ) { ComponentFunctionUPP gcProc; ComponentResult result; MusicComponent self; gcProc = 0; result = 0; self = (MusicComponent)params->params[0]; gcProc = FindRoutine(params->what); if (gcProc) result = CallComponentFunctionWithStorage(storage, params, gcProc); else result = DelegateComponentCall(params, ((GGlobals *)storage)->super); return result; } #define CCaseSelect(callName) \ case kComponent##callName##Select: \ componentProc = (ComponentFunctionUPP) MUSIC_BASENAME()callName; \ break #define CaseSelect(callName) \ case kMusic##callName##Select: \ componentProc = (ComponentFunctionUPP) MUSIC_BASENAME()callName; \ break #define DCaseSelect(callName) \ case kMusicDerived##callName##Select: \ componentProc = (ComponentFunctionUPP) MUSIC_BASENAME()Derived##callName; \ break static ComponentFunctionUPP FindRoutine(short selektor) { ComponentFunctionUPP componentProc; switch (selektor) { CCaseSelect(Open); CCaseSelect(Close); CCaseSelect(CanDo); CCaseSelect(Version); CaseSelect(SetMIDIProc); DCaseSelect(SetKnob); DCaseSelect(SetPart); DCaseSelect(SetInstrument); default: componentProc = 0; break; } return componentProc; } pascal ComponentResult MT32CanDo (GGlobals *g, short selektor) { ComponentResult result; result = FindRoutine(selektor) != 0; if(!result) result = ComponentFunctionImplemented(g->super,selektor); return result; } pascal ComponentResult MT32Version (GGlobals *g) { return 0x00010001; } pascal ComponentResult MT32Open (GGlobals *g, ComponentInstance self) { ComponentResult result; g = (GGlobals *)NewPtrClear(sizeof(GGlobals)); if (result = MemError()) goto goHome; g->self = self; SetComponentInstanceStorage(self, (Handle)g); g->super = OpenDefaultComponent(kMusicComponentType,kGenericMusicComponentSubtype); if(!g->super) { result = -1; /* cant open synth err */ fail: SetComponentInstanceStorage(self, nil); DisposePtr((Ptr)g); goto goHome; } result = ComponentSetTarget(g->super,g->self); if(result) goto fail; result = MusicGenericConfigure(g->super,0, kGenericMusicDoMIDI + kGenericMusicCallKnobs + kGenericMusicCallParts + kGenericMusicCallInstrument, kBaseResID); /* tell it our resource ID */ if(result) goto fail; goHome: return result; } pascal ComponentResult MT32Close (GGlobals *g, ComponentInstance self) { ComponentResult result; SetMT32Parameter(g,0x1FFFFF,0); /* reset all parameters */ result = CloseComponent(g->super); DisposePtr((Ptr)g); SetComponentInstanceStorage(self,0); return result; } /* -------------------------------- -------------------------------- */ pascal ComponentResult MT32SetMIDIProc(GGlobals *g, MusicMIDISendProcPtr midiProc, long refCon) { ComponentResult result; short i; g->midiProc = midiProc; g->midiProcRefCon = refCon; result = MusicSetMIDIProc(g->super,midiProc,refCon); /* * Turn off the 6 PCM voices above, if * it happens to be a CM500. * This assumes we chose mode B for our unit. */ MT32WriteMIDI(g,0xF0,0x41,0x10,0x16,0x12, 0x52,0x00,0x0A, 0x10,0x10,0x10, 0x10,0x10,0x10, 0 ,0xF7,-3); /* * Turn off all 9 parts of the CM32 */ MT32WriteMIDI(g,0xF0,0x41,0x10,0x16,0x12, 0x10,0x00,0x0D, 0x10,0x10,0x10, 0x10,0x10,0x10, 0x10,0x10,0x10, 0 ,0xF7,-3); return result; } static ComponentResult MT32WriteMIDI(GGlobals *g,int firstByte,...) { MusicMIDIPacket somePacket; register unsigned char *w; register int *source; register short x; OSErr result; if(!g->midiProc) { result = cantSendToSynthesizerErr; goto goHome; } w = somePacket.data; source = &firstByte; do { x = *source++; if(x >= 0) *w++ = x; } while (x >= 0); if(x == -2 || x == -3) /* we're asked to compute checksum */ { unsigned char *w1,*w2; short sum; w1 = somePacket.data + 5; w2 = w - 2; sum = 0; while(w1 < w2) sum -= *w1++; *w2 = sum & 0x7F; } if(x == -3) // -3 is checksum and time gap before & after { MusicMIDIPacket gapPacket; gapPacket.length = 1; gapPacket.reserved = kMusicPacketTimeGap; gapPacket.data[0] = kSysexTimeGap; /* pause in milliseconds */ result = (*g->midiProc)(g->self,g->midiProcRefCon,&gapPacket;); somePacket.length = w - somePacket.data + 1; *w = kSysexTimeGap; somePacket.reserved = kMusicPacketTimeGap; } else { somePacket.length = w - somePacket.data; somePacket.reserved = 0; } result = (*g->midiProc)(g->self,g->midiProcRefCon,&somePacket;); goHome: return result; } pascal ComponentResult MT32DerivedSetKnob(GGlobals *g, long knobType,long knobNumber,long knobValue, long partNumber,GCPart *p, GenericKnobDescription *gkd) { ComponentResult result; short effectSetting; if(knobType == kGenericMusicKnob) result = SetMT32Parameter(g,gkd->hw1,knobValue); else if(knobType == kGenericMusicInstrumentKnob) { long param; partNumber--; if(gkd->hw1 & 0x80000000) param = mt32ParamPatch + partNumber * 0x10 + (gkd->hw1 & 0xFF); else param = mt32ParamTimbre + partNumber * 0xF6 + gkd->hw1; knobValue = knobValue + gkd->hw3 - gkd->kd.lowValue; result = SetMT32Parameter(g,param,knobValue); } return result; } ComponentResult SetMT32Parameter(GGlobals *g,long p,short v) { unsigned short ah,am,al; ComponentResult result; ah = (p>>14) & 0x7F; am = (p>>7) & 0x7F; al = p & 0x7F; result = MT32WriteMIDI(g, (int)0xF0, (int)0x41, (int)0x10, (int)0x16, (int)0x12, (int)ah, (int)am, (int)al, (int)v, (int)0, // checksum computed by writemidi (int)0xF7, (int)-3); #if 0 lame, lame, attach to packet if(g->midiProc) { MusicMIDIPacket somePacket; somePacket.length = 1; somePacket.reserved = kMusicPacketTimeGap; somePacket.data[0] = kSysexTimeGap; /* pause in milliseconds */ result = (*g->midiProc)(g->self,g->midiProcRefCon,&somePacket;); } #endif return result; } pascal ComponentResult MUSIC_BASENAME()DerivedSetPart(GGlobals *g, long partNumber,GCPart *p) { long param; short v; ComponentResult result; result = noErr; v = p->midiChannel; param = mt32ParamChannels + partNumber - 1; if(v == 0) v = 16; else v--; result = SetMT32Parameter(g,param,v); return result; } pascal ComponentResult MUSIC_BASENAME()DerivedSetInstrument(GGlobals *g, long partNumber,GCPart *p) /* * Set the knobs one by one. It would be cooler * if we could set them all at once. !!! */ { short i; ComponentResult result; result = noErr; for(i = 0; i < p->id.knobCount; i++) MusicSetPartKnob(g->self,partNumber,i+1,p->id.knob[i]); return result; }