예제 #1
0
 public void Serialize(ref ulong i)
 {
     crc = CRC32.Compute(BitConverter.GetBytes(i), crc);
 }
예제 #2
0
 public void Serialize(ref sbyte[] values)
 {
     crc = CRC32.Compute(BitConverter.GetBytes(values.Length), crc);
     crc = CRC32.Compute(values, crc);
 }
예제 #3
0
 public void Serialize(ref sbyte b)
 {
     crc = CRC32.Compute((byte)b, crc);
 }
예제 #4
0
 public void Serialize(ref byte b)
 {
     crc = CRC32.Compute(b, crc);
 }
예제 #5
0
 public void Serialize(ref bool b)
 {
     crc = CRC32.Compute((byte)(b ? 1 : 0), crc);
 }
예제 #6
0
        private int OutputInstruments()
        {
            // Process all envelope, make unique, etc.
            var uniqueEnvelopes     = new SortedList <uint, byte[]>();
            var instrumentEnvelopes = new Dictionary <Envelope, uint>();

            var defaultEnv    = new byte[] { 0xc0, 0x00, 0x00 };
            var defaultEnvCRC = CRC32.Compute(defaultEnv);

            uniqueEnvelopes.Add(defaultEnvCRC, defaultEnv);

            foreach (var instrument in project.Instruments)
            {
                foreach (var env in instrument.Envelopes)
                {
                    var processed = ProcessEnvelope(env);

                    if (processed == null)
                    {
                        instrumentEnvelopes[env] = defaultEnvCRC;
                    }
                    else
                    {
                        uint crc = CRC32.Compute(processed);
                        uniqueEnvelopes[crc]     = processed;
                        instrumentEnvelopes[env] = crc;
                    }
                }
            }

            int size = 0;

            // Write instruments
            lines.Add($"{ll}instruments:");

            for (int i = 0; i < project.Instruments.Count; i++)
            {
                var instrument = project.Instruments[i];

                var volumeEnvIdx   = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Volume]]);
                var arpeggioEnvIdx = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Arpeggio]]);
                var pitchEnvIdx    = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Pitch]]);

                lines.Add($"\t{db} ${(instrument.DutyCycle << 6) | 0x30:x2} ;instrument {i:x2} ({instrument.Name})");
                lines.Add($"\t{dw} {ll}env{volumeEnvIdx},{ll}env{arpeggioEnvIdx},{ll}env{pitchEnvIdx}");
                lines.Add($"\t{db} $00");

                size += 2 * 3 + 2;
            }

            lines.Add("");

            // Write samples.
            lines.Add($"{ll}samples:");

            if (project.UsesSamples)
            {
                for (int i = 1; i < project.SamplesMapping.Length; i++)
                {
                    var mapping            = project.SamplesMapping[i];
                    var sampleOffset       = 0;
                    var sampleSize         = 0;
                    var samplePitchAndLoop = 0;
                    var sampleName         = "";

                    if (mapping != null && mapping.Sample != null)
                    {
                        sampleOffset       = project.GetAddressForSample(mapping.Sample) >> 6;
                        sampleSize         = mapping.Sample.Data.Length >> 4;
                        sampleName         = $"({mapping.Sample.Name})";
                        samplePitchAndLoop = mapping.Pitch | ((mapping.Loop ? 1 : 0) << 6);
                    }

                    lines.Add($"\t{db} ${sampleOffset:x2}+{lo}(FT_DPCM_PTR),${sampleSize:x2},${samplePitchAndLoop:x2}\t;{i} {sampleName}");
                    size += 3;
                }

                lines.Add("");
            }

            // Write envelopes.
            int idx = 0;

            foreach (var env in uniqueEnvelopes.Values)
            {
                lines.Add($"{ll}env{idx++}:");
                lines.Add($"\t{db} {String.Join(",", env.Select(i => $"${i:x2}"))}");
                size += env.Length;
            }

            return(size);
        }
예제 #7
0
        private int OutputInstruments()
        {
            // Process all envelope, make unique, etc.
            var uniqueEnvelopes     = new SortedList <uint, byte[]>();
            var instrumentEnvelopes = new Dictionary <Envelope, uint>();

            var defaultEnv          = new byte[] { 0xc0, 0x7f, 0x00, 0x00 };
            var defaultPitchEnv     = new byte[] { 0x00, 0xc0, 0x7f, 0x00, 0x01 };
            var defaultEnvCRC       = CRC32.Compute(defaultEnv);
            var defaultPitchEnvCRC  = CRC32.Compute(defaultPitchEnv);
            var defaultEnvName      = "";
            var defaultPitchEnvName = "";

            uniqueEnvelopes.Add(defaultEnvCRC, defaultEnv);

            if (kernel == FamiToneKernel.FamiTone2FS)
            {
                uniqueEnvelopes.Add(defaultPitchEnvCRC, defaultPitchEnv);
            }

            foreach (var instrument in project.Instruments)
            {
                for (int i = 0; i < Envelope.Max; i++)
                {
                    var env       = instrument.Envelopes[i];
                    var processed =
                        ProcessEnvelope(env,
                                        i == Envelope.Volume && kernel == FamiToneKernel.FamiTone2FS,
                                        i == Envelope.Pitch && kernel == FamiToneKernel.FamiTone2FS);

                    if (processed == null)
                    {
                        if (kernel == FamiToneKernel.FamiTone2FS && i == Envelope.Pitch)
                        {
                            instrumentEnvelopes[env] = defaultPitchEnvCRC;
                        }
                        else
                        {
                            instrumentEnvelopes[env] = defaultEnvCRC;
                        }
                    }
                    else
                    {
                        uint crc = CRC32.Compute(processed);
                        uniqueEnvelopes[crc]     = processed;
                        instrumentEnvelopes[env] = crc;
                    }
                }
            }

            int size = 0;

            // Write instruments
            lines.Add($"{ll}instruments:");

            for (int i = 0; i < project.Instruments.Count; i++)
            {
                var instrument = project.Instruments[i];

                var volumeEnvIdx   = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Volume]]);
                var arpeggioEnvIdx = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Arpeggio]]);
                var pitchEnvIdx    = uniqueEnvelopes.IndexOfKey(instrumentEnvelopes[instrument.Envelopes[Envelope.Pitch]]);
                var dutyShift      = instrument.ExpansionType == Project.ExpansionVrc6 ? 4 : 6;
                var dutyBits       = instrument.ExpansionType == Project.ExpansionVrc6 ? 0 : 0x30;

                lines.Add($"\t{db} ${(instrument.DutyCycle << dutyShift) | dutyBits:x2} ;instrument {i:x2} ({instrument.Name})");
                lines.Add($"\t{dw} {ll}env{volumeEnvIdx},{ll}env{arpeggioEnvIdx},{ll}env{pitchEnvIdx}");
                lines.Add($"\t{db} $00");

                size += 2 * 3 + 2;
            }

            lines.Add("");

            // Write samples.
            lines.Add($"{ll}samples:");

            if (project.UsesSamples)
            {
                for (int i = 1; i < project.SamplesMapping.Length; i++)
                {
                    var mapping            = project.SamplesMapping[i];
                    var sampleOffset       = 0;
                    var sampleSize         = 0;
                    var samplePitchAndLoop = 0;
                    var sampleName         = "";

                    if (mapping != null && mapping.Sample != null)
                    {
                        sampleOffset       = project.GetAddressForSample(mapping.Sample) >> 6;
                        sampleSize         = mapping.Sample.Data.Length >> 4;
                        sampleName         = $"({mapping.Sample.Name})";
                        samplePitchAndLoop = mapping.Pitch | ((mapping.Loop ? 1 : 0) << 6);
                    }

                    lines.Add($"\t{db} ${sampleOffset:x2}+{lo}(FT_DPCM_PTR),${sampleSize:x2},${samplePitchAndLoop:x2}\t;{i} {sampleName}");
                    size += 3;
                }

                lines.Add("");
            }

            // Write envelopes.
            int idx = 0;

            foreach (var kv in uniqueEnvelopes)
            {
                var name = $"{ll}env{idx++}";
                lines.Add($"{name}:");
                lines.Add($"\t{db} {String.Join(",", kv.Value.Select(i => $"${i:x2}"))}");
                size += kv.Value.Length;

                if (kv.Key == defaultEnvCRC)
                {
                    defaultEnvName = name;
                }
                if (kv.Key == defaultPitchEnvCRC)
                {
                    defaultPitchEnvName = name;
                }
            }

            // Write the unique vibrato envelopes.
            if (kernel == FamiToneKernel.FamiTone2FS)
            {
                // Create all the unique vibrato envelopes.
                foreach (var s in project.Songs)
                {
                    foreach (var c in s.Channels)
                    {
                        foreach (var p in c.Patterns)
                        {
                            for (int n = 0; n < s.PatternLength; n++)
                            {
                                var note = p.Notes[n];

                                if (note.HasVibrato)
                                {
                                    if (note.VibratoDepth == 0 || note.VibratoSpeed == 0)
                                    {
                                        p.Notes[n].Vibrato      = 0;
                                        vibratoEnvelopeNames[0] = defaultPitchEnvName;
                                        continue;
                                    }

                                    var  env       = Envelope.CreateVibratoEnvelope(note.VibratoSpeed, note.VibratoDepth);
                                    var  processed = ProcessEnvelope(env, false, true);
                                    uint crc       = CRC32.Compute(processed);
                                    if (!uniqueEnvelopes.ContainsKey(crc))
                                    {
                                        var name = $"{ll}env{idx++}";
                                        lines.Add($"{name}:");
                                        lines.Add($"\t{db} {String.Join(",", processed.Select(i => $"${i:x2}"))}");
                                        size += env.Length;

                                        uniqueEnvelopes[crc] = processed;
                                        vibratoEnvelopeNames[note.Vibrato] = name;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(size);
        }