commonMain.korlibs.audio.format.MP3Decoder.kt Maven / Gradle / Ivy
The newest version!
package korlibs.audio.format
import korlibs.audio.sound.*
import korlibs.datastructure.*
import korlibs.io.stream.*
import korlibs.memory.*
import korlibs.time.*
import kotlin.math.*
import kotlin.time.*
open class MP3Decoder() : AudioFormat("mp3") {
companion object : MP3Decoder()
private val format = Minimp3AudioFormat
override suspend fun tryReadInfo(data: AsyncStream, props: AudioDecodingProps): Info? = format.tryReadInfo(data, props)
override suspend fun decodeStreamInternal(data: AsyncStream, props: AudioDecodingProps): AudioStream? = format.decodeStream(data, props)
override fun toString(): String = "NativeMp3DecoderFormat"
}
abstract class BaseMinimp3AudioFormat : AudioFormat("mp3") {
override suspend fun tryReadInfo(data: AsyncStream, props: AudioDecodingProps): Info? {
return MP3.tryReadInfo(data, props)
}
override suspend fun decodeStreamInternal(data: AsyncStream, props: AudioDecodingProps): AudioStream? {
return createDecoderStream(data, props, null)
}
private suspend fun createDecoderStream(data: AsyncStream, props: AudioDecodingProps, table: MP3Base.SeekingTable? = null): AudioStream {
val dataStartPosition = data.position
val decoder = createMp3Decoder()
decoder.info.reset()
var mp3SeekingTable: MP3Base.SeekingTable? = when (props.exactTimings) {
true -> table ?: (if (data.hasLength()) MP3Base.Parser(data, data.getLength()).getSeekingTable() else null)
else -> null
}
suspend fun readMoreSamples(): Boolean {
//println("currentThreadId=$currentThreadId, currentThreadName=$currentThreadName")
while (true) {
if (decoder.info.compressedData.availableRead < decoder.info.tempBuffer.size && data.hasAvailable()) {
decoder.info.compressedData.write(data.readBytesUpTo(0x1000))
}
val result = decoder.info.step(decoder)
if (decoder.info.hz == 0 || decoder.info.nchannels == 0) continue
return result
}
}
readMoreSamples()
//println("Minimp3AudioFormat: decoder.hz=${decoder.hz}, decoder.nchannels=${decoder.nchannels}")
return object : AudioStream(decoder.info.hz, decoder.info.nchannels) {
override var finished: Boolean = false
override var totalLengthInSamples: Long? = decoder.info.totalSamples.toLong().takeIf { it != 0L }
?: mp3SeekingTable?.lengthSamples(decoder.info.hz)
var _currentPositionInSamples: Long = 0L
override val currentPositionInSamples: Long get() = _currentPositionInSamples
override suspend fun seek(position: Duration) {
finished = false
if (position == 0.0.seconds) {
data.position = 0L
_currentPositionInSamples = 0L
} else {
//if (decoder.info.bitrate_kbps != 0 && mp3SeekingTable == null) {
// data.position = 0L
// _currentPositionInSamples = estimateSamplesFromTime(position)
//}
if (mp3SeekingTable == null) {
mp3SeekingTable = table ?: (if (data.hasLength()) MP3Base.Parser(data, data.getLength()).getSeekingTable() else null)
}
if (mp3SeekingTable != null) {
val offset = mp3SeekingTable!!.locate(position)
data.position = offset
_currentPositionInSamples = estimateSamplesFromTime(position)
//println("Seeked to offset=$offset, data.position=${data.position} for $position :: ${mp3SeekingTable?.filePositions} :: ${mp3SeekingTable?.microseconds}")
} else {
println("Couldn't create mp3SeekingTable")
}
}
decoder.info.reset()
}
override suspend fun read(out: AudioSamples, offset: Int, length: Int): Int {
var noMoreSamples = false
while (decoder.info.pcmDeque!!.availableRead < length) {
if (!readMoreSamples()) {
//println("no more samples!")
noMoreSamples = true
break
}
}
//println("audioSamplesDeque!!.availableRead=${audioSamplesDeque!!.availableRead}")
return if (noMoreSamples && decoder.info.pcmDeque!!.availableRead == 0) {
finished = true
0
} else {
decoder.info.pcmDeque!!.read(out, offset, length)
}.also {
_currentPositionInSamples += it
//println(" -> $it")
//println("MP3.read: offset=$offset, length=$length, noMoreSamples=$noMoreSamples, finished=$finished")
}
}
override fun close() {
decoder.close()
}
override suspend fun clone(): AudioStream = createDecoderStream(data.duplicate().also { it.position = dataStartPosition }, props, table)
}
}
protected abstract fun createMp3Decoder(): BaseMp3Decoder
class BaseMp3DecoderInfo {
val tempBuffer = ByteArray(1152 * 2 * 2)
val compressedData = ByteArrayDeque()
var pcmDeque: AudioSamplesDeque? = null
var hz = 0
var bitrate_kbps = 0
var nchannels = 0
var samples: Int = 0
var frame_bytes: Int = 0
var skipRemaining: Int = 0
var samplesAvailable: Int = 0
var totalSamples: Int = 0
var samplesRead: Int = 0
var xingFrames: Int = 0
var xingDelay: Int = 0
var xingPadding: Int = 0
fun reset() {
pcmDeque?.clear()
compressedData.clear()
skipRemaining = 0
samplesAvailable = -1
samplesRead = 0
}
fun step(decoder: BaseMp3Decoder): Boolean {
val availablePeek = compressedData.peek(tempBuffer, 0, tempBuffer.size)
val xingIndex = tempBuffer.indexOf(XingTag).takeIf { it >= 0 } ?: tempBuffer.size
val infoIndex = tempBuffer.indexOf(InfoTag).takeIf { it >= 0 } ?: tempBuffer.size
if (xingIndex < tempBuffer.size || infoIndex < tempBuffer.size) {
try {
val index = kotlin.math.min(xingIndex, infoIndex)
val data = FastByteArrayInputStream(tempBuffer, index)
data.skip(7)
if (data.available >= 1) {
val flags = data.readU8()
//println("xing=$xingIndex, infoIndex=$infoIndex, index=$index, flags=$flags")
val FRAMES_FLAG = 1
val BYTES_FLAG = 2
val TOC_FLAG = 4
val VBR_SCALE_FLAG = 8
if (flags.hasFlags(FRAMES_FLAG) && data.available >= 4) {
xingFrames = data.readS32BE()
if (flags.hasFlags(BYTES_FLAG)) data.skip(4)
if (flags.hasFlags(TOC_FLAG)) data.skip(100)
if (flags.hasFlags(VBR_SCALE_FLAG)) data.skip(4)
if (data.available >= 1) {
val info = data.readU8()
if (info != 0) {
data.skip(20)
if (data.available >= 3) {
val t0 = data.readU8()
val t1 = data.readU8()
val t2 = data.readU8()
xingDelay = ((t0 shl 4) or (t1 ushr 4)) + (528 + 1)
xingPadding = (((t1 and 0xF) shl 8) or (t2)) - (528 + 1)
}
//println("frames=$frames, flags=$flags, delay=$delay, padding=$padding, $t0,$t1,$t2")
}
}
}
}
} catch (e: Throwable) {
e.printStackTrace()
}
}
val buf = decoder.decodeFrame(availablePeek)
if (nchannels != 0 && (xingFrames != 0 || xingDelay != 0 || xingPadding != 0)) {
val rpadding = xingPadding * nchannels
val to_skip = xingDelay * nchannels
var detected_samples = samples * xingFrames * nchannels
if (detected_samples >= to_skip) detected_samples -= to_skip
if (rpadding in 1..detected_samples) detected_samples -= rpadding
skipRemaining = to_skip + (samples * nchannels)
samplesAvailable = detected_samples
//println("nchannels=$nchannels")
totalSamples = detected_samples / nchannels
//println("frames=$frames, delay=$delay, padding=$padding :: rpadding=$rpadding, to_skip=$to_skip, detected_samples=$detected_samples")
xingFrames = 0
xingDelay = 0
xingPadding = 0
}
//println("availablePeek=$availablePeek, frame_bytes=$frame_bytes, samples=$samples, nchannels=$nchannels, hz=$hz, bitrate_kbps=")
if (nchannels != 0 && pcmDeque == null) {
pcmDeque = AudioSamplesDeque(nchannels)
}
if (samples > 0) {
var offset = 0
var toRead = samples * nchannels
if (skipRemaining > 0) {
val skipNow = kotlin.math.min(skipRemaining, toRead)
offset += skipNow
toRead -= skipNow
skipRemaining -= skipNow
}
if (samplesAvailable >= 0) {
toRead = kotlin.math.min(toRead, samplesAvailable)
samplesAvailable -= toRead
}
//println("writeInterleaved. offset=$offset, toRead=$toRead")
pcmDeque!!.writeInterleaved(AudioSampleArray(buf!!), offset, toRead)
}
//println("mp3decFrameInfo: samples=$samples, channels=${struct.channels}, frame_bytes=${struct.frame_bytes}, frame_offset=${struct.frame_offset}, bitrate_kbps=${struct.bitrate_kbps}, hz=${struct.hz}, layer=${struct.layer}")
compressedData.skip(frame_bytes)
if (frame_bytes == 0 && samples == 0) {
return false
}
if (pcmDeque != null && pcmDeque!!.availableRead > 0) {
return true
}
return true
}
}
interface BaseMp3Decoder : AutoCloseable {
val info: BaseMp3DecoderInfo
fun decodeFrame(availablePeek: Int): ShortArray?
}
companion object {
val XingTag = byteArrayOf('X'.code.toByte(), 'i'.code.toByte(), 'n'.code.toByte(), 'g'.code.toByte())
val InfoTag = byteArrayOf('I'.code.toByte(), 'n'.code.toByte(), 'f'.code.toByte(), 'o'.code.toByte())
}
}
private object Minimp3AudioFormat : BaseMinimp3AudioFormat() {
override fun createMp3Decoder(): BaseMp3Decoder = Minimp3Decoder()
internal class Minimp3Decoder : MiniMp3Program(), BaseMp3Decoder {
private val pcmData = ShortArray(MINIMP3_MAX_SAMPLES_PER_FRAME * 2 * 2)
private val mp3dec = Mp3Dec()
private val mp3decFrameInfo = Mp3FrameInfo()
init {
mp3dec_init(mp3dec)
}
override val info: BaseMp3DecoderInfo = BaseMp3DecoderInfo()
override fun decodeFrame(availablePeek: Int): ShortArray? {
val samples = mp3dec_decode_frame(
mp3dec,
UByteArrayIntPtr(UByteArrayInt(info.tempBuffer)),
availablePeek,
ShortArrayPtr(pcmData),
mp3decFrameInfo
)
val struct = mp3decFrameInfo
info.nchannels = struct.channels
info.hz = struct.hz
info.bitrate_kbps = struct.bitrate_kbps
info.frame_bytes = struct.frame_bytes
info.samples = samples
//println("samples=$samples, hz=$hz, nchannels=$nchannels, bitrate_kbps=$bitrate_kbps, frameBytes=$frame_bytes")
if (info.nchannels == 0 || samples <= 0) return null
return pcmData.copyOf(samples * info.nchannels)
}
override fun close() {
}
}
}
//ENTRY Program
//Program.main(arrayOf())
@Suppress("MemberVisibilityCanBePrivate", "NAME_SHADOWING", "ObjectPropertyName", "FunctionName", "LocalVariableName")
@OptIn(ExperimentalUnsignedTypes::class)
private open class MiniMp3Program() {
companion object {
internal const val MINIMP3_MAX_SAMPLES_PER_FRAME = 2304
internal const val MAX_BITRESERVOIR_BYTES = 511
private fun arrayOfUByte(values: String, size: Int = values.length): UByteArrayInt =
UByteArrayInt(size) { values.getOrElse(it) { 0.toChar() }.code }
private fun arrayOfShort(values: String, size: Int = values.length): ShortArray =
ShortArray(size) { values.getOrElse(it) { 0.toChar() }.code.toShort() }
private val __STATIC_L3_imdct36_g_twid9: FloatArray = floatArrayOf(
0.7372773f, 0.7933533f, 0.8433915f, 0.8870108f, 0.9238795f, 0.95371693f, 0.976296f, 0.9914449f, 0.99904823f,
0.6755902f, 0.6087614f, 0.53729963f, 0.4617486f, 0.38268343f, 0.3007058f, 0.2164396f, 0.13052619f, 0.04361938f
)
private val __STATIC_L3_imdct12_g_twid3: FloatArray = floatArrayOf(
0.7933533f, 0.9238795f, 0.9914449f, 0.6087614f, 0.38268343f, 0.13052619f
)
private val __STATIC_mp3d_DCT_II_g_sec: FloatArray = floatArrayOf(
10.190008f, 0.500603f, 0.5024193f, 3.4076085f, 0.50547093f, 0.5224986f, 2.057781f, 0.5154473f,
0.56694406f, 1.4841646f, 0.5310426f, 0.6468218f, 1.1694399f, 0.5531039f, 0.7881546f, 0.9725682f,
0.582935f, 1.0606776f, 0.8393496f, 0.6225041f, 1.7224472f, 0.7445363f, 0.6748083f, 5.1011486f
)
private val __STATIC_L3_stereo_process_g_pan: FloatArray = floatArrayOf(
0f, 1f, 0.21132487f, 0.7886751f, 0.3660254f, 0.6339746f, 0.5f, 0.5f, 0.6339746f, 0.3660254f, 0.7886751f, 0.21132487f, 1f, 0f
)
private val __STATIC_mp3d_synth_g_win: FloatArray = floatArrayOf(
-1f, 26f, -31f, 208f, 218f, 401f, -519f, 2063f, 2000f, 4788f, -5517f, 7134f, 5959f, 35640f, -39336f, 74992f, -1f, 24f, -35f, 202f, 222f, 347f,
-581f, 2080f, 1952f, 4425f, -5879f, 7640f, 5288f, 33791f, -41176f, 74856f, -1f, 21f, -38f, 196f, 225f, 294f, -645f, 2087f, 1893f, 4063f, -6237f,
8092f, 4561f, 31947f, -43006f, 74630f, -1f, 19f, -41f, 190f, 227f, 244f, -711f, 2085f, 1822f, 3705f, -6589f, 8492f, 3776f, 30112f, -44821f, 74313f,
-1f, 17f, -45f, 183f, 228f, 197f, -779f, 2075f, 1739f, 3351f, -6935f, 8840f, 2935f, 28289f, -46617f, 73908f, -1f, 16f, -49f, 176f, 228f, 153f,
-848f, 2057f, 1644f, 3004f, -7271f, 9139f, 2037f, 26482f, -48390f, 73415f, -2f, 14f, -53f, 169f, 227f, 111f, -919f, 2032f, 1535f, 2663f, -7597f,
9389f, 1082f, 24694f, -50137f, 72835f, -2f, 13f, -58f, 161f, 224f, 72f, -991f, 2001f, 1414f, 2330f, -7910f, 9592f, 70f, 22929f, -51853f, 72169f,
-2f, 11f, -63f, 154f, 221f, 36f, -1064f, 1962f, 1280f, 2006f, -8209f, 9750f, -998f, 21189f, -53534f, 71420f, -2f, 10f, -68f, 147f, 215f, 2f,
-1137f, 1919f, 1131f, 1692f, -8491f, 9863f, -2122f, 19478f, -55178f, 70590f, -3f, 9f, -73f, 139f, 208f, -29f, -1210f, 1870f, 970f, 1388f, -8755f,
9935f, -3300f, 17799f, -56778f, 69679f, -3f, 8f, -79f, 132f, 200f, -57f, -1283f, 1817f, 794f, 1095f, -8998f, 9966f, -4533f, 16155f, -58333f,
68692f, -4f, 7f, -85f, 125f, 189f, -83f, -1356f, 1759f, 605f, 814f, -9219f, 9959f, -5818f, 14548f, -59838f, 67629f, -4f, 7f, -91f, 117f, 177f,
-106f, -1428f, 1698f, 402f, 545f, -9416f, 9916f, -7154f, 12980f, -61289f, 66494f, -5f, 6f, -97f, 111f, 163f, -127f, -1498f, 1634f, 185f, 288f,
-9585f, 9838f, -8540f, 11455f, -62684f, 65290f
)
private val __STATIC_L3_antialias_g_aa: Array = arrayOf(
floatArrayOf(0.8574929f, 0.881742f, 0.94962865f, 0.9833146f, 0.9955178f, 0.9991606f, 0.9998992f, 0.99999315f),
floatArrayOf(0.51449573f, 0.47173196f, 0.31337744f, 0.1819132f, 0.09457419f, 0.04096558f, 0.01419856f, 0.00369997f)
)
private val __STATIC_L3_imdct_gr_g_mdct_window: Array = arrayOf(
floatArrayOf(
0.99904823f,
0.9914449f,
0.976296f,
0.95371693f,
0.9238795f,
0.8870108f,
0.8433915f,
0.7933533f,
0.7372773f, 0.04361938f, 0.13052619f,
0.2164396f, 0.3007058f, 0.38268343f,
0.4617486f,
0.53729963f,
0.6087614f,
0.6755902f
),
floatArrayOf(1f, 1f, 1f, 1f, 1f, 1f, 0.9914449f, 0.9238795f, 0.7933533f, 0f, 0f, 0f, 0f, 0f, 0f, 0.13052619f, 0.38268343f, 0.6087614f)
)
private val __STATIC_L3_ldexp_q2_g_expfrac: FloatArray = floatArrayOf(9.313226E-10f, 7.831458E-10f, 6.585445E-10f, 5.537677E-10f)
private val __STATIC_L12_read_scalefactors_g_deq_L12: FloatArray = floatArrayOf(
(9.536743E-7f / 3f), (7.569318E-7f / 3f), (6.007772E-7f / 3f), (9.536743E-7f / 7f), (7.569318E-7f / 7f), (6.007772E-7f / 7f),
(9.536743E-7f / 15f), (7.569318E-7f / 15f), (6.007772E-7f / 15f), (9.536743E-7f / 31f), (7.569318E-7f / 31f), (6.007772E-7f / 31f),
(9.536743E-7f / 63f), (7.569318E-7f / 63f), (6.007772E-7f / 63f), (9.536743E-7f / 127f), (7.569318E-7f / 127f), (6.007772E-7f / 127f),
(9.536743E-7f / 255f), (7.569318E-7f / 255f), (6.007772E-7f / 255f), (9.536743E-7f / 511f), (7.569318E-7f / 511f), (6.007772E-7f / 511f),
(9.536743E-7f / 1023f), (7.569318E-7f / 1023f), (6.007772E-7f / 1023f), (9.536743E-7f / 2047f), (7.569318E-7f / 2047f),
(6.007772E-7f / 2047f), (9.536743E-7f / 4095f), (7.569318E-7f / 4095f), (6.007772E-7f / 4095f), (9.536743E-7f / 8191f),
(7.569318E-7f / 8191f), (6.007772E-7f / 8191f), (9.536743E-7f / 16383f), (7.569318E-7f / 16383f), (6.007772E-7f / 16383f),
(9.536743E-7f / 32767f), (7.569318E-7f / 32767f), (6.007772E-7f / 32767f), (9.536743E-7f / 65535f), (7.569318E-7f / 65535f),
(6.007772E-7f / 65535f), (9.536743E-7f / 3f), (7.569318E-7f / 3f), (6.007772E-7f / 3f), (9.536743E-7f / 5f), (7.569318E-7f / 5f),
(6.007772E-7f / 5f), (9.536743E-7f / 9f), (7.569318E-7f / 9f), (6.007772E-7f / 9f)
)
private val __STATIC_hdr_sample_rate_hz_g_hz: IntArray = intArrayOf(44100, 48000, 32000)
private val __STATIC_hdr_bitrate_kbps_halfrate: Array> = arrayOf(
arrayOf(
arrayOfUByte("\u0000\u0004\u0008\u000c\u0010\u0014\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u0048\u0050"),
arrayOfUByte("\u0000\u0004\u0008\u000c\u0010\u0014\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u0048\u0050"),
arrayOfUByte("\u0000\u0010\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u0048\u0050\u0058\u0060\u0070\u0080")
),
arrayOf(
arrayOfUByte("\u0000\u0010\u0014\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u0050\u0060\u0070\u0080\u00a0"),
arrayOfUByte("\u0000\u0010\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u0050\u0060\u0070\u0080\u00a0\u00c0"),
arrayOfUByte("\u0000\u0010\u0020\u0030\u0040\u0050\u0060\u0070\u0080\u0090\u00a0\u00b0\u00c0\u00d0\u00e0")
)
)
private val __STATIC_L3_decode_scalefactors_g_scfc_decode: UByteArrayInt =
arrayOfUByte("\u0000\u0001\u0002\u0003\u000c\u0005\u0006\u0007\u0009\u000a\u000b\u000d\u000e\u000f\u0012\u0013")
private val __STATIC_L3_decode_scalefactors_g_mod: UByteArrayInt =
arrayOfUByte("\u0005\u0005\u0004\u0004\u0005\u0005\u0004\u0001\u0004\u0003\u0001\u0001\u0005\u0006\u0006\u0001\u0004\u0004\u0004\u0001\u0004\u0003\u0001\u0001")
private val __STATIC_L3_decode_scalefactors_g_preamp: UByteArrayInt = arrayOfUByte("\u0001\u0001\u0001\u0001\u0002\u0002\u0003\u0003\u0003\u0002")
private val __STATIC_L3_huffman_tabs: ShortArray = arrayOfShort(
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0311\u0311\u0311\u0311\u0310\u0310\u0310\u0310\u0201\u0201\u0201\u0201\u0201\u0201\u0201" +
"\u0201\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\uff01\u0521\u0512\u0502\u0311\u0311" +
"\u0311\u0311\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100" +
"\u0100\u0100\u0100\u0122\u0120\uff01\u0521\u0512\u0502\u0301\u0301\u0301\u0301\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0210\u0210" +
"\u0210\u0210\u0210\u0210\u0210\u0210\u0200\u0200\u0200\u0200\u0200\u0200\u0200\u0200\u0122\u0120\uff03\ufec2\ufea1\ufe91\u0311\u0311\u0311" +
"\u0311\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100" +
"\u0100\u0100\u0333\u0332\u0223\u0223\u0113\u0113\u0113\u0113\u0231\u0230\u0203\u0222\u0121\u0112\u0120\u0102\uff02\ufee1\u0531\u0513\u0522" +
"\u0520\u0421\u0421\u0412\u0412\u0402\u0402\u0310\u0310\u0310\u0310\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0301\u0301\u0301\u0301" +
"\u0300\u0300\u0300\u0300\u0233\u0230\u0132\u0132\u0123\u0103\uff04\ufe63\ufe23\ufde2\u0512\ufdc1\u0411\u0411\u0310\u0310\u0310\u0310\u0301" +
"\u0301\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\ufe81\ufe71\u0453\u0444" +
"\u0452\u0425\u0351\u0351\u0315\u0315\u0450\u0443\u0305\u0305\u0434\u0433\u0155\u0154\u0145\u0135\u0342\u0324\u0241\u0241\u0214\u0214\u0204" +
"\u0204\u0340\u0332\u0323\u0330\u0231\u0231\u0213\u0213\u0203\u0222\u0121\u0121\u0120\u0102\uff04\ufe53\ufe13\ufdd1\u0421\u0421\u0412\u0412" +
"\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0211\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301\u0200\u0200\u0200\u0200\u0200\u0200\u0200" +
"\u0200\ufe82\u0435\ufe61\u0452\u0425\u0450\u0351\u0351\u0315\u0315\u0443\u0434\u0405\u0433\u0342\u0342\u0255\u0245\u0154\u0154\u0153\u0144" +
"\u0324\u0341\u0214\u0214\u0340\u0304\u0332\u0323\u0331\u0313\u0330\u0303\u0122\u0122\u0122\u0122\u0120\u0102\uff03\ufea3\ufe62\ufe41\ufe31" +
"\u0531\u0513\ufe21\u0522\u0520\u0421\u0421\u0412\u0412\u0402\u0402\u0311\u0311\u0311\u0311\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301" +
"\u0300\u0300\u0300\u0300\ufec1\u0353\u0335\ufeb1\u0344\u0352\u0325\u0351\u0155\u0154\u0145\u0150\u0215\u0215\u0243\u0243\u0234\u0234\u0305" +
"\u0340\u0242\u0224\u0233\u0204\u0141\u0114\u0132\u0123\u0130\u0103\uff05\ufdc4\ufd23\ufcc2\ufca1\ufc91\u0411\u0411\u0310\u0310\u0310\u0310" +
"\u0301\u0301\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\ufe01\ufdf1\ufde1" +
"\u0574\u0547\u0565\u0556\u0573\u0537\u0564\ufdd1\u0536\u0472\u0472\u0427\u0427\u0546\u0570\u0407\u0407\u0426\u0426\u0554\u0553\u0460\u0460" +
"\u0535\u0544\u0371\u0371\u0371\u0371\u0177\u0176\u0167\u0175\u0157\u0166\u0155\u0145\u0317\u0317\u0463\u0462\ufd41\u0451\u0415\ufd31\u0361" +
"\u0361\u0316\u0316\u0306\u0306\u0450\u0405\u0152\u0125\u0143\u0134\ufce1\ufcd1\u0341\u0314\u0304\u0332\u0323\u0330\u0142\u0124\u0133\u0140" +
"\u0231\u0213\u0203\u0222\u0121\u0112\u0120\u0102\uff05\ufdf3\ufda3\ufd53\ufd03\ufcc1\ufcb2\u0512\u0421\u0421\u0520\u0502\u0311\u0311\u0311" +
"\u0311\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301\u0200\u0200\u0200\u0200\u0200\u0200\u0200\u0200\u0577\u0576\u0567\u0557\u0566\u0574" +
"\u0547\ufe01\u0565\u0556\u0473\u0473\u0437\u0437\u0464\u0464\u0554\u0545\u0553\u0535\u0372\u0372\u0372\u0372\u0327\u0327\u0327\u0327\u0446" +
"\u0446\u0470\u0470\u0175\u0155\u0217\u0217\u0371\u0307\u0363\u0336\u0306\ufdb1\u0144\u0152\ufd61\u0351\u0226\u0226\u0362\u0360\u0261\u0261" +
"\u0125\u0150\u0216\u0216\u0315\u0343\u0305\ufd11\u0342\u0324\u0134\u0133\u0341\u0314\u0340\u0304\u0232\u0232\u0223\u0223\u0131\u0113\u0230" +
"\u0203\u0122\u0122\uff04\ufe73\ufe23\ufdd3\ufd92\ufd73\ufd31\ufd21\ufd12\u0531\u0513\u0522\u0421\u0421\u0412\u0412\u0520\u0502\u0400\u0400" +
"\u0311\u0311\u0311\u0311\u0310\u0310\u0310\u0310\u0301\u0301\u0301\u0301\ufe81\u0467\u0475\u0457\u0466\u0474\u0447\u0456\u0365\u0365\u0373" +
"\u0373\u0437\u0455\u0372\u0372\u0177\u0176\u0327\u0364\u0346\u0371\u0317\ufe31\u0363\u0336\u0170\u0107\u0354\u0345\u0344\ufde1\u0262\u0262" +
"\u0226\u0226\u0160\u0150\u0216\u0216\u0361\u0306\u0353\u0335\u0352\u0325\u0251\u0215\u0243\u0234\u0305\u0340\u0242\u0242\u0224\u0224\u0241" +
"\u0241\u0133\u0114\u0132\u0123\u0204\u0230\u0103\u0103\uff06\uf7c5\uf635\uf534\uf4a3\uf462\uf441\uf431\u0411\u0411\u0410\u0410\u0301\u0301" +
"\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\ufd01\ufbe4\ufb43\ufb03\ufab2" +
"\ufa83\ufa43\ufa01\uf9f2\uf9d2\uf9b2\uf991\uf982\uf962\uf942\uf921\uf912\uf8f1\uf8e2\uf8c2\uf8a2\u061d\uf881\uf871\uf861\uf851\u06c3\u06c2" +
"\u062c\u06b5\uf841\u06c1\u061c\uf831\u060c\uf821\uf811\u06b3\u063b\uf801\u06b2\uf7f1\u064a\uf7e1\u0649\uf7d1\u052b\u052b\u05b1\u05b1\u051b" +
"\u051b\u06b0\u060b\u0669\u06a4\u06a3\u063a\u0695\u0659\u05a2\u05a2\u052a\u052a\ufcf4\ufc33\ufc72\u04ff\u04fe\u04fd\u04ee\u04fc\u04ed\u04fb" +
"\u04bf\u04ec\u04cd\ufc41\u03ce\u03ce\u03dd\u03dd\ufc51\u02df\u01de\u01de\u01ef\u01cf\u01fa\u019e\ufbf1\u03eb\u03be\u03f9\u039f\u03ae\u03db" +
"\u03bd\u01af\u01dc\u04f8\u048f\u04cc\ufb61\u04e8\ufb51\u037f\u037f\u03ad\u03ad\u04da\u04cb\u04bc\u046f\u03f6\u03f6\u01ea\u01e9\u01f7\u01e7" +
"\u038e\u03f5\u03d9\u039d\u035f\u037e\u03ca\u03bb\u03f4\u034f\ufac1\u033f\u02f3\u02f3\u03d8\u038d\u01ac\u016e\u02f2\u022f\ufa91\u02f0\u01e6" +
"\u01c9\u039c\u03e5\u02ba\u02ba\u03d7\u037d\u02e4\u02e4\u038c\u036d\u02e3\u02e3\u029b\u029b\u03b9\u03aa\u01f1\u011f\u010f\u010f\u02ab\u025e" +
"\u024e\u02c8\u02d6\u023e\u012e\u012e\u02e2\u02e0\u01e1\u011e\u020e\u02d5\u025d\u02c7\u027c\u02d4\u02b8\u028b\u024d\u02a9\u029a\u02c6\u016c" +
"\u01d3\u023d\u02b7\u01d2\u01d2\u012d\u01d1\u017b\u017b\u02c5\u025c\u0299\u02a7\u013c\u013c\u027a\u0279\u01b4\u01b4\u01d0\u010d\u01a8\u018a" +
"\u01c4\u014c\u01b6\u016b\u015b\u0198\u0189\u01c0\u014b\u01a6\u016a\u0197\u0188\u01a5\u015a\u0196\u0187\u0178\u0177\u0167\u05a1\u051a\uf6c1" +
"\u050a\uf6b1\u0539\uf6a1\uf691\u0592\u0529\uf681\u0583\u0538\uf671\uf661\uf651\u0491\u0491\u0419\u0419\u0590\u0509\u0584\u0548\u0527\uf641" +
"\u0482\u0482\u0428\u0428\u0481\u0481\u01a0\u0186\u0168\u0194\u0193\u0185\u0158\u0176\u0175\u0157\u0166\u0174\u0147\u0165\u0156\u0137\u0164" +
"\u0146\u0573\u0572\u0471\u0471\u0417\u0417\u0555\u0570\u0507\u0563\u0536\u0554\u0545\u0562\u0526\u0553\u0318\u0318\u0318\u0318\u0480\u0480" +
"\u0408\u0408\u0461\u0461\u0416\u0416\u0460\u0460\u0406\u0406\uf4b1\u0452\u0425\u0450\u0351\u0351\u0315\u0315\u0443\u0434\u0405\u0442\u0424" +
"\u0433\u0341\u0341\u0135\u0144\u0214\u0214\u0340\u0304\u0332\u0323\u0231\u0231\u0213\u0230\u0203\u0222\u0121\u0112\u0120\u0102\uff06\ufb65" +
"\uf9d5\uf8d4\uf834\uf7b4\uf733\uf6e3\uf693\uf653\uf612\uf5f2\uf5d1\uf5c2\uf5a1\u0522\u0521\u0512\u0520\u0502\u0311\u0311\u0311\u0311\u0410" +
"\u0410\u0401\u0401\u0300\u0300\u0300\u0300\ufd02\ufce2\ufcc2\ufca2\ufc81\ufc71\ufc61\ufc51\ufc41\ufc31\ufc21\ufc11\ufc01\ufbf1\ufbe1\ufbd2" +
"\u06bc\u066f\ufbb1\ufba1\u065f\u06e7\u067e\u06ca\u06ac\u06bb\ufb91\u06f4\u064f\u06f3\u063f\u068d\u066e\u06f2\u062f\ufb81\u06f1\u061f\u06c9" +
"\u069c\u06e5\u06ba\u06ab\u065e\u06d7\u067d\u06e4\u064e\u06c8\u068c\u06e3\u06d6\u066d\u063e\u06b9\u069b\u06e2\u06aa\u062e\u06e1\u061e\ufb71" +
"\u06d5\u065d\u02ff\u02fe\u02ef\u02fd\u01ee\u01ee\u02df\u02fc\u02cf\u02ed\u02de\u02fb\u01bf\u01bf\u02ec\u02ce\u01dd\u01fa\u01af\u01eb\u01be" +
"\u01dc\u01cd\u01f9\u019f\u01ae\u01db\u01bd\u01f8\u018f\u01cc\u01e9\u019e\u01f7\u017f\u01da\u01ad\u01cb\u01f6\u01f6\u02ea\u02f0\u01e8\u018e" +
"\u01f5\u01d9\u019d\u01d8\u01e6\u010f\u01e0\u010e\ufa61\ufa51\u054d\ufa41\ufa31\ufa21\u053d\u052d\ufa11\u05d1\u05b7\u057b\u051d\ufa01\u055c\u05a8\u058a\u05c4\u054c\u05b6\u056b\uf9f1\u05c3\u053c\u05a7\u057a\u056a\uf9e1\u042c\u042c\u05c2\u05b5\u01c7\u017c\u01d4\u01b8\u018b\u01a9\u019a\u01c6\u016c\u01d3\u01d2\u01d0\u01c5\u010d\u0199\u01c0\u010c\u01b0\u055b\u05c1\u0598\u0589\u051c\u05b4\u054b\u05a6" +
"\u05b3\u0597\u043b\u043b\u0579\u0588\u05b2\u05a5\u042b\u042b\u055a\u05b1\u041b\u041b\u050b\u0596\u0569\u05a4\u054a\u0587\u0578\u05a3\u043a\u043a\u0495\u0459\u04a2\u042a\u04a1\u041a\uf851\u0486\u0468\u0494\u0449\u0493\u0439\uf841\u0485\u0458\u01a0\u010a\u0177\u0190\u0492\u0476\u0467\u0429\u0319\u0319\u0491\u0409\u0484\u0448\u0475\u0457\u0483\u0438\u0466\u0474\u0382\u0382\u0328\u0328\u0381\u0381" +
"\u0318\u0318\u0447\u0480\u0408\u0465\u0456\u0473\u0437\u0464\u0372\u0327\u0346\u0371\u0355\u0317\uf6f1\u0363\u0170\u0107\u0336\u0354\u0345\u0362\u0326\u0361\uf6a1\u0353\u0160\u0106" +
"\u0216\u0216\u0335\u0344\u0252\u0252\u0225\u0225\u0251\u0251\u0215\u0215\u0350\u0305\u0243\u0243\u0234\u0242\u0224\u0233\u0114\u0114\u0241\u0240\u0132\u0123\u0204\u0230\u0131\u0131\u0113\u0103\uff05\ufc84\uf7f6\uf5c4\uf4f4\uf473\uf431\uf421\u0411\u0411\u0410\u0410\u0301\u0301\u0301\u0301\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\ufe01\ufdf1" +
"\ufde1\ufdd1\u05fa\ufdc1\ufdb1\u05f8\u05f7\u057f\u05f6\u056f\u03ff\u03ff\u03ff\u03ff\u05f5\u055f\u04f4\u04f4\u044f\u044f\u043f\u043f\u040f\u040f\u05f3\ufda4\u032f\u032f\u032f\u032f\u01fe\u01ef\u01fd\u01df\u01fc\u01cf\u01fb\u01bf\u01af\u01f9\u019f\u018f\ufd22\ufcf2\u04ee\ufcd1\u04eb\u04dc\ufcc1\u04ea\u04cc\ufcb1\ufca1\u04ac\ufc91\u04e5\u03db\u03db\u02ec\ufd01\u01ed\u01ed\u01ce\u01dd\u019e\u019e" +
"\u02ae\u029d\u01de\u01be\u01cd\u01bd\u01da\u01ad\u01e7\u01ca\u019c\u01d7\u04f2\u04f0\u03f1\u03f1\u031f\u031f\ufc05\ufb04\ufa54\uf9d3\uf973\uf923\uf8e3\uf8a2\uf873\uf833\u04e9\u04e9" +
"\u05cb\u05bc\u05e8\u058e\u05d9\u057e\u05bb\u05d8\u058d\u05e6\u046e\u046e\u04c9\u04c9\u05ba\u05ab\u055e\u057d\u04e4\u04e4\u054e\u05c8" +
"\u048c\u048c\u04e3\u04e3\u04d6\u04d6\u056d\u05b9\ufa81\u041e\u044d\ufa71\u04b7\ufa61\u033e\u033e\u04e0\u040e\u04d5\u045d\u04c7\u047c\u04d4\u04b8\u019b\u01aa\u018b\u019a\u017b\u010d\u04a9\u04c6\u046c\u04d3\u04c5\u045c\u03d0\u03d0\u04a8\u048a\u0499\u04c4\u046b\u04a7\u03c3\u03c3\uf991\u03c1\u030c\uf981\u022e\u022e\u03e2\u03e1\u01b5\u0198\u0189\u0197\u033d\u03d2\u032d\u031d\u03b3\uf931\u02d1\u02d1" +
"\u0179\u0188\u034c\u03b6\u033c\u037a\u02c2\u02c2\u032c\u035b\u031c\u03c0\u03b4\u034b\u03a6\u036a\u023b\u023b\uf881\u02b2\u022b\u02b1\u01a5\u015a\u021b\u021b\u03b0\u030b\u0396\u0369\u03a4\u034a\u0387\u0378\u023a\u023a\u03a3\u0395\u02a2\u02a2\uf5f1\u061a\uf5e1\u0649\uf5d1\u0676\u052a\u052a\u05a1\u05a1\u06a0\u060a\u0693\u0639\u0685\u0658\u0592\u0592\u0529\u0529\u0667\u0690\u0591\u0591\u0519\u0519" +
"\u0609\u0684\u0648\u0657\u0683\u0638\u0666\u0682\u0528\u0528\u0674\u0647\u0581\u0581\u0518\u0518\u0508\u0508\u0680\u0665\u0573\u0573\u0537\u0537\u0656\u0664\u0572\u0572\u0527\u0527" +
"\u0646\u0655\u0570\u0570\u0471\u0471\u0471\u0471\u0159\u0186\u0168\u0177\u0194\u0175\u0417\uf541\uf531\uf521\u0426\u0461\u0416\uf511\u0435\uf501\u0452\u0425\u0315\u0315\u0451\u0450\u0107\u0163\u0136\u0154\u0145\u0162\u0160\u0106\u0153\u0144\u0443\u0434\u0405\u0442" +
"\u0424\u0433\u0341\u0341\u0314\u0314\u0440\u0404\u0332\u0332\u0323\u0323\u0231\u0231\u0213\u0213\u0330\u0303\u0222\u0222\u0121\u0112\u0120\u0102\uff03\ufec3\ufe83\ufe42\ufe22\ufe03\u04ff\u04ff\ufcd5\ufb65\ufa55\uf924\uf894\uf814\uf773\uf733\uf6e3\uf692\uf673\uf631\uf622\u0521\u0512\uf601\u0411\u0411\u0410\u0410\u0401\u0401\u0400\u0400\u03fe\u03ef\u03fd\u03df\u03fc\u03cf\u03fb\u03bf\u02af\u02af" +
"\u03fa\u03f9\u029f\u029f\u028f\u028f\u03f8\u03f7\u027f\u027f\u02f6\u02f6\u026f\u026f\u02f5\u025f\u02f4\u024f\u02f3\u023f\u02f2\u022f\u021f\u021f\u03f1\u030f\ufdc1\ufd93\ufd53\ufd13\u01f0\ufdb2\u02ee\u02ed\u02de\u02ec\u03ce\u03dd\u03eb\u03be\u03dc\u03cd\u03ea\u03ae\u03db\u03bd\u03cc\u03e9\u039e\u03da\u03ad\u03cb\u03bc\u03e8\u038e\u03d9\u039d\u03e7\u037e\u03ca\ufbd1\ufbc1\ufbb2\u056e\ufb91\u059c" +
"\u05e5\u05ab\u055e\ufb81\u057d\u054e\u05c8\u058c\ufb71\u05e3\u05d6\u056d\u053e\u05b9\u059b\u05aa\u052e\u05e1\u051e\u05d5\u055d\u05c7\u057c\u05d4\u05b8\u058b\u01ac\u01bb\u01d8\u018d" +
"\u02e0\u020e\u01d0\u01d0\u01e6\u01c9\u01ba\u01d7\u01e4\u01e2\u054d\u05a9\u059a\u05c6\u056c\u05d3\u053d\u05d2\u052d\u05d1\u05b7\u057b\u051d\u05c5\u055c\u05a8\u058a\u0599\u05c4\u054c\u05b6\u056b\ufa61\u05c3\u053c\u05a7\u057a\u05c2\u052c\u05b5\u055b\u05c1\u010d\u01c0\u0598\u0589\u051c\u05b4\uf951\u05b3\uf941\u05a1\u044b\u044b\u05a6\u056a\u0597\u0579\uf931\u0509\u043b\u043b\u0488\u0488\u05b2\u05a5" +
"\u042b\u042b\u055a\u05b1\u051b\u0596\u0469\u0469\u044a\u044a\u010c\u01b0\u010b\u01a0\u010a\u0190\uf8a1\u0478\u04a3\u043a\u0495\u0459\u04a2\u042a\u041a\u0486\u0468\u0477\u0494\u0449\u0493\u0439\u01a4\u0187\u0485\u0458\u0492\u0476\u0467\u0429\u0491\u0419\u0484\u0448\u0475\u0457\u0483\u0438\u0466\u0482\u0428\u0481\u0474\u0447\u0418\uf791\u0465\u0456\u0471\uf781\u0337\u0337\u0473\u0472\u0327\u0327" +
"\u0180\u0108\u0170\u0107\u0364\u0346\u0355\u0317\u0363\u0336\u0354\u0345\u0362\u0326\u0361\u0316\uf6f1\u0353\u0335\u0344\u0160\u0106\u0352\u0325\u0351\uf6a1\u0215\u0215\u0343\u0334" +
"\u0150\u0105\u0242\u0224\u0233\u0241\u0214\u0214\u0340\u0304\u0232\u0232\u0223\u0223\u0131\u0113\u0230\u0203\u0122\u0122\u0120\u0102"
)
private val __STATIC_L3_huffman_tab32: UByteArrayInt =
arrayOfUByte("\u0082\u00a2\u00c1\u00d1\u002c\u001c\u004c\u008c\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u00be\u00fe\u00de\u00ee\u007e\u005e\u009d\u009d\u006d\u003d\u00ad\u00cd")
private val __STATIC_L3_huffman_tab33: UByteArrayInt =
arrayOfUByte("\u00fc\u00ec\u00dc\u00cc\u00bc\u00ac\u009c\u008c\u007c\u006c\u005c\u004c\u003c\u002c\u001c\u000c")
private val __STATIC_L3_huffman_tabindex: ShortArray =
arrayOfShort("\u0000\u0020\u0040\u0062\u0000\u0084\u00b4\u00da\u0124\u016c\u01aa\u021a\u0288\u02ea\u0000\u0466\u05b4\u05b4\u05b4\u05b4\u05b4\u05b4\u05b4\u05b4\u0732\u0732\u0732\u0732\u0732\u0732\u0732\u0732")
private val __STATIC_L3_huffman_g_linbits: UByteArrayInt =
arrayOfUByte("\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0006\u0008\u000a\u000d\u0004\u0005\u0006\u0007\u0008\u0009\u000b\u000d")
private val __STATIC_L12_read_scale_info_g_bitalloc_code_tab: UByteArrayInt = arrayOfUByte(
"\u0000\u0011\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0010\u0000\u0011\u0012\u0003\u0013\u0004\u0005\u0006" +
"\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u0010\u0000\u0011\u0012\u0003\u0013\u0004\u0005\u0010\u0000\u0011\u0012\u0010\u0000\u0011\u0012" +
"\u0013\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0000\u0011\u0012\u0003\u0013\u0004\u0005\u0006\u0007\u0008" +
"\u0009\u000a\u000b\u000c\u000d\u000e\u0000\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0010"
)
private val __STATIC_L3_read_side_info_g_scf_long: Array = arrayOf(
arrayOfUByte("\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u000a\u000c\u000e\u0010\u0014\u0018\u001c\u0020\u0026\u002e\u0034\u003c\u0044\u003a\u0036\u0000"),
arrayOfUByte("\u000c\u000c\u000c\u000c\u000c\u000c\u0010\u0014\u0018\u001c\u0020\u0028\u0030\u0038\u0040\u004c\u005a\u0002\u0002\u0002\u0002\u0002\u0000"),
arrayOfUByte("\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u000a\u000c\u000e\u0010\u0014\u0018\u001c\u0020\u0026\u002e\u0034\u003c\u0044\u003a\u0036\u0000"),
arrayOfUByte("\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u000a\u000c\u000e\u0010\u0012\u0016\u001a\u0020\u0026\u002e\u0036\u003e\u0046\u004c\u0024\u0000"),
arrayOfUByte("\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u000a\u000c\u000e\u0010\u0014\u0018\u001c\u0020\u0026\u002e\u0034\u003c\u0044\u003a\u0036\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0008\u0008\u000a\u000c\u0010\u0014\u0018\u001c\u0022\u002a\u0032\u0036\u004c\u009e\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u000a\u000c\u0010\u0012\u0016\u001c\u0022\u0028\u002e\u0036\u0036\u00c0\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0008\u000a\u000c\u0010\u0014\u0018\u001e\u0026\u002e\u0038\u0044\u0054\u0066\u001a\u0000")
)
private val __STATIC_L3_read_side_info_g_scf_short: Array = arrayOf(
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u001e\u001e\u001e\u0028\u0028\u0028\u0012\u0012\u0012\u0000"),
arrayOfUByte("\u0008\u0008\u0008\u0008\u0008\u0008\u0008\u0008\u0008\u000c\u000c\u000c\u0010\u0010\u0010\u0014\u0014\u0014\u0018\u0018\u0018\u001c\u001c\u001c\u0024\u0024\u0024\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u001a\u001a\u001a\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000e\u000e\u000e\u0012\u0012\u0012\u001a\u001a\u001a\u0020\u0020\u0020\u002a\u002a\u002a\u0012\u0012\u0012\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u0020\u0020\u0020\u002c\u002c\u002c\u000c\u000c\u000c\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u001e\u001e\u001e\u0028\u0028\u0028\u0012\u0012\u0012\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0016\u0016\u0016\u001e\u001e\u001e\u0038\u0038\u0038\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0006\u0006\u0006\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0010\u0010\u0010\u0014\u0014\u0014\u001a\u001a\u001a\u0042\u0042\u0042\u0000"),
arrayOfUByte("\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000c\u000c\u000c\u0010\u0010\u0010\u0014\u0014\u0014\u001a\u001a\u001a\u0022\u0022\u0022\u002a\u002a\u002a\u000c\u000c\u000c\u0000")
)
private val __STATIC_L3_read_side_info_g_scf_mixed: Array = arrayOf(
arrayOfUByte(
"\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u001e\u001e\u001e\u0028\u0028\u0028\u0012\u0012\u0012\u0000",
size = 40
),
arrayOfUByte("\u000c\u000c\u000c\u0004\u0004\u0004\u0008\u0008\u0008\u000c\u000c\u000c\u0010\u0010\u0010\u0014\u0014\u0014\u0018\u0018\u0018\u001c\u001c\u001c\u0024\u0024\u0024\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u001a\u001a\u001a\u0000"),
arrayOfUByte(
"\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000e\u000e\u000e\u0012\u0012\u0012\u001a\u001a\u001a\u0020\u0020\u0020\u002a\u002a\u002a\u0012\u0012\u0012\u0000",
size = 40
),
arrayOfUByte(
"\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u0020\u0020\u0020\u002c\u002c\u002c\u000c\u000c\u000c\u0000",
size = 40
),
arrayOfUByte(
"\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0018\u0018\u0018\u001e\u001e\u001e\u0028\u0028\u0028\u0012\u0012\u0012\u0000",
size = 40
),
arrayOfUByte(
"\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0012\u0012\u0012\u0016\u0016\u0016\u001e\u001e\u001e\u0038\u0038\u0038\u0000",
size = 40
),
arrayOfUByte(
"\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0004\u0004\u0004\u0006\u0006\u0006\u0006\u0006\u0006\u000a\u000a\u000a\u000c\u000c\u000c\u000e\u000e\u000e\u0010\u0010\u0010\u0014\u0014\u0014\u001a\u001a\u001a\u0042\u0042\u0042\u0000",
size = 40
),
arrayOfUByte(
"\u0004\u0004\u0004\u0004\u0004\u0004\u0006\u0006\u0004\u0004\u0004\u0006\u0006\u0006\u0008\u0008\u0008\u000c\u000c\u000c\u0010\u0010\u0010\u0014\u0014\u0014\u001a\u001a\u001a\u0022\u0022\u0022\u002a\u002a\u002a\u000c\u000c\u000c\u0000",
size = 40
)
)
private val __STATIC_L3_decode_scalefactors_g_scf_partitions: Array = arrayOf(
arrayOfUByte("\u0006\u0005\u0005\u0005\u0006\u0005\u0005\u0005\u0006\u0005\u0007\u0003\u000b\u000a\u0000\u0000\u0007\u0007\u0007\u0000\u0006\u0006\u0006\u0003\u0008\u0008\u0005\u0000"),
arrayOfUByte("\u0008\u0009\u0006\u000c\u0006\u0009\u0009\u0009\u0006\u0009\u000c\u0006\u000f\u0012\u0000\u0000\u0006\u000f\u000c\u0000\u0006\u000c\u0009\u0006\u0006\u0012\u0009\u0000"),
arrayOfUByte("\u0009\u0009\u0006\u000c\u0009\u0009\u0009\u0009\u0009\u0009\u000c\u0006\u0012\u0012\u0000\u0000\u000c\u000c\u000c\u0000\u000c\u0009\u0009\u0006\u000f\u000c\u0009\u0000")
)
private val __STATIC_L12_subband_alloc_table_g_alloc_L1: Array = arrayOf(
L12_subband_alloc_tStruct(76u, 4u, 32u),
)
private val __STATIC_L12_subband_alloc_table_g_alloc_L2M2: Array = arrayOf(
L12_subband_alloc_tStruct(60u, 4u, 4u),
L12_subband_alloc_tStruct(44u, 3u, 7u),
L12_subband_alloc_tStruct(44u, 2u, 19u),
)
private val __STATIC_L12_subband_alloc_table_g_alloc_L2M1: Array = arrayOf(
L12_subband_alloc_tStruct(0u, 4u, 3u),
L12_subband_alloc_tStruct(16u, 4u, 8u),
L12_subband_alloc_tStruct(32u, 3u, 12u),
L12_subband_alloc_tStruct(40u, 2u, 7u),
)
private val __STATIC_L12_subband_alloc_table_g_alloc_L2M1_lowrate: Array = arrayOf(
L12_subband_alloc_tStruct(44u, 4u, 2u),
L12_subband_alloc_tStruct(44u, 3u, 10u),
)
private val g_pow43: FloatArray = floatArrayOf(
0f, -1f, -2.519842f, -4.326749f, -6.349604f, -8.54988f, -10.902724f, -13.390518f, -16f, -18.720755f, -21.544348f, -24.463781f, -27.473143f,
-30.56735f, -33.741993f, -36.99318f, 0f, 1f, 2.519842f, 4.326749f, 6.349604f, 8.54988f, 10.902724f, 13.390518f, 16f, 18.720755f, 21.544348f,
24.463781f, 27.473143f, 30.56735f, 33.741993f, 36.99318f, 40.317474f, 43.71179f, 47.173344f, 50.69963f, 54.288353f, 57.93741f, 61.644863f,
65.40894f, 69.22798f, 73.10044f, 77.024895f, 81f, 85.02449f, 89.09719f, 93.21697f, 97.3828f, 101.593666f, 105.84863f, 110.146805f,
114.48732f, 118.869385f, 123.292206f, 127.755066f, 132.25725f, 136.79808f, 141.3769f, 145.99312f, 150.64612f, 155.33533f, 160.0602f,
164.8202f, 169.61482f, 174.44357f, 179.30598f, 184.20157f, 189.12991f, 194.09058f, 199.08315f, 204.10721f, 209.16238f, 214.24829f,
219.36456f, 224.51085f, 229.68678f, 234.89206f, 240.12633f, 245.38928f, 250.6806f, 256f, 261.34717f, 266.72183f, 272.12372f,
277.55255f, 283.00806f, 288.48996f, 293.99805f, 299.53207f, 305.09177f, 310.6769f, 316.28726f, 321.92258f, 327.5827f, 333.26736f,
338.97638f, 344.70956f, 350.46664f, 356.24747f, 362.05188f, 367.8796f, 373.73053f, 379.60443f, 385.50113f, 391.4205f, 397.3623f,
403.32642f, 409.31268f, 415.3209f, 421.3509f, 427.4026f, 433.47574f, 439.57028f, 445.68597f, 451.82275f, 457.98044f, 464.15887f,
470.35797f, 476.57755f, 482.81744f, 489.0776f, 495.35788f, 501.65808f, 507.97815f, 514.31793f, 520.6773f, 527.0562f, 533.4544f,
539.8719f, 546.3085f, 552.76404f, 559.2386f, 565.7319f, 572.2439f, 578.7744f, 585.3235f, 591.89087f, 598.47656f, 605.08044f,
611.70233f, 618.3422f, 625f, 631.67554f, 638.3688f, 645.0796f
)
}
data class L12_subband_alloc_tStruct(val tab_offset: UByte, val code_tab_width: UByte, val band_count: UByte)
class Mp3Dec(
var mdct_overlap: Array,
var qmf_state: FloatArray,
var reserv: Int,
var free_format_bytes_array: IntArray,
var header: UByteArrayInt,
var reserv_buf: UByteArrayInt,
) {
constructor() : this(
mdct_overlap = Array(2) { FloatArray(288) },
qmf_state = FloatArray(960),
reserv = 0,
free_format_bytes_array = IntArray(1),
header = UByteArrayInt(4),
reserv_buf = UByteArrayInt(MAX_BITRESERVOIR_BYTES),
)
}
class Bs(
var buf: UByteArrayIntPtr = UByteArrayIntPtr(UByteArrayInt(0)),
var pos: Int = 0,
var limit: Int = 0,
)
class Mp3Scratch(
var bs: Bs,
var maindata: UByteArrayIntPtr,
var gr_info: ArrayPtr,
var grbuf: Array,
var scf: FloatArrayPtr,
var syn: Array,
var ist_pos: Array,
) {
constructor() : this(
bs = Bs(),
maindata = UByteArrayIntPtr(UByteArrayInt(2815)),
gr_info = ArrayPtr(Array(4) { GrInfo() }, 0),
grbuf = kotlin.run {
val CSIZE = 576
val data = FloatArray(2 * CSIZE)
Array(2) {
FloatArrayPtr(data, CSIZE * it)
}
},
scf = FloatArrayPtr(FloatArray(40)),
syn = kotlin.run {
val CSIZE = 64
val data = FloatArray(33 * CSIZE)
Array(33) { FloatArrayPtr(data, CSIZE * it) }
},
ist_pos = Array(2) { UByteArrayInt(39) },
)
}
// mp3dec_frame_info_t
class Mp3FrameInfo(
var frame_bytes: Int = 0,
var frame_offset: Int = 0,
var channels: Int = 0,
var hz: Int = 0,
var layer: Int = 0,
var bitrate_kbps: Int = 0,
) {
val value get() = this
}
class ArrayPtr(val array: Array, val pos: Int) {
var value: T
get() = array[pos]
set(value) {
array[pos] = value
}
operator fun get(index: Int): T = array[pos + index]
operator fun set(index: Int, value: T) {
array[pos + index] = value
}
operator fun inc(): ArrayPtr = ArrayPtr(array, pos + 1)
operator fun plus(other: Int): ArrayPtr = ArrayPtr(array, pos + other)
operator fun minus(other: ArrayPtr): Int = pos - other.pos
fun fill(value: T, from: Int, to: Int) {
array.fill(value, this.pos + from, this.pos + to)
}
}
class UByteArrayIntPtr(val array: UByteArrayInt, val pos: Int = 0) {
var value: Int
get() = array[pos]
set(value) {
array[pos] = value
}
operator fun get(index: Int): Int = array[pos + index]
operator fun set(index: Int, value: Int) {
array[pos + index] = value
}
operator fun inc(): UByteArrayIntPtr = UByteArrayIntPtr(array, pos + 1)
operator fun plus(other: Int): UByteArrayIntPtr = UByteArrayIntPtr(array, pos + other)
operator fun minus(other: UByteArrayIntPtr): Int = pos - other.pos
fun minusPtrUByte(other: UByteArrayIntPtr): Int = pos - other.pos
fun fill(value: UByte, from: Int, to: Int) {
array.bytes.fill(value.toByte(), this.pos + from, this.pos + to)
}
}
class FloatArrayPtr(val array: FloatArray, val pos: Int = 0) {
var value: Float
get() = array[pos]
set(value) {
array[pos] = value
}
operator fun get(index: Int): Float = array[pos + index]
operator fun set(index: Int, value: Float) {
array[pos + index] = value
}
operator fun inc(): FloatArrayPtr = FloatArrayPtr(array, pos + 1)
operator fun plus(other: Int): FloatArrayPtr = FloatArrayPtr(array, pos + other)
operator fun minus(other: FloatArrayPtr): Int = pos - other.pos
fun fill(value: Float, from: Int, to: Int) {
array.fill(value, this.pos + from, this.pos + to)
}
}
class ShortArrayPtr(val array: ShortArray, val pos: Int = 0) {
var value: Short
get() = array[pos]
set(value) {
array[pos] = value
}
operator fun get(index: Int): Short = array[pos + index]
operator fun set(index: Int, value: Short) {
array[pos + index] = value
}
operator fun inc(): ShortArrayPtr = ShortArrayPtr(array, pos + 1)
operator fun plus(other: Int): ShortArrayPtr = ShortArrayPtr(array, pos + other)
operator fun minus(other: ShortArrayPtr): Int = pos - other.pos
fun fill(value: Short, from: Int, to: Int) {
array.fill(value, this.pos + from, this.pos + to)
}
}
fun memcpy(dst: FloatArrayPtr, src: FloatArrayPtr, size: Int) {
arraycopy(src.array, src.pos, dst.array, dst.pos, size)
}
fun memcpy(dst: UByteArrayIntPtr, src: UByteArrayIntPtr, size: Int) {
arraycopy(src.array, src.pos, dst.array, dst.pos, size)
}
class GrInfo(
var sfbtab: UByteArrayIntPtr = UByteArrayIntPtr(UByteArrayInt(0)),
var part_23_length: Int = 0,
var big_values: Int = 0,
var scalefac_compress: Int = 0,
var global_gain: Int = 0,
var block_type: Int = 0,
var mixed_block_flag: Int = 0,
var n_long_sfb: Int = 0,
var n_short_sfb: Int = 0,
var table_select: UByteArrayInt = UByteArrayInt(3),
var region_count: UByteArrayInt = UByteArrayInt(3),
var subblock_gain: UByteArrayInt = UByteArrayInt(3),
var preflag: Int = 0,
var scalefac_scale: Int = 0,
var count1_table: Int = 0,
var scfsi: Int = 0,
)
// CPointer
class ScaleInfo(
var scf: FloatArray = FloatArray(192),
var total_bands: Int = 0,
var stereo_bands: Int = 0,
var bitalloc: UByteArrayInt = UByteArrayInt(64),
var scfcod: UByteArrayInt = UByteArrayInt(64),
)
///////////////////////////////////
// PROGRAM
///////////////////////////////////
private fun Boolean.toInt(): Int = if (this) 1 else 0
fun bs_init(bs: Bs, data: UByteArrayIntPtr, bytes: Int) {
bs.buf = data
bs.pos = 0
bs.limit = bytes * 8
}
fun get_bits(bs: Bs, n: Int): Int {
var cache = 0
val s: Int = ((bs.pos and 7))
var shl: Int = n + (s)
var p: UByteArrayIntPtr = bs.buf + ((bs.pos ushr 3))
bs.pos += n
if (bs.pos > bs.limit) return 0
var next = p.value and (0xFF ushr s)
p++
while (true) {
shl -= 8
if (shl <= 0) break
cache = cache or (next shl shl)
next = p.value
p++
}
return cache or (next ushr (-shl))
}
fun hdr_valid(h: UByteArrayIntPtr): Boolean {
val h0 = h[0]
val h1 = h[1]
val h2 = h[2]
return h0 == 255 && (h1 and 240 == 240 || (h1 and 254 == 226)) && (h1 shr 1 and 3 != 0) && (h2 shr 4 != 15) && (h2 shr 2 and 3 != 3)
}
fun hdr_compare(h1: UByteArrayIntPtr, h2: UByteArrayIntPtr): Int {
return (hdr_valid(h2) && (h1[1] xor h2[1] and 254) == 0 && (h1[2] xor (h2[2]) and 12) == 0 && (((h1[2]) and 240) == 0).toInt() xor ((h2[2] and 240) == 0).toInt() == 0).toInt()
}
fun hdr_bitrate_kbps(h: UByteArrayIntPtr): Int {
return (2 * __STATIC_hdr_bitrate_kbps_halfrate[(h[1] and 8 != 0).toInt()][(h[1] shr 1 and 3) - 1][h[2] shr 4])
}
fun hdr_sample_rate_hz(h: UByteArrayIntPtr): Int {
val g_hz = __STATIC_hdr_sample_rate_hz_g_hz
return (g_hz[h[2] shr 2 and 3] shr (h[1] and 8 == 0).toInt() shr (h[1] and 16 == 0).toInt()).toInt()
}
fun hdr_frame_samples(h: UByteArrayIntPtr): Int {
return (if (h[1] and 6 == 6) 384 else 1152 shr (h[1] and 14 == 2).toInt()).toInt()
}
fun hdr_frame_bytes(h: UByteArrayIntPtr, free_format_size: Int): Int {
var frame_bytes: Int = (hdr_frame_samples(h) * hdr_bitrate_kbps(h) * 125 / hdr_sample_rate_hz(h))
if (h[1] and 6 == 6) {
frame_bytes = frame_bytes and ((3).inv())
}
return if (frame_bytes != 0) frame_bytes else free_format_size
}
fun hdr_padding(h: UByteArrayIntPtr): Int = when {
h[2] and 2 != 0 -> if (h[1] and 6 == 6) 4 else 1
else -> 0
}
fun L12_subband_alloc_table(hdr: UByteArrayIntPtr, sci: ScaleInfo): Array {
var alloc: Array = __STATIC_L12_subband_alloc_table_g_alloc_L1
val mode: Int = hdr[3] shr 6 and 3
var nbands: Int
val stereo_bands: Int = when (mode) {
3 -> 0
1 -> (hdr[3] shr 4 and 3 shl 2) + 4
else -> 32
}
when {
hdr[1] and 6 == 6 -> {
alloc = __STATIC_L12_subband_alloc_table_g_alloc_L1
nbands = 32
}
hdr[1] and 8 == 0 -> {
alloc = __STATIC_L12_subband_alloc_table_g_alloc_L2M2
nbands = 30
}
else -> {
val sample_rate_idx: Int = hdr[2] shr 2 and 3
var kbps: Int = hdr_bitrate_kbps(hdr) shr (mode != 3).toInt()
if (kbps == 0) kbps = 192
alloc = __STATIC_L12_subband_alloc_table_g_alloc_L2M1
nbands = 27
when {
kbps < 56 -> {
alloc = __STATIC_L12_subband_alloc_table_g_alloc_L2M1_lowrate
nbands = if (sample_rate_idx == 2) 12 else 8
}
kbps >= 96 && sample_rate_idx != 1 -> {
nbands = 30
}
}
}
}
sci.total_bands = nbands
sci.stereo_bands = if (stereo_bands > nbands) nbands else stereo_bands
return alloc
}
fun L12_read_scalefactors(bs: Bs, pba: UByteArrayInt, scfcod: UByteArrayInt, bands: Int, scf: FloatArrayPtr) {
var scfOffset = 0
val g_deq_L12 = __STATIC_L12_read_scalefactors_g_deq_L12
for (i in 0 until bands) {
var s = 0f
val ba: Int = pba[i]
val mask: Int = if (ba != 0) 4 + (19 shr scfcod[i] and 3) else 0
var m = 4
while (m != 0) {
if (((mask and m)) != 0) {
val b: Int = get_bits(bs, 6)
s = g_deq_L12[((ba * 3) - 6) + (b % 3)] * ((((1 shl 21) shr (b / 3))).toFloat())
}
scf[scfOffset] = s
m = m shr 1
scfOffset++
}
}
}
fun L12_read_scale_info(hdr: UByteArrayIntPtr, bs: Bs, sci: ScaleInfo) {
val g_bitalloc_code_tab = UByteArrayIntPtr(__STATIC_L12_read_scale_info_g_bitalloc_code_tab)
val subband_alloc = L12_subband_alloc_table(hdr, sci)
var subband_alloc_n = 0
var k = 0
var ba_bits: Int = 0
var ba_code_tab: UByteArrayIntPtr = (g_bitalloc_code_tab)
for (i in 0 until sci.total_bands) {
var ba: Int = 0
if (i == k) {
k += (subband_alloc[subband_alloc_n].band_count.toInt())
ba_bits = subband_alloc[subband_alloc_n].code_tab_width.toInt()
ba_code_tab = g_bitalloc_code_tab + subband_alloc[subband_alloc_n].tab_offset.toInt()
subband_alloc_n++
}
ba = ba_code_tab[get_bits(bs, ba_bits)]
sci.bitalloc[2 * i] = ba
if (i < (sci.stereo_bands)) {
ba = ba_code_tab[get_bits(bs, ba_bits)]
}
sci.bitalloc[(2 * i) + 1] = if (sci.stereo_bands != 0) ba else 0
}
for (i in 0 until 2 * sci.total_bands) {
sci.scfcod[i] = when {
sci.bitalloc[i] != 0 -> when {
hdr[1] and 6 == 6 -> 2
else -> get_bits(bs, 2)
}
else -> 6
}
}
L12_read_scalefactors(
bs,
sci.bitalloc,
sci.scfcod,
sci.total_bands * 2,
FloatArrayPtr(sci.scf)
)
for (i in sci.stereo_bands until sci.total_bands) {
sci.bitalloc[(2 * i) + 1] = 0
}
}
fun L12_dequantize_granule(grbuf: FloatArrayPtr, bs: Bs, sci: ScaleInfo, group_size: Int): Int {
var choff = 576
for (j in 0 until 4) {
var dst: FloatArrayPtr = grbuf + ((group_size * j))
for (i in 0 until (2 * (sci.total_bands))) {
val ba: Int = sci.bitalloc[i]
if (ba != 0) {
if (ba < 17) {
val half: Int = (1 shl (ba - 1)) - 1
for (k in 0 until group_size) {
dst[k] = (((get_bits(bs, ba)) - half)).toFloat()
}
} else {
val mod = (((2 shl (ba - 17)) + 1))
var code = get_bits(bs, mod + 2 - (mod shr 3))
for (k in 0 until group_size) {
dst[k] = (code % mod - (mod / 2)).toFloat()
code /= mod
}
}
}
dst += choff
choff = 18 - choff
}
}
return group_size * 4
}
fun L12_apply_scf_384(sci: ScaleInfo, scf: FloatArrayPtr, dst: FloatArrayPtr) {
var scf: FloatArrayPtr = scf // Mutating parameter
var dst: FloatArrayPtr = dst // Mutating parameter
memcpy(
dst + 576 + sci.stereo_bands * 18,
dst + sci.stereo_bands * 18,
(sci.total_bands - sci.stereo_bands) * 18
)
for (i in 0 until sci.total_bands) {
for (k in 0 until 12) {
dst[k + 0] = dst[k + 0] * scf[0]
dst[k + 576] = dst[k + 576] * scf[3]
}
dst += 18
scf += 6
}
}
fun L3_read_side_info(bs: Bs, gr: ArrayPtr, hdr: UByteArrayIntPtr): Int {
var gr: ArrayPtr = gr // Mutating parameter
val g_scf_long = __STATIC_L3_read_side_info_g_scf_long
val g_scf_short = __STATIC_L3_read_side_info_g_scf_short
val g_scf_mixed = __STATIC_L3_read_side_info_g_scf_mixed
var tables: Int
var scfsi: Int = 0
val main_data_begin: Int
var part_23_sum = 0
var sr_idx: Int = (hdr[2] shr 2 and 3) + ((hdr[1] shr 3 and 1) + (hdr[1] shr 4 and 1)) * 3
sr_idx -= (sr_idx != 0).toInt()
var gr_count: Int = (if (hdr[3] and 192 == 192) 1 else 2)
if (hdr[1] and 8 != 0) {
gr_count *= 2
main_data_begin = get_bits(bs, 9)
scfsi = get_bits(bs, (7 + gr_count))
} else {
main_data_begin = ((get_bits(bs, (8 + gr_count)) shr gr_count))
}
do {
if (hdr[3] and 192 == 192) {
scfsi = scfsi shl 4
}
gr.value.part_23_length = get_bits(bs, 12)
part_23_sum += (gr.value.part_23_length)
gr.value.big_values = get_bits(bs, 9)
if (gr.value.big_values > 288) return -1
gr.value.global_gain = get_bits(bs, 8)
gr.value.scalefac_compress = get_bits(bs, if (hdr[1] and 8 != 0) 4 else 9)
gr.value.sfbtab = UByteArrayIntPtr(g_scf_long[sr_idx])
gr.value.n_long_sfb = 22
gr.value.n_short_sfb = 0
if (get_bits(bs, 1) != 0) {
gr.value.block_type = get_bits(bs, 2)
if (gr.value.block_type == 0) return -1
gr.value.mixed_block_flag = get_bits(bs, 1)
gr.value.region_count[0] = 7u
gr.value.region_count[1] = 255
if (gr.value.block_type == 2) {
scfsi = scfsi and 3855
if (gr.value.mixed_block_flag == 0) {
gr.value.region_count[0] = 8
gr.value.sfbtab = UByteArrayIntPtr(g_scf_short[sr_idx])
gr.value.n_long_sfb = 0
gr.value.n_short_sfb = 39
} else {
gr.value.sfbtab = UByteArrayIntPtr(g_scf_mixed[sr_idx])
gr.value.n_long_sfb = if (hdr[1] and 8 != 0) 8 else 6
gr.value.n_short_sfb = 30
}
}
tables = get_bits(bs, 10)
tables = tables shl 5
gr.value.subblock_gain[0] = get_bits(bs, 3)
gr.value.subblock_gain[1] = get_bits(bs, 3)
gr.value.subblock_gain[2] = get_bits(bs, 3)
} else {
gr.value.block_type = 0
gr.value.mixed_block_flag = 0
tables = get_bits(bs, 15)
gr.value.region_count[0] = get_bits(bs, 4)
gr.value.region_count[1] = get_bits(bs, 3)
gr.value.region_count[2] = 255
}
gr.value.table_select[0] = tables shr 10
gr.value.table_select[1] = tables shr 5 and 31
gr.value.table_select[2] = tables and 31
gr.value.preflag = if (hdr[1] and 8 != 0) get_bits(bs, 1) else (gr.value.scalefac_compress >= 500).toInt()
gr.value.scalefac_scale = get_bits(bs, 1)
gr.value.count1_table = get_bits(bs, 1)
gr.value.scfsi = (scfsi shr 12) and 15
scfsi = scfsi shl 4
gr++
} while (--gr_count != 0)
if (part_23_sum + bs.pos > bs.limit + (main_data_begin * 8)) return -1
return main_data_begin
}
fun L3_read_scalefactors(scf: UByteArrayIntPtr, ist_pos: UByteArrayInt, scf_size: UByteArrayInt, scf_count: UByteArrayIntPtr, bitbuf: Bs, scfsi: Int) {
var scf: UByteArrayIntPtr = scf // Mutating parameter
var ist_pos = UByteArrayIntPtr(ist_pos) // Mutating parameter
var scfsi: Int = scfsi // Mutating parameter
for (i in 0 until 4) {
if (scf_count[i] == 0) break
val cnt: Int = scf_count[i]
if (((scfsi and 8)) != 0) {
for (n in 0 until cnt) scf[n] = ist_pos[n]
} else {
val bits: Int = scf_size[i]
if (bits == 0) {
scf.fill(0u, 0, cnt)
ist_pos.fill(0u, 0, cnt)
} else {
val max_scf: Int = ((if (scfsi < 0) ((((1 shl bits) - 1)).toLong()) else -1L)).toInt()
for (k in 0 until cnt) {
val s: Int = get_bits(bitbuf, bits)
ist_pos[k] = ((if (s == max_scf) -1L else (s.toLong()))).toInt()
scf[k] = s
}
}
}
ist_pos += cnt
scf += cnt
scfsi *= 2
}
scf[0] = 0
scf[1] = 0
scf[2] = 0
}
fun L3_ldexp_q2(y: Float, exp_q2: Int): Float {
var y: Float = y
var exp_q2: Int = exp_q2 // Mutating parameter
val g_expfrac: FloatArray = __STATIC_L3_ldexp_q2_g_expfrac
do {
val e = (if ((30 * 4) > exp_q2) exp_q2 else (30 * 4))
y *= (g_expfrac[e and 3] * ((((1 shl 30) shr (e shr 2))).toFloat()))
exp_q2 -= e
} while (exp_q2 > 0)
return y
}
fun L3_decode_scalefactors(hdr: UByteArrayInt, ist_pos: UByteArrayInt, bs: Bs, gr: ArrayPtr, scf: FloatArrayPtr, ch: Int) {
val g_scf_partitions = __STATIC_L3_decode_scalefactors_g_scf_partitions
var scf_partition = UByteArrayIntPtr(g_scf_partitions[(gr.value.n_short_sfb != 0).toInt() + (gr.value.n_long_sfb == 0).toInt()])
val scf_size = UByteArrayInt(4)
val iscf = UByteArrayInt(40)
val scf_shift: Int = gr.value.scalefac_scale + 1
var scfsi: Int = gr.value.scfsi
if (hdr[1] and 8 != 0) {
val g_scfc_decode = __STATIC_L3_decode_scalefactors_g_scfc_decode
val part: Int = g_scfc_decode[gr.value.scalefac_compress]
scf_size[0] = part shr 2
scf_size[1] = scf_size[0]
scf_size[2] = part and 3
scf_size[3] = scf_size[2]
} else {
val g_mod = __STATIC_L3_decode_scalefactors_g_mod
val ist: Int = (hdr[3] and 16 != 0 && (ch != 0)).toInt()
var sfc = gr.value.scalefac_compress shr ist
var k = (ist * 3) * 4
while (sfc >= 0) {
var modprod = 1
for (i in 3 downTo 0) {
scf_size[i] = (sfc / modprod) % g_mod[k + i]
modprod *= (g_mod[k + i])
}
sfc -= modprod
k += 4
}
scf_partition += k
scfsi = -16
}
L3_read_scalefactors(UByteArrayIntPtr(iscf), ist_pos, ((scf_size)), scf_partition, bs, scfsi)
if (gr.value.n_short_sfb != 0) {
val sh: Int = 3 - scf_shift
for (i in 0 until gr.value.n_short_sfb step 3) {
iscf[gr.value.n_long_sfb + i + 0] = iscf[gr.value.n_long_sfb + i + 0] + (gr.value.subblock_gain[0] shl sh)
iscf[gr.value.n_long_sfb + i + 1] = iscf[gr.value.n_long_sfb + i + 1] + (gr.value.subblock_gain[1] shl sh)
iscf[gr.value.n_long_sfb + i + 2] = iscf[gr.value.n_long_sfb + i + 2] + (gr.value.subblock_gain[2] shl sh)
}
} else {
if (gr.value.preflag != 0) {
val g_preamp = __STATIC_L3_decode_scalefactors_g_preamp
for (i in 0 until 10) {
iscf[11 + i] = iscf[11 + i] + g_preamp[i]
}
}
}
val gain_exp = (gr.value.global_gain + -1L * 4L).toInt() - 210 - if (hdr[3] and 224 == 96) 2 else 0
val gain = L3_ldexp_q2(
(1 shl ((255L + (-1L * 4L) - 210L + 3L and 3.inv().toLong()) / 4L).toInt()).toFloat(),
((255L + (-1L * 4L) - 210L + 3L and (3.inv().toLong())) - (gain_exp.toLong())).toInt()
)
for (i in 0 until gr.value.n_long_sfb + gr.value.n_short_sfb) {
scf[i] = L3_ldexp_q2(gain, iscf[i] shl scf_shift)
}
}
fun L3_pow_43(x: Int): Float {
var x: Int = x // Mutating parameter
var mult = 256
if (x < 129) return g_pow43[16 + x]
if (x < 1024) {
mult = 16
x = x shl 3
}
val sign = (2 * x) and 64
val frac = ((x and 63) - sign).toFloat() / ((x and ((63).inv())) + sign).toFloat()
return (g_pow43[16 + ((x + sign) shr 6)] * (1f + (frac * ((4f / 3f) + (frac * (2f / 9f)))))) * (mult.toFloat())
}
fun L3_huffman(dst: FloatArrayPtr, bs: Bs, gr_info: ArrayPtr, scf: FloatArrayPtr, layer3gr_limit: Int) {
var dst: FloatArrayPtr = dst // Mutating parameter
var scf: FloatArrayPtr = scf // Mutating parameter
val tabs = __STATIC_L3_huffman_tabs
val tab32 = __STATIC_L3_huffman_tab32
val tab33 = __STATIC_L3_huffman_tab33
val tabindex = __STATIC_L3_huffman_tabindex
val g_linbits = __STATIC_L3_huffman_g_linbits
var one = 0f
var ireg = 0
var big_val_cnt: Int = gr_info.value.big_values
var sfb: UByteArrayIntPtr = gr_info.value.sfbtab
var bs_next_ptr: UByteArrayIntPtr = bs.buf + ((bs.pos / 8))
var bs_cache: UInt = (((bs_next_ptr[0] * 256 + (bs_next_ptr[1])) * 256 + bs_next_ptr[2]) * 256 + bs_next_ptr[3] shl (bs.pos and 7)).toUInt()
var pairs_to_decode = 0
var np = 0
var bs_sh: Int = (bs.pos and 7) - 8
bs_next_ptr += 4
while (big_val_cnt > 0) {
val tab_num: Int = gr_info.value.table_select[ireg]
var sfb_cnt: Int = gr_info.value.region_count[ireg++]
val codebook = tabindex[tab_num].toInt()
val linbits: Int = g_linbits[tab_num]
if (linbits != 0) {
do {
np = sfb.value / 2
sfb++
pairs_to_decode = if (big_val_cnt > np) np else big_val_cnt
one = scf++.value
do {
var w: Int = 5
var leaf: Int = tabs[codebook + ((bs_cache shr (32 - w))).toInt()].toInt()
while (leaf < 0) {
bs_cache = bs_cache shl w
bs_sh += w
w = leaf and 7
leaf = tabs[codebook + (((bs_cache shr (32 - w))).toInt()) - (leaf shr 3)].toInt()
}
bs_cache = bs_cache shl (leaf shr 8)
bs_sh += (leaf shr 8)
for (j in 0 until 2) {
var lsb: Int = leaf and 15
if (lsb == 15) {
lsb += (((bs_cache shr (32 - linbits))).toInt())
bs_cache = bs_cache shl linbits
bs_sh += linbits
while (bs_sh >= 0) {
bs_cache = bs_cache or (bs_next_ptr.value shl bs_sh).toUInt()
bs_next_ptr++
bs_sh -= 8
}
dst.value = (one * L3_pow_43(lsb)) * (((if ((bs_cache.toInt()) < 0) -1L else 1L)).toFloat())
} else {
dst.value = g_pow43[(16 + lsb) - (16 * (((bs_cache shr 31)).toInt()))] * one
}
bs_cache = bs_cache shl (if (lsb != 0) 1 else 0)
bs_sh += (if (lsb != 0) 1 else 0)
dst++
leaf = leaf shr 4
}
while (bs_sh >= 0) {
bs_cache = bs_cache or (bs_next_ptr.value shl bs_sh).toUInt()
bs_next_ptr++
bs_sh -= 8
}
} while (--pairs_to_decode != 0)
big_val_cnt -= np
} while (big_val_cnt > 0 && (--sfb_cnt >= 0))
} else {
do {
np = sfb.value / 2
sfb++
pairs_to_decode = if (big_val_cnt > np) np else big_val_cnt
one = scf++.value
do {
var w = 5
var leaf: Int = tabs[codebook + ((bs_cache shr (32 - w))).toInt()].toInt()
while (leaf < 0) {
bs_cache = bs_cache shl w
bs_sh += w
w = leaf and 7
leaf = tabs[codebook + (((bs_cache shr (32 - w))).toInt()) - (leaf shr 3)].toInt()
}
bs_cache = bs_cache shl (leaf shr 8)
bs_sh += (leaf shr 8)
for (j in 0 until 2) {
val lsb: Int = leaf and 15
dst.value = g_pow43[(16 + lsb) - (16 * (((bs_cache shr 31)).toInt()))] * one
bs_cache = bs_cache shl (if (lsb != 0) 1 else 0)
bs_sh += (if (lsb != 0) 1 else 0)
dst++
leaf = leaf shr 4
}
while (bs_sh >= 0) {
bs_cache = bs_cache or (bs_next_ptr.value shl bs_sh).toUInt()
bs_next_ptr++
bs_sh -= 8
}
} while (((--pairs_to_decode)) != 0)
big_val_cnt -= np
} while (big_val_cnt > 0 && --sfb_cnt >= 0)
}
}
np = 1 - big_val_cnt
while (true) {
val codebook_count1 = if (gr_info.value.count1_table != 0) tab33 else tab32
var leaf: Int = codebook_count1[((bs_cache shr (32 - 4))).toInt()]
if ((leaf and 8) == 0) leaf = codebook_count1[(leaf shr 3) + (bs_cache shl 4 shr 32 - (leaf and 3)).toInt()]
bs_cache = bs_cache shl (leaf and 7)
bs_sh += (leaf and 7)
if ((bs_next_ptr.minusPtrUByte(bs.buf)) * 8 - 24 + bs_sh > layer3gr_limit) {
break
}
if ((--np) == 0) {
np = sfb.value / 2
sfb++
if (np == 0) break
one = scf++.value
}
if (leaf and (128 shr 0) != 0) {
dst[0] = if ((bs_cache.toInt()) < 0) (-one) else one
bs_cache = bs_cache shl 1
bs_sh++
}
if ((leaf and (128 shr 1)) != 0) {
dst[1] = if ((bs_cache.toInt()) < 0) (-one) else one
bs_cache = bs_cache shl 1
bs_sh++
}
if (--np == 0) {
np = sfb.value / 2
sfb++
if (np == 0) break
one = scf++.value
}
if ((leaf and (128 shr 2)) != 0) {
dst[2] = if (bs_cache.toInt() < 0) -one else one
bs_cache = bs_cache shl 1
bs_sh++
}
if ((leaf and (128 shr 3)) != 0) {
dst[3] = if (bs_cache.toInt() < 0) -one else one
bs_cache = bs_cache shl 1
bs_sh++
}
while (bs_sh >= 0) {
bs_cache = bs_cache or (bs_next_ptr.value shl bs_sh).toUInt()
bs_next_ptr++
bs_sh -= 8
}
dst += 4
}
bs.pos = layer3gr_limit
}
fun L3_midside_stereo(left: FloatArrayPtr, n: Int) {
val right: FloatArrayPtr = left + 576
for (i in 0 until n) {
val a: Float = left[i]
val b: Float = right[i]
left[i] = a + b
right[i] = a - b
}
}
fun L3_intensity_stereo_band(left: FloatArrayPtr, n: Int, kl: Float, kr: Float) {
for (i in 0 until n) {
left[i + 576] = left[i] * kr
left[i] = left[i] * kl
}
}
fun L3_stereo_top_band(right: FloatArrayPtr, sfb: UByteArrayIntPtr, nbands: Int, max_band: IntArray) {
var right: FloatArrayPtr = right // Mutating parameter
max_band[0] = -1
max_band[1] = -1
max_band[2] = -1
for (i in 0 until nbands) {
var k = 0
while (k < (sfb[i])) {
if (right[k] != 0f || right[k + 1] != 0f) {
max_band[i % 3] = i
break
}
k += 2
}
right += (sfb[i])
}
}
fun L3_stereo_process(left: FloatArrayPtr, ist_pos: UByteArrayInt, sfb: UByteArrayIntPtr, hdr: UByteArrayInt, max_band: IntArray, mpeg2_sh: Int) {
var left: FloatArrayPtr = left // Mutating parameter
val g_pan: FloatArray = __STATIC_L3_stereo_process_g_pan
val max_pos: Int = if (hdr[1] and 8 != 0) 7 else 64
var i = 0
while (sfb[i] != 0) {
val ipos: Int = ist_pos[i]
if ((i > max_band[i % 3]) && ipos < max_pos) {
var kl: Float
var kr: Float
val s: Float = if ((hdr[3] and 32) != 0) 1.4142135f else 1f
if (hdr[1] and 8 != 0) {
kl = g_pan[2 * ipos + 0]
kr = g_pan[2 * ipos + 1]
} else {
kl = 1f
kr = L3_ldexp_q2(1f, ipos + 1 shr 1 shl mpeg2_sh)
if (ipos and 1 != 0) {
kl = kr
kr = 1f
}
}
L3_intensity_stereo_band(left, (sfb[i]), (kl * s), (kr * s))
} else {
if (hdr[3] and 32 != 0) {
L3_midside_stereo(left, (sfb[i]))
}
}
left += sfb[i]
i++
}
}
val tempInt3 = IntArray(3)
fun L3_intensity_stereo(left: FloatArrayPtr, ist_pos: UByteArrayInt, gr: ArrayPtr, hdr: UByteArrayInt) {
val max_band = tempInt3
val n_sfb: Int = gr.value.n_long_sfb + gr.value.n_short_sfb
val max_blocks: Int = if (gr.value.n_short_sfb != 0) 3 else 1
L3_stereo_top_band(left + 576, gr.value.sfbtab, n_sfb, max_band)
if (gr.value.n_long_sfb != 0) {
val v = max(max(max_band[0], max_band[1]), max_band[2])
max_band[0] = v
max_band[1] = v
max_band[2] = v
}
for (i in 0 until max_blocks) {
val default_pos: Int = if (hdr[1] and 8 != 0) 3 else 0
val itop: Int = (n_sfb - max_blocks) + i
val prev: Int = itop - max_blocks
ist_pos[itop] = if (max_band[i] >= prev) default_pos else ist_pos[prev]
}
L3_stereo_process(left, ist_pos, gr.value.sfbtab, hdr, max_band, gr[1].scalefac_compress and 1)
}
fun L3_reorder(grbuf: FloatArrayPtr, scratch: FloatArrayPtr, sfb: UByteArrayIntPtr) {
var sfb: UByteArrayIntPtr = sfb // Mutating parameter
var i: Int = 0
var len: Int = 0
var src: FloatArrayPtr = grbuf
var dst: FloatArrayPtr = scratch
while (true) {
len = sfb.value
if (len == 0) break
i = 0
while (i < len) {
dst++.value = src[0 * len]
dst++.value = src[1 * len]
dst++.value = src[2 * len]
i++
src++
}
sfb += 3
src += (2 * len)
}
memcpy((grbuf), (scratch), (dst - scratch))
}
fun L3_antialias(grbuf: FloatArrayPtr, nbands: Int) {
var grbuf: FloatArrayPtr = grbuf // Mutating parameter
var nbands: Int = nbands // Mutating parameter
val g_aa: Array = __STATIC_L3_antialias_g_aa
while (nbands > 0) {
for (i in 0 until 8) {
val u: Float = grbuf[18 + i]
val d: Float = grbuf[17 - i]
grbuf[18 + i] = (u * g_aa[0][i]) - (d * g_aa[1][i])
grbuf[17 - i] = (u * g_aa[1][i]) + (d * g_aa[0][i])
}
nbands--
grbuf += 18
}
}
fun L3_dct3_9(y: FloatArray) {
var s0: Float = y[0]
var s2: Float = y[2]
var s4: Float = y[4]
var s6: Float = y[6]
var s8: Float = y[8]
var t0 = s0 + (s6 * 0.5f)
s0 -= s6
var t4 = (s4 + s2) * 0.9396926f
var t2 = (s8 + s2) * 0.76604444f
s6 = (s4 - s8) * 0.17364818f
s4 += (s8 - s2)
s2 = s0 - (s4 * 0.5f)
y[4] = s4 + s0
s8 = (t0 - t2) + s6
s0 = (t0 - t4) + t2
s4 = (t0 + t4) - s6
var s1: Float = y[1]
var s3: Float = y[3]
var s5: Float = y[5]
var s7: Float = y[7]
s3 *= 0.8660254f
t0 = (s5 + s1) * 0.9848077f
t4 = (s5 - s7) * 0.34202015f
t2 = (s1 + s7) * 0.64278764f
s1 = ((s1 - s5) - s7) * 0.8660254f
s5 = (t0 - s3) - t2
s7 = (t4 - s3) - t0
s3 = (t4 + s3) - t2
y[0] = s4 - s7
y[1] = s2 + s1
y[2] = s0 - s3
y[3] = s8 + s5
y[5] = s8 - s5
y[6] = s0 + s3
y[7] = s2 - s1
y[8] = s4 + s7
}
private val co = FloatArray(9)
private val si = FloatArray(9)
fun L3_imdct36(grbuf: FloatArrayPtr, overlap: FloatArrayPtr, window: FloatArray, nbands: Int) {
var grbuf: FloatArrayPtr = grbuf // Mutating parameter
var overlap: FloatArrayPtr = overlap // Mutating parameter
val g_twid9 = __STATIC_L3_imdct36_g_twid9
for (j in 0 until nbands) {
val co = this.co
val si = this.si
co[0] = -grbuf[0]
si[0] = grbuf[17]
for (i in 0 until 4) {
si[8 - (2 * i)] = grbuf[(4 * i) + 1] - grbuf[(4 * i) + 2]
co[1 + (2 * i)] = grbuf[(4 * i) + 1] + grbuf[(4 * i) + 2]
si[7 - (2 * i)] = grbuf[(4 * i) + 4] - grbuf[(4 * i) + 3]
co[2 + (2 * i)] = -(grbuf[(4 * i) + 3] + grbuf[(4 * i) + 4])
}
L3_dct3_9(co)
L3_dct3_9(si)
si[1] = -si[1]
si[3] = -si[3]
si[5] = -si[5]
si[7] = -si[7]
for (i in 0 until 9) {
val ovl: Float = overlap[i]
val sum: Float = (co[i] * g_twid9[9 + i]) + (si[i] * g_twid9[0 + i])
overlap[i] = (co[i] * g_twid9[0 + i]) - (si[i] * g_twid9[9 + i])
grbuf[i] = (ovl * window[0 + i]) - (sum * window[9 + i])
grbuf[17 - i] = (ovl * window[9 + i]) + (sum * window[0 + i])
}
grbuf += 18
overlap += 9
}
}
fun L3_idct3(x0: Float, x1: Float, x2: Float, dst: FloatArray) {
val m1: Float = x1 * 0.8660254f
val a1: Float = x0 - (x2 * 0.5f)
dst[1] = x0 + x2
dst[0] = a1 + m1
dst[2] = a1 - m1
}
private val temp1F3 = FloatArray(4)
private val temp2F3 = FloatArray(4)
fun L3_imdct12(x: FloatArrayPtr, dst: FloatArrayPtr, overlap: FloatArrayPtr) {
val g_twid3: FloatArray = __STATIC_L3_imdct12_g_twid3
val co = temp1F3
val si = temp2F3
L3_idct3((-x[0]), (x[6] + x[3]), (x[12] + x[9]), co)
L3_idct3(x[15], (x[12] - x[9]), (x[6] - x[3]), si)
si[1] = -si[1]
for (i in 0 until 3) {
val ovl: Float = overlap[i]
val sum: Float = (co[i] * g_twid3[3 + i]) + (si[i] * g_twid3[0 + i])
overlap[i] = (co[i] * g_twid3[0 + i]) - (si[i] * g_twid3[3 + i])
dst[i] = (ovl * g_twid3[2 - i]) - (sum * g_twid3[5 - i])
dst[5 - i] = (ovl * g_twid3[5 - i]) + (sum * g_twid3[2 - i])
}
}
fun L3_imdct_short(grbuf: FloatArrayPtr, overlap: FloatArrayPtr, nbands: Int) {
var grbuf: FloatArrayPtr = grbuf // Mutating parameter
var overlap: FloatArrayPtr = overlap // Mutating parameter
var nbands: Int = nbands // Mutating parameter
while (nbands > 0) {
val tmp = FloatArrayPtr(FloatArray(18))
memcpy(tmp, grbuf, 72 / 4)
memcpy(grbuf, overlap, 6)
L3_imdct12(tmp, grbuf + 6, overlap + 6)
L3_imdct12(tmp + 1, grbuf + 12, overlap + 6)
L3_imdct12(tmp + 2, overlap, overlap + 6)
nbands--
overlap += 9
grbuf += 18
}
}
fun L3_change_sign(grbuf: FloatArrayPtr) {
var p = 18
for (b in 0 until 32 step 2) {
for (i in 1 until 18 step 2) {
val index = p + i
grbuf[index] = -grbuf[index]
}
p += 36
}
}
fun L3_imdct_gr(grbuf: FloatArrayPtr, overlap: FloatArrayPtr, block_type: Int, n_long_bands: Int) {
var grbuf: FloatArrayPtr = grbuf // Mutating parameter
var overlap: FloatArrayPtr = (overlap) // Mutating parameter
val g_mdct_window: Array = __STATIC_L3_imdct_gr_g_mdct_window
if (n_long_bands != 0) {
L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands)
grbuf += 18 * n_long_bands
overlap += 9 * n_long_bands
}
if (block_type == 2) {
L3_imdct_short(grbuf, overlap, 32 - n_long_bands)
} else {
L3_imdct36(grbuf, overlap, g_mdct_window[(block_type == 3).toInt()], 32 - n_long_bands)
}
}
fun L3_save_reservoir(h: Mp3Dec, s: Mp3Scratch) {
var pos: Int = (s.bs.pos + 7) / 8
var remains: Int = (s.bs.limit / 8) - pos
if (remains > MAX_BITRESERVOIR_BYTES) {
pos += (remains - MAX_BITRESERVOIR_BYTES)
remains = MAX_BITRESERVOIR_BYTES
}
if (remains > 0) {
memcpy(UByteArrayIntPtr(h.reserv_buf), s.maindata + pos, remains)
}
h.reserv = remains
}
fun L3_restore_reservoir(h: Mp3Dec, bs: Bs, s: Mp3Scratch, main_data_begin: Int): Int {
val frame_bytes: Int = (bs.limit - bs.pos) / 8
val bytes_have: Int = if (h.reserv > main_data_begin) main_data_begin else h.reserv
memcpy(
s.maindata,
UByteArrayIntPtr(h.reserv_buf) + if (0 < (h.reserv - main_data_begin)) (h.reserv - main_data_begin) else 0,
if (h.reserv > main_data_begin) main_data_begin else h.reserv
)
memcpy(s.maindata + bytes_have, bs.buf + (bs.pos / 8), frame_bytes)
bs_init(s.bs, s.maindata, (bytes_have + frame_bytes))
return ((h.reserv >= main_data_begin)).toInt()
}
fun L3_decode(h: Mp3Dec, s: Mp3Scratch, gr_info: ArrayPtr, nch: Int) {
var gr_info: ArrayPtr = gr_info // Mutating parameter
for (ch in 0 until nch) {
val layer3gr_limit: Int = s.bs.pos + (gr_info[ch].part_23_length)
L3_decode_scalefactors(((h.header)), s.ist_pos[ch], s.bs, (gr_info + ch), ((s.scf)), ch)
L3_huffman(s.grbuf[ch], s.bs, gr_info + ch, ((s.scf)), layer3gr_limit)
}
when {
h.header[3] and 16 != 0 -> L3_intensity_stereo(s.grbuf[0], (s.ist_pos[1]), gr_info, ((h.header)))
h.header[3] and 224 == 96 -> L3_midside_stereo(s.grbuf[0], 576)
}
for (ch in 0 until nch) {
var aa_bands = 31
val n_long_bands: Int =
(if (gr_info.value.mixed_block_flag != 0) 2 else 0) shl ((h.header[2] shr 2 and 3) + ((h.header[1] shr 3 and 1) + (h.header[1] shr 4 and 1)) * 3 == 2).toInt()
if (gr_info.value.n_short_sfb != 0) {
aa_bands = n_long_bands - 1
L3_reorder(s.grbuf[ch] + n_long_bands * 18, s.syn[0], gr_info.value.sfbtab + gr_info.value.n_long_sfb)
}
L3_antialias(s.grbuf[ch], aa_bands)
L3_imdct_gr(s.grbuf[ch], FloatArrayPtr(h.mdct_overlap[ch]), gr_info.value.block_type, n_long_bands)
L3_change_sign(s.grbuf[ch])
gr_info += 1
}
}
fun mp3d_DCT_II(grbuf: FloatArrayPtr, n: Int) {
val g_sec: FloatArray = __STATIC_mp3d_DCT_II_g_sec
val t = Array(4) { FloatArray(8) }
for (k in 0 until n) {
var y: FloatArrayPtr = grbuf + k
for (i in 0 until 8) {
val x0: Float = y[i * 18]
val x1: Float = y[(15 - i) * 18]
val x2: Float = y[(16 + i) * 18]
val x3: Float = y[(31 - i) * 18]
val t0: Float = x0 + x3
val t1: Float = x1 + x2
val t2: Float = (x1 - x2) * g_sec[(3 * i) + 0]
val t3: Float = (x0 - x3) * g_sec[(3 * i) + 1]
t[0][i] = t0 + t1
t[1][i] = (t0 - t1) * g_sec[(3 * i) + 2]
t[2][i] = t3 + t2
t[3][i] = (t3 - t2) * g_sec[(3 * i) + 2]
}
for (i in 0 until 4) {
val x = t[i]
var x0: Float = x[0]
var x1: Float = x[1]
var x2: Float = x[2]
var x3: Float = x[3]
var x4: Float = x[4]
var x5: Float = x[5]
var x6: Float = x[6]
var x7: Float = x[7]
var xt: Float = x0 - x7
x0 += x7
x7 = x1 - x6
x1 += x6
x6 = x2 - x5
x2 += x5
x5 = x3 - x4
x3 += x4
x4 = x0 - x3
x0 += x3
x3 = x1 - x2
x1 += x2
x[0] = x0 + x1
x[4] = (x0 - x1) * 0.70710677f
x5 += x6
x6 = (x6 + x7) * 0.70710677f
x7 += xt
x3 = (x3 + x4) * 0.70710677f
x5 -= (x7 * 0.19891237f)
x7 += (x5 * 0.38268343f)
x5 -= (x7 * 0.19891237f)
x0 = xt - x6
xt += x6
x[1] = (xt + x7) * 0.5097956f
x[2] = (x4 + x3) * 0.5411961f
x[3] = (x0 - x5) * 0.6013449f
x[5] = (x0 + x5) * 0.8999762f
x[6] = (x4 - x3) * 1.306563f
x[7] = (xt - x7) * 2.5629156f
}
for (i in 0 until 7) {
y[0 * 18] = t[0][i]
y[1 * 18] = (t[2][i] + t[3][i]) + t[3][i + 1]
y[2 * 18] = t[1][i] + t[1][i + 1]
y[3 * 18] = (t[2][i + 1] + t[3][i]) + t[3][i + 1]
y += 4 * 18
}
y[0 * 18] = t[0][7]
y[1 * 18] = t[2][7] + t[3][7]
y[2 * 18] = t[1][7]
y[3 * 18] = t[3][7]
}
}
fun mp3d_scale_pcm(sample: Float): Short {
if (sample >= 32766.5f) return 32767
if (sample <= -32767.5f) return -32768
val s: Short = (sample + 0.5f).toInt().toShort()
return (s.toInt() - (s < 0).toInt()).toShort()
}
fun mp3d_synth_pair(pcm: ShortArrayPtr, nch: Int, z: FloatArrayPtr) {
var z: FloatArrayPtr = z // Mutating parameter
var a = 0f
a += (z[14 * 64] - z[0]) * 29f
a += ((z[1 * 64] + z[13 * 64]) * 213f)
a += ((z[12 * 64] - z[2 * 64]) * 459f)
a += ((z[3 * 64] + z[11 * 64]) * 2037f)
a += ((z[10 * 64] - z[4 * 64]) * 5153f)
a += ((z[5 * 64] + z[9 * 64]) * 6574f)
a += ((z[8 * 64] - z[6 * 64]) * 37489f)
a += (z[7 * 64] * 75038f)
pcm[0] = mp3d_scale_pcm(a)
z += 2
a = z[14 * 64] * 104f
a += (z[12 * 64] * 1567f)
a += (z[10 * 64] * 9727f)
a += (z[8 * 64] * 64019f)
a += (z[6 * 64] * -9975f)
a += (z[4 * 64] * -45f)
a += (z[2 * 64] * 146f)
a += (z[0 * 64] * -5f)
pcm[16 * nch] = mp3d_scale_pcm(a)
}
fun mp3d_synth(xl: FloatArrayPtr, dstl: ShortArrayPtr, nch: Int, lins: FloatArrayPtr) {
val xr: FloatArrayPtr = xl + ((576 * (nch - 1)))
val dstr: ShortArrayPtr = dstl + ((nch - 1))
val g_win: FloatArray = __STATIC_mp3d_synth_g_win
val zlin: FloatArrayPtr = lins + ((15 * 64))
var w = 0
zlin[4 * 15] = xl[18 * 16]
zlin[(4 * 15) + 1] = xr[18 * 16]
zlin[(4 * 15) + 2] = xl[0]
zlin[(4 * 15) + 3] = xr[0]
zlin[4 * 31] = xl[1 + (18 * 16)]
zlin[(4 * 31) + 1] = xr[1 + (18 * 16)]
zlin[(4 * 31) + 2] = xl[1]
zlin[(4 * 31) + 3] = xr[1]
mp3d_synth_pair(dstr, nch, ((lins + ((4 * 15))) + 1))
mp3d_synth_pair((dstr + ((32 * nch))), nch, (((lins + ((4 * 15))) + 64) + 1))
mp3d_synth_pair(dstl, nch, (lins + ((4 * 15))))
mp3d_synth_pair((dstl + ((32 * nch))), nch, ((lins + ((4 * 15))) + 64))
for (i in 14 downTo 0) {
val a = temp1F3
val b = temp2F3
zlin[4 * i] = xl[18 * (31 - i)]
zlin[(4 * i) + 1] = xr[18 * (31 - i)]
zlin[(4 * i) + 2] = xl[1 + (18 * (31 - i))]
zlin[(4 * i) + 3] = xr[1 + (18 * (31 - i))]
zlin[4 * (i + 16)] = xl[1 + (18 * (1 + i))]
zlin[(4 * (i + 16)) + 1] = xr[1 + (18 * (1 + i))]
zlin[(4 * (i - 16)) + 2] = xl[18 * (1 + i)]
zlin[(4 * (i - 16)) + 3] = xr[18 * (1 + i)]
for (j in 0 until 4) {
b[j] = 0f
a[j] = 0f
}
for (n in 0 until 8) {
val w0: Float = g_win[w++]
val w1: Float = g_win[w++]
val vz: FloatArrayPtr = zlin + ((4 * i) - (n * 64))
val vy: FloatArrayPtr = zlin + ((4 * i) - ((15 - n) * 64))
if (n % 2 == 0) {
for (j in 0 until 4) {
b[j] = b[j] + (vz[j] * w1) + (vy[j] * w0)
a[j] = a[j] + (vz[j] * w0) - (vy[j] * w1)
}
} else {
for (j in 0 until 4) {
b[j] = b[j] + ((vz[j] * w1) + (vy[j] * w0))
a[j] = a[j] + ((vy[j] * w1) - (vz[j] * w0))
}
}
}
dstr[(15 - i) * nch] = mp3d_scale_pcm(a[1])
dstr[(17 + i) * nch] = mp3d_scale_pcm(b[1])
dstl[(15 - i) * nch] = mp3d_scale_pcm(a[0])
dstl[(17 + i) * nch] = mp3d_scale_pcm(b[0])
dstr[(47 - i) * nch] = mp3d_scale_pcm(a[3])
dstr[(49 + i) * nch] = mp3d_scale_pcm(b[3])
dstl[(47 - i) * nch] = mp3d_scale_pcm(a[2])
dstl[(49 + i) * nch] = mp3d_scale_pcm(b[2])
}
}
fun mp3d_synth_granule(qmf_state: FloatArrayPtr, grbuf: FloatArrayPtr, nbands: Int, nch: Int, pcm: ShortArrayPtr, lins: FloatArrayPtr) {
var i: Int = 0
i = 0
while (i < nch) {
mp3d_DCT_II((grbuf + ((576 * i))), nbands)
i++
}
memcpy(lins, qmf_state, 15 * 64)
i = 0
while (i < nbands) {
mp3d_synth((grbuf + i), (pcm + ((32 * (nch * i)))), nch, (lins + ((i * 64))))
i += 2
}
if (nch == 1) {
i = 0
while (i < (15 * 64)) {
qmf_state[i] = lins[(nbands * 64) + i]
i += 2
}
} else {
memcpy(qmf_state, lins + nbands * 64, 15 * 64)
}
}
fun mp3d_match_frame(hdr: UByteArrayIntPtr, mp3_bytes: Int, frame_bytes: Int): Int {
var i: Int = 0
for (nmatch in 0 until 10) {
i += hdr_frame_bytes(hdr + i, frame_bytes) + hdr_padding((hdr + i))
if ((i + 4) > mp3_bytes) return (nmatch > 0).toInt()
if (hdr_compare(hdr, (hdr + i)) == 0) return 0
}
return 1
}
fun mp3d_find_frame(mp3: UByteArrayIntPtr, mp3_bytes: Int, free_format_bytes: IntArray, ptr_frame_bytes: IntArray): Int {
var mp3: UByteArrayIntPtr = mp3 // Mutating parameter
var i: Int = 0
var k: Int = 0
i = 0
while (i < mp3_bytes - 4) {
if (hdr_valid(mp3)) {
var frame_bytes: Int = hdr_frame_bytes(mp3, free_format_bytes[0])
var frame_and_padding: Int = frame_bytes + hdr_padding(mp3)
k = 4
while (((frame_bytes == 0) && (k < 2304)) && (((i + (2 * (((k < (mp3_bytes - 4))).toInt())))) != 0)) {
if (hdr_compare(mp3, (mp3 + k)) != 0) {
val fb: Int = k - hdr_padding(mp3)
val nextfb: Int = fb + hdr_padding((mp3 + k))
if (((((i + k) + nextfb) + 4) > mp3_bytes) || (hdr_compare(mp3, ((mp3 + k) + nextfb)) == 0)) {
k += 1
continue
}
frame_and_padding = k
frame_bytes = fb
free_format_bytes[0] = fb
}
k++
}
if ((((frame_bytes != 0) && (((i + (((frame_and_padding <= mp3_bytes)).toInt()))) != 0)) && (mp3d_match_frame(
mp3,
(mp3_bytes - i),
frame_bytes
) != 0)) || ((i == 0) && (frame_and_padding == mp3_bytes))
) {
ptr_frame_bytes[0] = frame_and_padding
return i
}
free_format_bytes[0] = 0
}
i++
mp3 += 1
}
ptr_frame_bytes[0] = 0
return mp3_bytes
}
fun mp3dec_init(dec: Mp3Dec) {
dec.header[0] = 0
}
private val scratch = Mp3Scratch()
private val bs_frame = Bs()
fun mp3dec_decode_frame(dec: Mp3Dec, mp3: UByteArrayIntPtr, mp3_bytes: Int, pcm: ShortArrayPtr, info: Mp3FrameInfo): Int {
var pcm: ShortArrayPtr = pcm // Mutating parameter
var i = 0
val frame_size = IntArray(1)
var success = 1
val bs_frame = this.bs_frame
val scratch = this.scratch
if (mp3_bytes > 4 && ((dec.header[0]) == 255) && (hdr_compare(((UByteArrayIntPtr(dec.header))), mp3) != 0)) {
frame_size[0] = hdr_frame_bytes(mp3, dec.free_format_bytes_array[0]) + hdr_padding(mp3)
if (frame_size[0] != mp3_bytes && (((frame_size[0] + 4) > mp3_bytes) || (hdr_compare(mp3, (mp3 + frame_size[0])) == 0))) {
frame_size[0] = 0
}
}
if (frame_size[0] == 0) {
dec.reserv = 0
dec.free_format_bytes_array[0] = 0
dec.reserv_buf.fill(0)
dec.header.fill(0)
dec.qmf_state.fill(0f)
dec.mdct_overlap[0].fill(0f)
dec.mdct_overlap[1].fill(0f)
i = mp3d_find_frame(mp3, mp3_bytes, dec.free_format_bytes_array, frame_size)
if ((frame_size[0] == 0) || (((i + (((frame_size[0] > mp3_bytes)).toInt()))) != 0)) {
info.value.frame_bytes = i
return 0
}
}
val hdr = mp3 + i
memcpy(UByteArrayIntPtr(dec.header), hdr, 4)
info.value.frame_bytes = i + frame_size[0]
info.value.frame_offset = i
info.value.channels = if (hdr[3] and 192 == 192) 1 else 2
info.value.hz = hdr_sample_rate_hz(hdr)
info.value.layer = 4 - (hdr[1] shr 1 and 3)
info.value.bitrate_kbps = hdr_bitrate_kbps(hdr)
if (pcm.array.isEmpty()) {
return hdr_frame_samples(hdr)
}
bs_init(bs_frame, hdr + 4, frame_size[0] - 4)
if (hdr[1] and 1 == 0) {
get_bits(bs_frame, 16)
}
if (info.value.layer == 3) {
val main_data_begin: Int = L3_read_side_info(bs_frame, scratch.gr_info, hdr)
if (main_data_begin < 0 || bs_frame.pos > bs_frame.limit) {
mp3dec_init(dec)
return 0
}
success = L3_restore_reservoir(dec, bs_frame, scratch, main_data_begin)
if (success != 0) {
var igr = 0
while (igr < if (hdr[1] and 8 != 0) 2 else 1) {
scratch.grbuf[0].fill(0f, 0, 576 * 2)
L3_decode(dec, scratch, scratch.gr_info + igr * info.value.channels, info.value.channels)
mp3d_synth_granule(FloatArrayPtr(dec.qmf_state), scratch.grbuf[0], 18, info.value.channels, pcm, scratch.syn[0])
igr++
pcm += 576 * info.value.channels
}
}
L3_save_reservoir(dec, scratch)
} else {
val sci = ScaleInfo()
L12_read_scale_info(hdr, bs_frame, sci)
scratch.grbuf[0].fill(0f, 0, 576 * 2)
i = 0
var igr = 0
while (igr < 3) {
i += L12_dequantize_granule(
scratch.grbuf[0] + i,
(bs_frame),
(sci),
info.value.layer or 1
)
if (12 == i) {
i = 0
L12_apply_scf_384(sci, FloatArrayPtr(sci.scf) + igr, scratch.grbuf[0])
mp3d_synth_granule(FloatArrayPtr(dec.qmf_state), scratch.grbuf[0], 12, info.value.channels, pcm, scratch.syn[0])
scratch.grbuf[0].fill(0f, 0, 576 * 2)
pcm += 384 * info.value.channels
}
if (bs_frame.pos > bs_frame.limit) {
mp3dec_init(dec)
return 0
}
igr++
}
}
return success * (hdr_frame_samples(UByteArrayIntPtr(dec.header)))
}
}