music: add texttags tests
Add tests for the TextTags processing wrapper.
This commit is contained in:
parent
502dd8ccc4
commit
782b570b38
5 changed files with 113 additions and 14 deletions
2
.github/workflows/android.yml
vendored
2
.github/workflows/android.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
|||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Test app with Gradle
|
||||
run: ./gradlew app:test
|
||||
run: ./gradlew app:testDebug
|
||||
- name: Build debug APK with Gradle
|
||||
run: ./gradlew app:packageDebug
|
||||
- name: Upload debug APK artifact
|
||||
|
|
|
@ -160,9 +160,9 @@ class Task(context: Context, private val raw: Song.Raw) {
|
|||
|
||||
val metadata = format.metadata
|
||||
if (metadata != null) {
|
||||
val tags = Tags(metadata)
|
||||
populateWithId3v2(tags.id3v2)
|
||||
populateWithVorbis(tags.vorbis)
|
||||
val textTags = TextTags(metadata)
|
||||
populateWithId3v2(textTags.id3v2)
|
||||
populateWithVorbis(textTags.vorbis)
|
||||
} else {
|
||||
logD("No metadata could be extracted for ${raw.name}")
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ import com.google.android.exoplayer2.metadata.vorbis.VorbisComment
|
|||
import org.oxycblt.auxio.music.parsing.correctWhitespace
|
||||
|
||||
/**
|
||||
* Processing wrapper for [Metadata] that allows access to more organized music tags.
|
||||
* Processing wrapper for [Metadata] that allows organized access to text-based audio tags.
|
||||
* @param metadata The [Metadata] to wrap.
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class Tags(metadata: Metadata) {
|
||||
class TextTags(metadata: Metadata) {
|
||||
private val _id3v2 = mutableMapOf<String, List<String>>()
|
||||
/** The ID3v2 text identification frames found in the file. Can have more than one value. */
|
||||
val id3v2: Map<String, List<String>>
|
||||
|
@ -65,6 +65,10 @@ class Tags(metadata: Metadata) {
|
|||
is VorbisComment -> {
|
||||
// Vorbis comment keys can be in any case, make them uppercase for simplicity.
|
||||
val id = tag.key.sanitize().lowercase()
|
||||
if (id == "metadata_block_picture") {
|
||||
// Picture, we don't care about these
|
||||
continue
|
||||
}
|
||||
val value = tag.value.sanitize().correctWhitespace()
|
||||
if (value != null) {
|
||||
_vorbis.getOrPut(id) { mutableListOf() }.add(value)
|
|
@ -30,7 +30,7 @@ import java.nio.ByteBuffer
|
|||
import kotlin.math.pow
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.extractor.Tags
|
||||
import org.oxycblt.auxio.music.extractor.TextTags
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.Settings
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
@ -166,23 +166,23 @@ class ReplayGainAudioProcessor(private val context: Context) :
|
|||
* @return A [Adjustment] adjustment, or null if there were no valid adjustments.
|
||||
*/
|
||||
private fun parseReplayGain(format: Format): Adjustment? {
|
||||
val tags = Tags(format.metadata ?: return null)
|
||||
val textTags = TextTags(format.metadata ?: return null)
|
||||
var trackGain = 0f
|
||||
var albumGain = 0f
|
||||
|
||||
// Most ReplayGain tags are formatted as a simple decibel adjustment in a custom
|
||||
// replaygain_*_gain tag.
|
||||
if (format.sampleMimeType != MimeTypes.AUDIO_OPUS) {
|
||||
tags.id3v2["TXXX:$TAG_RG_TRACK_GAIN"]
|
||||
textTags.id3v2["TXXX:$TAG_RG_TRACK_GAIN"]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { trackGain = it }
|
||||
tags.id3v2["TXXX:$TAG_RG_ALBUM_GAIN"]
|
||||
textTags.id3v2["TXXX:$TAG_RG_ALBUM_GAIN"]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { albumGain = it }
|
||||
tags.vorbis[TAG_RG_ALBUM_GAIN]
|
||||
textTags.vorbis[TAG_RG_ALBUM_GAIN]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { trackGain = it }
|
||||
tags.vorbis[TAG_RG_TRACK_GAIN]
|
||||
textTags.vorbis[TAG_RG_TRACK_GAIN]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { albumGain = it }
|
||||
} else {
|
||||
|
@ -191,10 +191,10 @@ class ReplayGainAudioProcessor(private val context: Context) :
|
|||
// intrinsic to the format to create the normalized adjustment. That base adjustment
|
||||
// is already handled by the media framework, so we just need to apply the more
|
||||
// specific adjustments.
|
||||
tags.vorbis[TAG_R128_TRACK_GAIN]
|
||||
textTags.vorbis[TAG_R128_TRACK_GAIN]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { trackGain = it / 256f }
|
||||
tags.vorbis[TAG_R128_ALBUM_GAIN]
|
||||
textTags.vorbis[TAG_R128_ALBUM_GAIN]
|
||||
?.run { first().parseReplayGainAdjustment() }
|
||||
?.let { albumGain = it / 256f }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.music.extractor
|
||||
|
||||
import com.google.android.exoplayer2.metadata.Metadata
|
||||
import com.google.android.exoplayer2.metadata.flac.PictureFrame
|
||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame
|
||||
import com.google.android.exoplayer2.metadata.id3.InternalFrame
|
||||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame
|
||||
import com.google.android.exoplayer2.metadata.vorbis.VorbisComment
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class TextTagsTest {
|
||||
@Test
|
||||
fun textTags_vorbis() {
|
||||
val textTags = TextTags(VORBIS_METADATA)
|
||||
assertTrue(textTags.id3v2.isEmpty())
|
||||
assertEquals(listOf("Wheel"), textTags.vorbis["title"])
|
||||
assertEquals(listOf("Paraglow"), textTags.vorbis["album"])
|
||||
assertEquals(listOf("Parannoul", "Asian Glow"), textTags.vorbis["artist"])
|
||||
assertEquals(listOf("2022"), textTags.vorbis["date"])
|
||||
assertEquals(listOf("ep"), textTags.vorbis["releasetype"])
|
||||
assertEquals(listOf("+2 dB"), textTags.vorbis["replaygain_track_gain"])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textTags_id3v2() {
|
||||
val textTags = TextTags(ID3V2_METADATA)
|
||||
assertTrue(textTags.vorbis.isEmpty())
|
||||
assertEquals(listOf("Wheel"), textTags.id3v2["TIT2"])
|
||||
assertEquals(listOf("Paraglow"), textTags.id3v2["TALB"])
|
||||
assertEquals(listOf("Parannoul", "Asian Glow"), textTags.id3v2["TPE1"])
|
||||
assertEquals(listOf("2022"), textTags.id3v2["TDRC"])
|
||||
assertEquals(listOf("ep"), textTags.id3v2["TXXX:musicbrainz album type"])
|
||||
assertEquals(listOf("+2 dB"), textTags.id3v2["TXXX:replaygain_track_gain"])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textTags_combined() {
|
||||
val textTags = TextTags(VORBIS_METADATA.copyWithAppendedEntriesFrom(ID3V2_METADATA))
|
||||
assertEquals(listOf("Wheel"), textTags.vorbis["title"])
|
||||
assertEquals(listOf("Paraglow"), textTags.vorbis["album"])
|
||||
assertEquals(listOf("Parannoul", "Asian Glow"), textTags.vorbis["artist"])
|
||||
assertEquals(listOf("2022"), textTags.vorbis["date"])
|
||||
assertEquals(listOf("ep"), textTags.vorbis["releasetype"])
|
||||
assertEquals(listOf("+2 dB"), textTags.vorbis["replaygain_track_gain"])
|
||||
assertEquals(listOf("Wheel"), textTags.id3v2["TIT2"])
|
||||
assertEquals(listOf("Paraglow"), textTags.id3v2["TALB"])
|
||||
assertEquals(listOf("Parannoul", "Asian Glow"), textTags.id3v2["TPE1"])
|
||||
assertEquals(listOf("2022"), textTags.id3v2["TDRC"])
|
||||
assertEquals(listOf("ep"), textTags.id3v2["TXXX:musicbrainz album type"])
|
||||
assertEquals(listOf("+2 dB"), textTags.id3v2["TXXX:replaygain_track_gain"])
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val VORBIS_METADATA =
|
||||
Metadata(
|
||||
VorbisComment("TITLE", "Wheel"),
|
||||
VorbisComment("ALBUM", "Paraglow"),
|
||||
VorbisComment("ARTIST", "Parannoul"),
|
||||
VorbisComment("ARTIST", "Asian Glow"),
|
||||
VorbisComment("DATE", "2022"),
|
||||
VorbisComment("RELEASETYPE", "ep"),
|
||||
VorbisComment("METADATA_BLOCK_PICTURE", ""),
|
||||
VorbisComment("REPLAYGAIN_TRACK_GAIN", "+2 dB"),
|
||||
PictureFrame(0, "", "", 0, 0, 0, 0, byteArrayOf()))
|
||||
|
||||
private val ID3V2_METADATA =
|
||||
Metadata(
|
||||
TextInformationFrame("TIT2", null, listOf("Wheel")),
|
||||
TextInformationFrame("TALB", null, listOf("Paraglow")),
|
||||
TextInformationFrame("TPE1", null, listOf("Parannoul", "Asian Glow")),
|
||||
TextInformationFrame("TDRC", null, listOf("2022")),
|
||||
TextInformationFrame("TXXX", "MusicBrainz Album Type", listOf("ep")),
|
||||
InternalFrame("com.apple.iTunes", "replaygain_track_gain", "+2 dB"),
|
||||
ApicFrame("", "", 0, byteArrayOf()))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue