Exemple #1
0
        /// <summary>
        /// Event handler for individual miniGrid (holding 1-4 sounds) in mastergrid
        /// </summary>
        void OnMiniGridTapped(MiniGrid miniGrid)
        {
            Instrument selectedInstrument = selectedInstrButton.Instrument;

            // Changes UI represenation and returns new set of colors on this grid
            bool added = miniGrid.ToggleColor(selectedInstrument.color);

            // If sidebar color isn't part of button's new set of colors, remove it
            Instrument.Note toggledNote = selectedInstrument.AtPitch(miniGrid.semitoneShift);

            //If sidebar button color = clicked button color
            if (added)
            {
                song.AddNote(toggledNote, Grid.GetColumn(miniGrid));        // Add the note

                if (!player.IsPlaying)
                {
                    SingleNotePlayer.PlayNote(selectedInstrument.AtPitch(miniGrid.semitoneShift));   // Play note so long as not already playing a song
                }
            }
            else
            {
                song.RemoveNote(toggledNote, Grid.GetColumn(miniGrid));
            }

            //Undo clear stops woking when user adds stuff to grid so they don't accidentally undo clear
            clearedSong       = null;
            loadedSongChanged = true;  // If song is empty, no need to worry about changes, otherwise
        }
        /// <summary>
        /// Plays a single note. Separate from the rest of the song playing code
        /// </summary>
        public static void PlayNote(Instrument.Note note)
        {
            lock (syncObj)
            {
#if __ANDROID__
                if (playingTrack != null)
                {
                    //We use pause instead of stop because pause stops playing immediately
                    playingTrack.Pause();
                    playingTrack.Release();
                    playingTrack.Dispose();
                }
#endif
#if __IOS__
                if (audioQueue != null)
                {
                    //Pass true to stop immediately
                    audioQueue.Stop(true);
                    audioQueue.Dispose();
                }
#endif

#if __ANDROID__
                playingTrack = new AudioTrack(
                    // Stream type
                    Android.Media.Stream.Music,
                    // Frequency
                    SongPlayer.PLAYBACK_RATE,
                    // Mono or stereo
                    ChannelOut.Mono,
                    // Audio encoding
                    Android.Media.Encoding.Pcm16bit,
                    // Length of the audio clip in bytes
                    (note.data.Length * 2),
                    // Mode. Stream or static.
                    AudioTrackMode.Static);

                playingTrack.Write(note.data, 0, note.data.Length);
                playingTrack.Play();
#endif
#if __IOS__
                audioQueue = new OutputAudioQueue(AudioStreamBasicDescription.CreateLinearPCM(SongPlayer.PLAYBACK_RATE, 1, 16, false));
                unsafe
                {
                    AudioQueueBuffer *buffer;
                    audioQueue.AllocateBuffer(note.data.Length * 2, out buffer);

                    fixed(short *beatData = note.data)
                    {
                        buffer->CopyToAudioData((IntPtr)beatData, note.data.Length * 2);
                    }

                    audioQueue.EnqueueBuffer((IntPtr)buffer, note.data.Length * 2, null);
                }

                audioQueue.Start();
#endif
            }
        }
Exemple #3
0
 /// <summary>
 /// Remove a note from the song at a specific beat
 /// </summary>
 /// <param name="note">The note to remove from the song</param>
 /// <param name="beat">The beat to remove the note from</param>
 public void RemoveNote(Instrument.Note note, int beat)
 {
     //We use a lock so that the beat data is not modified while we are removing
     lock (beats)
     {
         beats[beat].Remove(note);
     }
 }
Exemple #4
0
 /// <summary>
 /// Add a note to the song at a specific beat
 /// </summary>
 /// <param name="note">The note to add to the song</param>
 /// <param name="beat">The beat to add the note at</param>
 public void AddNote(Instrument.Note note, int beat)
 {
     //We use a lock so that the beat data is not modified while we are adding
     lock (beats)
     {
         beats[beat].Add(note);
     }
 }
        /// <summary>
        /// Generates a Song object from a stream containing a text representation of a song
        /// </summary>
        public static Song LoadSongFromStream(Stream stream)
        {
            //Use StreamReader because the songs are in text foma
            StreamReader file = new StreamReader(stream);

            String versionString = file.ReadLine();

            if (versionString != "VERSION 1" && versionString != "VERSION 1.0.2")
            {
                throw new FileLoadException("Save file is in an invalid format");
            }

            //The first line of a song file contains the number of beats
            //and the song's instruments. It usually looks something like
            //16 beats|Snare|BassDrum|Piano|Clap

            //Get total beats
            String[] firstLineParts = file.ReadLine().Split('|');
            int      totalBeats     = int.Parse(firstLineParts[0].Split(' ')[0]);

            //Load instruments
            Instrument[] songInstruments = new Instrument[firstLineParts.Length - 1];
            for (int i = 1; i < firstLineParts.Length; i++)
            {
                songInstruments[i - 1] = Instrument.GetByName(firstLineParts[i]);
            }

            //Tempo is stored at the end of the file, so for now set the tempo to be -1
            Song loadedSong = new Song(totalBeats, songInstruments, -1);

            //Load notes
            for (int i = 0; i < totalBeats; i++)
            {
                //Each beat starts with a header of the form
                //Beat <beat number>|<number of notes>
                String header   = file.ReadLine();
                int    numNotes = int.Parse(header.Split('|')[1]);

                for (int n = 0; n < numNotes; n++)
                {
                    //Each note is stored like so:
                    //<instrument name>:<semitone shift>
                    String[] noteStringParts = file.ReadLine().Split(':');
                    String   instrName       = noteStringParts[0];
                    int      semitoneShift   = int.Parse(noteStringParts[1]);

                    Instrument.Note note = Instrument.GetByName(instrName).AtPitch(semitoneShift);
                    loadedSong.AddNote(note, i);
                }
            }
            //The last line of the file is the tempo
            loadedSong.Tempo = int.Parse(file.ReadLine());
            return(loadedSong);
        }
Exemple #6
0
        /// <summary>
        /// Returns an array containing the notes at the given beat
        /// </summary>
        /// <param name="beat">The beat to get the notes from</param>
        /// <returns>The notes at <code>beat</code></returns>
        public Instrument.Note[] NotesAtBeat(int beat)
        {
            Instrument.Note[] notes;

            //Lock so that the notes do not change while they are being copied
            lock (beats)
            {
                notes = new Instrument.Note[beats[beat].Count];
                beats[beat].CopyTo(notes);
            }
            return(notes);
        }
Exemple #7
0
        /// <summary>
        /// Replaces the instruments listed in oldInstruments with the respective instrument in newInstruments
        /// </summary>
        public void ReplaceInstruments(IList <Instrument> oldInstruments, IList <Instrument> newInstruments)
        {
            //Lock so that the beats do not change while they are being modified
            lock (beats)
            {
                foreach (HashSet <Instrument.Note> beat in beats)
                {
                    List <Instrument.Note> oldNotes = beat.ToList();
                    beat.Clear();

                    foreach (Instrument.Note oldNote in oldNotes)
                    {
                        //If this note's instrument is in oldInstrument, replace it with a note
                        //of the same pitch but from the new instrument
                        int index = oldInstruments.IndexOf(oldNote.instrument);
                        if (index < 0)
                        {
                            //Not supposed to be replaced, so just readd it.
                            beat.Add(oldNote);
                        }
                        else
                        {
                            //Replace with new note
                            Instrument.Note newNote = newInstruments[index].AtPitch(oldNote.semitoneShift);
                            beat.Add(newNote);
                        }
                    }
                }

                //Update Instruments
                for (int i = 0; i < oldInstruments.Count; i++)
                {
                    Instrument oldInstr = oldInstruments[i];
                    Instruments[Array.IndexOf(Instruments, oldInstr)] = newInstruments[i];
                }
            }
        }
Exemple #8
0
 public PlayingNote(Instrument.Note note, int startSample)
 {
     this.note        = note;
     this.startSample = startSample;
 }