music: fix enqueueing

Fix enqueuing issues encountered during testing.
This commit is contained in:
Alexander Capehart 2023-01-05 11:38:32 -07:00
parent 743220d0aa
commit a10cf1e0c3
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 27 additions and 13 deletions

View file

@ -242,13 +242,7 @@ class ReplayGainAudioProcessor(private val context: Context) :
} else { } else {
for (i in pos until limit step 2) { for (i in pos until limit step 2) {
// 16-bit PCM audio, deserialize a little-endian short. // 16-bit PCM audio, deserialize a little-endian short.
var sample = var sample = inputBuffer.getLeShort(i)
inputBuffer
.get(i + 1)
.toInt()
.shl(8)
.or(inputBuffer.get(i).toInt().and(0xFF))
.toShort()
// Ensure we clamp the values to the minimum and maximum values possible // Ensure we clamp the values to the minimum and maximum values possible
// for the encoding. This prevents issues where samples amplified beyond // for the encoding. This prevents issues where samples amplified beyond
// 1 << 16 will end up becoming truncated during the conversion to a short, // 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()) .coerceAtLeast(Short.MIN_VALUE.toInt())
.coerceAtMost(Short.MAX_VALUE.toInt()) .coerceAtMost(Short.MAX_VALUE.toInt())
.toShort() .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() 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. * The resolved ReplayGain adjustment for a file.
* @param track The track adjustment (in dB), or 0 if it is not present. * @param track The track adjustment (in dB), or 0 if it is not present.

View file

@ -238,6 +238,8 @@ class PlaybackStateManager private constructor() {
when (queue.playNext(songs)) { when (queue.playNext(songs)) {
Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING) Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING)
Queue.ChangeResult.SONG -> { Queue.ChangeResult.SONG -> {
// Enqueueing actually started a new playback session from all songs.
parent = null
internalPlayer.loadSong(queue.currentSong, true) internalPlayer.loadSong(queue.currentSong, true)
notifyNewPlayback() notifyNewPlayback()
} }
@ -261,6 +263,8 @@ class PlaybackStateManager private constructor() {
when (queue.addToQueue(songs)) { when (queue.addToQueue(songs)) {
Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING) Queue.ChangeResult.MAPPING -> notifyQueueChanged(Queue.ChangeResult.MAPPING)
Queue.ChangeResult.SONG -> { Queue.ChangeResult.SONG -> {
// Enqueueing actually started a new playback session from all songs.
parent = null
internalPlayer.loadSong(queue.currentSong, true) internalPlayer.loadSong(queue.currentSong, true)
notifyNewPlayback() notifyNewPlayback()
} }

View file

@ -102,7 +102,7 @@ class Queue {
// Since we are re-shuffling existing songs, we use the previous mapping size // Since we are re-shuffling existing songs, we use the previous mapping size
// instead of the total queue 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))) shuffledMapping.add(0, shuffledMapping.removeAt(shuffledMapping.indexOf(trueIndex)))
index = 0 index = 0
} else if (shuffledMapping.isNotEmpty()) { } 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 // 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. // of the analogous list song in the ordered mapping.
val orderedIndex = orderedMapping.indexOf(shuffledMapping[index]) val orderedIndex = orderedMapping.indexOf(shuffledMapping[index])
orderedMapping.addAll(orderedIndex, heapIndices) orderedMapping.addAll(orderedIndex + 1, heapIndices)
shuffledMapping.addAll(index, heapIndices) shuffledMapping.addAll(index + 1, heapIndices)
} else { } else {
// Add the new song in front of the current index in the ordered mapping. // 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 return ChangeResult.MAPPING
} }
@ -207,7 +207,7 @@ class Queue {
orderedMapping.removeAt(orderedMapping.indexOf(shuffledMapping[at])) orderedMapping.removeAt(orderedMapping.indexOf(shuffledMapping[at]))
shuffledMapping.removeAt(at) shuffledMapping.removeAt(at)
} else { } else {
// Remove the spe // Remove the specified index in the shuffled mapping
orderedMapping.removeAt(at) orderedMapping.removeAt(at)
} }