From a10cf1e0c3040863438625357576842a6e39700a Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Thu, 5 Jan 2023 11:38:32 -0700 Subject: [PATCH] music: fix enqueueing Fix enqueuing issues encountered during testing. --- .../replaygain/ReplayGainAudioProcessor.kt | 26 +++++++++++++------ .../playback/state/PlaybackStateManager.kt | 4 +++ .../org/oxycblt/auxio/playback/state/Queue.kt | 10 +++---- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt index 5c09579b6..ecd8a1eec 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt @@ -242,13 +242,7 @@ class ReplayGainAudioProcessor(private val context: Context) : } else { for (i in pos until limit step 2) { // 16-bit PCM audio, deserialize a little-endian short. - var sample = - inputBuffer - .get(i + 1) - .toInt() - .shl(8) - .or(inputBuffer.get(i).toInt().and(0xFF)) - .toShort() + var sample = inputBuffer.getLeShort(i) // Ensure we clamp the values to the minimum and maximum values possible // for the encoding. This prevents issues where samples amplified beyond // 1 << 16 will end up becoming truncated during the conversion to a short, @@ -259,7 +253,7 @@ class ReplayGainAudioProcessor(private val context: Context) : .coerceAtLeast(Short.MIN_VALUE.toInt()) .coerceAtMost(Short.MAX_VALUE.toInt()) .toShort() - buffer.put(sample.toByte()).put(sample.toInt().shr(8).toByte()) + buffer.putLeShort(sample) } } @@ -267,6 +261,22 @@ class ReplayGainAudioProcessor(private val context: Context) : buffer.flip() } + /** + * Always read a little-endian [Short] from the [ByteBuffer] at the given index. + * @param at The index to read the [Short] from. + */ + private fun ByteBuffer.getLeShort(at: Int) = + get(at + 1).toInt().shl(8).or(get(at).toInt().and(0xFF)).toShort() + + /** + * Always write a little-endian [Short] at the end of the [ByteBuffer]. + * @param short The [Short] to write. + */ + private fun ByteBuffer.putLeShort(short: Short) { + put(short.toByte()) + put(short.toInt().shr(8).toByte()) + } + /** * The resolved ReplayGain adjustment for a file. * @param track The track adjustment (in dB), or 0 if it is not present. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index c5a588226..639fa6381 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -238,6 +238,8 @@ class PlaybackStateManager private constructor() { when (queue.playNext(songs)) { Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING) Queue.ChangeResult.SONG -> { + // Enqueueing actually started a new playback session from all songs. + parent = null internalPlayer.loadSong(queue.currentSong, true) notifyNewPlayback() } @@ -261,6 +263,8 @@ class PlaybackStateManager private constructor() { when (queue.addToQueue(songs)) { Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING) Queue.ChangeResult.SONG -> { + // Enqueueing actually started a new playback session from all songs. + parent = null internalPlayer.loadSong(queue.currentSong, true) notifyNewPlayback() } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/Queue.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/Queue.kt index 025485f53..045bb4110 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/Queue.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/Queue.kt @@ -102,7 +102,7 @@ class Queue { // Since we are re-shuffling existing songs, we use the previous mapping size // instead of the total queue size. - shuffledMapping = MutableList(orderedMapping.size) { it }.apply { shuffle() } + shuffledMapping = orderedMapping.shuffled().toMutableList() shuffledMapping.add(0, shuffledMapping.removeAt(shuffledMapping.indexOf(trueIndex))) index = 0 } else if (shuffledMapping.isNotEmpty()) { @@ -130,11 +130,11 @@ class Queue { // Add the new songs in front of the current index in the shuffled mapping and in front // of the analogous list song in the ordered mapping. val orderedIndex = orderedMapping.indexOf(shuffledMapping[index]) - orderedMapping.addAll(orderedIndex, heapIndices) - shuffledMapping.addAll(index, heapIndices) + orderedMapping.addAll(orderedIndex + 1, heapIndices) + shuffledMapping.addAll(index + 1, heapIndices) } else { // Add the new song in front of the current index in the ordered mapping. - orderedMapping.addAll(index, heapIndices) + orderedMapping.addAll(index + 1, heapIndices) } return ChangeResult.MAPPING } @@ -207,7 +207,7 @@ class Queue { orderedMapping.removeAt(orderedMapping.indexOf(shuffledMapping[at])) shuffledMapping.removeAt(at) } else { - // Remove the spe + // Remove the specified index in the shuffled mapping orderedMapping.removeAt(at) }