void ScheduleNextSong(AudioGroup group, int startSampleOffset, int sampleLength, uint busStartTime) { lock (anchorLock) { // Adjust the sampleLength. sampleLength = (sampleLength > 0) ? sampleLength : group.TotalSampleTime - startSampleOffset; nextSong = new AudioToBusAnchor(group, startSampleOffset, sampleLength); nextSong.busSampleStartTime = busStartTime; } }
int GetSampleTimeOfAnchor(AudioToBusAnchor anchor) { int sampleTime = 0; lock (anchorLock) { if (busPlaySampleTime < anchor.busSampleStartTime) { sampleTime = anchor.audioSampleStartTime; } else { sampleTime = anchor.audioSampleStartTime + (int)(busPlaySampleTime - anchor.busSampleStartTime); } } return sampleTime; }
void ReadBusAudioCallback(float[] data) { int sampleTimeToRead = data.Length / busChannels; //TODO: Clean this up! Lots of maths are repeated; this can be condensed! // Doing a bunch of operations on the song anchors. Lock them. lock (anchorLock) { if (!curSong.IsValid()) { // Silence. Possibly transitioning to actual song. if (!nextSong.IsValid()) { // Debug.Log("Read: silence"); System.Array.Clear(data, 0, data.Length); } else { // Transition if (nextSong.busSampleStartTime == 0) { // Debug.Log("Read: transition silence-song"); // Set the current time! nextSong.busSampleStartTime = busReadSampleTime; // Read the audio data. nextSong.audioGroup.GetAudioData(nextSong.audioSampleStartTime, data, 0, data.Length); // Commit transition. curSong = nextSong; nextSong = invalidSong; } else if (nextSong.busSampleStartTime < busReadSampleTime + sampleTimeToRead) { // Debug.Log("Read: transition silence-song, timed"); if (nextSong.busSampleStartTime > busReadSampleTime) { Debug.LogError("ERROR: We are somehow transitioning too late into the nextSong. Handle this somehow!"); } int dataSampleStride = (int)(nextSong.busSampleStartTime - busReadSampleTime) * busChannels; // Read in some silence. System.Array.Clear(data, 0, dataSampleStride); // Read the audio data. nextSong.audioGroup.GetAudioData(nextSong.audioSampleStartTime, data, dataSampleStride, data.Length - dataSampleStride); // Commit transition. curSong = nextSong; nextSong = invalidSong; } else { // Debug.Log("Read: transition but not away from silence"); // Just read silence for now. System.Array.Clear(data, 0, data.Length); } } } else { // The current song time! int curSongReadPos = (curSong.audioSampleStartTime + (int)(busReadSampleTime - curSong.busSampleStartTime)); // Options: // Transition - nextSong is scheduled to go // Transition - curSong is ending // Continue - simply continue curSong. if (nextSong.busSampleStartTime > 0 && // A setting of 0 means "play this when the current song ends". nextSong.busSampleStartTime < (busReadSampleTime + sampleTimeToRead)) { // Debug.Log("Read: transition song-song, timed"); if (nextSong.busSampleStartTime > busReadSampleTime) { Debug.LogError("ERROR: We are somehow transitioning too late into the nextSong. Handle this somehow!"); } // Scheduled transition! // Read current song up to busSampleStartTime. int dataSampleStride = (int)(nextSong.busSampleStartTime - busReadSampleTime) * busChannels; curSong.audioGroup.GetAudioData(curSongReadPos, data, 0, dataSampleStride); // Start up next song! nextSong.audioGroup.GetAudioData(nextSong.audioSampleStartTime, data, dataSampleStride, data.Length - dataSampleStride); // Commit transition. prevSong = curSong; curSong = nextSong; nextSong = invalidSong; } else if (curSongReadPos + sampleTimeToRead > curSong.audioSampleLength) { // CurSong is ending! int numSamplesLeftToReadFromSong = (int)((curSong.busSampleStartTime + (uint)curSong.audioSampleLength) - busReadSampleTime); int dataSampleStride = numSamplesLeftToReadFromSong * busChannels; curSong.audioGroup.GetAudioData(curSongReadPos, data, 0, dataSampleStride); // Commit transition 1/3. prevSong = curSong; if (nextSong.IsValid()) { // Debug.Log("Read: transition song-song, song1 ended"); // Anchor this song to the bus! nextSong.busSampleStartTime = busReadSampleTime + (uint)numSamplesLeftToReadFromSong; // Start up next song! nextSong.audioGroup.GetAudioData(nextSong.audioSampleStartTime, data, dataSampleStride, data.Length - dataSampleStride); // Commit transition 2/3. curSong = nextSong; } else { // Debug.Log("Read: transition song-silence, song ended"); // Silence. System.Array.Clear(data, dataSampleStride, data.Length - dataSampleStride); // Commit transition 2/3. curSong = invalidSong; } // Commit transition 3/3. nextSong = invalidSong; } else { // Debug.Log("Read: song"); // Continue playing CurSong! curSong.audioGroup.GetAudioData(curSongReadPos, data, 0, data.Length); } } } busReadSampleTime += (uint)sampleTimeToRead; }
public void Stop(bool bDoCallback = false) { AudioGroup stoppedGroup = null; int stoppedTime = 0; lock (anchorLock) { sourceCom.Stop(); bPaused = false; bColdStart = true; if (bDoCallback) { // If there's a song to stop, store it. if (prevSong.IsValid()) { stoppedGroup = prevSong.audioGroup; stoppedTime = prevSong.SampleTimeAtBusTime(busPlaySampleTime); } else if (curSong.IsValid()) { stoppedGroup = curSong.audioGroup; stoppedTime = curSong.SampleTimeAtBusTime(busPlaySampleTime); } } // Clear the song Anchors. prevSong = invalidSong; curSong = invalidSong; nextSong = invalidSong; } if (stoppedGroup != null) { OnAudioEnded(stoppedGroup, stoppedTime); } }