Files
BirdDeterrentSystem/src/main/java/Audio/AudioPlayer.java
2024-11-13 08:35:32 +07:00

258 lines
8.7 KiB
Java

package Audio;
import lombok.Getter;
import org.tinylog.Logger;
import java.io.File;
public class AudioPlayer {
private final Bass bass;
private int deviceid = -1;
@Getter private boolean inited = false;
int playbackhandle = 0;
float playbackvolume = 1.0f;
public AudioPlayer(){
bass = Bass.Instance;
Logger.info("Bass Version = {}", Integer.toHexString(bass.BASS_GetVersion()));
}
/**
* Unload Bass
*/
public void Unload(){
if (inited){
Logger.info("Freeing Device {}", deviceid);
bass.BASS_SetDevice(deviceid);
bass.BASS_Free();
}
deviceid = -1;
inited = false;
}
/**
* Detect Output Devices
*/
public void DetectOutputDevices(){
Logger.info("Detecting Output Devices...");
int ii = 1;
while (true){
Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
if (bass.BASS_GetDeviceInfo(ii, info)){
Logger.info("Device {} = {}, flags = {}", ii, info.name, Integer.toHexString(info.flags));
ii++;
} else {
break;
}
}
}
/**
* Get BASS_DEVICEINFO for a device
* @param device device id
* @return BASS_DEVICEINFO object or null if failed
*/
public Bass.BASS_DEVICEINFO GetDeviceInfo(int device){
Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
if (bass.BASS_GetDeviceInfo(device, info)){
return info;
}
return null;
}
/**
* Find Device ID with Name
* @param name device name
* @return device id, or -1 if not found
*/
public int FindDeviceIDWithName(String name){
int result = -1;
int ii = 1;
while(true){
Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
if (bass.BASS_GetDeviceInfo(ii, info)){
if (info.name.contains(name)){
result = ii;
break;
}
ii++;
} else {
// gak ada lagi
break;
}
}
return result;
}
/**
* Open Output Device
* @param device device id, starts from 1
* @param freq output frequency
* @return true if success
*/
public boolean OpenDevice(int device, int freq){
int flag = Bass.BASS_DEVICE_REINIT | Bass.BASS_DEVICE_16BITS | Bass.BASS_DEVICE_MONO | Bass.BASS_DEVICE_FREQ;
boolean success = bass.BASS_Init(device, freq, flag);
if (success){
Logger.info("Device {} opened successfully", device);
deviceid = device;
inited = true;
} else {
Logger.error("Failed to open device {}, Error Code {}", device, bass.BASS_ErrorGetCode());
}
return success;
}
/**
* Set Master Output Volume
* Master Output Volume related to the system volume (Alsamixer on Linux, Volume Mixer on Windows)
* @param value volume value, 0-100
*/
public void setMasterVolume(int value){
if (value<0) value = 0;
if (value>100) value = 100;
if (inited){
bass.BASS_SetDevice(deviceid);
if (!bass.BASS_SetVolume(value/100.0f)){
Logger.error("Failed to set Master Volume to {}, Error Code {}", value, bass.BASS_ErrorGetCode());
} else Logger.info("Master Volume set to {}", value);
} else Logger.info("AudioPlayer not initialized");
}
/**
* Get Master Output Volume
* Master Output Volume related to the system volume (Alsamixer on Linux, Volume Mixer on Windows)
* @return 0 - 100, or -1 if failed
*/
@SuppressWarnings("unused")
public int getMasterVolume(){
if (inited){
bass.BASS_SetDevice(deviceid);
float vol = bass.BASS_GetVolume();
if (vol>=0 && vol<=1){
return (int)(vol*100);
}
} else Logger.info("AudioPlayer not initialized");
return -1;
}
/**
* Get Playback Volume
* is the volume of the currently playing audio file
* @return 0 - 100
*/
public int getPlaybackvolume(){
if (playbackvolume<0)
return 0;
else if (playbackvolume>1.0f)
return 100;
else
return (int)(playbackvolume*100);
}
/**
* Set Playback Volume
* is the volume of the currently playing audio file
* @param value 0 - 100
*/
public void setPlaybackvolume(int value){
if (value<0) value = 0;
if (value>100) value = 100;
playbackvolume = value/100.0f;
if (playbackhandle!=0){
bass.BASS_ChannelSetAttribute(playbackhandle, Bass.BASS_ATTRIB_VOL, playbackvolume);
}
}
private float lastplaybackvolume = 1.0f;
/**
* Set Playback Volume to 0
*/
public void Mute(){
lastplaybackvolume = playbackvolume;
setPlaybackvolume(0);
}
/**
* Set Playback Volume to last volume before Mute
*/
public void Unmute(){
setPlaybackvolume((int)lastplaybackvolume*100);
}
/**
* Open Audio File
* @param ff audio file name to open
* @return AudioFileProperties object or null if failed
*/
public AudioFileProperties OpenAudioFile(File ff){
if (inited){
int handle = bass.BASS_StreamCreateFile(false, ff.getAbsolutePath(), 0, 0,0);
if (handle!=0){
Logger.info("Audio file {} opened successfully", ff.getName());
AudioFileProperties prop = new AudioFileProperties(handle, ff.getName());
prop.Length = bass.BASS_ChannelGetLength(handle, Bass.BASS_POS_BYTE);
prop.duration = bass.BASS_ChannelBytes2Seconds(handle, prop.Length);
return prop;
} else Logger.error("Failed to open audio file {}, Error Code {}", ff.getAbsolutePath(), bass.BASS_ErrorGetCode());
} else Logger.info("AudioPlayer not initialized");
return null;
}
/**
* Close Audio File
* @param prop AudioFileProperties object to close
*/
public void CloseAudioFile(AudioFileProperties prop) {
playbackhandle = 0;
if (inited) {
if (prop != null) {
if (!bass.BASS_StreamFree(prop.handle)) {
{
Logger.error("Failed to close audio file {}, Error Code {}", prop.filename, bass.BASS_ErrorGetCode());
}
} else Logger.info("Audio file {} closed successfully", prop.filename);
} else Logger.info("AudioPlayer not initialized");
}
}
/**
* Play Audio File
* @param prop AudioFileProperties object to play
* @param looping set true to loop the audio file
* @param event PlaybackEvent object to handle playback event
*/
public void PlayAudioFile(AudioFileProperties prop, boolean looping, PlaybackEvent event){
if (inited){
if (prop!=null){
if (bass.BASS_ChannelStart(prop.handle)){
playbackhandle = prop.handle;
bass.BASS_ChannelSetAttribute(prop.handle, Bass.BASS_ATTRIB_VOL, playbackvolume);
if (looping) bass.BASS_ChannelFlags(prop.handle, Bass.BASS_SAMPLE_LOOP, Bass.BASS_SAMPLE_LOOP);
if (event!=null) event.onPlaybackStart(prop);
int devfailsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_DEV_FAIL,0, (handle, channel, data, user)->{
if (event!=null) event.onPlaybackFailure(prop, "Device Failure");
}, null);
if (devfailsync==0) Logger.error("Failed to set Device Failure Sync, Error Code {}", bass.BASS_ErrorGetCode());
int endsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_END, 0, (handle, channel, data, user)->{
if (looping) {
if (event!=null) event.onPlaybackLooped(prop);
} else if (event!=null) event.onPlaybackFinished(prop);
}, null);
if (endsync==0) Logger.error("Failed to set End Sync, Error Code {}", bass.BASS_ErrorGetCode());
} else {
if (event!=null) event.onPlaybackFailure(prop, String.format("Failed to play audio file %s, Error Code %d", prop.filename, bass.BASS_ErrorGetCode()));
}
} else {
if (event!=null) event.onPlaybackFailure(null, "AudioFileProperties is null");
}
} else {
if (event!=null) event.onPlaybackFailure(prop, "AudioPlayer not initialized");
}
}
}