Commit 31/07/2025
This commit is contained in:
@@ -5,6 +5,7 @@ import zello.ZelloEvent
|
||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
||||
fun main() {
|
||||
|
||||
val z = ZelloClient.fromConsumerZello()
|
||||
z.Start(object : ZelloEvent {
|
||||
override fun onChannelStatus(
|
||||
|
||||
@@ -1,10 +1,35 @@
|
||||
package somecodes
|
||||
|
||||
@Suppress("unused")
|
||||
class Codes {
|
||||
|
||||
companion object{
|
||||
fun ValidString(s : String?) : Boolean {
|
||||
return s != null && s.isNotEmpty() && s.isNotBlank()
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec header for Zello audio packet is base64 encoded string from {samplingrate (16 Little Endian), frames_per_packet, frame_size_ms}
|
||||
* @param samplingrate Sampling rate in Hz (e.g., 8000, 16000, 32000, etc.)
|
||||
* @param frames_per_packet Number of frames per packet (usually 1 or 2)
|
||||
* @param frame_size_ms Size of each frame in milliseconds (e.g., 20, 30, 40, etc.)
|
||||
*/
|
||||
fun toCodecHeader(samplingrate: Int, frames_per_packet: Byte, frame_size_ms: Byte) : String{
|
||||
val xx = ByteArray(4)
|
||||
xx[0] = (samplingrate and 0xFF).toByte() // Little Endian
|
||||
xx[1] = ((samplingrate shr 8) and 0xFF).toByte()
|
||||
xx[2] = frames_per_packet
|
||||
xx[3] = frame_size_ms
|
||||
return java.util.Base64.getEncoder().encodeToString(xx)
|
||||
}
|
||||
|
||||
fun fromCodecHeader(header: String) : Triple<Int, Byte, Byte>? {
|
||||
val decoded = java.util.Base64.getDecoder().decode(header)
|
||||
if (decoded.size != 4) return null
|
||||
val samplingrate = (decoded[0].toInt() and 0xFF) or ((decoded[1].toInt() and 0xFF) shl 8)
|
||||
val frames_per_packet = decoded[2]
|
||||
val frame_size_ms = decoded[3]
|
||||
return Triple(samplingrate, frames_per_packet, frame_size_ms)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package zello
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder
|
||||
import somecodes.Codes.Companion.ValidString
|
||||
import somecodes.Codes.Companion.fromCodecHeader
|
||||
|
||||
@Suppress("unused")
|
||||
@JsonPropertyOrder(value = ["command", "type", "codec", "codec_header", "packet_duration", "stream_id", "channel", "from", "for"])
|
||||
@@ -14,4 +16,46 @@ class Event_OnStreamStart {
|
||||
var channel: String=""
|
||||
var from: String = "" // the user who started the stream
|
||||
var For: String = "" // the user who is receiving the stream, should be "for" not "For"
|
||||
|
||||
/**
|
||||
* Get Sampling Rate from codec_header.
|
||||
* @return sampling rate in Hz, or 0 if codec_header is not valid.
|
||||
*/
|
||||
fun getSamplingRate() : Int{
|
||||
if (ValidString(codec_header)){
|
||||
val triple = fromCodecHeader(codec_header)
|
||||
if (triple!=null){
|
||||
return triple.first
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of frames per packet, either 1 or 2
|
||||
* @return number of frames per packet, or 0 if codec_header is not valid.
|
||||
*/
|
||||
fun getFramesPerSecond() : Byte{
|
||||
if (ValidString(codec_header)){
|
||||
val triple = fromCodecHeader(codec_header)
|
||||
if (triple!=null){
|
||||
return triple.second
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get audio frame size in miliseconds
|
||||
* @return audio frame size in milliseconds, or 0 if codec_header is not valid.
|
||||
*/
|
||||
fun getFrameSizePerMs() : Byte{
|
||||
if (ValidString(codec_header)){
|
||||
val triple = fromCodecHeader(codec_header)
|
||||
if (triple!=null){
|
||||
return triple.third
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user