package engine import os "core:os/os2" import "core:container/queue" import "core:log" import "ljud" Sound :: struct { path: string, // Where I was loaded from. data: []u8, backend: ^Sound_Backend, // Backend-representation. } Sound_Instance :: struct { parent: ^Sound, // What I'm an instance of. backend: Sound_Instance_Backend, // Backend-representation. spatialized: bool, volume: f32, // 0..1 position: [3]f32, min_distance, max_distance: f32, // .. } Sound_Instance_ID :: distinct u32 load_sound_from_path :: proc(engine: ^Engine, path: string) -> (Sound, bool) { assert(engine != nil) if len(path) == 0 { return {}, false } base, ext := os.split_filename(path) log.info("Loading sound '%v' with extension '%v'.", base, ext) // TODO: SS - Check extension. data, err := os.read_entire_file(path, context.allocator) if err != nil { log.errorf("Failed to load sound! Could not read entire file. Error: %v", err) return {}, false } if len(data) == 0 { log.errorf("Failed to load sound! No data.") return {}, false } when AUDIO_ENGINE_LJUD { backend, ok := ljud.load_sound_from_data(&engine.backend, data, ext) if !ok { return {}, false } assert(backend != nil) log.info("Loaded sound, returning") return Sound { path = path, data = data, backend = backend, }, true } else when AUDIO_ENGINE_FMOD { } else when AUDIO_ENGINE_WWISE { } log.info("No engine defined") return {}, false } unload_sound :: proc(engine: ^Engine, sound: ^Sound) { assert(engine != nil) assert(sound != nil) assert(sound.data != nil) when AUDIO_ENGINE_LJUD { ljud.unload_sound(&engine.backend, sound.backend) } else when AUDIO_ENGINE_FMOD { } else when AUDIO_ENGINE_WWISE { } delete(sound.data) sound.data = nil free(sound.backend) sound.backend = nil } create_sound_instance :: proc(engine: ^Engine, sound: ^Sound, bus: ^Bus) -> (^Sound_Instance, bool) { assert(engine != nil) assert(sound != nil) // TODO: SS - Get an available instance from a pre-allocated buffer. sound_instance_id, pop_ok := queue.pop_front_safe(&engine.sound_instance_ids) if !pop_ok { log.warnf("No free sound-instance available.") return {}, false } sound_instance := &engine.sound_instances[sound_instance_id] assert(sound_instance != nil) sound_instance.parent = sound sound_instance.backend = {} instance_ok: bool when AUDIO_ENGINE_LJUD { instance_ok = ljud.init_sound_instance(&engine.backend, bus != nil ? bus.backend : nil, sound.backend, &sound_instance.backend) } else when AUDIO_ENGINE_FMOD { } else when AUDIO_ENGINE_WWISE { } if !instance_ok { log.errorf("Failed to create a Sound-Instance for sound '%v'.", sound.path) return nil, false } return sound_instance, true } play_sound_instance :: proc(engine: ^Engine, sound_instance: ^Sound_Instance) -> bool { assert(engine != nil) assert(sound_instance != nil) when AUDIO_ENGINE_LJUD { spec := ljud.Play_Sound_Instance_Spec { spatialized = sound_instance.spatialized, volume = sound_instance.volume, position = sound_instance.position, distance = { min = sound_instance.min_distance, max = sound_instance.max_distance, }, } return ljud.play_sound_instance(&engine.backend, &sound_instance.backend, spec) } else when AUDIO_ENGINE_FMOD { } else when AUDIO_ENGINE_WWISE { } return false }