Single-Buffer Sound Streaming
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next timestamp
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 and Index Controls

a
w
s
d
h j k l


Esc Close menu / unfocus timestamp

Quotes and References Menus and Index

Enter Jump to timestamp

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)
0:05Note the upgrade to remedybg 0.2.2.0 with thanks to x13pixels
🗩
0:05Note the upgrade to remedybg 0.2.2.0 with thanks to x13pixels
🗩
0:05Note the upgrade to remedybg 0.2.2.0 with thanks to x13pixels
🗩
1:18Set up to get our audio streaming into the game, checking out intro_cutscene.hha in TabView
🗹
1:18Set up to get our audio streaming into the game, checking out intro_cutscene.hha in TabView
🗹
1:18Set up to get our audio streaming into the game, checking out intro_cutscene.hha in TabView
🗹
4:06Streaming audio into 256KiB fixed-size chunks, with thoughts on audio-visual budgetary considerations
🗩
4:06Streaming audio into 256KiB fixed-size chunks, with thoughts on audio-visual budgetary considerations
🗩
4:06Streaming audio into 256KiB fixed-size chunks, with thoughts on audio-visual budgetary considerations
🗩
8:46Streaming audio into a crazy sound buffer
🗩
8:46Streaming audio into a crazy sound buffer
🗩
8:46Streaming audio into a crazy sound buffer
🗩
12:32Crazy Sound Buffer
🖌
12:32Crazy Sound Buffer
🖌
12:32Crazy Sound Buffer
🖌
17:45Crazy sound buffer vs fixed-chunk scheme
🖌
17:45Crazy sound buffer vs fixed-chunk scheme
🖌
17:45Crazy sound buffer vs fixed-chunk scheme
🖌
20:22Implement our crazy sound buffer in LoadSound()
20:22Implement our crazy sound buffer in LoadSound()
20:22Implement our crazy sound buffer in LoadSound()
28:18Note a subtlety that could cause an incorrect sound to be played back
🗩
28:18Note a subtlety that could cause an incorrect sound to be played back
🗩
28:18Note a subtlety that could cause an incorrect sound to be played back
🗩
30:24Continue to implement our crazy sound buffer in LoadSound(), independent of sample bit-depth
30:24Continue to implement our crazy sound buffer in LoadSound(), independent of sample bit-depth
30:24Continue to implement our crazy sound buffer in LoadSound(), independent of sample bit-depth
33:56Introduce Agner Fog's instruction tables1
📖
33:56Introduce Agner Fog's instruction tables1
📖
33:56Introduce Agner Fog's instruction tables1
📖
38:19Consult Agner Fog's Skylake instruction table for the performance of DIV instructions2
📖
38:19Consult Agner Fog's Skylake instruction table for the performance of DIV instructions2
📖
38:19Consult Agner Fog's Skylake instruction table for the performance of DIV instructions2
📖
40:19Add a SampleBufferMappingMask to the game_assets with which LoadSound() may set the SampleBufferIndex using bitwise AND, rather than the less performant modulus
40:19Add a SampleBufferMappingMask to the game_assets with which LoadSound() may set the SampleBufferIndex using bitwise AND, rather than the less performant modulus
40:19Add a SampleBufferMappingMask to the game_assets with which LoadSound() may set the SampleBufferIndex using bitwise AND, rather than the less performant modulus
42:23Check the L2 cache latency of an Intel Skylake CPU3
📖
42:23Check the L2 cache latency of an Intel Skylake CPU3
📖
42:23Check the L2 cache latency of an Intel Skylake CPU3
📖
43:39Continue to implement our crazy sound buffer in LoadSound()
43:39Continue to implement our crazy sound buffer in LoadSound()
43:39Continue to implement our crazy sound buffer in LoadSound()
48:02Reflect on the simplicity of our crazy sound buffer
🗩
48:02Reflect on the simplicity of our crazy sound buffer
🗩
48:02Reflect on the simplicity of our crazy sound buffer
🗩
48:24Introduce ReserveSoundMemory() for LoadSound() (and the playback function) to know about the area of the crazy sound buffer that should not get evicted
48:24Introduce ReserveSoundMemory() for LoadSound() (and the playback function) to know about the area of the crazy sound buffer that should not get evicted
48:24Introduce ReserveSoundMemory() for LoadSound() (and the playback function) to know about the area of the crazy sound buffer that should not get evicted
51:33Enable GetSoundSamples() to play back from our crazy sound buffer, introducing GetSoundBufferMemory()
51:33Enable GetSoundSamples() to play back from our crazy sound buffer, introducing GetSoundBufferMemory()
51:33Enable GetSoundSamples() to play back from our crazy sound buffer, introducing GetSoundBufferMemory()
1:01:48Awareness of overlap in a circular buffer
🖌
1:01:48Awareness of overlap in a circular buffer
🖌
1:01:48Awareness of overlap in a circular buffer
🖌
1:03:49Make ReserveSoundMemory() return a more informative sound_buffer_memory for LoadSound() and GetSoundSamples() to use
1:03:49Make ReserveSoundMemory() return a more informative sound_buffer_memory for LoadSound() and GetSoundSamples() to use
1:03:49Make ReserveSoundMemory() return a more informative sound_buffer_memory for LoadSound() and GetSoundSamples() to use
1:11:39Implement GetSoundBufferRanges()
1:11:39Implement GetSoundBufferRanges()
1:11:39Implement GetSoundBufferRanges()
1:12:53Introduce InitSoundMemory() for AllocateGameAssets() to call
1:12:53Introduce InitSoundMemory() for AllocateGameAssets() to call
1:12:53Introduce InitSoundMemory() for AllocateGameAssets() to call
1:18:13Reacquaint ourselves with the audio playing code
📖
1:18:13Reacquaint ourselves with the audio playing code
📖
1:18:13Reacquaint ourselves with the audio playing code
📖
1:21:33Enable GameUpdateAndRender() to call ChangeVolume() and PlaySound() on our piano music_test.wav
1:21:33Enable GameUpdateAndRender() to call ChangeVolume() and PlaySound() on our piano music_test.wav
1:21:33Enable GameUpdateAndRender() to call ChangeVolume() and PlaySound() on our piano music_test.wav
1:27:39Listen to our piano music_test.wav in-game, to find that only the first chunk plays
🏃
1:27:39Listen to our piano music_test.wav in-game, to find that only the first chunk plays
🏃
1:27:39Listen to our piano music_test.wav in-game, to find that only the first chunk plays
🏃
1:29:04Make PrefetchSound() call GetSoundSamples() to pull samples into the non-eviction region of our crazy sound buffer
1:29:04Make PrefetchSound() call GetSoundSamples() to pull samples into the non-eviction region of our crazy sound buffer
1:29:04Make PrefetchSound() call GetSoundSamples() to pull samples into the non-eviction region of our crazy sound buffer
1:31:44Continue to reacquaint ourselves with OutputPlayingSounds()
📖
1:31:44Continue to reacquaint ourselves with OutputPlayingSounds()
📖
1:31:44Continue to reacquaint ourselves with OutputPlayingSounds()
📖
1:35:04Make OutputPlayingSounds() correctly compute the SampleCount and retrieve a full hha_asset * from GetSoundInfo()
1:35:04Make OutputPlayingSounds() correctly compute the SampleCount and retrieve a full hha_asset * from GetSoundInfo()
1:35:04Make OutputPlayingSounds() correctly compute the SampleCount and retrieve a full hha_asset * from GetSoundInfo()
1:39:40Listen to our piano music_test.wav in-game, to find that we get choppy playback when we miss our framerate
🏃
1:39:40Listen to our piano music_test.wav in-game, to find that we get choppy playback when we miss our framerate
🏃
1:39:40Listen to our piano music_test.wav in-game, to find that we get choppy playback when we miss our framerate
🏃
1:41:43Reacquaint ourselves with the single-play audio code
📖
1:41:43Reacquaint ourselves with the single-play audio code
📖
1:41:43Reacquaint ourselves with the single-play audio code
📖
1:45:02Make ExecuteBrainHero() call PlaySound() on the Glove
1:45:02Make ExecuteBrainHero() call PlaySound() on the Glove
1:45:02Make ExecuteBrainHero() call PlaySound() on the Glove
1:46:19Find that we cannot hear the glove
🏃
1:46:19Find that we cannot hear the glove
🏃
1:46:19Find that we cannot hear the glove
🏃
1:47:42Step through ExecuteBrain() to PlaySound() to find that we passed a bogus SoundID
🏃
1:47:42Step through ExecuteBrain() to PlaySound() to find that we passed a bogus SoundID
🏃
1:47:42Step through ExecuteBrain() to PlaySound() to find that we passed a bogus SoundID
🏃
1:48:23Fix ExecuteBrainHero() to only call PlaySound() on attack, rebuild and crash remedybg
1:48:23Fix ExecuteBrainHero() to only call PlaySound() on attack, rebuild and crash remedybg
1:48:23Fix ExecuteBrainHero() to only call PlaySound() on attack, rebuild and crash remedybg
1:50:13Step in to ExecuteBrainHero()
🏃
1:50:13Step in to ExecuteBrainHero()
🏃
1:50:13Step in to ExecuteBrainHero()
🏃
1:50:49Make ExecuteBrainHero() set the Weight for our bloop sound asset, rebuild and crash remedybg
1:50:49Make ExecuteBrainHero() set the Weight for our bloop sound asset, rebuild and crash remedybg
1:50:49Make ExecuteBrainHero() set the Weight for our bloop sound asset, rebuild and crash remedybg
1:51:16Try to figure out the repro case for this remedybg crash
🗹
1:51:16Try to figure out the repro case for this remedybg crash
🗹
1:51:16Try to figure out the repro case for this remedybg crash
🗹
1:53:03Step in to ExecuteBrainHero() to determine that GetBestMatchSoundFrom() fails to find a sound
🏃
1:53:03Step in to ExecuteBrainHero() to determine that GetBestMatchSoundFrom() fails to find a sound
🏃
1:53:03Step in to ExecuteBrainHero() to determine that GetBestMatchSoundFrom() fails to find a sound
🏃
1:53:56remedybg feature request: Casting to an enum
🗹
1:53:56remedybg feature request: Casting to an enum
🗹
1:53:56remedybg feature request: Casting to an enum
🗹
1:55:20Step through GetBestMatchAssetFrom() to see how it's handling our request for the bloop asset
🏃
1:55:20Step through GetBestMatchAssetFrom() to see how it's handling our request for the bloop asset
🏃
1:55:20Step through GetBestMatchAssetFrom() to see how it's handling our request for the bloop asset
🏃
1:57:56Check out base_game.hha in TabView to find that our bloop audio assets are absent
🗹
1:57:56Check out base_game.hha in TabView to find that our bloop audio assets are absent
🗹
1:57:56Check out base_game.hha in TabView to find that our bloop audio assets are absent
🗹
2:00:44Check out our import errors
🏃
2:00:44Check out our import errors
🏃
2:00:44Check out our import errors
🏃
2:01:11Fix typos in base_game.hht
🗹
2:01:11Fix typos in base_game.hht
🗹
2:01:11Fix typos in base_game.hht
🗹
2:01:30Reimport our assets, step through ExecuteBrainHero() and successfully hear our glove bloop
🏃
2:01:30Reimport our assets, step through ExecuteBrainHero() and successfully hear our glove bloop
🏃
2:01:30Reimport our assets, step through ExecuteBrainHero() and successfully hear our glove bloop
🏃
2:02:29Investigate why we hear the glove bloop on repeat
📖
2:02:29Investigate why we hear the glove bloop on repeat
📖
2:02:29Investigate why we hear the glove bloop on repeat
📖
2:04:00Listen to the repeated audio
🏃
2:04:00Listen to the repeated audio
🏃
2:04:00Listen to the repeated audio
🏃
2:04:40Temporarily reduce the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:04:40Temporarily reduce the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:04:40Temporarily reduce the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:04:45Find that the bloop audio continues to repeat
🏃
2:04:45Find that the bloop audio continues to repeat
🏃
2:04:45Find that the bloop audio continues to repeat
🏃
2:05:40Fix ExecuteBrainHero() to correctly perform a single attack
2:05:40Fix ExecuteBrainHero() to correctly perform a single attack
2:05:40Fix ExecuteBrainHero() to correctly perform a single attack
2:07:07See and hear our non-repeated glove attack bloop
🏃
2:07:07See and hear our non-repeated glove attack bloop
🏃
2:07:07See and hear our non-repeated glove attack bloop
🏃
2:07:14Revert the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:07:14Revert the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:07:14Revert the Entity->tMovement of our glove swipe in UpdateAndRenderEntities()
2:07:27Find that our glove is absent
🏃
2:07:27Find that our glove is absent
🏃
2:07:27Find that our glove is absent
🏃
2:07:42Fix ExecuteBrainHero() to float our glove when we're not attacking, rebuild and crash remedybg
2:07:42Fix ExecuteBrainHero() to float our glove when we're not attacking, rebuild and crash remedybg
2:07:42Fix ExecuteBrainHero() to float our glove when we're not attacking, rebuild and crash remedybg
2:08:10See and hear our glove in-game, and hear some clicking
🏃
2:08:10See and hear our glove in-game, and hear some clicking
🏃
2:08:10See and hear our glove in-game, and hear some clicking
🏃
2:09:01Q&A
🗩
2:09:01Q&A
🗩
2:09:01Q&A
🗩
2:09:40mtsmox Q: In the LRU copy path you might have forgotten to set Result?
🗪
2:09:40mtsmox Q: In the LRU copy path you might have forgotten to set Result?
🗪
2:09:40mtsmox Q: In the LRU copy path you might have forgotten to set Result?
🗪
2:10:25Fix GetSoundSamples() to set the correct Result
2:10:25Fix GetSoundSamples() to set the correct Result
2:10:25Fix GetSoundSamples() to set the correct Result
2:10:55guybru5h_vi Q: Just started at a new job that has a gargantuan codebase (in the millions of lines of code) and it's very hard to follow what's going on. Do you have any general advice or approach to gaining an understanding of what's going on in files that are part of very large codebases? Also thanks! It's in a large part thanks to Handmade Hero that I managed to land the job!
🗪
2:10:55guybru5h_vi Q: Just started at a new job that has a gargantuan codebase (in the millions of lines of code) and it's very hard to follow what's going on. Do you have any general advice or approach to gaining an understanding of what's going on in files that are part of very large codebases? Also thanks! It's in a large part thanks to Handmade Hero that I managed to land the job!
🗪
2:10:55guybru5h_vi Q: Just started at a new job that has a gargantuan codebase (in the millions of lines of code) and it's very hard to follow what's going on. Do you have any general advice or approach to gaining an understanding of what's going on in files that are part of very large codebases? Also thanks! It's in a large part thanks to Handmade Hero that I managed to land the job!
🗪
2:15:05nickito97 Is there a name for that type of buffer?
🗪
2:15:05nickito97 Is there a name for that type of buffer?
🗪
2:15:05nickito97 Is there a name for that type of buffer?
🗪
2:16:34jkfsda Q: John Carmack likes Rust, is Rust > C++?
🗪
2:16:34jkfsda Q: John Carmack likes Rust, is Rust > C++?
🗪
2:16:34jkfsda Q: John Carmack likes Rust, is Rust > C++?
🗪
2:18:41ivereadthesequel Q: On an interview I was given a debugging task on a new piece of code (it was a web scraper written in Python). This company was actually generous enough to provide feedback on performance and said I would have done better if I had "debugged more systematically". Do you have any tips on better debugging practices?
🗪
2:18:41ivereadthesequel Q: On an interview I was given a debugging task on a new piece of code (it was a web scraper written in Python). This company was actually generous enough to provide feedback on performance and said I would have done better if I had "debugged more systematically". Do you have any tips on better debugging practices?
🗪
2:18:41ivereadthesequel Q: On an interview I was given a debugging task on a new piece of code (it was a web scraper written in Python). This company was actually generous enough to provide feedback on performance and said I would have done better if I had "debugged more systematically". Do you have any tips on better debugging practices?
🗪
2:19:33vtlmks Q: <joke question> Why can't we use the GF2P8AFFINEINVQB instruction all the time?4,5
🗪
2:19:33vtlmks Q: <joke question> Why can't we use the GF2P8AFFINEINVQB instruction all the time?4,5
🗪
2:19:33vtlmks Q: <joke question> Why can't we use the GF2P8AFFINEINVQB instruction all the time?4,5
🗪
2:25:00panthalassadigital Q: After reading your "About" on your website, Casey, what does it mean to be in gaming research and development? What's your company's bread and butter? Are you basically a consultant for other game companies?
🗪
2:25:00panthalassadigital Q: After reading your "About" on your website, Casey, what does it mean to be in gaming research and development? What's your company's bread and butter? Are you basically a consultant for other game companies?
🗪
2:25:00panthalassadigital Q: After reading your "About" on your website, Casey, what does it mean to be in gaming research and development? What's your company's bread and butter? Are you basically a consultant for other game companies?
🗪
2:29:57ivereadthesequel Q: Regarding story engines: what sort of advancements are in yours, if you can mention anything? What does it achieve?
🗪
2:29:57ivereadthesequel Q: Regarding story engines: what sort of advancements are in yours, if you can mention anything? What does it achieve?
🗪
2:29:57ivereadthesequel Q: Regarding story engines: what sort of advancements are in yours, if you can mention anything? What does it achieve?
🗪
2:30:43Close it down with an exercise for the reader: preventing the sound from skipping when we miss our frame rate
🗩
2:30:43Close it down with an exercise for the reader: preventing the sound from skipping when we miss our frame rate
🗩
2:30:43Close it down with an exercise for the reader: preventing the sound from skipping when we miss our frame rate
🗩