Exemple #1
0
        public int Scan(uint totrack, uint tobeat, uint totick)
        {
            if (!_active || _parser == null)
            {
                return(-1);
            }

            if (tobeat == 0)
            {
                tobeat++;
            }

            TurnOffParts();
            Array.Clear(_active_notes, 0, _active_notes.Length);
            _scanning = true;

            // If the scan involves a track switch, scan to the end of
            // the current track so that our state when starting the
            // new track is fully up to date.
            if (totrack != _track_index)
            {
                _parser.JumpToTick(uint.MaxValue, true);
            }
            _parser.ActiveTrack = (int)totrack;
            if (!_parser.JumpToTick((tobeat - 1) * TicksPerBeat + totick, true))
            {
                _scanning = false;
                return(-1);
            }

            _scanning = false;
            _se.ReallocateMidiChannels(_midi);
            PlayActiveNotes();

            if (_track_index != totrack)
            {
                _track_index  = (int)totrack;
                _loop_counter = 0;
            }
            return(0);
        }
Exemple #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;
            }
        }