Handmade Hero»Episode Guide
Debugging the Audio Sync
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
2:44Fixing an off by one error
2:44Fixing an off by one error
2:44Fixing an off by one error
5:12Explanation of off by one errors
5:12Explanation of off by one errors
5:12Explanation of off by one errors
7:13Overview of the state of our audio code
7:13Overview of the state of our audio code
7:13Overview of the state of our audio code
11:05A breakdown of how time is spent during each frame
11:05A breakdown of how time is spent during each frame
11:05A breakdown of how time is spent during each frame
14:07A possible, though not great, solution to audio latency
14:07A possible, though not great, solution to audio latency
14:07A possible, though not great, solution to audio latency
16:22Tradeoff between audio lag and input lag
16:22Tradeoff between audio lag and input lag
16:22Tradeoff between audio lag and input lag
17:51Falling back to a little bit stupider
17:51Falling back to a little bit stupider
17:51Falling back to a little bit stupider
21:58Beginning to change the code for the audio output method
21:58Beginning to change the code for the audio output method
21:58Beginning to change the code for the audio output method
22:48Finding the minimum expected audio latency
22:48Finding the minimum expected audio latency
22:48Finding the minimum expected audio latency
27:31Converting to seconds using dimensional analysis
27:31Converting to seconds using dimensional analysis
27:31Converting to seconds using dimensional analysis
31:34Writing sound based on the audio latency
31:34Writing sound based on the audio latency
31:34Writing sound based on the audio latency
34:14Great aside about keeping code fluid and a bit messy in the early stages
34:14Great aside about keeping code fluid and a bit messy in the early stages
34:14Great aside about keeping code fluid and a bit messy in the early stages
37:00Determining the position to write the audio to
37:00Determining the position to write the audio to
37:00Determining the position to write the audio to
46:27How to deal with the low latency case
46:27How to deal with the low latency case
46:27How to deal with the low latency case
51:16A puzzling situation
51:16A puzzling situation
51:16A puzzling situation
53:00The aha moment
53:00The aha moment
53:00The aha moment
55:34The approach we will be taking for low latency
55:34The approach we will be taking for low latency
55:34The approach we will be taking for low latency
57:36The higher latency approach
57:36The higher latency approach
57:36The higher latency approach
1:01:14Another snag
1:01:14Another snag
1:01:14Another snag
1:07:08Putting our approach down in words
1:07:08Putting our approach down in words
1:07:08Putting our approach down in words
1:13:02Implementing the two case latency handling
1:13:02Implementing the two case latency handling
1:13:02Implementing the two case latency handling
1:18:34Do over due to deleted code
1:18:34Do over due to deleted code
1:18:34Do over due to deleted code
1:20:08Putting in the latency branching code
1:20:08Putting in the latency branching code
1:20:08Putting in the latency branching code
1:23:35Determining if the sound card is latent
1:23:35Determining if the sound card is latent
1:23:35Determining if the sound card is latent
1:26:02Mapping the WriteCursor and the PlayCursor into the same space
1:26:02Mapping the WriteCursor and the PlayCursor into the same space
1:26:02Mapping the WriteCursor and the PlayCursor into the same space
1:27:51Overview of the code determining how to write the sound
1:27:51Overview of the code determining how to write the sound
1:27:51Overview of the code determining how to write the sound
1:30:00Cleaning up
1:30:00Cleaning up
1:30:00Cleaning up
1:31:22How can we possibly predict how many bytes the game should write?
1:31:22How can we possibly predict how many bytes the game should write?
1:31:22How can we possibly predict how many bytes the game should write?
1:33:02Getting sound output separately with GameGetSoundSamples()
1:33:02Getting sound output separately with GameGetSoundSamples()
1:33:02Getting sound output separately with GameGetSoundSamples()
1:36:45More cleaning up
1:36:45More cleaning up
1:36:45More cleaning up
1:37:43Computing SafetyBytes
1:37:43Computing SafetyBytes
1:37:43Computing SafetyBytes
1:39:06Implementing GameGetSoundSamples() in the game code
1:39:06Implementing GameGetSoundSamples() in the game code
1:39:06Implementing GameGetSoundSamples() in the game code
1:40:10Testing is surprisingly successful, no bugs? NO WAY!
1:40:10Testing is surprisingly successful, no bugs? NO WAY!
1:40:10Testing is surprisingly successful, no bugs? NO WAY!
1:42:47Improving our sound output debug drawing
1:42:47Improving our sound output debug drawing
1:42:47Improving our sound output debug drawing
1:48:25Recording some additional details in our markers
1:48:25Recording some additional details in our markers
1:48:25Recording some additional details in our markers
1:56:36An assertion fires and some cleanup
1:56:36An assertion fires and some cleanup
1:56:36An assertion fires and some cleanup
1:58:33First look at the debug drawing output and adding global pause key
1:58:33First look at the debug drawing output and adding global pause key
1:58:33First look at the debug drawing output and adding global pause key
2:02:38Taking a good look at the debug drawing output
2:02:38Taking a good look at the debug drawing output
2:02:38Taking a good look at the debug drawing output
2:04:40A couple early questions
2:04:40A couple early questions
2:04:40A couple early questions
2:05:47Final Thoughts?
2:05:47Final Thoughts?
2:05:47Final Thoughts?
2:06:42Drawing another debug marker
2:06:42Drawing another debug marker
2:06:42Drawing another debug marker
2:10:53Improving our estimate of the PlayCursor position to reduce latency
2:10:53Improving our estimate of the PlayCursor position to reduce latency
2:10:53Improving our estimate of the PlayCursor position to reduce latency
2:17:59Taking a look at how our estimate lines up
2:17:59Taking a look at how our estimate lines up
2:17:59Taking a look at how our estimate lines up
2:19:13Drawing our 480 sample jitter window
2:19:13Drawing our 480 sample jitter window
2:19:13Drawing our 480 sample jitter window
2:22:15Q&A
🗩
2:22:15Q&A
🗩
2:22:15Q&A
🗩
2:22:58Did you try the audio without OBS?
2:22:58Did you try the audio without OBS?
2:22:58Did you try the audio without OBS?
2:24:15Is it inexpensive to query for the play cursor and the write cursor?
2:24:15Is it inexpensive to query for the play cursor and the write cursor?
2:24:15Is it inexpensive to query for the play cursor and the write cursor?
2:25:03Audio seems to be the most complex part until now, which will be the next most complicated thing?
2:25:03Audio seems to be the most complex part until now, which will be the next most complicated thing?
2:25:03Audio seems to be the most complex part until now, which will be the next most complicated thing?
2:26:58Audio asserts are a pain when you're debugging other things. Change to log messages.
2:26:58Audio asserts are a pain when you're debugging other things. Change to log messages.
2:26:58Audio asserts are a pain when you're debugging other things. Change to log messages.
2:27:46If we had a buffer that played from start to finish, would it be a valid syncing method to manually set AudioTimer = VideoTimer?
2:27:46If we had a buffer that played from start to finish, would it be a valid syncing method to manually set AudioTimer = VideoTimer?
2:27:46If we had a buffer that played from start to finish, would it be a valid syncing method to manually set AudioTimer = VideoTimer?
2:28:45Fully visualize waveforms and remove gradient. Turn entire thing into massive audio visualizer.
2:28:45Fully visualize waveforms and remove gradient. Turn entire thing into massive audio visualizer.
2:28:45Fully visualize waveforms and remove gradient. Turn entire thing into massive audio visualizer.
2:29:42Could you please increase ToneHz to 512, my crappy laptop speakers can't output 256?
2:29:42Could you please increase ToneHz to 512, my crappy laptop speakers can't output 256?
2:29:42Could you please increase ToneHz to 512, my crappy laptop speakers can't output 256?
2:30:29Will this audio system be able to handle music and sound, or will the game have to mux the audio for us?
2:30:29Will this audio system be able to handle music and sound, or will the game have to mux the audio for us?
2:30:29Will this audio system be able to handle music and sound, or will the game have to mux the audio for us?
2:31:08How will you make sure that you don't have regressions in some parts that are not that easy to spot right away?
2:31:08How will you make sure that you don't have regressions in some parts that are not that easy to spot right away?
2:31:08How will you make sure that you don't have regressions in some parts that are not that easy to spot right away?
2:31:54I'm sorry if I'm being slow, but I still don't truly understand why exactly the audio is jumping. It just seems like we should be able to handle it more simply.
2:31:54I'm sorry if I'm being slow, but I still don't truly understand why exactly the audio is jumping. It just seems like we should be able to handle it more simply.
2:31:54I'm sorry if I'm being slow, but I still don't truly understand why exactly the audio is jumping. It just seems like we should be able to handle it more simply.
2:32:39Why is the pitch of the sound changing after the game has been running a little while?
2:32:39Why is the pitch of the sound changing after the game has been running a little while?
2:32:39Why is the pitch of the sound changing after the game has been running a little while?
2:39:55Callback to earlier half of question: (I'm sorry if I'm being slow, but I don't truly understand why the audio is skipping.) The original audio skipped when we moved the latency to be inside of three frames.
2:39:55Callback to earlier half of question: (I'm sorry if I'm being slow, but I don't truly understand why the audio is skipping.) The original audio skipped when we moved the latency to be inside of three frames.
2:39:55Callback to earlier half of question: (I'm sorry if I'm being slow, but I don't truly understand why the audio is skipping.) The original audio skipped when we moved the latency to be inside of three frames.
2:42:25If it's not too much of an issue, can we have line numbers on the side when you are coding so we can get a grip of where you are.
2:42:25If it's not too much of an issue, can we have line numbers on the side when you are coding so we can get a grip of where you are.
2:42:25If it's not too much of an issue, can we have line numbers on the side when you are coding so we can get a grip of where you are.
2:43:08It's more likely to be the accumulation of a small value onto a larger value that is a numerical problem. Mantissas not lining up.
2:43:08It's more likely to be the accumulation of a small value onto a larger value that is a numerical problem. Mantissas not lining up.
2:43:08It's more likely to be the accumulation of a small value onto a larger value that is a numerical problem. Mantissas not lining up.
2:44:03Wrap-up
🗩
2:44:03Wrap-up
🗩
2:44:03Wrap-up
🗩