2025-08-05 01:04:39 +03:00

133 lines
4.2 KiB
Scala

package ocelot.desktop.audio
import ocelot.desktop.geometry.Vector3D
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
class SoundSource(
val kind: SoundSource.Kind,
val soundCategory: SoundCategory.Value,
val looping: Boolean,
val pitch: Float,
var volume: Float,
var position: Vector3D = Vector3D(0, 0, 0),
) {
def duration: Option[Duration] = kind match {
case SoundSource.KindSoundBuffer(buffer) =>
Some(Duration(buffer.numSamples.toFloat / buffer.sampleRate, TimeUnit.SECONDS))
case SoundSource.KindSoundSamples(SoundSamples(buffer, rate, format)) =>
val bps = format match {
case SoundSamples.Format.Stereo16 => 2
case SoundSamples.Format.Mono8 => 1
case SoundSamples.Format.Mono16 => 2
}
Some(Duration(buffer.limit().toFloat / (rate * bps), TimeUnit.SECONDS))
case SoundSource.KindStream(_) =>
None
}
def status: SoundSource.Status.Value = {
Audio.getSourceStatus(this)
}
def playing: Boolean = {
status == SoundSource.Status.Playing
}
def paused: Boolean = {
status == SoundSource.Status.Paused
}
def stopped: Boolean = {
status == SoundSource.Status.Stopped
}
def play(): Unit = {
Audio.playSource(this)
}
def pause(): Unit = {
Audio.pauseSource(this)
}
def stop(): Unit = {
Audio.stopSource(this)
}
}
object SoundSource {
sealed trait Kind
case class KindSoundBuffer(buffer: SoundBuffer) extends Kind
case class KindSoundSamples(samples: SoundSamples) extends Kind
case class KindStream(stream: SoundStream) extends Kind
def fromBuffer(buffer: SoundBuffer, soundCategory: SoundCategory.Value,
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundBuffer(buffer), soundCategory, looping, pitch, volume)
}
def fromSamples(samples: SoundSamples, soundCategory: SoundCategory.Value,
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundSamples(samples), soundCategory, looping, pitch, volume)
}
def fromStream(stream: SoundStream, soundCategory: SoundCategory.Value,
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindStream(stream), soundCategory, looping, pitch, volume)
}
object Status extends Enumeration {
val Playing, Paused, Stopped = Value
}
// ----------------------------------------------------------------
object InterfaceClick extends ClickSoundSource {
override lazy val press: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface)
override lazy val release: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface)
}
object InterfaceClickLow extends ClickSoundSource {
override lazy val press: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface, pitch = 0.8f)
override lazy val release: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface, pitch = 0.8f)
}
object InterfaceTick extends ClickSoundSource {
override lazy val press: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceTickPress, SoundCategory.Interface)
override lazy val release: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceTickRelease, SoundCategory.Interface)
}
lazy val InterfaceShutter: SoundSource =
SoundSource.fromBuffer(SoundBuffers.InterfaceShutter, SoundCategory.Interface)
object MinecraftClick extends ClickSoundSource {
override lazy val press: SoundSource =
SoundSource.fromBuffer(SoundBuffers.MinecraftClickPress, SoundCategory.Interface)
override lazy val release: SoundSource =
SoundSource.fromBuffer(SoundBuffers.MinecraftClickRelease, SoundCategory.Interface)
}
lazy val MachineFloppyInsert: SoundSource =
SoundSource.fromBuffer(SoundBuffers.MachineFloppyInsert, SoundCategory.Environment)
lazy val MachineFloppyEject: SoundSource =
SoundSource.fromBuffer(SoundBuffers.MachineFloppyEject, SoundCategory.Environment)
}