Пример #1
0
        /// <summary>
        /// Generates a list of chords by pulling the live cells from the underlying TokenGroup with the current NoteGroup parameters.
        /// </summary>
        private void InitChordsFromTokenGroup()
        {
            Chords = new List<Chord>();

            // Grab all of the cells from the token group that are within the specified left and right bounds.
            // Then, sort them so that notes played first are nearest to the zero index.

            // Need to find the pop index of the farthest right cell for use with the set right bound.
            int rightmostPop = _tokenGroup.Cells.Max(x => x[0]);

            List<int[]> validCells = new List<int[]>(_tokenGroup.Cells.Where(x => x[0] >= _leftBound && x[0] < rightmostPop-_rightBound));
            validCells.Sort((cell1, cell2) => cell1[0].CompareTo(cell2[0]));

            // Iterate through the cells, joining cells w/ the same population index into the same Chord, adding them to the Chord list.
            // Set the beginning beat & duration of each chord/note as appropriate to the beat # of the song, by the parameters set for this NG.
            // Also, "shift" cells over by the first cell[0] so that groups modified by the left bound will still start on beat 0.
            // ALSO, skip the first n notes the first time through, where n is the value of the Horizontal Offset.

            double currentTotalBeat = 0;        // The actual beat counter for the song.

            Chord currentChord = new Chord(new List<Note>(), 0); // The first chord of every NG starst at beat 0.

            if (validCells.Count == 0)
                return;

            List<int[]> horizOffsetCells = new List<int[]>();

            if (HorizOffset > 0)
            {
                int startRangeIndex = HorizOffset%validCells.Count;
                horizOffsetCells.AddRange(validCells.GetRange(startRangeIndex, validCells.Count - startRangeIndex));
                validCells.RemoveRange(startRangeIndex, validCells.Count - startRangeIndex);
            }

            float cellOffset = validCells[0][0];

            // Keep going until we've added enough chords for the duration of the entire "song".
            while (currentTotalBeat < SongDuration)
            {
                double currentPatternBeat = 0;      // The current beat in a single run-through of the pattern.

                foreach (int[] cell in validCells)
                {
                    // Adjust the start beat of the note by the left bounds, so the pattern starts at beat zero.
                    float startBeat = (cell[0] - cellOffset);

                    // If we're finished with the current chord, make a new one.
                    if (startBeat*_noteDuration > currentPatternBeat)
                    {
                        currentPatternBeat = startBeat*_noteDuration;

                        // Go directly to jail. Do not pass Go, do not collect $200.
                        if (currentTotalBeat + currentPatternBeat > SongDuration)
                            return;

                        Chords.Add(new Chord(currentChord.Notes, currentChord.StartBeat));
                        currentChord = new Chord(new List<Note>(), (float)(currentPatternBeat+currentTotalBeat));     // Note: I hope this cast doesn't bite me in the ass.
                    }

                    // Add a new note to the chord with the correct pitch, duration, and on the correct beat. Adjust the pitch by the vertical shift, wrapping
                    // around if necessary.
                    // Also add the "current" beat to it to allow for repitition if this isn't the first time through the while loop.
                    currentChord.Notes.Add(new Note(_scale[Utilities.Mod(cell[1] + _vertOffset, _scale.Length)],
                                                    _noteDuration, currentPatternBeat+currentTotalBeat));
                }

                // Add that last chord to the song, since we're repeating.
                Chords.Add(new Chord(currentChord.Notes, currentChord.StartBeat)); // NOTE: Deadly copypasta

                // We've made a full pass through the cells of the TokenGroup, so add on the repetition delay to the current beat, and go back to see if we should
                // cycle back through the cells again.
                currentTotalBeat += currentPatternBeat + _noteDuration + _repetitionInterval;

                currentChord = new Chord(new List<Note>(), (float)currentTotalBeat); // Set the next chord to be made to the current total beat

                if (horizOffsetCells.Count != 0)
                {
                    validCells.InsertRange(0, horizOffsetCells);
                    horizOffsetCells.Clear();
                }
            }
        }
Пример #2
0
        private void PlayChord(Chord chord)
        {
            // Spawn a new thread to play each note. This way the notes in a chord don't all have to have the same duration.
            for (int i = 0; i < chord.Notes.Count; i++)
            {
                Note note = chord.Notes[i];

                _sineWaveProviders[(int)note.Pitch].Amplitude = _defaultPitchAmp;

                _notesBeingPlayed.Add(new PlayedNote(note, _currentBeat + note.Duration));

                //Console.WriteLine("On" + " " + _pitchUsageCounters[(int)note.Pitch]);
            }

            //            Console.WriteLine(DateTime.Now);
            //Console.WriteLine("\n");
        }