Beispiel #1
0
 private void updateCurrentLine()
 {
     this.lineNumber++;
     if (this.lineNumber >= this.currentPattern.Lines.Length)
     {
         if (playMode == PlayMode.FullSong)
         {
             this.patternNumber++;
             if (this.patternNumber >= this.currentSong.PlayOrder.Count)
             {
                 if (this.currentSong.Looped && (this.LimitLoops == -1 || loopCount < this.LimitLoops))
                 {
                     this.patternNumber = this.currentSong.LoopToPattern;
                     this.loopCount++;
                 }
                 else
                 {
                     this.OnSongFinished();
                 }
             }
         }
         GoToPattern(this.patternNumber);
     }
     else
     {
         this.CurrentLine = this.currentPattern.Lines[this.lineNumber];
     }
     this.OnNextLine(new NextLineEventArgs(this.patternNumber, this.lineNumber));
 }
Beispiel #2
0
 public void GoToPattern(int patternOrder)
 {
     if (patternOrder < this.currentSong.PlayOrder.Count)
     {
         this.lineNumber     = 0;
         this.patternNumber  = patternOrder;
         this.currentPattern = this.currentSong.Patterns[this.currentSong.PlayOrder[patternOrder]];
         this.CurrentLine    = this.currentPattern.Lines[0];
         this.periodCount    = 0;
     }
 }
Beispiel #3
0
        public void Play(int patternIdx)
        {
            this.playState = PlayStatus.Playing;

            periodCount      = 0;
            effectPosition   = int.MinValue;
            this.CurrentLine = null;
            this.initializeParams();
            this.GoToPattern(patternIdx);
            for (int i = 0; i < ayEmus.Length; i++)
            {
                ayEmus[i].Reset();
            }
        }
Beispiel #4
0
        private void resizeNotesList()
        {
            ChannelLine[] newLinesList = new ChannelLine[length];

            int maxIdx = (length > lines.Length) ? lines.Length : length;

            Array.Copy(lines, newLinesList, maxIdx);

            for (int idx = maxIdx; idx < length; idx++)
            {
                newLinesList[idx] = new ChannelLine(channels);
            }

            // Nos quedamos con la nueva...
            lines = newLinesList;
        }
Beispiel #5
0
        private void resizeNotesList()
        {
            ChannelLine[] newLinesList = new ChannelLine[length];

            int maxIdx = (length > lines.Length) ? lines.Length : length;

            Array.Copy(lines, newLinesList, maxIdx);

            for (int idx = maxIdx; idx < length; idx++)
            {
                newLinesList[idx] = new ChannelLine(channels);
            }

            // Nos quedamos con la nueva...
            lines = newLinesList;
        }
Beispiel #6
0
 private ChannelLine[] getSelectedBuffer(out bool containsFx)
 {
     ChannelLine[] result = new ChannelLine[this.selectionEnd - this.selectionStart + 1];
     containsFx = false;
     int lineIdx = this.selectionStart;
     for (int i = 0; i < result.Length; i++)
     {
         if (this.selectionChanEnd >= this.CurrentSong.Channels)
         {
             result[i] = new ChannelLine((byte)(this.selectionChanEnd - this.selectionChanStart));
         }
         else
         {
             result[i] = new ChannelLine((byte)(this.selectionChanEnd - this.selectionChanStart + 1));
         }
         int chanIdx = this.selectionChanStart;
         for (int j = 0; j < this.selectionChanEnd - this.selectionChanStart + 1; j++)
         {
             if (this.currentSong.Channels <= chanIdx)
             {
                 result[i].Fx = this.currentPattern.Lines[lineIdx].Fx;
                 containsFx = true;
             }
             else
             {
                 result[i].Notes[j] = cloneNote(this.currentPattern.Lines[lineIdx].Notes[chanIdx]);
             }
             chanIdx++;
         }
         lineIdx++;
     }
     return result;
 }
        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());
        }