Skip to content

Instantly share code, notes, and snippets.

@kalsprite
Last active July 28, 2025 05:34
Show Gist options
  • Select an option

  • Save kalsprite/3d3a21646b6b2d8d5cda5e848d45da84 to your computer and use it in GitHub Desktop.

Select an option

Save kalsprite/3d3a21646b6b2d8d5cda5e848d45da84 to your computer and use it in GitHub Desktop.
dsound init
// Released as Public Domain, Attribution appreciated but not required, Jon Lipstate
package scratch
import win32 "core:sys/windows"
import "core:dynlib"
import "core:fmt"
import "vendor:directx/dxgi"
IDirectSound :: struct {
using lpVtbl: ^IDirectSoundVtbl,
}
IDirectSoundVtbl :: struct {
using iunknown_vtable: dxgi.IUnknown_VTable,
CreateSoundBuffer: proc "stdcall" (
this: ^IDirectSound,
pcDSBufferDesc: ^DSBUFFERDESC,
ppDSBuffer: ^^IDirectSoundBuffer,
pUnkOuter: rawptr,
) -> win32.HRESULT,
GetCaps: proc "stdcall" (this: ^IDirectSound, pDSCaps: ^DSCAPS) -> win32.HRESULT,
DuplicateSoundBuffer: proc "stdcall" (
this: ^IDirectSound,
pDSBufferOriginal: ^IDirectSoundBuffer,
ppDSBufferDuplicate: ^^IDirectSoundBuffer,
) -> win32.HRESULT,
SetCooperativeLevel: proc "stdcall" (this: ^IDirectSound, hwnd: win32.HWND, dwLevel: win32.DWORD) -> win32.HRESULT,
Compact: proc "stdcall" (this: ^IDirectSound) -> win32.HRESULT,
GetSpeakerConfig: proc "stdcall" (this: ^IDirectSound, pdwSpeakerConfig: ^win32.DWORD) -> win32.HRESULT,
SetSpeakerConfig: proc "stdcall" (this: ^IDirectSound, dwSpeakerConfig: win32.DWORD) -> win32.HRESULT,
Initialize: proc "stdcall" (this: ^IDirectSound, pcGuidDevice: ^win32.GUID) -> win32.HRESULT,
}
DSBUFFERDESC :: struct {
dwSize: win32.DWORD,
dwFlags: win32.DWORD,
dwBufferBytes: win32.DWORD,
dwReserved: win32.DWORD,
lpwfxFormat: ^WAVEFORMATEX,
// #if DIRECTSOUND_VERSION >= 0x0700
guid3DAlgorithm: win32.GUID,
// #endif
}
WAVEFORMATEX :: struct {
wFormatTag: win32.WORD, /* format type */
nChannels: win32.WORD, /* number of channels (i.e. mono, stereo...) */
nSamplesPerSec: win32.DWORD, /* sample rate */
nAvgBytesPerSec: win32.DWORD, /* for buffer estimation */
nBlockAlign: win32.WORD, /* block size of data */
wBitsPerSample: win32.WORD, /* number of bits per sample of mono data */
cbSize: win32.WORD, /* the count in bytes of the size of */
/* extra information (after cbSize) */
}
IDirectSoundBuffer :: struct {
using lpVtbl: ^IDirectSoundBufferVtbl,
}
IDirectSoundBufferVtbl :: struct {
using iunknown_vtable: dxgi.IUnknown_VTable,
GetCaps: proc "stdcall" (this: ^IDirectSoundBuffer, pDSBufferCaps: ^DSBCAPS) -> win32.HRESULT, //LPDSBCAPS
GetCurrentPosition: proc "stdcall" (
this: ^IDirectSoundBuffer,
pdwCurrentPlayCursor: ^win32.DWORD,
pdwCurrentWriteCursor: ^win32.DWORD,
) -> win32.HRESULT,
GetFormat: proc "stdcall" (
this: ^IDirectSoundBuffer,
pwfxFormat: ^WAVEFORMATEX,
dwSizeAllocated: win32.DWORD,
pdwSizeWritten: ^win32.DWORD,
) -> win32.HRESULT,
GetVolume: proc "stdcall" (this: ^IDirectSoundBuffer, plVolume: ^win32.LONG) -> win32.HRESULT,
GetPan: proc "stdcall" (this: ^IDirectSoundBuffer, plPan: ^win32.LONG) -> win32.HRESULT,
GetFrequency: proc "stdcall" (this: ^IDirectSoundBuffer, pdwFrequency: ^win32.DWORD) -> win32.HRESULT,
GetStatus: proc "stdcall" (this: ^IDirectSoundBuffer, pdwStatus: ^win32.DWORD) -> win32.HRESULT,
Initialize: proc "stdcall" (
this: ^IDirectSoundBuffer,
pDirectSound: ^IDirectSound,
pcDSBufferDesc: ^DSBUFFERDESC,
) -> win32.HRESULT,
Lock: proc "stdcall" (
this: ^IDirectSoundBuffer,
dwOffset: win32.DWORD,
dwBytes: win32.DWORD,
ppvAudioPtr1: ^win32.LPVOID,
pdwAudioBytes1: ^win32.DWORD,
ppvAudioPtr2: ^win32.LPVOID,
pdwAudioBytes2: ^win32.DWORD,
dwFlags: win32.DWORD,
) -> win32.HRESULT,
Play: proc "stdcall" (
this: ^IDirectSoundBuffer,
dwReserved1: win32.DWORD,
dwPriority: win32.DWORD,
dwFlags: win32.DWORD,
) -> win32.HRESULT,
SetCurrentPosition: proc "stdcall" (this: ^IDirectSoundBuffer, dwNewPosition: win32.DWORD) -> win32.HRESULT,
SetFormat: proc "stdcall" (this: ^IDirectSoundBuffer, pcfxFormat: ^WAVEFORMATEX) -> win32.HRESULT,
SetVolume: proc "stdcall" (this: ^IDirectSoundBuffer, lVolume: win32.LONG) -> win32.HRESULT,
SetPan: proc "stdcall" (this: ^IDirectSoundBuffer, lPan: win32.LONG) -> win32.HRESULT,
SetFrequency: proc "stdcall" (this: ^IDirectSoundBuffer, dwFrequency: win32.DWORD) -> win32.HRESULT,
Stop: proc "stdcall" (this: ^IDirectSoundBuffer) -> win32.HRESULT,
Unlock: proc "stdcall" (
this: ^IDirectSoundBuffer,
pvAudioPtr1: win32.LPVOID,
dwAudioBytes1: win32.DWORD,
pvAudioPtr2: win32.LPVOID,
dwAudioBytes2: win32.DWORD,
) -> win32.HRESULT,
Restore: proc "stdcall" (this: ^IDirectSoundBuffer) -> win32.HRESULT,
}
WAVE_FORMAT_PCM :: 1
DSSCL_PRIORITY :: 0x00000002
DSBCAPS_PRIMARYBUFFER :: 0x00000001
DSBCAPS_GETCURRENTPOSITION2 :: 0x00010000
DSBCAPS_GLOBALFOCUS :: 0x00008000
DSCAPS :: struct {
dwSize:win32.DWORD,
dwFlags:win32.DWORD,
dwMinSecondarySampleRate:win32.DWORD,
dwMaxSecondarySampleRate:win32.DWORD,
dwPrimaryBuffers:win32.DWORD,
dwMaxHwMixingAllBuffers:win32.DWORD,
dwMaxHwMixingStaticBuffers:win32.DWORD,
dwMaxHwMixingStreamingBuffers:win32.DWORD,
dwFreeHwMixingAllBuffers:win32.DWORD,
dwFreeHwMixingStaticBuffers:win32.DWORD,
dwFreeHwMixingStreamingBuffers:win32.DWORD,
dwMaxHw3DAllBuffers:win32.DWORD,
dwMaxHw3DStaticBuffers:win32.DWORD,
dwMaxHw3DStreamingBuffers:win32.DWORD,
dwFreeHw3DAllBuffers:win32.DWORD,
dwFreeHw3DStaticBuffers:win32.DWORD,
dwFreeHw3DStreamingBuffers:win32.DWORD,
dwTotalHwMemBytes:win32.DWORD,
dwFreeHwMemBytes:win32.DWORD,
dwMaxContigFreeHwMemBytes:win32.DWORD,
dwUnlockTransferRateHwBuffers:win32.DWORD,
dwPlayCpuOverheadSwBuffers:win32.DWORD,
dwReserved1:win32.DWORD,
dwReserved2:win32.DWORD,
}
DSBCAPS :: struct
{
dwSize:win32.DWORD,
dwFlags:win32.DWORD,
dwBufferBytes:win32.DWORD,
dwUnlockTransferRate:win32.DWORD,
dwPlayCpuOverhead:win32.DWORD,
}
// Released as Public Domain, Attribution appreciated but not required, Jon Lipstate
package scratch
import win32 "core:sys/windows"
import "core:c"
import "core:dynlib"
import "core:fmt"
import "vendor:directx/dxgi"
global_secondary_buffer:^IDirectSoundBuffer
main :: proc() {
window,ok := win32_make_window()
if ok {
win32_init_dsound(window,48000,48000*2*size_of(i16))
}
}
win32_init_dsound :: proc(window: win32.HWND, samples_per_second: int, secondary_buffer_size: int) {
lib, ok := dynlib.load_library("dsound.dll")
assert(ok)
sym, found := dynlib.symbol_address(lib, "DirectSoundCreate")
assert(found)
ds: ^IDirectSound = {}
DirectSoundCreate := cast(proc(lpGuid: ^win32.GUID, ppDS: ^^IDirectSound, pUnkOuter: rawptr) -> win32.HRESULT)sym
ds_result := DirectSoundCreate(nil, &ds, nil)
if ds_result < 0 {
fmt.eprintf("Error in DirectSoundCreate: 0x%X\n",u32(u64(ds_result) & 0x0000_0000_FFFF_FFFF))
return
}
wave_format: WAVEFORMATEX = {
wFormatTag = WAVE_FORMAT_PCM,
nChannels = 2,
nSamplesPerSec = u32(samples_per_second),
wBitsPerSample = 16,
nBlockAlign = 2 * 16 / 8,
nAvgBytesPerSec = u32(samples_per_second * (2 * 16 / 8)),
cbSize = 0,
}
scl_res := ds->SetCooperativeLevel(window, DSSCL_PRIORITY)
if scl_res < 0 {
fmt.eprintf("Error in SetCooperativeLevel: 0x%X\n",u32(u64(scl_res) & 0x0000_0000_FFFF_FFFF))
return
}
p_buffer_desc: DSBUFFERDESC = {
dwSize = size_of(DSBUFFERDESC),
dwFlags = DSBCAPS_PRIMARYBUFFER,
}
primary_buffer: ^IDirectSoundBuffer = {}
pb_res := ds->CreateSoundBuffer(&p_buffer_desc, &primary_buffer, nil)
if pb_res < 0 {
fmt.eprintf("Error in CreateSoundBuffer:Primary: 0x%X\n",u32(u64(pb_res) & 0x0000_0000_FFFF_FFFF) )
return
}
sf_res := primary_buffer->SetFormat(&wave_format)
if sf_res < 0 {
fmt.eprintf("Error in SetFormat:Primary: 0x%X\n",u32(u64(sf_res) & 0x0000_0000_FFFF_FFFF))
return
}
s_buffer_desc :DSBUFFERDESC= {
dwSize = size_of(DSBUFFERDESC),
dwFlags = DSBCAPS_GETCURRENTPOSITION2,
dwBufferBytes = u32(secondary_buffer_size),
lpwfxFormat = &wave_format,
}
sb_res := ds->CreateSoundBuffer(&s_buffer_desc,&global_secondary_buffer,nil)
if sb_res < 0 {
fmt.eprintf("Error in SetFormat:Secondary: 0x%X\n",u32(u64(sb_res) & 0x0000_0000_FFFF_FFFF))
return
}
}
win32_make_window::proc() ->(window:win32.HWND,ok:bool){
instance := win32.HINSTANCE(nil)
window_class: win32.WNDCLASSA = {}
window_class.style = win32.CS_HREDRAW | win32.CS_VREDRAW
window_class.lpfnWndProc = win32.WNDPROC(win32_main_window_callback)
window_class.hInstance = instance
window_class.hCursor = win32.LoadCursorA(win32.HINSTANCE(nil), win32.IDC_ARROW)
window_class.lpszClassName = "ScratchWindowClass"
ok= RegisterClassA(&window_class) != 0
window = nil
if ok {
window = CreateWindowExA(
0,
window_class.lpszClassName,
"Scratch",
win32.WS_OVERLAPPEDWINDOW | win32.WS_VISIBLE,
win32.CW_USEDEFAULT,
win32.CW_USEDEFAULT,
10,
10,
nil,
nil,
instance,
nil,
)
ok = window!=nil
}
return window,ok
}
@(export)
win32_main_window_callback :: proc(window: win32.HWND, message: u32, wparam: win32.WPARAM, lparam: win32.LPARAM) -> win32.LRESULT {
result: win32.LRESULT = 0
switch message {
case:
result = win32.DefWindowProcA(window, message, wparam, lparam)
}
return result
}
foreign import User32 "system:User32.lib"
@(default_calling_convention = "stdcall")
foreign User32 {
CreateWindowExA :: proc(dwExStyle: win32.DWORD, lpClassName: win32.LPCSTR, lpWindowName: win32.LPCSTR, dwStyle: win32.DWORD, X: c.int, Y: c.int, nWidth: c.int, nHeight: c.int, hWndParent: win32.HWND, hMenu: win32.HMENU, hInstance: win32.HINSTANCE, lpParam: rawptr) -> win32.HWND ---
RegisterClassA :: proc(lpWndClass: ^win32.WNDCLASSA) -> win32.ATOM ---
}
@kalsprite
Copy link
Copy Markdown
Author

complete bindings exist here -
https://github.com/ftphikari/direct_sound

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment