app/src/main/kotlin/com/honjimaku/subrep/Pcm.kt (1538 bytes)
1 package com.honjimaku.subrep 2 3 /** Sums and conversions over 16-bit little-endian PCM. */ 4 object Pcm { 5 6 /** The largest sample size in the first [count] bytes of [bytes]: 0 for silence, up to 32768. */ 7 fun peak(bytes: ByteArray, count: Int): Int { 8 var peak = 0 9 var i = 0 10 while (i + 1 < count) { 11 val sample = (bytes[i].toInt() and 0xFF) or (bytes[i + 1].toInt() shl 8) 12 val size = if (sample < 0) -sample else sample 13 if (size > peak) peak = size 14 i += 2 15 } 16 return peak 17 } 18 19 /** 20 * The first [count] bytes of [bytes] as samples from -1 to 1, into [out]. Returns how many 21 * samples were written: half of [count], or the size of [out] when that is less. 22 */ 23 fun toFloat(bytes: ByteArray, count: Int, out: FloatArray): Int { 24 var i = 0 25 var n = 0 26 while (i + 1 < count && n < out.size) { 27 val sample = (bytes[i].toInt() and 0xFF) or (bytes[i + 1].toInt() shl 8) 28 out[n++] = sample / 32768f 29 i += 2 30 } 31 return n 32 } 33 34 /** [samples] from -1 to 1 as 16-bit little-endian PCM: the reverse of [toFloat]. */ 35 fun toBytes(samples: FloatArray): ByteArray { 36 val out = ByteArray(samples.size * 2) 37 for ((n, value) in samples.withIndex()) { 38 val sample = Math.round(value * 32768f).coerceIn(-32768, 32767) 39 out[2 * n] = sample.toByte() 40 out[2 * n + 1] = (sample shr 8).toByte() 41 } 42 return out 43 } 44 }