private void OnStreamingAudioPeriodicNotification(object sender, AudioTrack.PeriodicNotificationEventArgs args) { BeatStarted?.BeginInvoke(((nextBeat - 1) + totalBeats) % totalBeats, false, null, null); AppendStreamingAudio(MixBeat(GetNotes(nextBeat))); nextBeat = (nextBeat + 1) % totalBeats; }
/// <summary> /// Begins playing a song /// </summary> public void BeginPlaying(Song song) { //This lock is used to ensure that starting and stopping of songs do not happen at the same time. lock (startStopSyncObject) { if (IsPlaying) { throw new InvalidOperationException("Audio is already playing."); } //Need to keep track of the playing song beyond this method this.song = song; //Get rid of any old playing notes left over from the last time a song was played playingNotes.Clear(); //(60 secs/min * PLAYBACK_RATE samples/sec) / song.Tempo beats/min = samples/beat samplesPerBeat = ((60 * PLAYBACK_RATE) / song.Tempo); //To start playback we need some initial data short[] beat0 = MixBeat(song.NotesAtBeat(0)); short[] beat1 = MixBeat(song.NotesAtBeat(1)); StartStreamingAudio(beat0, beat1); //Beats 0 and 1 have already been generated, so the next beet to generate is 2 nextBeat = 2; //Call the BeatStarted event, since playback has started BeatStarted?.Invoke(0, true); } }
public void BeginPlaying(int bpm) { samplesPerBeat = ((60 * playbackRate) / bpm); totalBeats = songDataReference.GetLength(0); short[] beat0 = MixBeat(GetNotes(0)); short[] beat1 = MixBeat(GetNotes(1)); StartStreamingAudio(beat0); AppendStreamingAudio(beat1); nextBeat = 2; BeatStarted?.Invoke(0, true); }
private void OnStreamingAudioPeriodicNotification(object sender, BufferCompletedEventArgs args) #endif { //nextBeat refers to the next beat to generate - the current beat is the one before nextBeat int currentBeat = ((nextBeat - 1) + song.BeatCount) % song.BeatCount; //Call the BeatStarted callback on a separate thread BeatStarted?.BeginInvoke(currentBeat, false, null, null); //Mix the audio data for this beat short[] data = MixBeat(song.NotesAtBeat(nextBeat)); //Make sure the track isnt disposed of after we check if it's playing lock (trackDisposedOfSyncObject) { if (IsPlaying) { #if __ANDROID__ //Add the audio data to the track playingTrack.Write(data, 0, data.Length); #endif #if __IOS__ //Copy the audio data to the buffer passed in to this method unsafe { fixed(short *beatData = data) { args.UnsafeBuffer->CopyToAudioData((IntPtr)beatData, data.Length * 2); } } //Add the buffer to the audio queue audioQueue.EnqueueBuffer(args.IntPtrBuffer, data.Length * 2, null); #endif } } nextBeat = (nextBeat + 1) % song.BeatCount; }