mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-22 06:14:45 -08:00
Day 9 completed
This commit is contained in:
parent
d87eb51698
commit
3a0d1124c9
@ -11,11 +11,14 @@
|
|||||||
#include "grime.h"
|
#include "grime.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "math_constants.h"
|
||||||
|
|
||||||
// #include <stdio.h>
|
// #include <stdio.h>
|
||||||
|
|
||||||
#include "win32.h"
|
// TODO : Implement sound ourselves
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "win32.h"
|
||||||
// Using this to get dualsense controllers
|
// Using this to get dualsense controllers
|
||||||
#include "JoyShockLibrary/JoyShockLibrary.h"
|
#include "JoyShockLibrary/JoyShockLibrary.h"
|
||||||
|
|
||||||
@ -67,18 +70,19 @@ struct WinDimensions
|
|||||||
u32 Height;
|
u32 Height;
|
||||||
};
|
};
|
||||||
|
|
||||||
global OffscreenBuffer BackBuffer;
|
|
||||||
global WinDimensions WindowDimensions;
|
|
||||||
|
|
||||||
global LPDIRECTSOUNDBUFFER DS_SecondaryBuffer;
|
|
||||||
global s32 DS_SecondaryBufferSize;
|
|
||||||
|
|
||||||
HRESULT WINAPI
|
HRESULT WINAPI
|
||||||
DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
|
DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
|
||||||
|
|
||||||
using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
|
using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
|
||||||
global DirectSoundCreateFn* direct_sound_create;
|
global DirectSoundCreateFn* direct_sound_create;
|
||||||
|
|
||||||
|
global OffscreenBuffer BackBuffer;
|
||||||
|
global WinDimensions WindowDimensions;
|
||||||
|
|
||||||
|
global LPDIRECTSOUNDBUFFER DS_SecondaryBuffer;
|
||||||
|
global s32 DS_SecondaryBuffer_Size;
|
||||||
|
global s32 DS_SecondaryBuffer_SamplesPerSecond;
|
||||||
|
global s32 DS_SecondaryBuffer_BytesPerSample;
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
|
init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
|
||||||
@ -152,6 +156,87 @@ init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct DS_SoundOutputTest
|
||||||
|
{
|
||||||
|
DWORD IsPlaying;
|
||||||
|
u32 RunningSampleIndex;
|
||||||
|
s32 WaveToneHz;
|
||||||
|
s32 WavePeriod;
|
||||||
|
s32 ToneVolume;
|
||||||
|
s32 LatencySampleCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
using DS_FillSoundBuffer_GetSampleValueFn = s16( DS_SoundOutputTest* sound_output );
|
||||||
|
|
||||||
|
internal s16
|
||||||
|
square_wave_sample_value( DS_SoundOutputTest* sound_output )
|
||||||
|
{
|
||||||
|
s16 sample_value = (sound_output->RunningSampleIndex / (sound_output->WavePeriod /2)) % 2 ?
|
||||||
|
sound_output->ToneVolume : - sound_output->ToneVolume;
|
||||||
|
|
||||||
|
return sample_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal s16
|
||||||
|
sine_wave_sample_value( DS_SoundOutputTest* sound_output )
|
||||||
|
{
|
||||||
|
local_persist f32 time = 0.f;
|
||||||
|
|
||||||
|
f32 sine_value = sinf( time );
|
||||||
|
s16 sample_value = scast(u16, sine_value * sound_output->ToneVolume);
|
||||||
|
|
||||||
|
time += TAU * 1.0f / scast(f32, sound_output->WavePeriod );
|
||||||
|
return sample_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ds_fill_soundbuffer_region( LPVOID region, DWORD region_size
|
||||||
|
, DS_SoundOutputTest* sound_output, DS_FillSoundBuffer_GetSampleValueFn* get_sample_value )
|
||||||
|
{
|
||||||
|
DWORD region_sample_count = region_size / DS_SecondaryBuffer_BytesPerSample;
|
||||||
|
s16* sample_out = rcast( s16*, region );
|
||||||
|
for ( DWORD sample_index = 0; sample_index < region_sample_count; ++ sample_index )
|
||||||
|
{
|
||||||
|
s16 sample_value = get_sample_value( sound_output );
|
||||||
|
++ sound_output->RunningSampleIndex;
|
||||||
|
|
||||||
|
*sample_out = sample_value;
|
||||||
|
++ sample_out;
|
||||||
|
|
||||||
|
*sample_out = sample_value;
|
||||||
|
++ sample_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ds_fill_sound_buffer_test( DS_SoundOutputTest* sound_output, DWORD byte_to_lock, DWORD bytes_to_write, DS_FillSoundBuffer_GetSampleValueFn* get_sample_value )
|
||||||
|
{
|
||||||
|
LPVOID region_1;
|
||||||
|
DWORD region_1_size;
|
||||||
|
LPVOID region_2;
|
||||||
|
DWORD region_2_size;
|
||||||
|
|
||||||
|
HRESULT ds_lock_result = DS_SecondaryBuffer->Lock( byte_to_lock, bytes_to_write
|
||||||
|
, & region_1, & region_1_size
|
||||||
|
, & region_2, & region_2_size
|
||||||
|
, 0 );
|
||||||
|
if ( ! SUCCEEDED( ds_lock_result ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : Assert that region sizes are valid
|
||||||
|
|
||||||
|
ds_fill_soundbuffer_region( region_1, region_1_size, sound_output, get_sample_value );
|
||||||
|
ds_fill_soundbuffer_region( region_2, region_2_size, sound_output, get_sample_value );
|
||||||
|
|
||||||
|
if ( ! SUCCEEDED( DS_SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size ) ))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal WinDimensions
|
internal WinDimensions
|
||||||
get_window_dimensions( HWND window_handle )
|
get_window_dimensions( HWND window_handle )
|
||||||
{
|
{
|
||||||
@ -484,12 +569,23 @@ WinMain(
|
|||||||
WinDimensions dimensions = get_window_dimensions( window_handle );
|
WinDimensions dimensions = get_window_dimensions( window_handle );
|
||||||
resize_dib_section( &BackBuffer, 1280, 720 );
|
resize_dib_section( &BackBuffer, 1280, 720 );
|
||||||
|
|
||||||
s32 ds_samples = 48000;
|
DS_SoundOutputTest sound_output;
|
||||||
s32 ds_samples_per_second = ds_samples * sizeof(s16) * 2;
|
sound_output.IsPlaying = 0;
|
||||||
s32 ds_bytes_per_sample = sizeof(s16) * 2;
|
DS_SecondaryBuffer_SamplesPerSecond = 48000;
|
||||||
DS_SecondaryBufferSize = ds_samples_per_second * ds_bytes_per_sample;
|
DS_SecondaryBuffer_BytesPerSample = sizeof(s16) * 2;
|
||||||
|
|
||||||
init_sound( window_handle, ds_samples, DS_SecondaryBufferSize );
|
DS_SecondaryBuffer_Size = DS_SecondaryBuffer_SamplesPerSecond * DS_SecondaryBuffer_BytesPerSample;
|
||||||
|
init_sound( window_handle, DS_SecondaryBuffer_SamplesPerSecond, DS_SecondaryBuffer_Size );
|
||||||
|
|
||||||
|
// Wave Sound Test
|
||||||
|
bool wave_switch = false;
|
||||||
|
sound_output.RunningSampleIndex = 0;
|
||||||
|
sound_output.WaveToneHz = 262;
|
||||||
|
sound_output.WavePeriod = DS_SecondaryBuffer_SamplesPerSecond / sound_output.WaveToneHz;
|
||||||
|
sound_output.ToneVolume = 3000;
|
||||||
|
sound_output.LatencySampleCount = DS_SecondaryBuffer_SamplesPerSecond / 15;
|
||||||
|
ds_fill_sound_buffer_test( & sound_output, 0, sound_output.LatencySampleCount * DS_SecondaryBuffer_BytesPerSample, & sine_wave_sample_value );
|
||||||
|
DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
|
||||||
|
|
||||||
// Graphics & Input Test
|
// Graphics & Input Test
|
||||||
u32 x_offset = 0;
|
u32 x_offset = 0;
|
||||||
@ -498,29 +594,23 @@ WinMain(
|
|||||||
// Controller State
|
// Controller State
|
||||||
bool xinput_detected = false;
|
bool xinput_detected = false;
|
||||||
|
|
||||||
u32 dpad_up = false;
|
b32 dpad_up = false;
|
||||||
u32 dpad_down = false;
|
b32 dpad_down = false;
|
||||||
u32 dpad_left = false;
|
b32 dpad_left = false;
|
||||||
u32 dpad_right = false;
|
b32 dpad_right = false;
|
||||||
u32 start = false;
|
b32 start = false;
|
||||||
u32 back = false;
|
b32 back = false;
|
||||||
u32 left_shoulder = false;
|
b32 left_shoulder = false;
|
||||||
u32 right_shoulder = false;
|
b32 right_shoulder = false;
|
||||||
u32 btn_a_button = false;
|
b32 btn_a = false;
|
||||||
u32 btn_b_button = false;
|
b32 btn_b = false;
|
||||||
u32 btn_x_button = false;
|
b32 btn_x = false;
|
||||||
u32 btn_y_button = false;
|
b32 btn_y = false;
|
||||||
u16 stick_left_x = 0;
|
u16 stick_left_x = 0;
|
||||||
u16 stick_left_y = 0;
|
u16 stick_left_y = 0;
|
||||||
u16 stick_right_x = 0;
|
u16 stick_right_x = 0;
|
||||||
u16 stick_right_y = 0;
|
u16 stick_right_y = 0;
|
||||||
|
|
||||||
// Square Wave - Sound Test
|
|
||||||
u32 ds_running_sample_index = 0;
|
|
||||||
s32 square_wave_tone_hz = 262;
|
|
||||||
s32 square_wave_period = ds_samples_per_second / square_wave_tone_hz;
|
|
||||||
s32 half_square_wave_period = square_wave_period / 2;
|
|
||||||
s32 square_wave_tone_volume = 3000;
|
|
||||||
|
|
||||||
// TODO : Add sine wave test
|
// TODO : Add sine wave test
|
||||||
|
|
||||||
@ -564,10 +654,10 @@ WinMain(
|
|||||||
back = pad->wButtons & XINPUT_GAMEPAD_BACK;
|
back = pad->wButtons & XINPUT_GAMEPAD_BACK;
|
||||||
left_shoulder = pad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER;
|
left_shoulder = pad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER;
|
||||||
right_shoulder = pad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
right_shoulder = pad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
||||||
btn_a_button = pad->wButtons & XINPUT_GAMEPAD_A;
|
btn_a = pad->wButtons & XINPUT_GAMEPAD_A;
|
||||||
btn_b_button = pad->wButtons & XINPUT_GAMEPAD_B;
|
btn_b = pad->wButtons & XINPUT_GAMEPAD_B;
|
||||||
btn_x_button = pad->wButtons & XINPUT_GAMEPAD_X;
|
btn_x = pad->wButtons & XINPUT_GAMEPAD_X;
|
||||||
btn_y_button = pad->wButtons & XINPUT_GAMEPAD_Y;
|
btn_y = pad->wButtons & XINPUT_GAMEPAD_Y;
|
||||||
|
|
||||||
stick_left_x = pad->sThumbLX;
|
stick_left_x = pad->sThumbLX;
|
||||||
stick_left_y = pad->sThumbLY;
|
stick_left_y = pad->sThumbLY;
|
||||||
@ -598,10 +688,10 @@ WinMain(
|
|||||||
back = state.buttons & JSMASK_MINUS;
|
back = state.buttons & JSMASK_MINUS;
|
||||||
left_shoulder = state.buttons & JSMASK_L;
|
left_shoulder = state.buttons & JSMASK_L;
|
||||||
right_shoulder = state.buttons & JSMASK_R;
|
right_shoulder = state.buttons & JSMASK_R;
|
||||||
btn_a_button = state.buttons & JSMASK_S;
|
btn_a = state.buttons & JSMASK_S;
|
||||||
btn_b_button = state.buttons & JSMASK_E;
|
btn_b = state.buttons & JSMASK_E;
|
||||||
btn_x_button = state.buttons & JSMASK_W;
|
btn_x = state.buttons & JSMASK_W;
|
||||||
btn_y_button = state.buttons & JSMASK_N;
|
btn_y = state.buttons & JSMASK_N;
|
||||||
|
|
||||||
stick_left_x = state.stickLX;
|
stick_left_x = state.stickLX;
|
||||||
stick_left_y = state.stickLY;
|
stick_left_y = state.stickLY;
|
||||||
@ -613,8 +703,6 @@ WinMain(
|
|||||||
x_offset -= dpad_left;
|
x_offset -= dpad_left;
|
||||||
y_offset += dpad_up;
|
y_offset += dpad_up;
|
||||||
y_offset -= dpad_down;
|
y_offset -= dpad_down;
|
||||||
// x_offset += left_stick_x;
|
|
||||||
// y_offset += left_stick_y;
|
|
||||||
|
|
||||||
if ( start )
|
if ( start )
|
||||||
{
|
{
|
||||||
@ -657,13 +745,33 @@ WinMain(
|
|||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
do {
|
do {
|
||||||
if ( btn_y_button )
|
if ( btn_y )
|
||||||
{
|
{
|
||||||
square_wave_tone_volume += 10;
|
sound_output.ToneVolume += 10;
|
||||||
}
|
}
|
||||||
if ( btn_b_button )
|
if ( btn_b )
|
||||||
{
|
{
|
||||||
square_wave_tone_volume -= 10;
|
sound_output.ToneVolume -= 10;
|
||||||
|
}
|
||||||
|
if ( btn_x )
|
||||||
|
{
|
||||||
|
sound_output.WaveToneHz += 1;
|
||||||
|
sound_output.WavePeriod = DS_SecondaryBuffer_SamplesPerSecond / sound_output.WaveToneHz;
|
||||||
|
}
|
||||||
|
if ( btn_a )
|
||||||
|
{
|
||||||
|
sound_output.WaveToneHz -= 1;
|
||||||
|
sound_output.WavePeriod = DS_SecondaryBuffer_SamplesPerSecond / sound_output.WaveToneHz;
|
||||||
|
}
|
||||||
|
if ( back )
|
||||||
|
{
|
||||||
|
wave_switch ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD ds_status = 0;
|
||||||
|
if ( SUCCEEDED( DS_SecondaryBuffer->GetStatus( & ds_status ) ) )
|
||||||
|
{
|
||||||
|
sound_output.IsPlaying = ds_status & DSBSTATUS_PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ds_play_cursor;
|
DWORD ds_play_cursor;
|
||||||
@ -673,76 +781,43 @@ WinMain(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD byte_to_lock = ds_running_sample_index * ds_bytes_per_sample % DS_SecondaryBufferSize;
|
DWORD target_cursor = (ds_play_cursor + sound_output.LatencySampleCount * DS_SecondaryBuffer_BytesPerSample) % DS_SecondaryBuffer_Size;
|
||||||
|
|
||||||
|
DWORD byte_to_lock = (sound_output.RunningSampleIndex * DS_SecondaryBuffer_BytesPerSample) % DS_SecondaryBuffer_Size;
|
||||||
DWORD bytes_to_write;
|
DWORD bytes_to_write;
|
||||||
if ( byte_to_lock == ds_play_cursor )
|
|
||||||
|
if ( byte_to_lock == target_cursor )
|
||||||
{
|
{
|
||||||
// At play cursor
|
// We are in the middle of playing. Wait for the write cursor to catch up.
|
||||||
bytes_to_write = DS_SecondaryBufferSize;
|
bytes_to_write = 0;
|
||||||
}
|
}
|
||||||
else if ( byte_to_lock > ds_play_cursor)
|
else if ( byte_to_lock > target_cursor)
|
||||||
{
|
{
|
||||||
// Infront of play cursor |--play--byte_to_write-->--|
|
// Infront of play cursor |--play--byte_to_write-->--|
|
||||||
bytes_to_write = DS_SecondaryBufferSize - byte_to_lock;
|
bytes_to_write = DS_SecondaryBuffer_Size - byte_to_lock;
|
||||||
bytes_to_write += ds_play_cursor;
|
bytes_to_write += target_cursor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Behind play cursor |--byte_to_write-->--play--|
|
// Behind play cursor |--byte_to_write-->--play--|
|
||||||
bytes_to_write = ds_play_cursor - byte_to_lock;
|
bytes_to_write = target_cursor - byte_to_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_to_write = max(bytes_to_write, 1);
|
if ( wave_switch )
|
||||||
|
{
|
||||||
|
ds_fill_sound_buffer_test( & sound_output, byte_to_lock, bytes_to_write, square_wave_sample_value );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ds_fill_sound_buffer_test( & sound_output, byte_to_lock, bytes_to_write, sine_wave_sample_value );
|
||||||
|
}
|
||||||
|
|
||||||
LPVOID region_1;
|
#if 1
|
||||||
DWORD region_1_size;
|
if ( sound_output.IsPlaying )
|
||||||
LPVOID region_2;
|
|
||||||
DWORD region_2_size;
|
|
||||||
|
|
||||||
HRESULT ds_lock_result = DS_SecondaryBuffer->Lock( byte_to_lock, bytes_to_write
|
|
||||||
, & region_1, & region_1_size
|
|
||||||
, & region_2, & region_2_size
|
|
||||||
, 0 );
|
|
||||||
if ( ! SUCCEEDED( ds_lock_result ) )
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// TODO : Assert that region sizes are valid
|
|
||||||
|
|
||||||
// TODO : Collapse these loops
|
|
||||||
DWORD region_1_sample_count = region_1_size / ds_bytes_per_sample;
|
|
||||||
s16* sample_out = rcast( s16*, region_1 );
|
|
||||||
for ( DWORD sample_index = 0; sample_index < region_1_sample_count; ++ sample_index )
|
|
||||||
{
|
|
||||||
s16 sample_value = (ds_running_sample_index / half_square_wave_period) % 2 ?
|
|
||||||
square_wave_tone_volume : -square_wave_tone_volume;
|
|
||||||
++ ds_running_sample_index;
|
|
||||||
|
|
||||||
*sample_out = sample_value;
|
|
||||||
++ sample_out;
|
|
||||||
|
|
||||||
*sample_out = sample_value;
|
|
||||||
++ sample_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD region_2_sample_count = region_2_size / ds_bytes_per_sample;
|
|
||||||
sample_out = rcast( s16*, region_2 );
|
|
||||||
for ( DWORD sample_index = 0; sample_index < region_2_sample_count; ++ sample_index )
|
|
||||||
{
|
|
||||||
s16 sample_value = (ds_running_sample_index / half_square_wave_period) % 2 ?
|
|
||||||
square_wave_tone_volume : -square_wave_tone_volume;
|
|
||||||
++ ds_running_sample_index;
|
|
||||||
|
|
||||||
*sample_out = sample_value;
|
|
||||||
++ sample_out;
|
|
||||||
|
|
||||||
*sample_out = sample_value;
|
|
||||||
++ sample_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DS_SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size );
|
|
||||||
|
|
||||||
DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
|
DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
|
||||||
} while(0);
|
} while(0);
|
||||||
}
|
}
|
||||||
|
22
project/platform/math_constants.h
Normal file
22
project/platform/math_constants.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# define CONSTANTS
|
||||||
|
# define EPSILON 1.19209290e-7f
|
||||||
|
# define ZERO 0.0f
|
||||||
|
# define ONE 1.0f
|
||||||
|
# define TWO_THIRDS 0.666666666666666666666666666666666666667f
|
||||||
|
|
||||||
|
# define TAU 6.28318530717958647692528676655900576f
|
||||||
|
# define PI 3.14159265358979323846264338327950288f
|
||||||
|
# define ONE_OVER_TAU 0.636619772367581343075535053490057448f
|
||||||
|
# define ONE_OVER_PI 0.159154943091895335768883763372514362f
|
||||||
|
|
||||||
|
# define TAU_OVER_2 3.14159265358979323846264338327950288f
|
||||||
|
# define TAU_OVER_4 1.570796326794896619231321691639751442f
|
||||||
|
# define TAU_OVER_8 0.785398163397448309615660845819875721f
|
||||||
|
|
||||||
|
# define E 2.71828182845904523536f
|
||||||
|
# define SQRT_TWO 1.41421356237309504880168872420969808f
|
||||||
|
# define SQRT_THREE 1.73205080756887729352744634150587236f
|
||||||
|
# define SQRT_FIVE 2.23606797749978969640917366873127623f
|
||||||
|
|
||||||
|
# define LOG_TWO 0.693147180559945309417232121458176568f
|
||||||
|
# define LOG_TEN 2.30258509299404568401799145468436421f
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user