Renamed 'ljud' to 'miniaudio' to better represent what engine it is.

This commit is contained in:
2026-02-08 19:40:53 +01:00
parent 034b318059
commit cdbc7ba264
8 changed files with 69 additions and 73 deletions

157
engine/miniaudio/sound.odin Normal file
View File

@@ -0,0 +1,157 @@
package miniaudio_wrapper
import "core:sys/orca"
import "base:runtime"
import "core:log"
import "core:strings"
import "core:c"
import ma "vendor:miniaudio"
Sound :: struct {
// data_source_base: ma.data_source_base,
decoder: ma.decoder,
}
Sound_Instance :: ma.sound
@(private) on_read :: proc "c" (pDataSource: ^ma.data_source, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> ma.result {
// Read data here. Output in the same format returned by my_data_source_get_data_format().
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
@(private) on_seek :: proc "c" (pDataSource: ^ma.data_source, frameIndex: u64) -> ma.result {
// Seek to a specific PCM frame here. Return MA_NOT_IMPLEMENTED if seeking is not supported.
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
@(private) on_get_data_format :: proc "c" (pDataSource: ^ma.data_source, pFormat: ^ma.format, pChannels: ^u32, pSampleRate: ^u32, pChannelMap: [^]ma.channel, channelMapCap: c.size_t) -> ma.result {
// Return the format of the data here.
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
@(private) on_get_cursor :: proc "c" (pDataSource: ^ma.data_source, pCursor: ^u64) -> ma.result {
// Retrieve the current position of the cursor here. Return MA_NOT_IMPLEMENTED and set *pCursor to 0 if there is no notion of a cursor.
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
@(private) on_get_length :: proc "c" (pDataSource: ^ma.data_source, pLength: ^u64) -> ma.result {
// Retrieve the length in PCM frames here. Return MA_NOT_IMPLEMENTED and set *pLength to 0 if there is no notion of a length or if the length is unknown.
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
@(private) on_set_looping :: proc "c" (pDataSource: ^ma.data_source, isLooping: b32) -> ma.result {
context = runtime.default_context()
log.infof("%v", #procedure)
return .ERROR
}
load_sound_from_data :: proc(engine: ^Engine, data: []u8, extension: string) -> (^Sound, bool) {
assert(engine != nil)
sound := new(Sound)
assert(sound != nil)
// Configure our decoder
decoder_config := ma.decoder_config_init(
outputFormat = .f32,
outputChannels = 0,
outputSampleRate = 0,
)
// NOTE: SS - "When loading a decoder, miniaudio uses a trial and error technique to find the appropriate decoding backend. This can be unnecessarily inefficient if the type is already known. In this case you can use encodingFormat variable in the device config to specify a specific encoding format you want to decode."
decoder_config.encodingFormat = .unknown // TODO: SS - Check 'extension'.
decoder_result := ma.decoder_init_memory(
pData = raw_data(data),
dataSize = len(data),
pConfig = &decoder_config,
pDecoder = &sound.decoder,
)
if decoder_result != .SUCCESS {
log.errorf("Failed to initialize decoder! Result: %v.", decoder_result)
free(sound)
return nil, false
}
return sound, true
}
unload_sound :: proc(engine: ^Engine, sound: ^Sound) {
assert(engine != nil)
assert(sound != nil)
// assert(sound.data_source != nil)
ma.data_source_uninit(sound.decoder.ds.pCurrent)
}
init_sound_instance :: proc(engine: ^Engine, bus: ^Bus, sound: ^Sound, sound_instance: ^Sound_Instance) -> bool {
result := ma.sound_init_from_data_source(
pEngine = &engine.ma_engine,
pDataSource = sound.decoder.ds.pCurrent,
flags = {},
pGroup = bus,
pSound = sound_instance,
)
if result != .SUCCESS {
log.errorf("Failed to create a sound instance! Result: %v.", result)
return false
}
ma.sound_stop(sound_instance)
return true
}
play_sound_instance :: proc(
engine: ^Engine,
sound_instance: ^Sound_Instance,
spatialized: bool,
loop: bool,
volume: f32,
position: [3]f32,
min_distance, max_distance: f32,
) -> bool {
assert(engine != nil)
assert(sound_instance != nil)
ma.sound_set_spatialization_enabled(sound_instance, b32(spatialized))
ma.sound_set_looping(sound_instance, b32(loop))
ma.sound_set_volume(sound_instance, volume)
ma.sound_set_position(sound_instance, expand_values(position))
ma.sound_set_min_distance(sound_instance, min_distance)
ma.sound_set_max_distance(sound_instance, max_distance)
// TODO: SS - So many cool thingss available! Expose them.
// 'ma.sound_set_pitch' etc.
seek_result := ma.sound_seek_to_pcm_frame(sound_instance, 0)
if seek_result != .SUCCESS {
log.warnf("Failed to play sound instance! Could not seek to start. Result: %v", seek_result)
return false
}
start_result := ma.sound_start(sound_instance)
if start_result != .SUCCESS {
log.warnf("Failed to play sound instance! Result: %v", start_result)
return false
}
return true
}