Mercurial > games > semicongine
annotate semiconginev2/old/audio.nim @ 1218:56781cc0fc7c compiletime-tests
did: renamge main package
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 21:01:37 +0700 |
parents | semicongine/old/audio.nim@a3eb305bcac2 |
children |
rev | line source |
---|---|
1007 | 1 import std/monotimes |
1019 | 2 import std/strformat |
1007 | 3 import std/times |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
4 import std/tables |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
5 import std/locks |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
6 import std/logging except Level |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
7 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
8 when defined(windows): # used for setting audio thread priority |
1010 | 9 import winim except Level |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
10 when defined(linux): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
11 import std/posix |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
12 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
13 import ./core |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
14 import ./platform/audio |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
15 import ./resources |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
16 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
17 export audiotypes |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
18 |
1169
d88f0286681b
fix: not enough buffers for smooth audio output
sam@sambook-windows.localdomain
parents:
1166
diff
changeset
|
19 const NBUFFERS = 32 |
1166
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
20 const BUFFERSAMPLECOUNT = 256 |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
21 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
22 type |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
23 Playback = object |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
24 sound: Sound |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
25 position: int |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
26 loop: bool |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
27 levelLeft: Level |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
28 levelRight: Level |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
29 paused: bool |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
30 Track = object |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
31 playing: Table[uint64, Playback] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
32 level: Level |
1007 | 33 targetLevel: Level |
34 fadeTime: float | |
35 fadeStep: float | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
36 Mixer* = object |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
37 playbackCounter: uint64 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
38 tracks: Table[string, Track] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
39 sounds*: Table[string, Sound] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
40 level: Level |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
41 device: NativeSoundDevice |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
42 lock: Lock |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
43 buffers: seq[SoundData] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
44 currentBuffer: int |
1007 | 45 lastUpdate: MonoTime |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
46 |
1023 | 47 proc initMixer(): Mixer = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
48 result = Mixer( |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
49 tracks: {"": Track(level: 1'f)}.toTable, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
50 level: 1'f, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
51 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
52 result.lock.initLock() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
53 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
54 proc setupDevice(mixer: var Mixer) = |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
55 # call this inside audio thread |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
56 var bufferaddresses: seq[ptr SoundData] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
57 for i in 0 ..< NBUFFERS: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
58 mixer.buffers.add newSeq[Sample](BUFFERSAMPLECOUNT) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
59 for i in 0 ..< mixer.buffers.len: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
60 bufferaddresses.add (addr mixer.buffers[i]) |
1138 | 61 mixer.device = OpenSoundDevice(AUDIO_SAMPLE_RATE, bufferaddresses) |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
62 |
1023 | 63 proc LoadSound*(mixer: var Mixer, name: string, resource: string) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
64 assert not (name in mixer.sounds) |
1139
114f395b9144
did: finish refactoring and updated all tests accordingly
sam <sam@basx.dev>
parents:
1138
diff
changeset
|
65 mixer.sounds[name] = LoadAudio(resource) |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
66 |
1023 | 67 proc AddSound*(mixer: var Mixer, name: string, sound: Sound) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
68 assert not (name in mixer.sounds) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
69 mixer.sounds[name] = sound |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
70 |
1023 | 71 proc ReplaceSound*(mixer: var Mixer, name: string, sound: Sound) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
72 assert (name in mixer.sounds) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
73 mixer.sounds[name] = sound |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
74 |
1023 | 75 proc AddTrack*(mixer: var Mixer, name: string, level: Level = 1'f) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
76 assert not (name in mixer.tracks) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
77 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
78 mixer.tracks[name] = Track(level: level) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
79 |
1023 | 80 proc Play*(mixer: var Mixer, soundName: string, track = "", stopOtherSounds = false, loop = false, levelLeft, levelRight: Level): uint64 = |
1019 | 81 assert track in mixer.tracks, &"Track '{track}' does not exists" |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
82 assert soundName in mixer.sounds, soundName & " not loaded" |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
83 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
84 if stopOtherSounds: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
85 mixer.tracks[track].playing.clear() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
86 mixer.tracks[track].playing[mixer.playbackCounter] = Playback( |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
87 sound: mixer.sounds[soundName], |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
88 position: 0, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
89 loop: loop, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
90 levelLeft: levelLeft, |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
91 levelRight: levelRight, |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
92 paused: false, |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
93 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
94 result = mixer.playbackCounter |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
95 inc mixer.playbackCounter |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
96 |
1023 | 97 proc Play*(mixer: var Mixer, soundName: string, track = "", stopOtherSounds = false, loop = false, level: Level = 1'f): uint64 = |
98 Play( | |
902 | 99 mixer = mixer, |
100 soundName = soundName, | |
101 track = track, | |
102 stopOtherSounds = stopOtherSounds, | |
103 loop = loop, | |
104 levelLeft = level, | |
105 levelRight = level | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
106 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
107 |
1023 | 108 proc Stop*(mixer: var Mixer) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
109 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
110 for track in mixer.tracks.mvalues: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
111 track.playing.clear() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
112 |
1023 | 113 proc GetLevel*(mixer: var Mixer): Level = mixer.level |
114 proc GetLevel*(mixer: var Mixer, track: string): Level = mixer.tracks[track].level | |
115 proc GetLevel*(mixer: var Mixer, playbackId: uint64): (Level, Level) = | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
116 for track in mixer.tracks.mvalues: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
117 if playbackId in track.playing: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
118 return (track.playing[playbackId].levelLeft, track.playing[playbackId].levelRight) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
119 |
1023 | 120 proc SetLevel*(mixer: var Mixer, level: Level) = mixer.level = level |
121 proc SetLevel*(mixer: var Mixer, track: string, level: Level) = | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
122 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
123 mixer.tracks[track].level = level |
1023 | 124 proc SetLevel*(mixer: var Mixer, playbackId: uint64, levelLeft, levelRight: Level) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
125 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
126 for track in mixer.tracks.mvalues: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
127 if playbackId in track.playing: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
128 track.playing[playbackId].levelLeft = levelLeft |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
129 track.playing[playbackId].levelRight = levelRight |
1023 | 130 proc SetLevel*(mixer: var Mixer, playbackId: uint64, level: Level) = |
131 SetLevel(mixer, playbackId, level, level) | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
132 |
1023 | 133 proc Stop*(mixer: var Mixer, track: string) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
134 assert track in mixer.tracks |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
135 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
136 mixer.tracks[track].playing.clear() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
137 |
1023 | 138 proc Stop*(mixer: var Mixer, playbackId: uint64) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
139 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
140 for track in mixer.tracks.mvalues: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
141 if playbackId in track.playing: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
142 track.playing.del(playbackId) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
143 break |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
144 |
1023 | 145 proc Pause*(mixer: var Mixer, value: bool) = |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
146 mixer.lock.withLock(): |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
147 for track in mixer.tracks.mvalues: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
148 for playback in track.playing.mvalues: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
149 playback.paused = value |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
150 |
1023 | 151 proc Pause*(mixer: var Mixer, track: string, value: bool) = |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
152 mixer.lock.withLock(): |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
153 for playback in mixer.tracks[track].playing.mvalues: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
154 playback.paused = value |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
155 |
1023 | 156 proc Pause*(mixer: var Mixer, playbackId: uint64, value: bool) = |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
157 mixer.lock.withLock(): |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
158 for track in mixer.tracks.mvalues: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
159 if playbackId in track.playing: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
160 track.playing[playbackId].paused = value |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
161 |
1023 | 162 proc Pause*(mixer: var Mixer) = mixer.Pause(true) |
163 proc Pause*(mixer: var Mixer, track: string) = mixer.Pause(track, true) | |
164 proc Pause*(mixer: var Mixer, playbackId: uint64) = mixer.Pause(playbackId, true) | |
165 proc Unpause*(mixer: var Mixer) = mixer.Pause(false) | |
166 proc Unpause*(mixer: var Mixer, track: string) = mixer.Pause(track, false) | |
167 proc Unpause*(mixer: var Mixer, playbackId: uint64) = mixer.Pause(playbackId, false) | |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
168 |
1023 | 169 proc FadeTo*(mixer: var Mixer, track: string, level: Level, time: float) = |
1007 | 170 mixer.tracks[track].targetLevel = level |
171 mixer.tracks[track].fadeTime = time | |
172 mixer.tracks[track].fadeStep = level.float - mixer.tracks[track].level.float / time | |
173 | |
1023 | 174 proc IsPlaying*(mixer: var Mixer): bool = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
175 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
176 for track in mixer.tracks.mvalues: |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
177 for playback in track.playing.values: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
178 if not playback.paused: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
179 return true |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
180 return false |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
181 |
1023 | 182 proc IsPlaying*(mixer: var Mixer, track: string): bool = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
183 mixer.lock.withLock(): |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
184 if mixer.tracks.contains(track): |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
185 for playback in mixer.tracks[track].playing.values: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
186 if not playback.paused: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
187 return true |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
188 return false |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
189 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
190 func applyLevel(sample: Sample, levelLeft, levelRight: Level): Sample = |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
191 [int16(float(sample[0]) * levelLeft), int16(float(sample[1]) * levelRight)] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
192 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
193 func clip(value: int32): int16 = |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
194 int16(max(min(int32(high(int16)), value), int32(low(int16)))) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
195 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
196 # used for combining sounds |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
197 func mix(a, b: Sample): Sample = |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
198 [ |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
199 clip(int32(a[0]) + int32(b[0])), |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
200 clip(int32(a[1]) + int32(b[1])), |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
201 ] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
202 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
203 proc updateSoundBuffer(mixer: var Mixer) = |
1007 | 204 let t = getMonoTime() |
1166
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
205 |
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
206 let tDebug = getTime() |
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
207 # echo "" |
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
208 # echo tDebug |
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
209 |
1007 | 210 let dt = (t - mixer.lastUpdate).inNanoseconds.float64 / 1_000_000_000'f64 |
211 mixer.lastUpdate = t | |
212 | |
213 # update fadings | |
214 for track in mixer.tracks.mvalues: | |
215 if track.fadeTime > 0: | |
216 track.fadeTime -= dt | |
217 track.level = (track.level.float64 + track.fadeStep.float64 * dt).clamp(Level.low, Level.high) | |
218 if track.fadeTime <= 0: | |
219 track.level = track.targetLevel | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
220 # mix |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
221 for i in 0 ..< mixer.buffers[mixer.currentBuffer].len: |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
222 var mixedSample = [0'i16, 0'i16] |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
223 mixer.lock.withLock(): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
224 for track in mixer.tracks.mvalues: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
225 var stoppedSounds: seq[uint64] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
226 for (id, playback) in track.playing.mpairs: |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
227 if playback.paused: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
228 continue |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
229 let sample = applyLevel( |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
230 playback.sound[][playback.position], |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
231 mixer.level * track.level * playback.levelLeft, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
232 mixer.level * track.level * playback.levelRight, |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
233 ) |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
234 mixedSample = mix(mixedSample, sample) |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
235 inc playback.position |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
236 if playback.position >= playback.sound[].len: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
237 if playback.loop: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
238 playback.position = 0 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
239 else: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
240 stoppedSounds.add id |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
241 for id in stoppedSounds: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
242 track.playing.del(id) |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
243 mixer.buffers[mixer.currentBuffer][i] = mixedSample |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
244 # send data to sound device |
1166
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
245 # echo getTime() - tDebug |
1138 | 246 mixer.device.WriteSoundData(mixer.currentBuffer) |
1166
92691ddcb9fe
fix: large audio-buffers lead to latency when playing sounds
sam <sam@basx.dev>
parents:
1139
diff
changeset
|
247 # echo getTime() - tDebug |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
248 mixer.currentBuffer = (mixer.currentBuffer + 1) mod mixer.buffers.len |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
249 |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
250 # DSP functions |
1023 | 251 # TODO: finish implementation, one day |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
252 |
1023 | 253 #[ |
254 # | |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
255 proc lowPassFilter(data: var SoundData, cutoff: int) = |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
256 let alpha = float(cutoff) / AUDIO_SAMPLE_RATE |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
257 var value = data[0] |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
258 for i in 0 ..< data.len: |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
259 value[0] += int16(alpha * float(data[i][0] - value[0])) |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
260 value[1] += int16(alpha * float(data[i][1] - value[1])) |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
261 data[i] = value |
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
262 |
1023 | 263 proc downsample(data: var SoundData, n: int) = |
264 let newLen = (data.len - 1) div n + 1 | |
265 for i in 0 ..< newLen: | |
266 data[i] = data[i * n] | |
267 data.setLen(newLen) | |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
268 |
1023 | 269 proc upsample(data: var SoundData, m: int) = |
270 data.setLen(data.len * m) | |
271 var i = data.len - 1 | |
272 while i < 0: | |
273 if i mod m == 0: | |
274 data[i] = data[i div m] | |
275 else: | |
276 data[i] = [0, 0] | |
277 i.dec | |
854
48a2ac8bec07
did: some more audio functionality, some unfinished grid-mesh code
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
278 |
1023 | 279 proc slowdown(data: var SoundData, m, n: int) = |
280 data.upsample(m) | |
281 # TODO | |
282 # data.lowPassFilter(m) | |
283 data.downsample(n) | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
284 |
1023 | 285 ]# |
286 | |
287 proc destroy(mixer: var Mixer) = | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
288 mixer.lock.deinitLock() |
1138 | 289 mixer.device.CloseSoundDevice() |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
290 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
291 # Threaded implementation, usually used for audio |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
292 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
293 var |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
294 mixer* = createShared(Mixer) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
295 audiothread: Thread[void] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
296 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
297 proc audioWorker() {.thread.} = |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
298 mixer[].setupDevice() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
299 onThreadDestruction(proc() = mixer[].lock.withLock(mixer[].destroy()); freeShared(mixer)) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
300 while true: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
301 mixer[].updateSoundBuffer() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
302 |
1023 | 303 proc StartMixerThread*() = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
304 mixer[] = initMixer() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
305 audiothread.createThread(audioWorker) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
306 debug "Created audio thread" |
941
e3ef8ebdda46
did: cleanup unnecessasry annotations, comments
sam <sam@basx.dev>
parents:
920
diff
changeset
|
307 when defined(windows): |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
308 SetThreadPriority(audiothread.handle(), THREAD_PRIORITY_TIME_CRITICAL) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
309 when defined(linux): |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
310 discard pthread_setschedprio(Pthread(audiothread.handle()), cint(-20)) |