Ejemplo n.º 1
0
 public ChannelNote()
 {
     octave     = int.MinValue;
     note       = char.MinValue;
     seminote   = char.MinValue;
     instrument = string.Empty;
     envData    = new EnvelopeData();
 }
Ejemplo n.º 2
0
 public static bool Compare(EnvelopeData e1, EnvelopeData e2)
 {
     return((null == e1 && null == e2) ||
            ((null != e1 && null != e2) &&
             (e1.ActiveFrequencies == e2.ActiveFrequencies) &&
             (e1.FrequencyRatio == e2.FrequencyRatio) &&
             (e1.Style == e2.Style)));
 }
Ejemplo n.º 3
0
 public static bool Compare(EnvelopeData e1, EnvelopeData e2)
 {
     return (null == e1 && null == e2) ||
            ((null != e1 && null != e2) &&
             (e1.ActiveFrequencies == e2.ActiveFrequencies) &&
             (e1.FrequencyRatio == e2.FrequencyRatio) &&
             (e1.Style == e2.Style));
 }
Ejemplo n.º 4
0
 public ChannelNote()
 {
     octave = int.MinValue;
     note = char.MinValue;
     seminote = char.MinValue;
     instrument = string.Empty;
     envData = new EnvelopeData();
 }
Ejemplo n.º 5
0
 public void CopyFrom(ChannelNote newValues)
 {
     this.octave      = newValues.octave;
     this.note        = newValues.note;
     this.seminote    = newValues.seminote;
     this.instrument  = newValues.instrument;
     this.envData     = newValues.EnvData.Clone();
     this.volModifier = newValues.volModifier;
 }
Ejemplo n.º 6
0
 private ApplicationState()
 {
     BaseOctave = 3;
     Stereo = LibAYEmu.Stereo.Mono;
     CurrentEnvData = new EnvelopeData();
 }
Ejemplo n.º 7
0
 private ApplicationState()
 {
     BaseOctave     = 3;
     Stereo         = LibAYEmu.Stereo.Mono;
     CurrentEnvData = new EnvelopeData();
 }
Ejemplo n.º 8
0
        public static byte[] GenerateSong(Song song)
        {
            List<byte> bytes = new List<byte>();
            Pattern current;
            ChannelNote note;
            int noteLen;
            bool lastNoteSilence;
            string[] lastInstrument = new string[song.Channels];
            EnvelopeData[] lastEnvelopes = new EnvelopeData[song.Channels];
            int[] loopLocations = new int[song.Channels + 1];

            int d;
            int dSeminote;
            int o;

            bytes.Add(song.Tempo);

            byte headerByte = (byte)(song.Looped ? 0x01 : 0x00);
            headerByte |= (byte)((song.FxChannel & 0x7) << 1);
            headerByte |= (byte)((song.Channels & 0x7) << 4);
            bytes.Add(headerByte);

            // Dos bytes reservados (de momento).
            bytes.Add(0); bytes.Add(0);

            // Metemos los bytes de offset de loops.
            int offsetLoopLocations = bytes.Count;
            bytes.AddRange(new byte[2 * (song.Channels + 1)]);

            for (int currentChannel = 0; currentChannel < song.Channels; currentChannel++)
            {
                lastInstrument[currentChannel] = string.Empty;
                lastEnvelopes[currentChannel] = null;
            }

            List<string> notesWithTempoModifier = new List<string>();
            for (int currentChannel = 0; currentChannel < song.Channels; currentChannel++)
            {
                noteLen = 0;
                lastNoteSilence = false;
                o = 0;
                d = 0;
                dSeminote = 0;

                sbyte? volModifier = null;
                sbyte tempoModifier;
                List<byte> bytesPatron = new List<byte>();
                bool calculatingFirstNoteOffset = false;
                int firstNoteOffsetInLoopToPattern = -1;

                for (int currentPattern = 0; currentPattern < song.PlayOrder.Count; currentPattern++)
                {
                    current = song.Patterns[song.PlayOrder[currentPattern]];

                    if (song.Looped && currentPattern == song.LoopToPattern)
                    {
                        calculatingFirstNoteOffset = true;
                        firstNoteOffsetInLoopToPattern = 0;
                    }

                    for (int currentLine = 0; currentLine < current.Length; currentLine++)
                    {
                        ChannelLine line = current.Lines[currentLine];
                        note = line.Notes[currentChannel];
                        tempoModifier = 0;
                        if (note.HasValue)
                        {
                            if (noteLen > 0)
                            {
                                noteLen = addNote(bytesPatron, noteLen, lastNoteSilence, d, dSeminote, o);
                            }
                            if (calculatingFirstNoteOffset && song.Looped)
                            {
                                loopLocations[currentChannel] = bytesPatron.Count; // + bytesAntesDeInstrumento.Count;
                                firstNoteOffsetInLoopToPattern += currentLine;
                                calculatingFirstNoteOffset = false;
                            }
                        }

                        if (note.HasOctave)
                        {
                            o = note.Octave - 2;
                        }

                        if (note.HasNote)
                        {
                            dSeminote = 0;

                            if (note.Note == 'P')
                            {
                                lastNoteSilence = true;
                            }
                            else
                            {
                                lastNoteSilence = false;
                                d = getNote(note.Note);
                            }
                            volModifier = note.VolModifier;
                            string key = string.Format("{0}_{1}", currentPattern, currentLine);
                            if (!notesWithTempoModifier.Contains(key))
                            {
                                tempoModifier = line.TempoModifier;
                                if (tempoModifier != 0)
                                {
                                    notesWithTempoModifier.Add(key);
                                }
                            }
                            else
                            {
                                tempoModifier = 0;
                            }
                        }

                        if (note.HasSeminote)
                        {
                            if (note.Seminote == '+')
                                dSeminote = 1;
                            else
                                dSeminote = -1;
                        }
                        if (note.HasInstrument || note.VolModifier.HasValue || tempoModifier != 0)
                        {
                            if (note.VolModifier.HasValue || note.Instrument != lastInstrument[currentChannel] ||
                                (note.IsSawtooth && !EnvelopeData.Compare(note.EnvData, lastEnvelopes[currentChannel])))
                            {
                                if (note.Instrument.ToUpper() == "R")
                                {
                                    bytesPatron.Add(0xbf);
                                    bytesPatron.Add(getSawtoothParamsByte(note));
                                    lastEnvelopes[currentChannel] = note.EnvData;
                                }
                                else
                                {
                                    bytesPatron.Add(0x3f);
                                    bytesPatron.Add(note.HasInstrument ? byte.Parse(note.Instrument) : byte.Parse(lastInstrument[currentChannel]));
                                    byte tModifier = tempoModifier == -1 ? (byte)(1 << 5) : tempoModifier == 1 ? (byte)(1 << 6) : (byte)0;
                                    byte modifiers = (byte)((note.VolModifier.GetValueOrDefault() & 0x1F) | tModifier);
                                    bytesPatron.Add(modifiers);
                                    lastEnvelopes[currentChannel] = null;
                                }

                                if (note.HasInstrument)
                                {
                                    lastInstrument[currentChannel] = note.Instrument;
                                }
                            }
                        }
                        noteLen++;
                    }

                    // Calculamos la longitud de la última nota haciendo que añada la longitud del canal actual completo
                    // si en este canal no hay notas, a la espera de encontrar una nota en este canal.
                    if (calculatingFirstNoteOffset)
                    {
                        firstNoteOffsetInLoopToPattern += current.Length;
                    }
                }
                if (noteLen > 0 && bytesPatron.Count > 0)
                {
                    noteLen = addNote(bytesPatron,
                        noteLen + ((song.Looped && firstNoteOffsetInLoopToPattern >= 0) ? firstNoteOffsetInLoopToPattern : 0),
                        lastNoteSilence, d, dSeminote, o);
                }

                // Si no se ha encontrado aún una nota a la que saltar cuando hay loop, entonces el salto del loop es
                // al final del canal.
                if (calculatingFirstNoteOffset)
                {
                    loopLocations[currentChannel] = bytesPatron.Count;
                }

                if (bytesPatron.Count == 0)
                {
                    bytesPatron.Add(0xC1);
                }
                bytes.AddRange(bytesPatron);
                bytes.Add(0x00); // Fin de canal.
            }

            // Canal de FX!!!
            List<byte> bytesFX = new List<byte>();
            int currentFx = int.MinValue;

            noteLen = 0;
            bool calculatingFirstFxOffset = false;
            int firstFxOffsetInLoopToPattern = -1;
            for (int currentPattern = 0; currentPattern < song.PlayOrder.Count; currentPattern++)
            {
                if (song.Looped && currentPattern == song.LoopToPattern)
                {
                    calculatingFirstFxOffset = true;
                    firstFxOffsetInLoopToPattern = 0;
                }
                current = song.Patterns[song.PlayOrder[currentPattern]];
                for (int currentNote = 0; currentNote < current.Length; currentNote++)
                {
                    // Ver cómo se tiene que generar los FX.
                    if (current.Lines[currentNote].Fx != int.MinValue && noteLen > 0)
                    {
                        noteLen = addFX(bytesFX, noteLen, currentFx, song);
                    }
                    if (current.Lines[currentNote].Fx != int.MinValue)
                    {
                        currentFx = current.Lines[currentNote].Fx;

                        if (song.Looped && calculatingFirstFxOffset)
                        {
                            calculatingFirstFxOffset = false;
                            firstFxOffsetInLoopToPattern += currentNote;
                            loopLocations[song.Channels] = bytesFX.Count;
                        }
                    }
                    noteLen++;
                }
                if (calculatingFirstFxOffset)
                {
                    firstFxOffsetInLoopToPattern += current.Length;
                }
            }

            if (noteLen > 0 && currentFx >= 0)
            {
                noteLen = addFX(bytesFX,
                    noteLen + ((song.Looped && firstFxOffsetInLoopToPattern >= 0) ? firstFxOffsetInLoopToPattern : 0),
                    currentFx,
                    song);
            }

            if (calculatingFirstFxOffset)
            {
                loopLocations[song.Channels] = bytesFX.Count;
            }

            if (bytesFX.Count == 0)
            {
                bytesFX.Add(0xC1);
            }

            bytes.AddRange(bytesFX);

            bytes.Add(0x00); // Fin de canal.

            bytes.Add(0x00); // Fin de canción. (¿¿Hace falta??)

            for (int c = 0; c <= song.Channels; ++c)
            {
                bytes[offsetLoopLocations + 2 * c] = (byte)(loopLocations[c] & 0x00FF);
                bytes[offsetLoopLocations + (2 * c) + 1] = (byte)((loopLocations[c] & 0x0FF00) >> 8);
            }

            return bytes.ToArray();
        }
Ejemplo n.º 9
0
        public static byte[] GenerateSong(Song song)
        {
            List <byte> bytes = new List <byte>();
            Pattern     current;
            ChannelNote note;
            int         noteLen;
            bool        lastNoteSilence;

            string[]       lastInstrument = new string[song.Channels];
            EnvelopeData[] lastEnvelopes  = new EnvelopeData[song.Channels];
            int[]          loopLocations  = new int[song.Channels + 1];

            int d;
            int dSeminote;
            int o;

            bytes.Add(song.Tempo);

            byte headerByte = (byte)(song.Looped ? 0x01 : 0x00);

            headerByte |= (byte)((song.FxChannel & 0x7) << 1);
            headerByte |= (byte)((song.Channels & 0x7) << 4);
            bytes.Add(headerByte);

            // Dos bytes reservados (de momento).
            bytes.Add(0); bytes.Add(0);

            // Metemos los bytes de offset de loops.
            int offsetLoopLocations = bytes.Count;

            bytes.AddRange(new byte[2 * (song.Channels + 1)]);

            for (int currentChannel = 0; currentChannel < song.Channels; currentChannel++)
            {
                lastInstrument[currentChannel] = string.Empty;
                lastEnvelopes[currentChannel]  = null;
            }

            List <string> notesWithTempoModifier = new List <string>();

            for (int currentChannel = 0; currentChannel < song.Channels; currentChannel++)
            {
                noteLen         = 0;
                lastNoteSilence = false;
                o         = 0;
                d         = 0;
                dSeminote = 0;

                sbyte?      volModifier = null;
                sbyte       tempoModifier;
                List <byte> bytesPatron = new List <byte>();
                bool        calculatingFirstNoteOffset     = false;
                int         firstNoteOffsetInLoopToPattern = -1;

                for (int currentPattern = 0; currentPattern < song.PlayOrder.Count; currentPattern++)
                {
                    current = song.Patterns[song.PlayOrder[currentPattern]];

                    if (song.Looped && currentPattern == song.LoopToPattern)
                    {
                        calculatingFirstNoteOffset     = true;
                        firstNoteOffsetInLoopToPattern = 0;
                    }

                    for (int currentLine = 0; currentLine < current.Length; currentLine++)
                    {
                        ChannelLine line = current.Lines[currentLine];
                        note          = line.Notes[currentChannel];
                        tempoModifier = 0;
                        if (note.HasValue)
                        {
                            if (noteLen > 0)
                            {
                                noteLen = addNote(bytesPatron, noteLen, lastNoteSilence, d, dSeminote, o);
                            }
                            if (calculatingFirstNoteOffset && song.Looped)
                            {
                                loopLocations[currentChannel]   = bytesPatron.Count; // + bytesAntesDeInstrumento.Count;
                                firstNoteOffsetInLoopToPattern += currentLine;
                                calculatingFirstNoteOffset      = false;
                            }
                        }

                        if (note.HasOctave)
                        {
                            o = note.Octave - 2;
                        }

                        if (note.HasNote)
                        {
                            dSeminote = 0;

                            if (note.Note == 'P')
                            {
                                lastNoteSilence = true;
                            }
                            else
                            {
                                lastNoteSilence = false;
                                d = getNote(note.Note);
                            }
                            volModifier = note.VolModifier;
                            string key = string.Format("{0}_{1}", currentPattern, currentLine);
                            if (!notesWithTempoModifier.Contains(key))
                            {
                                tempoModifier = line.TempoModifier;
                                if (tempoModifier != 0)
                                {
                                    notesWithTempoModifier.Add(key);
                                }
                            }
                            else
                            {
                                tempoModifier = 0;
                            }
                        }

                        if (note.HasSeminote)
                        {
                            if (note.Seminote == '+')
                            {
                                dSeminote = 1;
                            }
                            else
                            {
                                dSeminote = -1;
                            }
                        }
                        if (note.HasInstrument || note.VolModifier.HasValue || tempoModifier != 0)
                        {
                            if (note.VolModifier.HasValue || note.Instrument != lastInstrument[currentChannel] ||
                                (note.IsSawtooth && !EnvelopeData.Compare(note.EnvData, lastEnvelopes[currentChannel])))
                            {
                                if (note.Instrument.ToUpper() == "R")
                                {
                                    bytesPatron.Add(0xbf);
                                    bytesPatron.Add(getSawtoothParamsByte(note));
                                    lastEnvelopes[currentChannel] = note.EnvData;
                                }
                                else
                                {
                                    bytesPatron.Add(0x3f);
                                    bytesPatron.Add(note.HasInstrument ? byte.Parse(note.Instrument) : byte.Parse(lastInstrument[currentChannel]));
                                    byte tModifier = tempoModifier == -1 ? (byte)(1 << 5) : tempoModifier == 1 ? (byte)(1 << 6) : (byte)0;
                                    byte modifiers = (byte)((note.VolModifier.GetValueOrDefault() & 0x1F) | tModifier);
                                    bytesPatron.Add(modifiers);
                                    lastEnvelopes[currentChannel] = null;
                                }

                                if (note.HasInstrument)
                                {
                                    lastInstrument[currentChannel] = note.Instrument;
                                }
                            }
                        }
                        noteLen++;
                    }

                    // Calculamos la longitud de la última nota haciendo que añada la longitud del canal actual completo
                    // si en este canal no hay notas, a la espera de encontrar una nota en este canal.
                    if (calculatingFirstNoteOffset)
                    {
                        firstNoteOffsetInLoopToPattern += current.Length;
                    }
                }
                if (noteLen > 0 && bytesPatron.Count > 0)
                {
                    noteLen = addNote(bytesPatron,
                                      noteLen + ((song.Looped && firstNoteOffsetInLoopToPattern >= 0) ? firstNoteOffsetInLoopToPattern : 0),
                                      lastNoteSilence, d, dSeminote, o);
                }

                // Si no se ha encontrado aún una nota a la que saltar cuando hay loop, entonces el salto del loop es
                // al final del canal.
                if (calculatingFirstNoteOffset)
                {
                    loopLocations[currentChannel] = bytesPatron.Count;
                }

                if (bytesPatron.Count == 0)
                {
                    bytesPatron.Add(0xC1);
                }
                bytes.AddRange(bytesPatron);
                bytes.Add(0x00); // Fin de canal.
            }

            // Canal de FX!!!
            List <byte> bytesFX   = new List <byte>();
            int         currentFx = int.MinValue;

            noteLen = 0;
            bool calculatingFirstFxOffset     = false;
            int  firstFxOffsetInLoopToPattern = -1;

            for (int currentPattern = 0; currentPattern < song.PlayOrder.Count; currentPattern++)
            {
                if (song.Looped && currentPattern == song.LoopToPattern)
                {
                    calculatingFirstFxOffset     = true;
                    firstFxOffsetInLoopToPattern = 0;
                }
                current = song.Patterns[song.PlayOrder[currentPattern]];
                for (int currentNote = 0; currentNote < current.Length; currentNote++)
                {
                    // Ver cómo se tiene que generar los FX.
                    if (current.Lines[currentNote].Fx != int.MinValue && noteLen > 0)
                    {
                        noteLen = addFX(bytesFX, noteLen, currentFx, song);
                    }
                    if (current.Lines[currentNote].Fx != int.MinValue)
                    {
                        currentFx = current.Lines[currentNote].Fx;

                        if (song.Looped && calculatingFirstFxOffset)
                        {
                            calculatingFirstFxOffset      = false;
                            firstFxOffsetInLoopToPattern += currentNote;
                            loopLocations[song.Channels]  = bytesFX.Count;
                        }
                    }
                    noteLen++;
                }
                if (calculatingFirstFxOffset)
                {
                    firstFxOffsetInLoopToPattern += current.Length;
                }
            }

            if (noteLen > 0 && currentFx >= 0)
            {
                noteLen = addFX(bytesFX,
                                noteLen + ((song.Looped && firstFxOffsetInLoopToPattern >= 0) ? firstFxOffsetInLoopToPattern : 0),
                                currentFx,
                                song);
            }

            if (calculatingFirstFxOffset)
            {
                loopLocations[song.Channels] = bytesFX.Count;
            }

            if (bytesFX.Count == 0)
            {
                bytesFX.Add(0xC1);
            }

            bytes.AddRange(bytesFX);

            bytes.Add(0x00); // Fin de canal.

            bytes.Add(0x00); // Fin de canción. (¿¿Hace falta??)

            for (int c = 0; c <= song.Channels; ++c)
            {
                bytes[offsetLoopLocations + 2 * c]       = (byte)(loopLocations[c] & 0x00FF);
                bytes[offsetLoopLocations + (2 * c) + 1] = (byte)((loopLocations[c] & 0x0FF00) >> 8);
            }

            return(bytes.ToArray());
        }