commit 07/10/2025
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import audio.AudioFileInfo
|
||||
import audio.AudioPlayer
|
||||
import audio.ContentCache
|
||||
import audio.UDPReceiver
|
||||
import barix.BarixConnection
|
||||
import barix.TCP_Barix_Command_Server
|
||||
@@ -43,11 +43,8 @@ val urutan_bahasa = listOf(
|
||||
Language.ARABIC.name
|
||||
)
|
||||
|
||||
/**
|
||||
* Common audio files, seperti chimeup, chimedown, silence1s, silencehalf
|
||||
*/
|
||||
val commonAudio : MutableMap<String, AudioFileInfo> = HashMap()
|
||||
|
||||
val contentCache = ContentCache()
|
||||
/**
|
||||
* Create necessary folders if not exist
|
||||
*/
|
||||
@@ -75,7 +72,7 @@ fun files_preparation(){
|
||||
if (afi.isValid()){
|
||||
Logger.info { "Common audio $it loaded from ${pp.toAbsolutePath()}" }
|
||||
val key = it.substring(0, it.length - 4) // buang .wav
|
||||
commonAudio[key] = afi
|
||||
contentCache.addAudioFile(key, afi)
|
||||
} else {
|
||||
Logger.error { "Failed to load common audio $it from ${pp.toAbsolutePath()}" }
|
||||
}
|
||||
|
||||
@@ -553,18 +553,32 @@ class MainExtension01 {
|
||||
if (qp.Source == "PAGING") {
|
||||
// nama file ada di Message
|
||||
if (ValidFile(qp.Message)) {
|
||||
// file ketemu di path
|
||||
val afi = audioPlayer.LoadAudioFile(qp.Message)
|
||||
zz.forEach { z1 ->
|
||||
StreamerOutputs.values.find { it.channel == z1 }
|
||||
?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) })
|
||||
}
|
||||
val logmessage =
|
||||
"Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
|
||||
Logger.info { logmessage }
|
||||
db.Add_Log("AAS", logmessage)
|
||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||
if (afi.isValid()){
|
||||
// file bisa di load, kirim ke masing masing Streamer Output by IP address
|
||||
ips.forEach {
|
||||
ip ->
|
||||
val br = StreamerOutputs[ip]
|
||||
br?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) })
|
||||
}
|
||||
|
||||
val logmessage =
|
||||
"Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
|
||||
Logger.info { logmessage }
|
||||
db.Add_Log("AAS", logmessage)
|
||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||
|
||||
return
|
||||
} else {
|
||||
// file tidak valid, delete from queue paging
|
||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||
db.Add_Log(
|
||||
"AAS",
|
||||
"Cancelled paging message with index ${qp.index} due to invalid audio file"
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
} else {
|
||||
// file tidak valid, delete from queue paging
|
||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||
@@ -587,10 +601,18 @@ class MainExtension01 {
|
||||
listfile ->
|
||||
val listafi = mutableListOf<AudioFileInfo>()
|
||||
listfile.forEach { filenya ->
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
val afi = contentCache.getAudioFile(filenya)
|
||||
if (afi!=null && afi.isValid()){
|
||||
listafi.add(afi)
|
||||
} else {
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
listafi.add(afi)
|
||||
contentCache.addAudioFile(filenya, afi)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
val targetfile = SoundbankResult_directory.resolve(
|
||||
Make_WAV_FileName(
|
||||
@@ -728,10 +750,17 @@ class MainExtension01 {
|
||||
Get_Soundbank_Files(mb, variables ?: emptyMap(), {
|
||||
listfile ->
|
||||
listfile.forEach { filenya ->
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
val afi = contentCache.getAudioFile(filenya)
|
||||
if (afi!=null && afi.isValid()){
|
||||
listafi.add(afi)
|
||||
} else {
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
listafi.add(afi)
|
||||
contentCache.addAudioFile(filenya, afi)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -794,10 +823,17 @@ class MainExtension01 {
|
||||
listfile ->
|
||||
val listafi = mutableListOf<AudioFileInfo>()
|
||||
listfile.forEach { filenya ->
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
val afi = contentCache.getAudioFile(filenya)
|
||||
if (afi!=null && afi.isValid()){
|
||||
listafi.add(afi)
|
||||
} else {
|
||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||
if (afi.isValid()) {
|
||||
listafi.add(afi)
|
||||
contentCache.addAudioFile(filenya, afi)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Timer","")).toString()
|
||||
audioPlayer.WavWriter(listafi, targetfile, true,
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
package audio
|
||||
|
||||
import audio.Bass.BASS_ACTIVE_PLAYING
|
||||
import audio.Bass.BASS_DEVICE_ENABLED
|
||||
import audio.Bass.BASS_DEVICE_INIT
|
||||
import audio.Bass.BASS_POS_BYTE
|
||||
import audio.Bass.BASS_STREAM_DECODE
|
||||
import audio.Bass.BASS_SAMPLE_MONO
|
||||
import audio.Bass.STREAMPROC_PUSH
|
||||
import audio.BassEnc.BASS_ENCODE_PCM
|
||||
import codes.Somecodes.Companion.ValidFile
|
||||
import codes.Somecodes.Companion.ValidString
|
||||
import com.sun.jna.Memory
|
||||
import com.sun.jna.Pointer
|
||||
import commonAudio
|
||||
import contentCache
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import org.tinylog.Logger
|
||||
import java.util.function.BiConsumer
|
||||
@@ -162,7 +158,7 @@ class AudioPlayer (var samplingrate: Int) {
|
||||
}
|
||||
|
||||
|
||||
val job = CoroutineScope(Dispatchers.IO).launch(CoroutineName("WavWriter $target")) {
|
||||
CoroutineScope(Dispatchers.IO).launch(CoroutineName("WavWriter $target")) {
|
||||
bass.BASS_SetDevice(0) // Set to No Sound device for writing
|
||||
val streamhandle = bass.BASS_StreamCreate(samplingrate, 1, BASS_STREAM_DECODE, Pointer(-1), null)
|
||||
if (streamhandle==0){
|
||||
@@ -191,7 +187,7 @@ class AudioPlayer (var samplingrate: Int) {
|
||||
|
||||
var allsuccess = true
|
||||
if (withChime){
|
||||
val chup = commonAudio["chimeup"]
|
||||
val chup = contentCache.getAudioFile("chimeup")
|
||||
if (chup!=null && chup.isValid()){
|
||||
if (pushData(chup.bytes)){
|
||||
println("Chime up pushed")
|
||||
@@ -217,7 +213,7 @@ class AudioPlayer (var samplingrate: Int) {
|
||||
|
||||
}
|
||||
if (withChime){
|
||||
val chdn = commonAudio["chimedown"]
|
||||
val chdn = contentCache.getAudioFile("chimedown")
|
||||
if (chdn!=null && chdn.isValid()){
|
||||
if (pushData(chdn.bytes)){
|
||||
println("Chime down pushed")
|
||||
|
||||
55
src/audio/ContentCache.kt
Normal file
55
src/audio/ContentCache.kt
Normal file
@@ -0,0 +1,55 @@
|
||||
package audio
|
||||
|
||||
/**
|
||||
* Cache for audio content to avoid reloading from disk
|
||||
*/
|
||||
@Suppress("unused")
|
||||
class ContentCache {
|
||||
|
||||
private val map: MutableMap<String, AudioFileInfo> = HashMap()
|
||||
|
||||
/**
|
||||
* Clear the cache, but keep essential sounds : chimeup, chimedown, silence1s, silencehalf
|
||||
*/
|
||||
fun clear(){
|
||||
// dont clear chimeup, chimedown, silence1s, silencehalf
|
||||
val keysToKeep = setOf("chimeup", "chimedown", "silence1s", "silencehalf")
|
||||
map.keys.retainAll(keysToKeep)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audio file to the cache
|
||||
* @param key The key to identify the audio file
|
||||
* @param audioFile The AudioFileInfo object
|
||||
*/
|
||||
fun addAudioFile(key: String, audioFile: AudioFileInfo) {
|
||||
map[key] = audioFile
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an audio file from the cache
|
||||
* @param key The key to identify the audio file
|
||||
* @return The AudioFileInfo object, or null if not found
|
||||
*/
|
||||
fun getAudioFile(key: String): AudioFileInfo? {
|
||||
return map[key]
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an audio file from the cache
|
||||
* @param key The key to identify the audio file
|
||||
*/
|
||||
fun removeAudioFile(key: String) {
|
||||
map.remove(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cache contains the specified key
|
||||
* @param key The key to check in the cache
|
||||
* @return True if the key exists, false otherwise
|
||||
*/
|
||||
fun haveKey(key: String): Boolean {
|
||||
return map.containsKey(key)
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package content
|
||||
|
||||
import audio.AudioFileInfo
|
||||
|
||||
/**
|
||||
* Class to manage loaded content in the application.
|
||||
* This class provides methods to retrieve and add soundbank data based on specific criteria.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
class ContentCache {
|
||||
private val contentList = ArrayList<SoundbankData>()
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clears all loaded content from the cache.
|
||||
*/
|
||||
fun Clear(){
|
||||
contentList.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified SoundbankData from the content list.
|
||||
* @param SoundbankData The SoundbankData to be removed.
|
||||
*/
|
||||
fun Remove(SoundbankData: SoundbankData){
|
||||
contentList.remove(SoundbankData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified SoundbankData from the content list based on tag, category, language, and voiceType.
|
||||
* @param tag The tag of the SoundbankData to be removed.
|
||||
* @param category The category of the SoundbankData to be removed.
|
||||
* @param language The language of the SoundbankData to be removed.
|
||||
* @param voiceType The voice type of the SoundbankData to be removed.
|
||||
*/
|
||||
fun Remove(tag: String, category: Category, language: Language, voiceType: VoiceType){
|
||||
val existing = Get(tag, category, language, voiceType)
|
||||
if (existing!=null) contentList.remove(existing)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified SoundbankData from tag, category, language, and voiceType.
|
||||
* @return SoundbankData if found, null otherwise.
|
||||
*/
|
||||
fun Get(tag: String, category: Category, language: Language, voiceType: VoiceType): SoundbankData? {
|
||||
|
||||
return contentList.find {
|
||||
it.TAG == tag &&
|
||||
it.Category == category &&
|
||||
it.Language == language &&
|
||||
it.VoiceType == voiceType &&
|
||||
it.audio.isValid()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new soundbank to the content list if it does not already exist.
|
||||
*
|
||||
* @param tag The unique identifier for the soundbank.
|
||||
* @param category The category of the soundbank.
|
||||
* @param language The language of the soundbank.
|
||||
* @param voiceType The voice type of the soundbank.
|
||||
* @param audio The audio file information for the soundbank.
|
||||
* @return True if the soundbank was added, false if it already exists.
|
||||
*/
|
||||
fun Add(tag: String, category: Category, language: Language, voiceType: VoiceType, audio: AudioFileInfo): Boolean {
|
||||
val existing = Get(tag, category, language, voiceType)
|
||||
if (existing!=null) return false
|
||||
contentList.add(SoundbankData(tag, category, language, voiceType, audio))
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user