Beispiel #1
0
        private SongPlayer()
        {
            time   = new TimeBarrier();
            thread = new Thread(Tick)
            {
                Name = "SongPlayer Tick"
            };
            thread.Start();

            for (byte i = 0; i < 0x10; i++)
            {
                Tracks[i] = new Track(i);
            }
            for (int i = 0; i < soundVars.Length; i++)
            {
                soundVars[i] = new SoundVar();
            }
        }
Beispiel #2
0
        void ExecuteNext(Track track)
        {
            ArgType argOverrideType = 0;
            bool    useOverrideType = false;
            bool    doCmdWork       = true;
            byte    cmd             = sseq.Data[track.DataOffset++];

again:
            if (cmd == 0xA0) // Rand: [New Super Mario Bros (BGM_AMB_CHIKA)]
            {
                cmd             = sseq.Data[track.DataOffset++];
                argOverrideType = ArgType.Rand;
                useOverrideType = true;
                goto again;
            }
            else if (cmd == 0xA1) // Var: [New Super Mario Bros (BGM_AMB_SABAKU)]
            {
                cmd             = sseq.Data[track.DataOffset++];
                argOverrideType = ArgType.SoundVar;
                useOverrideType = true;
                goto again;
            }
            else if (cmd == 0xA2) // If: [Mario Kart DS (75)]
            {
                cmd       = sseq.Data[track.DataOffset++];
                doCmdWork = track.VariableFlag;
                goto again;
            }

            if (cmd < 0x80) // Notes
            {
                byte velocity = sseq.Data[track.DataOffset++];
                int  length   = ReadArg(track, useOverrideType ? argOverrideType : ArgType.VarLen);
                if (doCmdWork)
                {
                    byte key = (byte)(cmd + track.KeyShift).Clamp(0x0, 0x7F);
                    PlayNote(track, key, velocity, Math.Max(-1, length));
                    track.PortamentoKey = key;
                    if (track.ShouldWaitForNotesToFinish)
                    {
                        track.Delay = length;
                        if (length == 0)
                        {
                            track.WaitingForNoteToFinishBeforeContinuingXD = true;
                        }
                    }
                }
            }
            else
            {
                int cmdGroup = cmd & 0xF0;
                if (cmdGroup == 0x80)
                {
                    int arg = ReadArg(track, useOverrideType ? argOverrideType : ArgType.VarLen);
                    if (doCmdWork)
                    {
                        if (cmd == 0x80) // Rest
                        {
                            track.Delay = arg;
                        }
                        else if (cmd == 0x81 && arg <= byte.MaxValue) // Program Change
                        {
                            track.Voice = (byte)arg;
                        }
                    }
                }
                else if (cmdGroup == 0x90)
                {
                    switch (cmd)
                    {
                    case 0x93:     // Open Track
                    {
                        int index       = sseq.Data[track.DataOffset++];
                        int offset24bit = sseq.Data[track.DataOffset++] | (sseq.Data[track.DataOffset++] << 8) | (sseq.Data[track.DataOffset++] << 16);
                        if (doCmdWork)
                        {
                            Tracks[index].DataOffset = offset24bit;
                        }
                        break;
                    }

                    case 0x94:     // Goto
                    {
                        int offset24bit = sseq.Data[track.DataOffset++] | (sseq.Data[track.DataOffset++] << 8) | (sseq.Data[track.DataOffset++] << 16);
                        if (doCmdWork)
                        {
                            track.DataOffset = offset24bit;
                        }
                        break;
                    }

                    case 0x95:     // Call
                    {
                        int offset24bit = sseq.Data[track.DataOffset++] | (sseq.Data[track.DataOffset++] << 8) | (sseq.Data[track.DataOffset++] << 16);
                        if (doCmdWork && track.CallStackDepth < 3)
                        {
                            track.CallStack[track.CallStackDepth] = track.DataOffset;
                            track.CallStackDepth += 1;
                            track.DataOffset      = offset24bit;
                        }
                        break;
                    }
                    }
                }
                else if (cmdGroup == 0xB0)
                {
                    byte  varIndex = sseq.Data[track.DataOffset++];
                    short mathArg  = (short)ReadArg(track, useOverrideType ? argOverrideType : ArgType.Short);
                    if (doCmdWork)
                    {
                        SoundVar var = soundVars[varIndex];
                        switch (cmd)
                        {
                        case 0xB0:
                        {
                            Console.Write("Setvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            var.Value = mathArg;
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB1:
                        {
                            Console.Write("Addvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            var.Value += mathArg;
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB2:
                        {
                            Console.Write("Subvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            var.Value -= mathArg;
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB3:
                        {
                            Console.Write("Mulvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            var.Value *= mathArg;
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB4:
                        {
                            Console.Write("Divvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            if (mathArg != 0)
                            {
                                var.Value /= mathArg;
                            }
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB5:
                        {
                            Console.Write("Shiftvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            if (mathArg < 0)
                            {
                                var.Value = (short)(var.Value >> -mathArg);
                            }
                            else
                            {
                                var.Value = (short)(var.Value << mathArg);
                            }
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB6:     // [Mario Kart DS (75)]
                        {
                            Console.Write("Randvar {0} {1} (Old: {2}", varIndex, mathArg, var.Value);
                            bool negate = false;
                            if (mathArg < 0)
                            {
                                negate  = true;
                                mathArg = (short)-mathArg;
                            }
                            short val = (short)Utils.RNG.Next(mathArg + 1);
                            if (negate)
                            {
                                val = (short)-val;
                            }
                            var.Value = val;
                            Console.WriteLine(", New: {0})", var.Value);
                            break;
                        }

                        case 0xB8:
                        {
                            Console.WriteLine("CMPVar {0} == {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value == mathArg;
                            break;
                        }

                        case 0xB9:
                        {
                            Console.WriteLine("CMPVar {0} >= {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value >= mathArg;
                            break;
                        }

                        case 0xBA:
                        {
                            Console.WriteLine("CMPVar {0} > {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value > mathArg;
                            break;
                        }

                        case 0xBB:
                        {
                            Console.WriteLine("CMPVar {0} <= {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value <= mathArg;
                            break;
                        }

                        case 0xBC:
                        {
                            Console.WriteLine("CMPVar {0} < {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value < mathArg;
                            break;
                        }

                        case 0xBD:
                        {
                            Console.WriteLine("CMPVar {0} != {1} (Value: {2})", varIndex, mathArg, var.Value);
                            track.VariableFlag = var.Value != mathArg;
                            break;
                        }
                        }
                    }
                }
                else if (cmdGroup == 0xC0 || cmdGroup == 0xD0)
                {
                    int cmdArg = ReadArg(track, useOverrideType ? argOverrideType : ArgType.Byte);
                    if (doCmdWork)
                    {
                        switch (cmd)
                        {
                        case 0xC0:     // Panpot
                        {
                            track.Pan = (sbyte)(cmdArg - 0x40);
                            break;
                        }

                        case 0xC1:     // Volume
                        {
                            track.Volume = (byte)cmdArg;
                            break;
                        }

                        case 0xC2:     // Player Volume
                        {
                            Volume = (byte)cmdArg;
                            break;
                        }

                        case 0xC3:     // Key Shift
                        {
                            track.KeyShift = (sbyte)cmdArg;
                            break;
                        }

                        case 0xC4:     // Pitch Bend
                        {
                            track.Bend = (sbyte)cmdArg;
                            break;
                        }

                        case 0xC5:     // Pitch Bend Range
                        {
                            track.BendRange = (byte)cmdArg;
                            break;
                        }

                        case 0xC6:     // Priority
                        {
                            track.Priority = (byte)cmdArg;
                            break;
                        }

                        case 0xC7:     // Mono/Poly
                        {
                            track.ShouldWaitForNotesToFinish = cmdArg == 1;
                            break;
                        }

                        case 0xC8:     // Tie
                        {
                            track.Tie = cmdArg == 1;
                            track.CloseAllChannels();
                            break;
                        }

                        case 0xC9:     // Portamento Control
                        {
                            track.PortamentoKey = (byte)(cmdArg + track.KeyShift);
                            track.Portamento    = true;
                            break;
                        }

                        case 0xCA:     // LFO Depth
                        {
                            track.LFODepth = (byte)cmdArg;
                            break;
                        }

                        case 0xCB:     // LFO Speed
                        {
                            track.LFOSpeed = (byte)cmdArg;
                            break;
                        }

                        case 0xCC:     // LFO Type
                        {
                            track.LFOType = (LFOType)cmdArg;
                            break;
                        }

                        case 0xCD:     // LFO Range
                        {
                            track.LFORange = (byte)cmdArg;
                            break;
                        }

                        case 0xCE:     // Portamento Toggle
                        {
                            track.Portamento = cmdArg == 1;
                            break;
                        }

                        case 0xCF:     // Portamento Time
                        {
                            track.PortamentoTime = (byte)cmdArg;
                            break;
                        }

                        case 0xD0:     // Forced Attack
                        {
                            track.Attack = (byte)cmdArg;
                            break;
                        }

                        case 0xD1:     // Forced Decay
                        {
                            track.Decay = (byte)cmdArg;
                            break;
                        }

                        case 0xD2:     // Forced Sustain
                        {
                            track.Sustain = (byte)cmdArg;
                            break;
                        }

                        case 0xD3:     // Forced Release
                        {
                            track.Release = (byte)cmdArg;
                            break;
                        }

                        case 0xD4:     // Call
                        {
                            if (track.CallStackDepth < 3)
                            {
                                track.CallStack[track.CallStackDepth]      = track.DataOffset;
                                track.CallStackLoops[track.CallStackDepth] = (byte)cmdArg;
                                track.CallStackDepth += 1;
                            }
                            break;
                        }

                        case 0xD5:     // Expression
                        {
                            track.Expression = (byte)cmdArg;
                            break;
                        }

                        case 0xD6:     // Print
                        {
                            Console.WriteLine("Track {0}, Var {1}, Value{2}", track.Index, cmdArg, soundVars[cmdArg].Value);
                            break;
                        }
                        }
                    }
                }
                else if (cmdGroup == 0xE0)
                {
                    int cmdArg = ReadArg(track, useOverrideType ? argOverrideType : ArgType.Short);
                    if (doCmdWork)
                    {
                        switch (cmd)
                        {
                        case 0xE0:     // LFO Delay
                        {
                            track.LFODelay = (ushort)cmdArg;
                            break;
                        }

                        case 0xE1:     // Tempo
                        {
                            tempo = (ushort)cmdArg;
                            break;
                        }

                        case 0xE3:     // Sweep Pitch
                        {
                            track.SweepPitch = (short)cmdArg;
                            break;
                        }
                        }
                    }
                }
                else if (cmdGroup == 0xF0)
                {
                    if (doCmdWork)
                    {
                        switch (cmd)
                        {
                        case 0xFC:     // Loop End
                        {
                            if (track.CallStackDepth != 0)
                            {
                                byte count = track.CallStackLoops[track.CallStackDepth - 1];
                                if (count != 0)
                                {
                                    count--;
                                    if (count == 0)
                                    {
                                        track.CallStackDepth -= 1;
                                        break;
                                    }
                                }
                                track.CallStackLoops[track.CallStackDepth - 1] = count;
                                track.DataOffset = track.CallStack[track.CallStackDepth - 1];
                            }
                            break;
                        }

                        case 0xFD:     // Return
                        {
                            if (track.CallStackDepth != 0)
                            {
                                track.CallStackDepth -= 1;
                                track.DataOffset      = track.CallStack[track.CallStackDepth];
                            }
                            break;
                        }

                        case 0xFF:     // End
                        {
                            track.Stopped = true;
                            break;
                        }
                        }
                    }
                }
            }
        }