Mercurial > games > semicongine
changeset 854:48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
author | Sam <sam@basx.dev> |
---|---|
date | Tue, 26 Dec 2023 15:16:34 +0700 |
parents | f5009fbb2cbc |
children | 1ecc948dbacd |
files | semicongine/audio.nim semicongine/core/audiotypes.nim semicongine/mesh.nim tests/test_audio.nim |
diffstat | 4 files changed, 103 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/audio.nim Sat Dec 09 01:06:58 2023 +0700 +++ b/semicongine/audio.nim Tue Dec 26 15:16:34 2023 +0700 @@ -23,6 +23,7 @@ loop: bool levelLeft: Level levelRight: Level + paused: bool Track = object playing: Table[uint64, Playback] level: Level @@ -80,7 +81,8 @@ position: 0, loop: loop, levelLeft: levelLeft, - levelRight: levelRight + levelRight: levelRight, + paused: false, ) result = mixer.playbackCounter inc mixer.playbackCounter @@ -133,16 +135,45 @@ track.playing.del(playbackId) break +proc pause*(mixer: var Mixer, value: bool) = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + for playback in track.playing.mvalues: + playback.paused = value + +proc pause*(mixer: var Mixer, track: string, value: bool) = + mixer.lock.withLock(): + for playback in mixer.tracks[track].playing.mvalues: + playback.paused = value + +proc pause*(mixer: var Mixer, playbackId: uint64, value: bool) = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + if playbackId in track.playing: + track.playing[playbackId].paused = value + +proc pause*(mixer: var Mixer) = mixer.pause(true) +proc pause*(mixer: var Mixer, track: string) = mixer.pause(track, true) +proc pause*(mixer: var Mixer, playbackId: uint64) = mixer.pause(playbackId, true) +proc unpause*(mixer: var Mixer) = mixer.pause(false) +proc unpause*(mixer: var Mixer, track: string) = mixer.pause(track, false) +proc unpause*(mixer: var Mixer, playbackId: uint64) = mixer.pause(playbackId, false) + proc isPlaying*(mixer: var Mixer): bool = mixer.lock.withLock(): for track in mixer.tracks.mvalues: - if track.playing.len > 0: - return true + for playback in track.playing.values: + if not playback.paused: + return true return false proc isPlaying*(mixer: var Mixer, track: string): bool = mixer.lock.withLock(): - return mixer.tracks.contains(track) and mixer.tracks[track].playing.len > 0 + if mixer.tracks.contains(track): + for playback in mixer.tracks[track].playing.values: + if not playback.paused: + return true + return false func applyLevel(sample: Sample, levelLeft, levelRight: Level): Sample = [int16(float(sample[0]) * levelLeft), int16(float(sample[1]) * levelRight)] @@ -160,17 +191,19 @@ proc updateSoundBuffer(mixer: var Mixer) = # mix for i in 0 ..< mixer.buffers[mixer.currentBuffer].len: - var currentSample = [0'i16, 0'i16] + var mixedSample = [0'i16, 0'i16] mixer.lock.withLock(): for track in mixer.tracks.mvalues: var stoppedSounds: seq[uint64] for (id, playback) in track.playing.mpairs: + if playback.paused: + continue let sample = applyLevel( playback.sound[][playback.position], mixer.level * track.level * playback.levelLeft, mixer.level * track.level * playback.levelRight, ) - currentSample = mix(currentSample, sample) + mixedSample = mix(mixedSample, sample) inc playback.position if playback.position >= playback.sound[].len: if playback.loop: @@ -179,11 +212,42 @@ stoppedSounds.add id for id in stoppedSounds: track.playing.del(id) - mixer.buffers[mixer.currentBuffer][i] = currentSample + mixer.buffers[mixer.currentBuffer][i] = mixedSample # send data to sound device mixer.device.writeSoundData(mixer.currentBuffer) mixer.currentBuffer = (mixer.currentBuffer + 1) mod mixer.buffers.len +# DSP functions + +proc lowPassFilter(data: var SoundData, cutoff: int) = + let alpha = float(cutoff) / AUDIO_SAMPLE_RATE + var value = data[0] + for i in 0 ..< data.len: + value[0] += int16(alpha * float(data[i][0] - value[0])) + value[1] += int16(alpha * float(data[i][1] - value[1])) + data[i] = value + +proc downsample(data: var SoundData, n: int) = + let newLen = (data.len - 1) div n + 1 + for i in 0 ..< newLen: + data[i] = data[i * n] + data.setLen(newLen) + +proc upsample(data: var SoundData, m: int) = + data.setLen(data.len * m) + var i = data.len - 1 + while i < 0: + if i mod m == 0: + data[i] = data[i div m] + else: + data[i] = [0, 0] + i.dec + +proc slowdown(data: var SoundData, m, n: int) = + data.upsample(m) + # TODO + # data.lowPassFilter(m) + data.downsample(n) proc destroy*(mixer: var Mixer) = mixer.lock.deinitLock()
--- a/semicongine/core/audiotypes.nim Sat Dec 09 01:06:58 2023 +0700 +++ b/semicongine/core/audiotypes.nim Tue Dec 26 15:16:34 2023 +0700 @@ -18,12 +18,12 @@ sin(x * 2 * Pi * f) result = ret -proc sineSoundData*(f: float, len: float, rate: int): SoundData = +proc sineSoundData*(f: float, len: float, rate: int, amplitude = 0.5'f32): SoundData = let dt = 1'f / float(rate) var sine = sinewave(f) for i in 0 ..< int(float(rate) * len): let t = dt * float(i) - let value = int16(sine(t) * float(high(int16))) + let value = int16(sine(t) * float(high(int16)) * amplitude) result.add [value, value] proc newSound*(data: SoundData): Sound =
--- a/semicongine/mesh.nim Sat Dec 09 01:06:58 2023 +0700 +++ b/semicongine/mesh.nim Tue Dec 26 15:16:34 2023 +0700 @@ -502,6 +502,29 @@ result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) result[].initVertexAttribute("color", col) +proc grid*(rows, columns, cellSize=1.0'f32, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = + + result = Mesh( + vertexCount: rows * columns + (rows + columns + 1), + instanceTransforms: @[Unit4F32], + indexType: Small, + name: &"grid-{instanceCounter}", + material: material, + ) + inc instanceCounter + + var + pos = @[newVec3f(0, 0)] + col = @[c, c] + for h in 0 ..< rows: + for w in 0 ..< columns: + pos.add newVec3f(cos(float32(i) * step) * half_w, sin(float32(i) * step) * half_h) + col.add c + result[].smallIndices.add [uint16(0), uint16(i + 1), uint16(i + 2)] + + result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) + result[].initVertexAttribute("color", col) + # MESH TREES ============================================================================= type
--- a/tests/test_audio.nim Sat Dec 09 01:06:58 2023 +0700 +++ b/tests/test_audio.nim Tue Dec 26 15:16:34 2023 +0700 @@ -14,10 +14,11 @@ let s2 = mixer[].play("test2", loop=true) let t0 = now() + mixer[].setLevel(0.5) while true: let runtime = (now() - t0).inMilliseconds() if runtime > 1500: - mixer[].setLevel(0.1) + mixer[].setLevel(0.2) if runtime > 3000: mixer[].stop(s2) if runtime > 6000: @@ -72,9 +73,9 @@ when isMainModule: startMixerThread() - test1() + # test1() + # mixer[].stop() + # test2() + # mixer[].stop() + test3() mixer[].stop() - test2() - mixer[].stop() - # test3() - # mixer[].stop()