Ejemplo n.º 1
0
        public MOD(Data.Buffer data)
        {
            data.SetEndianess(Endian.Endianess.Big);

            Log.Info.Write(ErrorSystemType.Data, $"Loading MOD song: {System.Text.Encoding.ASCII.GetString(data.Pop(20).ReinterpretAsArray(20))}"); // songname

            // add dummy sample 0
            samples.Add(new Sample());

            for (int i = 1; i < 32; ++i)                                                                                                               // samples 1-31
            {
                Log.Info.Write(ErrorSystemType.Data, $"Sample {i} name: {System.Text.Encoding.ASCII.GetString(data.Pop(22).ReinterpretAsArray(22))}"); // samplename

                samples.Add(new Sample()
                {
                    Length            = data.Pop <UInt16>() * 2,
                    FineTune          = ConvertFineTune(data.Pop <byte>() & 0xf),
                    Volume            = data.Pop <byte>(), // 0-64, change in dB = 20*log10(Volume/64)
                    RepeatPointOffset = data.Pop <UInt16>() * 2,
                    RepeatLength      = Math.Max(0, data.Pop <UInt16>() - 1) * 2
                });
            }

            int songLength = data.Pop <byte>();

            if (songLength < 1 || songLength > 128)
            {
                throw new ExceptionAudio("Invalid MOD format.");
            }

            data.Skip(1);

            byte[] songPatterns = data.Pop(128).ReinterpretAsArray(128);

            var magic = data.Pop(4).ToString();

            if (magic != "M!K!" && magic != "M.K.")
            {
                throw new ExceptionAudio("Invalid or unsupported MOD format.");
            }

            int            numPatterns = songPatterns.Max() + 1;
            List <Pattern> patterns    = new List <Pattern>(numPatterns);

            for (int i = 0; i < numPatterns; ++i)
            {
                var pattern = new Pattern();

                for (int div = 0; div < 64; ++div)
                {
                    for (int chan = 0; chan < 4; ++chan)
                    {
                        pattern.AddNote(chan, new Note(data));
                    }
                }

                patterns.Add(pattern);
            }

            for (int i = 0; i < samples.Count; ++i)
            {
                if (samples[i].Length > 0)
                {
                    data.Skip(2); // ignore tracker word
                    samples[i].Length -= 2;

                    uint length = (uint)samples[i].Length;

                    if (length > 0)
                    {
                        samples[i].SetData(data.Pop(length).ReinterpretAsArray(length));
                    }
                }
            }

            for (int i = 0; i < songLength; ++i)
            {
                song.Add(patterns[songPatterns[i]]);
            }
        }