/*
 * sound.cm - Audio playback system for Prosperon
 *
 * Uses the soundwave package for audio decoding and mixing,
 * and routes output to SDL audio.
 *
 * USAGE:
 *   var audio = use('sound')
 *   var voice = audio.play("mysound.mp3")
 *   voice.loop = true
 *   voice.vol = 0.5
 *   voice.stopped = true  // stop it
 */

var io = use('cellfs')
var res = use('resources')
var soundwave = use('soundwave/soundwave')
var sdl_audio = use('sdl3/audio')

var audio = {}

// Output format constants
var OUTPUT_RATE = 44100
var OUTPUT_CHANNELS = 2
var FRAMES_PER_CHUNK = 1024
var BYTES_PER_SAMPLE = 4  // f32
var CHUNK_BYTES = FRAMES_PER_CHUNK * OUTPUT_CHANNELS * BYTES_PER_SAMPLE

// Create the audio player instance
var player = soundwave.create({
  sample_rate: OUTPUT_RATE,
  channels: OUTPUT_CHANNELS,
  frames_per_chunk: FRAMES_PER_CHUNK
})

// Load and cache PCM data from a file path
audio.pcm = function pcm(file) {
  file = res.find_sound(file)
  if (!file) return null
  
  // Check player's cache first
  if (player.pcm_cache[file]) return player.pcm_cache[file]
  
  var buf = io.slurp(file)
  if (!buf) return null
  
  return player.decode(buf, file)
}

// Play a sound file, returns voice object
audio.play = function play(file, opts) {
  var pcm_data = audio.pcm(file)
  if (!pcm_data) return null
  
  return player.play(pcm_data, opts)
}

// Convenience: play and return stop function
audio.cry = function cry(file) {
  var v = audio.play(file)
  if (!v) return null
  return function() { v.stopped = true }
}

// Get number of active voices
audio.voice_count = function() {
  return player.voice_count()
}

// SDL audio stream setup
var feeder = sdl_audio.open_stream("playback")
feeder.resume_device()

// Audio pump - called periodically to fill the audio buffer
function pump() {
  while (feeder.queued() < CHUNK_BYTES * 3) {
    var mixed = player.pull(FRAMES_PER_CHUNK)
    feeder.put(mixed)
  }
  
  $delay(pump, 1/240)
}

pump()

return audio
