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)); }
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; } }
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(); } }
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; }
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()); }