first commit 26/07/2025
This commit is contained in:
21
src/audio/AudioFileInfo.kt
Normal file
21
src/audio/AudioFileInfo.kt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package audio
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for storing audio file information.
|
||||||
|
*/
|
||||||
|
class AudioFileInfo {
|
||||||
|
var fileName : String = ""
|
||||||
|
var fileSize : Long = 0L
|
||||||
|
var duration : Double = 0.0
|
||||||
|
var bytes : ByteArray = ByteArray(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the audio file information is valid.
|
||||||
|
* A valid audio file must have a non-blank file name, a positive file size,
|
||||||
|
* a positive duration, and non-empty byte array.
|
||||||
|
* @return True if the audio file information is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
fun isValid() : Boolean {
|
||||||
|
return fileName.isNotBlank() && fileSize > 0 && duration > 0.0 && bytes.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,18 @@
|
|||||||
package audio
|
package audio
|
||||||
|
|
||||||
import audio.Bass.BASS_ERROR_ALREADY
|
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 codes.Somecodes.Companion.ValidFile
|
||||||
|
import com.sun.jna.Memory
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
class AudioPlayer {
|
class AudioPlayer {
|
||||||
var bass : Bass = Bass.Instance
|
var bass: Bass = Bass.Instance
|
||||||
var initedDevice : Int = -1
|
var initedDevice = -1
|
||||||
init {
|
init {
|
||||||
Logger.info("Audio version ${Integer.toHexString(bass.BASS_GetVersion())}" as Any)
|
Logger.info("Audio version ${Integer.toHexString(bass.BASS_GetVersion())}" as Any)
|
||||||
InitAudio(0) // Audio 0 is No Sound, use for reading and writing wav silently
|
InitAudio(0) // Audio 0 is No Sound, use for reading and writing wav silently
|
||||||
@@ -19,6 +26,22 @@ class AudioPlayer {
|
|||||||
*/
|
*/
|
||||||
fun InitAudio(id : Int) : Boolean {
|
fun InitAudio(id : Int) : Boolean {
|
||||||
|
|
||||||
|
val bdi = Bass.BASS_DEVICEINFO()
|
||||||
|
if (bass.BASS_GetDeviceInfo(id, bdi)){
|
||||||
|
Logger.info { "Audio ID=$id: ${bdi.name} (${bdi.driver})" }
|
||||||
|
if (bdi.flags and BASS_DEVICE_ENABLED == 0) {
|
||||||
|
Logger.error { "Audio ID=$id is not enabled, cannot initialize" }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (bdi.flags and BASS_DEVICE_INIT > 0){
|
||||||
|
Logger.info { "Audio ID=$id is already initialized" }
|
||||||
|
if (id > 0) {
|
||||||
|
initedDevice = id
|
||||||
|
Logger.info { "Real Audio Device reused ID=$initedDevice" }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bass.BASS_Init(id, 48000, 0)){
|
if (bass.BASS_Init(id, 48000, 0)){
|
||||||
Logger.info { "Audio ID=$id inited succesfully" }
|
Logger.info { "Audio ID=$id inited succesfully" }
|
||||||
@@ -28,19 +51,8 @@ class AudioPlayer {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
val err = bass.BASS_ErrorGetCode()
|
Logger.error { "Audio ID=$id initialization failed: ${bass.BASS_ErrorGetCode()}" }
|
||||||
if (err == BASS_ERROR_ALREADY) {
|
return false
|
||||||
Logger.info {"Audio ID=$id already initialized, reusing existing instance"}
|
|
||||||
if (id > 0) {
|
|
||||||
initedDevice = id
|
|
||||||
Logger.info { "Real Audio Device reused ID=$initedDevice" }
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
Logger.error { "Audio ID=$id initialization failed: ${bass.BASS_ErrorGetCode()}" }
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,4 +70,45 @@ class AudioPlayer {
|
|||||||
initedDevice = -1
|
initedDevice = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an audio file and retrieves its information.
|
||||||
|
* Check for isValid() method in AudioFileInfo class to verify the loaded file.
|
||||||
|
* @param fileName The name of the audio file to load.
|
||||||
|
* @return An AudioFileInfo object containing the file information.
|
||||||
|
*/
|
||||||
|
fun LoadAudioFile(fileName: String) : AudioFileInfo {
|
||||||
|
val result = AudioFileInfo()
|
||||||
|
if (ValidFile(fileName)){
|
||||||
|
result.fileName = fileName
|
||||||
|
bass.BASS_SetDevice(0) // Set to No Sound device for reading
|
||||||
|
val handle = bass.BASS_StreamCreateFile(false, fileName, 0L, 0L, BASS_STREAM_DECODE or BASS_SAMPLE_MONO)
|
||||||
|
if (handle!=0){
|
||||||
|
// successfully opened the file
|
||||||
|
// read file size
|
||||||
|
val size = bass.BASS_ChannelGetLength(handle, BASS_POS_BYTE)
|
||||||
|
if (size > 0) {
|
||||||
|
result.fileSize = size
|
||||||
|
}
|
||||||
|
// read file duration
|
||||||
|
val duration = bass.BASS_ChannelBytes2Seconds(handle, size)
|
||||||
|
if (duration > 0) {
|
||||||
|
result.duration = duration
|
||||||
|
}
|
||||||
|
// read file bytes
|
||||||
|
val mem = Memory(size)
|
||||||
|
val bytesRead = bass.BASS_ChannelGetData(handle, mem, size.toInt())
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
result.bytes = mem.getByteArray(0, bytesRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the handle
|
||||||
|
bass.BASS_StreamFree(handle)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package codes
|
package codes
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class Somecodes {
|
class Somecodes {
|
||||||
@@ -7,6 +10,13 @@ class Somecodes {
|
|||||||
fun ValidString(value: Any) : Boolean {
|
fun ValidString(value: Any) : Boolean {
|
||||||
return value is String && value.isNotBlank()
|
return value is String && value.isNotBlank()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ValidFile(value : String) : Boolean {
|
||||||
|
if (value.isNotBlank()){
|
||||||
|
return Files.exists(Path.of(value))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user