@@ -22,15 +22,22 @@ import (
2222)
2323
2424// the buffer length is important to get right. unfortunately, there's no
25- // special way (that I know of) that can tells us what the ideal value is. we
26- // don't want it to be long because we can introduce unnecessary lag between
27- // the audio and video signal; by the same token we don't want it too short because
28- // we will end up calling FlushAudio() too often - FlushAudio() is a
29- // computationally expensive function.
25+ // special way (that I know of) that can tells us what the ideal value is
3026//
31- // the following value has been discovered through trial and error. the precise
32- // value is not critical.
33- const bufferLength = 512
27+ // the bufferLegnth value is the maximum size of the buffer. once the buffer is
28+ // full the audio will be queued
29+ const bufferLength = 1024
30+
31+ // if the audio queue is ever less than minQueueLength then the buffer
32+ // will be pushed to the queue immediately
33+ const minQueueLength = 256
34+
35+ // if audio queue is ever less than critQueueLength the the buffer is pushed to
36+ // the queue but the buffer is not reset
37+ const critQueueLength = 64
38+
39+ // if queued audio ever exceeds this value then clip the audio
40+ const maxQueueLength = 8192
3441
3542// Audio outputs sound using SDL
3643type Audio struct {
@@ -42,6 +49,7 @@ type Audio struct {
4249 // repeatAudio()
4350 buffer []uint8
4451 bufferCt int
52+ critCt int
4553
4654 // some ROMs do not output 0 as the silence value. silence is technically
4755 // caused by constant unchanging value so this shouldn't be a problem. the
@@ -85,6 +93,7 @@ func NewAudio() (*Audio, error) {
8593 }
8694
8795 aud .spec = actualSpec
96+
8897 aud .detectedSilenceValue = aud .spec .Silence
8998
9099 // fill buffers with silence
@@ -119,18 +128,53 @@ func (aud *Audio) SetAudio(audioData uint8) error {
119128 }
120129 aud .bufferCt ++
121130
122- remaining := int (sdl .GetQueuedAudioSize (aud .id ))
123-
124131 if aud .bufferCt >= len (aud .buffer ) {
132+ // if buffer is full then queue audio unconditionally
125133 err := sdl .QueueAudio (aud .id , aud .buffer )
126134 if err != nil {
127135 return err
128136 }
129137 aud .bufferCt = 0
130- } else if remaining <= len (aud .buffer )/ 2 {
131- err := sdl .QueueAudio (aud .id , aud .buffer )
132- if err != nil {
133- return err
138+
139+ } else {
140+
141+ remaining := int (sdl .GetQueuedAudioSize (aud .id ))
142+
143+ if remaining < critQueueLength {
144+ // if we're running short of bits in the queue the queue what we have
145+ // in the buffer and NOT clearing the buffer
146+ //
147+ // condition valid when the frame rate is SIGNIFICANTLY LESS than 50/60fps
148+ err := sdl .QueueAudio (aud .id , aud .buffer )
149+ if err != nil {
150+ return err
151+ }
152+
153+ } else if remaining < minQueueLength && aud .bufferCt > 10 {
154+ // if we're running short of bits in the queue the queue what we have
155+ // in the buffer.
156+ //
157+ // condition valid when the frame rate is LESS than 50/60fps
158+ //
159+ // the additional condition makes sure we're not queueing a slice
160+ // that is too short. SDL has been known to hang with short audio
161+ // queues
162+ err := sdl .QueueAudio (aud .id , aud .buffer [:aud .bufferCt - 1 ])
163+ if err != nil {
164+ return err
165+ }
166+ aud .bufferCt = 0
167+
168+ } else if remaining > maxQueueLength {
169+ // if length of SDL audio queue is getting too long then clear it
170+ //
171+ // condition valid when the frame rate is SIGNIFICANTLY MORE than 50/60fps
172+ //
173+ // if we don't do this the video will get ahead of the audio (ie. the audio
174+ // will lag)
175+ //
176+ // this is a brute force approach but it'll do for now
177+ sdl .ClearQueuedAudio (aud .id )
134178 }
135179 }
136180
0 commit comments