WASAPI wrapper example that offers directsound-like lock/unlock buffer functionality (but simpler): https://gist.github.com/mmozeiko/5a5b168e61aff4c1eaec0381da62808f#file-win32_wasapi-h

Header has just 4 functions - start/stop, lock/unlock. And then you fill in the buffer between lock/unlock calls in every frame. No worrying about callbacks or multithreading for your audio code to mix the samples. The buffer to fill is a "magic ringbuffer" allocated with virtual memory mapping trick - it gives just one array to fill, no need to handle split in the middle for wrapping back to start like dsound requires. It wraps around automatically. Internally wrapper creates large ringbuffer that you fill on every frame as much as you want. This means no audio going out or glitching when frame time stutters and you get longer frame than expected. This is done by running a background thread where samples are submitted to wasapi from ringbuffer with smallest buffer size. And lock/unlock allows to overwrite portion of ringbuffer that has not been submitted yet, so you can get lower latency even if you have prepared more samples than necessary.

example.c file with example code at the top.