Exemplo n.º 1
0
        public Config(string bgmPath)
        {
            BGMPath  = bgmPath;
            BGMFiles = Directory.GetFiles(bgmPath, "bgm*.smd", SearchOption.TopDirectoryOnly);
            if (BGMFiles.Length == 0)
            {
                throw new Exception(Strings.ErrorDSENoSequences);
            }
            var songs = new Song[BGMFiles.Length];

            for (int i = 0; i < BGMFiles.Length; i++)
            {
                using (var reader = new EndianBinaryReader(File.OpenRead(BGMFiles[i])))
                {
                    SMD.Header header = reader.ReadObject <SMD.Header>();
                    songs[i] = new Song(i, $"{Path.GetFileNameWithoutExtension(BGMFiles[i])} - {new string(header.Label.TakeWhile(c => c != '\0').ToArray())}");
                }
            }
            Playlists.Add(new Playlist(Strings.PlaylistMusic, songs));
        }
Exemplo n.º 2
0
        public void LoadSong(long index)
        {
            if (_tracks != null)
            {
                for (int i = 0; i < _tracks.Length; i++)
                {
                    _tracks[i].StopAllChannels();
                }
                _tracks = null;
            }
            string bgm = _config.BGMFiles[index];

            _localSWD = new SWD(Path.ChangeExtension(bgm, "swd"));
            _smdFile  = File.ReadAllBytes(bgm);
            using (var reader = new EndianBinaryReader(new MemoryStream(_smdFile)))
            {
                SMD.Header     header = reader.ReadObject <SMD.Header>();
                SMD.ISongChunk songChunk;
                switch (header.Version)
                {
                case 0x402:
                {
                    songChunk = reader.ReadObject <SMD.SongChunk_V402>();
                    break;
                }

                case 0x415:
                {
                    songChunk = reader.ReadObject <SMD.SongChunk_V415>();
                    break;
                }

                default: throw new Exception(string.Format(Strings.ErrorDSEInvalidHeaderVersion, header.Version));
                }
                _tracks = new Track[songChunk.NumTracks];
                Events  = new List <SongEvent> [songChunk.NumTracks];
                for (byte trackIndex = 0; trackIndex < songChunk.NumTracks; trackIndex++)
                {
                    Events[trackIndex] = new List <SongEvent>();
                    bool EventExists(long offset)
                    {
                        return(Events[trackIndex].Any(e => e.Offset == offset));
                    }

                    long chunkStart = reader.BaseStream.Position;
                    reader.BaseStream.Position += 0x14; // Skip header
                    _tracks[trackIndex]         = new Track(trackIndex, reader.BaseStream.Position);

                    uint lastNoteDuration = 0, lastRest = 0;
                    bool cont = true;
                    while (cont)
                    {
                        long offset = reader.BaseStream.Position;
                        void AddEvent(ICommand command)
                        {
                            Events[trackIndex].Add(new SongEvent(offset, command));
                        }

                        byte cmd = reader.ReadByte();
                        if (cmd <= 0x7F)
                        {
                            byte arg       = reader.ReadByte();
                            int  numParams = (arg & 0xC0) >> 6;
                            int  oct       = ((arg & 0x30) >> 4) - 2;
                            int  k         = arg & 0xF;
                            if (k < 12)
                            {
                                uint duration;
                                if (numParams == 0)
                                {
                                    duration = lastNoteDuration;
                                }
                                else // Big Endian reading of 8, 16, or 24 bits
                                {
                                    duration = 0;
                                    for (int b = 0; b < numParams; b++)
                                    {
                                        duration = (duration << 8) | reader.ReadByte();
                                    }
                                    lastNoteDuration = duration;
                                }
                                if (!EventExists(offset))
                                {
                                    AddEvent(new NoteCommand {
                                        Key = (byte)k, OctaveChange = (sbyte)oct, Velocity = cmd, Duration = duration
                                    });
                                }
                            }
                            else
                            {
                                throw new Exception(string.Format(Strings.ErrorDSEInvalidKey, trackIndex, offset, k));
                            }
                        }
                        else if (cmd >= 0x80 && cmd <= 0x8F)
                        {
                            lastRest = Utils.FixedRests[cmd - 0x80];
                            if (!EventExists(offset))
                            {
                                AddEvent(new RestCommand {
                                    Rest = lastRest
                                });
                            }
                        }
                        else // 0x90-0xFF
                        {
                            // TODO: 0x95 - a rest that may or may not repeat depending on some condition within channels
                            // TODO: 0x9E - may or may not jump somewhere else depending on an unknown structure
                            switch (cmd)
                            {
                            case 0x90:
                            {
                                if (!EventExists(offset))
                                {
                                    AddEvent(new RestCommand {
                                            Rest = lastRest
                                        });
                                }
                                break;
                            }

                            case 0x91:
                            {
                                lastRest = (uint)(lastRest + reader.ReadSByte());
                                if (!EventExists(offset))
                                {
                                    AddEvent(new RestCommand {
                                            Rest = lastRest
                                        });
                                }
                                break;
                            }

                            case 0x92:
                            {
                                lastRest = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new RestCommand {
                                            Rest = lastRest
                                        });
                                }
                                break;
                            }

                            case 0x93:
                            {
                                lastRest = reader.ReadUInt16();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new RestCommand {
                                            Rest = lastRest
                                        });
                                }
                                break;
                            }

                            case 0x94:
                            {
                                lastRest = (uint)(reader.ReadByte() | (reader.ReadByte() << 8) | (reader.ReadByte() << 16));
                                if (!EventExists(offset))
                                {
                                    AddEvent(new RestCommand {
                                            Rest = lastRest
                                        });
                                }
                                break;
                            }

                            case 0x96:
                            case 0x97:
                            case 0x9A:
                            case 0x9B:
                            case 0x9F:
                            case 0xA2:
                            case 0xA3:
                            case 0xA6:
                            case 0xA7:
                            case 0xAD:
                            case 0xAE:
                            case 0xB7:
                            case 0xB8:
                            case 0xB9:
                            case 0xBA:
                            case 0xBB:
                            case 0xBD:
                            case 0xC1:
                            case 0xC2:
                            case 0xC4:
                            case 0xC5:
                            case 0xC6:
                            case 0xC7:
                            case 0xC8:
                            case 0xC9:
                            case 0xCA:
                            case 0xCC:
                            case 0xCD:
                            case 0xCE:
                            case 0xCF:
                            case 0xD9:
                            case 0xDA:
                            case 0xDE:
                            case 0xE6:
                            case 0xEB:
                            case 0xEE:
                            case 0xF4:
                            case 0xF5:
                            case 0xF7:
                            case 0xF9:
                            case 0xFA:
                            case 0xFB:
                            case 0xFC:
                            case 0xFD:
                            case 0xFE:
                            case 0xFF:
                            {
                                if (!EventExists(offset))
                                {
                                    AddEvent(new InvalidCommand {
                                            Command = cmd
                                        });
                                }
                                break;
                            }

                            case 0x98:
                            {
                                if (!EventExists(offset))
                                {
                                    AddEvent(new FinishCommand());
                                }
                                cont = false;
                                break;
                            }

                            case 0x99:
                            {
                                if (!EventExists(offset))
                                {
                                    AddEvent(new LoopStartCommand {
                                            Offset = reader.BaseStream.Position
                                        });
                                }
                                break;
                            }

                            case 0xA0:
                            {
                                byte octave = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new OctaveSetCommand {
                                            Octave = octave
                                        });
                                }
                                break;
                            }

                            case 0xA1:
                            {
                                sbyte change = reader.ReadSByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new OctaveAddCommand {
                                            OctaveChange = change
                                        });
                                }
                                break;
                            }

                            case 0xA4:
                            case 0xA5:     // The code for these two is identical
                            {
                                byte tempoArg = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new TempoCommand {
                                            Command = cmd, Tempo = tempoArg
                                        });
                                }
                                break;
                            }

                            case 0xAB:
                            {
                                byte[] bytes = reader.ReadBytes(1);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new SkipBytesCommand {
                                            Command = cmd, SkippedBytes = bytes
                                        });
                                }
                                break;
                            }

                            case 0xAC:
                            {
                                byte voice = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new VoiceCommand {
                                            Voice = voice
                                        });
                                }
                                break;
                            }

                            case 0xCB:
                            case 0xF8:
                            {
                                byte[] bytes = reader.ReadBytes(2);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new SkipBytesCommand {
                                            Command = cmd, SkippedBytes = bytes
                                        });
                                }
                                break;
                            }

                            case 0xD7:
                            {
                                ushort bend = reader.ReadUInt16();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new PitchBendCommand {
                                            Bend = bend
                                        });
                                }
                                break;
                            }

                            case 0xE0:
                            {
                                byte volume = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new VolumeCommand {
                                            Volume = volume
                                        });
                                }
                                break;
                            }

                            case 0xE3:
                            {
                                byte expression = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new ExpressionCommand {
                                            Expression = expression
                                        });
                                }
                                break;
                            }

                            case 0xE8:
                            {
                                byte panArg = reader.ReadByte();
                                if (!EventExists(offset))
                                {
                                    AddEvent(new PanpotCommand {
                                            Panpot = (sbyte)(panArg - 0x40)
                                        });
                                }
                                break;
                            }

                            case 0x9D:
                            case 0xB0:
                            case 0xC0:
                            {
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = Array.Empty <byte>()
                                        });
                                }
                                break;
                            }

                            case 0x9C:
                            case 0xA9:
                            case 0xAA:
                            case 0xB1:
                            case 0xB2:
                            case 0xB3:
                            case 0xB5:
                            case 0xB6:
                            case 0xBC:
                            case 0xBE:
                            case 0xBF:
                            case 0xC3:
                            case 0xD0:
                            case 0xD1:
                            case 0xD2:
                            case 0xDB:
                            case 0xDF:
                            case 0xE1:
                            case 0xE7:
                            case 0xE9:
                            case 0xEF:
                            case 0xF6:
                            {
                                byte[] args = reader.ReadBytes(1);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = args
                                        });
                                }
                                break;
                            }

                            case 0xA8:
                            case 0xB4:
                            case 0xD3:
                            case 0xD5:
                            case 0xD6:
                            case 0xD8:
                            case 0xF2:
                            {
                                byte[] args = reader.ReadBytes(2);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = args
                                        });
                                }
                                break;
                            }

                            case 0xAF:
                            case 0xD4:
                            case 0xE2:
                            case 0xEA:
                            case 0xF3:
                            {
                                byte[] args = reader.ReadBytes(3);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = args
                                        });
                                }
                                break;
                            }

                            case 0xDD:
                            case 0xE5:
                            case 0xED:
                            case 0xF1:
                            {
                                byte[] args = reader.ReadBytes(4);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = args
                                        });
                                }
                                break;
                            }

                            case 0xDC:
                            case 0xE4:
                            case 0xEC:
                            case 0xF0:
                            {
                                byte[] args = reader.ReadBytes(5);
                                if (!EventExists(offset))
                                {
                                    AddEvent(new UnknownCommand {
                                            Command = cmd, Args = args
                                        });
                                }
                                break;
                            }

                            default: throw new Exception(string.Format(Strings.ErrorAlphaDreamDSEMP2KSDATInvalidCommand, trackIndex, offset, cmd));
                            }
                        }
                    }
                    uint chunkLength = reader.ReadUInt32(chunkStart + 0xC);
                    reader.BaseStream.Position += chunkLength;
                    // Align 4
                    while (reader.BaseStream.Position % 4 != 0)
                    {
                        reader.BaseStream.Position++;
                    }
                }
                SetTicks();
            }
        }