commit 07/10/2025

This commit is contained in:
2025-10-07 09:28:48 +07:00
parent a8e5b027ef
commit 748301a5cb
5 changed files with 114 additions and 103 deletions

View File

@@ -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()}" }
}

View File

@@ -553,11 +553,16 @@ 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) })
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 }
@@ -573,6 +578,15 @@ class MainExtension01 {
"Cancelled paging message with index ${qp.index} due to invalid audio file"
)
}
} 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"
)
}
} else if (qp.Source == "SHALAT") {
val ann_id = Get_ANN_ID(qp.Message)
if (ann_id > 0) {
@@ -587,11 +601,19 @@ class MainExtension01 {
listfile ->
val listafi = mutableListOf<AudioFileInfo>()
listfile.forEach { filenya ->
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(
"Shalat",
@@ -728,11 +750,18 @@ class MainExtension01 {
Get_Soundbank_Files(mb, variables ?: emptyMap(), {
listfile ->
listfile.forEach { filenya ->
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)
}
}
}
},
{
err ->
@@ -794,11 +823,18 @@ class MainExtension01 {
listfile ->
val listafi = mutableListOf<AudioFileInfo>()
listfile.forEach { filenya ->
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,
) { success, message ->

View File

@@ -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
View 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)
}
}

View File

@@ -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
}
}