forked from PaulWoitaschek/Voice
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored vorbis-comment logic into separate files
- Loading branch information
1 parent
f22f1f1
commit b9f5763
Showing
10 changed files
with
168 additions
and
150 deletions.
There are no files selected for viewing
3 changes: 3 additions & 0 deletions
3
...obook/src/main/java/de/ph1b/audiobook/features/chapterReader/ogg/OGGPageParseException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg | ||
|
||
class OGGPageParseException(message: String) : Exception(message) |
41 changes: 41 additions & 0 deletions
41
audiobook/src/main/java/de/ph1b/audiobook/features/chapterReader/ogg/OggPage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg | ||
|
||
data class OggPage( | ||
val continuedPacket: Boolean, | ||
val finishedPacket: Boolean, | ||
val firstPageOfStream: Boolean, | ||
val lastPageOfStream: Boolean, | ||
val absoluteGranulePosition: Long, | ||
val streamSerialNumber: Int, | ||
val pageSequenceNumber: Long, | ||
val packets: List<ByteArray>) { | ||
|
||
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (other !is OggPage) return false | ||
return continuedPacket == other.continuedPacket | ||
&& finishedPacket == other.finishedPacket | ||
&& firstPageOfStream == other.firstPageOfStream | ||
&& lastPageOfStream == other.lastPageOfStream | ||
&& absoluteGranulePosition == other.absoluteGranulePosition | ||
&& streamSerialNumber == other.streamSerialNumber | ||
&& pageSequenceNumber == other.pageSequenceNumber | ||
&& packets.size == other.packets.size | ||
&& packets.indices.all { packets[it] contentEquals other.packets[it] } | ||
} | ||
|
||
override fun hashCode(): Int { | ||
var hashCode = 17 | ||
hashCode = 31 * hashCode + continuedPacket.hashCode() | ||
hashCode = 31 * hashCode + finishedPacket.hashCode() | ||
hashCode = 31 * hashCode + firstPageOfStream.hashCode() | ||
hashCode = 31 * hashCode + lastPageOfStream.hashCode() | ||
hashCode = 31 * hashCode + absoluteGranulePosition.hashCode() | ||
hashCode = 31 * hashCode + streamSerialNumber.hashCode() | ||
hashCode = 31 * hashCode + pageSequenceNumber.hashCode() | ||
packets.forEach { | ||
hashCode = 31 * hashCode + it.contentHashCode() | ||
} | ||
return hashCode | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
audiobook/src/main/java/de/ph1b/audiobook/features/chapterReader/ogg/OggStream.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg | ||
|
||
import java.util.ArrayDeque | ||
|
||
class OggStream(private val pullPage: OggStream.() -> Unit) : Iterator<ByteArray> { | ||
private val packetsQue = ArrayDeque<ByteArray>() | ||
private val packetBuffer = mutableListOf<ByteArray>() | ||
private var isDone = false | ||
|
||
fun pushPage(page: OggPage) { | ||
if (isDone) return | ||
val start = if (page.continuedPacket) { | ||
if (page.packets.size > 1 || page.finishedPacket) { | ||
packetBuffer.add(page.packets[0]) | ||
packetsQue.add(packetBuffer.concat()) | ||
packetBuffer.clear() | ||
} | ||
1 | ||
} else 0 | ||
val end = page.packets.lastIndex - if (page.finishedPacket) 0 else { | ||
packetBuffer.add(page.packets[page.packets.lastIndex]) | ||
1 | ||
} | ||
(start..end).mapTo(packetsQue) { page.packets[it] } | ||
if (page.lastPageOfStream) isDone = true | ||
} | ||
|
||
override fun hasNext(): Boolean { | ||
while (packetsQue.isEmpty()) { | ||
if (isDone) return false | ||
pullPage() | ||
} | ||
return true | ||
} | ||
|
||
override fun next(): ByteArray { | ||
if (!hasNext()) throw NoSuchElementException() | ||
return packetsQue.poll() | ||
} | ||
|
||
fun peek(): ByteArray { | ||
if (!hasNext()) throw NoSuchElementException() | ||
return packetsQue.peek() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...src/main/java/de/ph1b/audiobook/features/chapterReader/ogg/vorbisComment/VorbisComment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg.vorbisComment | ||
|
||
import android.util.SparseArray | ||
import de.ph1b.audiobook.misc.emptySparseArray | ||
|
||
data class VorbisComment(val vendor: String, val comments: Map<String, String>) { | ||
/** | ||
* Chapters extracted according to https://wiki.xiph.org/Chapter_Extension | ||
*/ | ||
val chapters: SparseArray<String> | ||
get() { | ||
val chapters = SparseArray<String>() | ||
var i = 1 | ||
while (true) { | ||
val iStr = i.toString().padStart(3, '0') | ||
val timeStr = comments["CHAPTER$iStr"] ?: break | ||
val name = comments["CHAPTER${iStr}NAME"] ?: return emptySparseArray() | ||
val time = VorbisCommentReader.parseChapterTime(timeStr) ?: return emptySparseArray() | ||
chapters.put(time, name) | ||
++i | ||
} | ||
return chapters | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
...de/ph1b/audiobook/features/chapterReader/ogg/vorbisComment/VorbisCommentParseException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg.vorbisComment | ||
|
||
class VorbisCommentParseException(message: String) : Exception(message) |
38 changes: 38 additions & 0 deletions
38
...in/java/de/ph1b/audiobook/features/chapterReader/ogg/vorbisComment/VorbisCommentReader.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package de.ph1b.audiobook.features.chapterReader.ogg.vorbisComment | ||
|
||
import de.ph1b.audiobook.features.chapterReader.readBytes | ||
import de.ph1b.audiobook.features.chapterReader.readLeUInt32 | ||
import java.io.InputStream | ||
|
||
object VorbisCommentReader { | ||
|
||
private val VORBIS_COMMENT_CHAPTER_TIME_REGEX = Regex("""(\d+):(\d+):(\d+).(\d+)""") | ||
|
||
/** | ||
* Reads vorbis comment according to [specification](https://xiph.org/vorbis/doc/v-comment.html) | ||
*/ | ||
fun readComment(stream: InputStream): VorbisComment { | ||
val vendorLength = stream.readLeUInt32() | ||
val vendor = stream.readBytes(vendorLength.toInt()).toString(Charsets.UTF_8) | ||
val numberComments = stream.readLeUInt32() | ||
val comments = (1..numberComments).map { | ||
val length = stream.readLeUInt32() | ||
val comment = stream.readBytes(length.toInt()).toString(Charsets.UTF_8) | ||
val parts = comment.split("=", limit = 2) | ||
if (parts.size != 2) throw VorbisCommentParseException("Expected TAG=value comment format") | ||
Pair(parts[0].toUpperCase(), parts[1]) | ||
}.toMap() | ||
return VorbisComment(vendor, comments) | ||
} | ||
|
||
fun parseChapterTime(timeStr: String): Int? { | ||
val matchResult = VORBIS_COMMENT_CHAPTER_TIME_REGEX.matchEntire(timeStr) | ||
?: return null | ||
val hours = matchResult.groups[1]!!.value.toInt() | ||
val minutes = hours * 60 + matchResult.groups[2]!!.value.toInt() | ||
val seconds = minutes * 60 + matchResult.groups[3]!!.value.toInt() | ||
val milliseconds = seconds * 1000 + matchResult.groups[4]!!.value.take(3).padEnd(3, '0').toInt() | ||
return milliseconds | ||
} | ||
} | ||
|
57 changes: 0 additions & 57 deletions
57
audiobook/src/main/java/de/ph1b/audiobook/features/chapterReader/ogg/vorbisCommentReading.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters