# HG changeset patch # User sam # Date 1713195204 -25200 # Node ID 6261baf559637e9109e26cad9f26add718f1e6c7 # Parent a96df6bc5545de8c943773bb270eacc43c5793a2 add: fading for audio tracks diff -r a96df6bc5545 -r 6261baf55963 semicongine/audio.nim --- a/semicongine/audio.nim Mon Apr 15 20:22:16 2024 +0700 +++ b/semicongine/audio.nim Mon Apr 15 22:33:24 2024 +0700 @@ -1,3 +1,5 @@ +import std/monotimes +import std/times import std/tables import std/locks import std/logging except Level @@ -27,6 +29,9 @@ Track = object playing: Table[uint64, Playback] level: Level + targetLevel: Level + fadeTime: float + fadeStep: float Mixer* = object playbackCounter: uint64 tracks: Table[string, Track] @@ -36,6 +41,7 @@ lock: Lock buffers: seq[SoundData] currentBuffer: int + lastUpdate: MonoTime proc initMixer*(): Mixer = result = Mixer( @@ -159,6 +165,11 @@ proc unpause*(mixer: var Mixer, track: string) = mixer.pause(track, false) proc unpause*(mixer: var Mixer, playbackId: uint64) = mixer.pause(playbackId, false) +proc fadeTo*(mixer: var Mixer, track: string, level: Level, time: float) = + mixer.tracks[track].targetLevel = level + mixer.tracks[track].fadeTime = time + mixer.tracks[track].fadeStep = level.float - mixer.tracks[track].level.float / time + proc isPlaying*(mixer: var Mixer): bool = mixer.lock.withLock(): for track in mixer.tracks.mvalues: @@ -189,6 +200,17 @@ ] proc updateSoundBuffer(mixer: var Mixer) = + let t = getMonoTime() + let dt = (t - mixer.lastUpdate).inNanoseconds.float64 / 1_000_000_000'f64 + mixer.lastUpdate = t + + # update fadings + for track in mixer.tracks.mvalues: + if track.fadeTime > 0: + track.fadeTime -= dt + track.level = (track.level.float64 + track.fadeStep.float64 * dt).clamp(Level.low, Level.high) + if track.fadeTime <= 0: + track.level = track.targetLevel # mix for i in 0 ..< mixer.buffers[mixer.currentBuffer].len: var mixedSample = [0'i16, 0'i16]