public void Do(Player player, byte[] msg, ushort len) { IMuseInternal se = player._se; switch (msg[0]) { case 0: // Trigger Event // Triggers are set by doCommand(ImSetTrigger). // When a SysEx marker is encountered whose sound // ID and marker ID match what was set by ImSetTrigger, // something magical is supposed to happen.... for (var a = 0; a < se._snm_triggers.Length; ++a) { if (se._snm_triggers[a].Sound == player.Id && se._snm_triggers[a].Id == msg[1]) { se._snm_triggers[a].Sound = se._snm_triggers[a].Id = 0; se.DoCommand(8, se._snm_triggers[a].Command); break; } } break; case 1: // maybe_jump. if (player.Scanning) break; using (var br = new BinaryReader(new MemoryStream(msg))) { br.ReadByte(); player.MaybeJump(br.ReadByte(), (uint)(br.ReadByte() - 1), (uint)((br.ReadUInt16BigEndian() - 1) * 4 + br.ReadByte()), (uint)((br.ReadByte() * TicksPerBeat) >> 2) + br.ReadByte()); } break; default: scummSysEx.Do(player, msg, len); break; } }
public void Do(Player player, byte[] msg, ushort len) { IMuseInternal se = player._se; int p = 0; byte code; switch (code = msg[p++]) { case 0: { // Allocate new part. // There are 8 bytes (after decoding!) of useful information here. // Here is what we know about them so far: // BYTE 0: Channel # // BYTE 1: BIT 01(0x01): Part on?(1 = yes) // BIT 02(0x02): Reverb? (1 = yes) [bug #1088045] // BYTE 2: Priority adjustment // BYTE 3: Volume [guessing] // BYTE 4: Pan [bug #1088045] // BYTE 5: BIT 8(0x80): Percussion?(1 = yes) [guessed?] // BYTE 5: Transpose, if set to 0x80(=-1) it means no transpose // BYTE 6: Detune // BYTE 7: Pitchbend factor [bug #1088045] // BYTE 8: Program var part = player.GetPart((byte)(msg[p] & 0x0F)); var buf = DecodeSysExBytes(msg, p + 1, len - 1); if (part != null) { part.SetOnOff((buf[0] & 0x01) != 0); part.EffectLevel((byte)(((buf[0] & 0x02) != 0) ? 127 : 0)); part.Priority = (sbyte)buf[1]; part.Volume = buf[2]; part.Pan = buf[3]; part.Percussion = player.SupportsPercussion && ((buf[4] & 0x80) > 0); part.SetTranspose((sbyte)buf[4]); part.Detune = buf[5]; part.PitchBendFactor(buf[6]); if (part.Percussion) { if (part.MidiChannel != null) { part.Off(); se.ReallocateMidiChannels(player.MidiDriver); } } else { if (player.IsMIDI) { // Even in cases where a program does not seem to be specified, // i.e. bytes 15 and 16 are 0, we send a program change because // 0 is a valid program number. MI2 tests show that in such // cases, a regular program change message always seems to follow // anyway. part.Instrument.Program(buf[7], player.IsMT32); } else { // Like the original we set up the instrument data of the // specified program here too. In case the global // instrument data is not loaded already, this will take // care of setting a default instrument too. se.CopyGlobalInstrument(buf[7], part.Instrument); } part.SendAll(); } } } break; case 1: // Shut down a part. [Bug 1088045, comments] { var part = player.GetPart(msg[p]); if (part != null) part.Uninit(); } break; case 2: // Start of song. Ignore for now. break; case 16: // AdLib instrument definition(Part) { var a = (byte)(msg[p++] & 0x0F); ++p; // Skip hardware type var part = player.GetPart(a); if (part != null) { if (len == 62 || len == 48) { var buf = DecodeSysExBytes(msg, p, len - 2); part.SetInstrument(buf); } else { part.ProgramChange(254); // Must be invalid, but not 255 (which is reserved) } } } break; case 17: // AdLib instrument definition(Global) { p += 2; // Skip hardware type and... whatever came right before it var a = msg[p++]; var buf = DecodeSysExBytes(msg, p, len - 3); if (len == 63 || len == 49) se.SetGlobalInstrument(a, buf); } break; case 33: // Parameter adjust { var a = msg[p++] & 0x0F; ++p; // Skip hardware type var buf = DecodeSysExBytes(msg, p, len - 2); var part = player.GetPart((byte)a); if (part != null) { using (var br = new BinaryReader(new MemoryStream(buf))) { part.SetParam((byte)br.ReadUInt16BigEndian(), (int)br.ReadUInt16BigEndian()); } } } break; case 48: // Hook - jump { if (player.Scanning) break; var buf = DecodeSysExBytes(msg, p + 1, len - 1); using (var br = new BinaryReader(new MemoryStream(buf))) { player.MaybeJump(br.ReadByte(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian()); } } break; case 49: // Hook - global transpose { var buf = DecodeSysExBytes(msg, p + 1, len - 1); player.MaybeSetTranspose(buf); } break; case 50: // Hook - part on/off { var tmp = msg[p++] & 0x0F; var buf = DecodeSysExBytes(msg, p, len - 1, 1); buf[0] = (byte)tmp; player.MaybePartOnOff(buf); } break; case 51: // Hook - set volume { var tmp = msg[p++] & 0x0F; var buf = DecodeSysExBytes(msg, p, len - 1, 1); buf[0] = (byte)tmp; player.MaybeSetVolume(buf); } break; case 52: // Hook - set program { var tmp = msg[p++] & 0x0F; var buf = DecodeSysExBytes(msg, p, len - 1, 1); buf[0] = (byte)tmp; player.MaybeSetProgram(buf); } break; case 53: // Hook - set transpose { var tmp = msg[p++] & 0x0F; var buf = DecodeSysExBytes(msg, p, len - 1, 1); buf[0] = (byte)tmp; player.MaybeSetTransposePart(buf); } break; case 64: // Marker p++; len--; while (len-- != 0) { se.HandleMarker(player.Id, msg[p++]); } break; case 80: // Loop { var buf = DecodeSysExBytes(msg, p + 1, len - 1); using (var br = new BinaryReader(new MemoryStream(buf))) { player.SetLoop(br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian(), br.ReadUInt16BigEndian()); } } break; case 81: // End loop player.ClearLoop(); break; case 96: // Set instrument { var part = player.GetPart((byte)(msg[p] & 0x0F)); var a = (msg[p + 1] & 0x0F) << 12 | (msg[p + 2] & 0x0F) << 8 | (msg[p + 3] & 0x0F) << 4 | (msg[p + 4] & 0x0F); if (part != null) part.SetInstrument((uint)a); } break; default: Debug.WriteLine("Unknown SysEx command {0}", (int)code); break; } }
public void Setup(Player player) { Player = player; Percussion = (player.IsMIDI && Channel == 9); // true; On = true; PriorityEffective = player.Priority; Priority = 0; _vol = 127; _vol_eff = player.GetEffectiveVolume(); _pan = Clamp(player.Pan, -64, 63); _transpose_eff = player.GetTranspose(); Transpose = 0; _detune = 0; _detune_eff = player.Detune; _pitchbend_factor = 2; _pitchbend = 0; _effect_level = player._se.IsNativeMT32 ? 127 : 64; Instrument.Clear(); _unassignedInstrument = true; _chorus = 0; _modwheel = 0; _bank = 0; Pedal = false; MidiChannel = null; }
public IMuseInternal() { _snm_triggers = new ImTrigger[16]; for (int i = 0; i < _snm_triggers.Length; i++) { _snm_triggers[i] = new ImTrigger(); } _channel_volume = new ushort[8]; _channel_volume_eff = new ushort[8]; _volchan_table = new ushort[8]; _players = new Player[8]; for (int i = 0; i < _players.Length; i++) { _players[i] = new Player(); } _player_limit = _players.Length; _parts = new Part[32]; for (int i = 0; i < _parts.Length; i++) { _parts[i] = new Part(); } _global_instruments = new Instrument[32]; for (int i = 0; i < _global_instruments.Length; i++) { _global_instruments[i] = new Instrument(); } _cmd_queue = new CommandQueue[64]; for (int i = 0; i < _cmd_queue.Length; i++) { _cmd_queue[i] = new CommandQueue(); } _deferredCommands = new DeferredCommand[4]; for (int i = 0; i < _deferredCommands.Length; i++) { _deferredCommands[i] = new DeferredCommand(); } _timer_info_adlib = new TimerCallbackInfo(); _timer_info_native = new TimerCallbackInfo(); }