상속: NScumm.Core.Audio.MidiDriverBase
예제 #1
0
        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;
            }
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
파일: Part.cs 프로젝트: scemino/nscumm
        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;
        }
예제 #4
0
 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();
 }