From 0eecb215efe4d858c4a48b4c54389c6f7a43b6c0 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 23 Nov 2020 19:32:35 -0800 Subject: [PATCH] Cleanup audio system; put mixer in custom layer; hooks in win32 layer --- 4ed_system_api.cpp | 15 +- custom/4coder_audio.cpp | 165 +++++++++++++++- custom/4coder_audio.h | 46 ++++- custom/4coder_default_hooks.cpp | 4 +- custom/4coder_examples.cpp | 64 +----- custom/4coder_types.h | 36 +--- custom/generated/command_metadata.h | 81 ++++---- custom/generated/system_api.cpp | 10 +- custom/generated/system_api.h | 25 +-- custom/generated/system_api_constructor.cpp | 14 +- custom/generated/system_api_master_list.h | 5 +- platform_win32/win32_4ed.cpp | 7 +- platform_win32/win32_audio.cpp | 208 +++++++------------- 13 files changed, 363 insertions(+), 317 deletions(-) diff --git a/4ed_system_api.cpp b/4ed_system_api.cpp index 198d6913..60c07f8a 100644 --- a/4ed_system_api.cpp +++ b/4ed_system_api.cpp @@ -304,19 +304,14 @@ define_api(Arena *arena){ } { - API_Call *call = api_call(arena, api, "play_clip", "void"); - api_param(arena, call, "Audio_Clip", "clip"); - api_param(arena, call, "Audio_Control*", "control"); + API_Call *call = api_call(arena, api, "set_source_mixer", "void"); + api_param(arena, call, "void*", "ctx"); + api_param(arena, call, "Audio_Mix_Sources_Function*", "mix_func"); } { - API_Call *call = api_call(arena, api, "audio_is_playing", "b32"); - api_param(arena, call, "Audio_Control*", "control"); - } - - { - API_Call *call = api_call(arena, api, "audio_stop", "void"); - api_param(arena, call, "Audio_Control*", "control"); + API_Call *call = api_call(arena, api, "set_destination_mixer", "void"); + api_param(arena, call, "Audio_Mix_Destination_Function*", "mix_func"); } return(api); diff --git a/custom/4coder_audio.cpp b/custom/4coder_audio.cpp index a12173f6..22b26a3f 100644 --- a/custom/4coder_audio.cpp +++ b/custom/4coder_audio.cpp @@ -1,5 +1,168 @@ //////////////////////////////// -// NOTE(allen): Load Clip +// NOTE(allen): Default Mixer Helpers + +// TODO(allen): intrinsics wrappers +#include + +function u32 +AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend) +{ + // NOTE(casey): Returns the original value _prior_ to adding + u32 Result = _InterlockedExchangeAdd((long volatile*)Value, (long)Addend); + return(Result); +} + +function void +def_audio_begin_ticket_mutex(Audio_System *Crunky) +{ + u32 Ticket = AtomicAddU32AndReturnOriginal(&Crunky->ticket, 1); + while(Ticket != Crunky->serving) {_mm_pause();} +} + +function void +def_audio_end_ticket_mutex(Audio_System *Crunky) +{ + AtomicAddU32AndReturnOriginal(&Crunky->serving, 1); +} + + +//////////////////////////////// +// NOTE(allen): Default Mixer + +global Audio_System def_audio_system = {}; + +function void +def_audio_init(void){ + block_zero_struct(&def_audio_system); + system_set_source_mixer(&def_audio_system, def_audio_mix_sources); + system_set_destination_mixer(def_audio_mix_destination); +} + +function void +def_audio_play_clip(Audio_Clip clip, Audio_Control *control){ + clip.control = control; + Audio_System *Crunky = &def_audio_system; + def_audio_begin_ticket_mutex(Crunky); + if (Crunky->pending_clip_count < ArrayCount(Crunky->pending_clips)) + { + Crunky->pending_clips[Crunky->pending_clip_count++] = clip; + } + def_audio_end_ticket_mutex(Crunky); +} + +internal b32 +def_audio_is_playing(Audio_Control *control){ + Audio_System *Crunky = &def_audio_system; + b32 result = (Crunky->generation - control->generation < 2); + return(result); +} + +internal void +def_audio_stop(Audio_Control *control){ + Audio_System *Crunky = &def_audio_system; + def_audio_begin_ticket_mutex(Crunky); + + Audio_Clip *clip = Crunky->playing_clips; + for(u32 i = 0; + i < ArrayCount(Crunky->playing_clips); + i += 1, clip += 1){ + if (clip->control == control){ + clip->at_sample_index = clip->sample_count; + clip->control = 0; + } + } + control->loop = false; + + def_audio_end_ticket_mutex(Crunky); +} + +function void +def_audio_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count){ + Audio_System *Crunky = (Audio_System*)ctx; + def_audio_begin_ticket_mutex(Crunky); + // NOTE(casey): Move pending sounds into the playing list + { + Crunky->generation += 1; + u32 PendIndex = 0; + Audio_Clip *clip = Crunky->playing_clips; + for(u32 DestIndex = 0; + (DestIndex < ArrayCount(Crunky->playing_clips)) && (PendIndex < Crunky->pending_clip_count); + DestIndex += 1, clip += 1) + { + if (clip->at_sample_index == clip->sample_count) + { + Audio_Control *control = clip->control; + if (control == 0 || !control->loop){ + *clip = Crunky->pending_clips[PendIndex++]; + } + } + } + Crunky->pending_clip_count = 0; + } + def_audio_end_ticket_mutex(Crunky); + + // NOTE(casey): Mix all sounds into the output buffer + { + Audio_Clip *clip = Crunky->playing_clips; + for(u32 SoundIndex = 0; + SoundIndex < ArrayCount(Crunky->playing_clips); + SoundIndex += 1, clip += 1) + { + // NOTE(allen): Determine starting point + Audio_Control *control = clip->control; + if (control != 0 && control->loop && clip->at_sample_index == clip->sample_count){ + clip->at_sample_index = 0; + } + u32 base_sample_index = clip->at_sample_index; + + // NOTE(casey): Determine how many samples are left to play in this + // sound (possible none) + u32 SamplesToMix = clamp_top((clip->sample_count - clip->at_sample_index), sample_count); + clip->at_sample_index += SamplesToMix; + + // NOTE(casey): Load the volume out of the control if there is one, + // and if there is, update the generation and sample index so + // external controllers can take action + f32 LeftVol = clip->channel_volume[0]; + f32 RightVol = clip->channel_volume[1]; + if(SamplesToMix && control != 0) + { + LeftVol *= control->channel_volume[0]; + RightVol *= control->channel_volume[1]; + control->generation = Crunky->generation; + control->last_played_sample_index = clip->at_sample_index; + } + + // NOTE(casey): Mix samples + for(u32 SampleIndex = 0; + SampleIndex < SamplesToMix; + ++SampleIndex) + { + u32 src_index = 2*(base_sample_index + SampleIndex); + f32 Left = LeftVol *(f32)clip->samples[src_index + 0]; + f32 Right = RightVol*(f32)clip->samples[src_index + 1]; + + u32 dst_index = 2*SampleIndex; + mix_buffer[dst_index + 0] += Left; + mix_buffer[dst_index + 1] += Right; + } + } + } +} + +function void +def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count){ + u32 opl = sample_count*2; + for(u32 i = 0; i < opl; i += 1){ + f32 sample = src[i]; + f32 sat_sample = clamp(-32768.f, sample, 32767.f); + dst[i] = (i16)sat_sample; + } +} + + +//////////////////////////////// +// NOTE(allen): Loading Clip #if !defined(FCODER_SKIP_WAV) #define FCODER_SKIP_WAV diff --git a/custom/4coder_audio.h b/custom/4coder_audio.h index 328d5da9..879fb630 100644 --- a/custom/4coder_audio.h +++ b/custom/4coder_audio.h @@ -4,8 +4,52 @@ #define FCODER_AUDIO_H //////////////////////////////// -// NOTE(allen): Load Clip +// NOTE(allen): Default Mixer Types + +struct Audio_Control{ + volatile f32 channel_volume[2]; + volatile u32 generation; + volatile u32 last_played_sample_index; + volatile b32 loop; +}; + +struct Audio_Clip{ + i16 *samples; + Audio_Control *control; + f32 channel_volume[2]; + + u32 sample_count; + u32 at_sample_index; +}; + +struct Audio_System{ + volatile u32 quit; + volatile u32 ticket; + volatile u32 serving; + volatile u32 generation; + + Audio_Clip playing_clips[64]; + + // NOTE(casey): Requests to play sounds are written to a pending array to avoid long locking + volatile u32 pending_clip_count; + Audio_Clip pending_clips[64]; +}; + +//////////////////////////////// +// NOTE(allen): Default Mixer + +function void def_audio_init(void); +function void def_audio_play_clip(Audio_Clip clip, Audio_Control *control); +function b32 def_audio_is_playing(Audio_Control *control); +function void def_audio_stop(Audio_Control *control); + +function void def_audio_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count); +function void def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count); + +//////////////////////////////// +// NOTE(allen): Loading Clip function Audio_Clip audio_clip_from_wav_data(String_Const_u8 data); +function Audio_Clip audio_clip_from_wav_file_name(char *file_name); #endif //4CODER_AUDIO_H diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index ecdd794f..a4538b11 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -20,12 +20,14 @@ CUSTOM_DOC("Default command for responding to a startup event") } { + def_audio_init(); + Audio_Clip test_clip = audio_clip_from_wav_file_name("W:\\4ed\\audio_test\\raygun_zap.wav"); local_persist Audio_Control test_control = {}; test_control.channel_volume[0] = 1.f; test_control.channel_volume[1] = 1.f; - system_play_clip(test_clip, &test_control); + def_audio_play_clip(test_clip, &test_control); } } diff --git a/custom/4coder_examples.cpp b/custom/4coder_examples.cpp index c11f74f7..291fd54f 100644 --- a/custom/4coder_examples.cpp +++ b/custom/4coder_examples.cpp @@ -208,60 +208,6 @@ CUSTOM_DOC("Example of query_user_string and query_user_number") } } - -CUSTOM_COMMAND_SIG(test_the_new_api) -CUSTOM_DOC("If you are reading this I forgot to delete this test, please let me know") -{ - Query_Bar_Group group(app); - Query_Bar bar = {}; - bar.prompt = SCu8("Testing ... "); - if (!start_query_bar(app, &bar, 0)){ - return; - } - - Input_Event events[10]; - i32 count = 0; - - User_Input in = {}; - - for (;;) { - in = get_next_input(app, EventProperty_AnyKey, 0); - if (in.abort){ - return; - } - events[count] = in.event; - count += 1; - if (!event_is_dead_key(&in.event)) { - break; - } - } - - u64 codepoints[10] = {}; - i32 index = 0; - - for (Input_Event event_text = event_next_text_event(&in.event); - event_text.kind != InputEventKind_None; - event_text = event_next_text_event(&event_text)){ - String_Const_u8 writable = to_writable(&event_text); - if (writable.size) { - codepoints[index] = utf8_consume(writable.str, writable.size).codepoint; - index += 1; - } - } - - Scratch_Block scratch(app); - for (i32 i = 0; i < count; i += 1){ - String_Const_u8 string = stringize_keyboard_event(scratch, &events[i]); - print_message(app, string); - } - - for (i32 i = 0; i < index; i += 1){ - String_Const_u8 string = push_u8_stringf(scratch, "%llu\n", codepoints[i]); - print_message(app, string); - } - -} - global Audio_Control the_music_control = {}; CUSTOM_COMMAND_SIG(music_start) @@ -274,18 +220,18 @@ CUSTOM_DOC("Starts the music.") the_music_clip = audio_clip_from_wav_file_name("W:\\4ed\\audio_test\\chtulthu.wav"); } - if (!system_audio_is_playing(&the_music_control)){ + if (!def_audio_is_playing(&the_music_control)){ the_music_control.loop = true; the_music_control.channel_volume[0] = 1.f; the_music_control.channel_volume[1] = 1.f; - system_play_clip(the_music_clip, &the_music_control); + def_audio_play_clip(the_music_clip, &the_music_control); } } CUSTOM_COMMAND_SIG(music_stop) CUSTOM_DOC("Stops the music.") { - system_audio_stop(&the_music_control); + def_audio_stop(&the_music_control); } CUSTOM_COMMAND_SIG(hit_sfx) @@ -302,11 +248,11 @@ CUSTOM_DOC("Play the hit sound effect") local_persist Audio_Control controls[8] = {}; Audio_Control *control = &controls[index%8]; - if (!system_audio_is_playing(control)){ + if (!def_audio_is_playing(control)){ control->loop = false; control->channel_volume[0] = 1.f; control->channel_volume[1] = 1.f; - system_play_clip(the_hit_clip, control); + def_audio_play_clip(the_hit_clip, control); index += 1; } } diff --git a/custom/4coder_types.h b/custom/4coder_types.h index b48d551e..62d98145 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -789,36 +789,10 @@ struct Process_State{ //////////////////////////////// -api(custom) -struct Audio_Control{ - volatile f32 channel_volume[2]; - volatile u32 generation; - volatile u32 last_played_sample_index; - volatile b32 loop; -}; - -api(custom) -struct Audio_Clip{ - i16 *samples; - Audio_Control *control; - f32 channel_volume[2]; - - u32 sample_count; - u32 at_sample_index; -}; - -api(custom) -struct Audio_System{ - volatile u32 quit; - volatile u32 ticket; - volatile u32 serving; - volatile u32 generation; - - Audio_Clip playing_clips[64]; - - // NOTE(casey): Requests to play sounds are written to a pending array to avoid long locking - volatile u32 pending_clip_count; - Audio_Clip pending_clips[64]; -}; +// NOTE(allen): buffers are allocate with: +// array_count = channel_count*sample_count +// channel_count = 2 +typedef void Audio_Mix_Sources_Function(void *ctx, f32 *buffer, u32 sample_count); +typedef void Audio_Mix_Destination_Function(i16 *dst, f32 *src, u32 sample_count); #endif diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 3c0e996d..ccb589f8 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -2,7 +2,7 @@ #define command_id(c) (fcoder_metacmd_ID_##c) #define command_metadata(c) (&fcoder_metacmd_table[command_id(c)]) #define command_metadata_by_id(id) (&fcoder_metacmd_table[id]) -#define command_one_past_last_id 251 +#define command_one_past_last_id 250 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -227,7 +227,6 @@ CUSTOM_COMMAND_SIG(snippet_lister); CUSTOM_COMMAND_SIG(string_repeat); CUSTOM_COMMAND_SIG(suppress_mouse); CUSTOM_COMMAND_SIG(swap_panels); -CUSTOM_COMMAND_SIG(test_the_new_api); CUSTOM_COMMAND_SIG(theme_lister); CUSTOM_COMMAND_SIG(to_lowercase); CUSTOM_COMMAND_SIG(to_uppercase); @@ -272,7 +271,7 @@ char *source_name; i32 source_name_len; i32 line_number; }; -static Command_Metadata fcoder_metacmd_table[251] = { +static Command_Metadata fcoder_metacmd_table[250] = { { PROC_LINKS(allow_mouse, 0), false, "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 485 }, { PROC_LINKS(auto_indent_line_at_cursor, 0), false, "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "W:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 417 }, { PROC_LINKS(auto_indent_range, 0), false, "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "W:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 427 }, @@ -310,8 +309,8 @@ static Command_Metadata fcoder_metacmd_table[251] = { { PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 757 }, { PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2062 }, { PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 }, -{ PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 32 }, -{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 76 }, +{ PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 34 }, +{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 78 }, { PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 161 }, { PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 79 }, { PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 112 }, @@ -338,7 +337,7 @@ static Command_Metadata fcoder_metacmd_table[251] = { { PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 511 }, { PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 704 }, { PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 690 }, -{ PROC_LINKS(hit_sfx, 0), false, "hit_sfx", 7, "Play the hit sound effect", 25, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 291 }, +{ PROC_LINKS(hit_sfx, 0), false, "hit_sfx", 7, "Play the hit sound effect", 25, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 237 }, { PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "W:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 869 }, { PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 }, { PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 564 }, @@ -413,8 +412,8 @@ static Command_Metadata fcoder_metacmd_table[251] = { { PROC_LINKS(multi_paste, 0), false, "multi_paste", 11, "Paste multiple entries from the clipboard at once", 49, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 229 }, { PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 371 }, { PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 380 }, -{ PROC_LINKS(music_start, 0), false, "music_start", 11, "Starts the music.", 17, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 267 }, -{ PROC_LINKS(music_stop, 0), false, "music_stop", 10, "Stops the music.", 16, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 285 }, +{ PROC_LINKS(music_start, 0), false, "music_start", 11, "Starts the music.", 17, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 213 }, +{ PROC_LINKS(music_stop, 0), false, "music_stop", 10, "Stops the music.", 16, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 231 }, { PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 850 }, { PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 856 }, { PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1574 }, @@ -491,7 +490,6 @@ static Command_Metadata fcoder_metacmd_table[251] = { { PROC_LINKS(string_repeat, 0), false, "string_repeat", 13, "Example of query_user_string and query_user_number", 50, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 179 }, { PROC_LINKS(suppress_mouse, 0), false, "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 479 }, { PROC_LINKS(swap_panels, 0), false, "swap_panels", 11, "Swaps the active panel with it's sibling.", 41, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1682 }, -{ PROC_LINKS(test_the_new_api, 0), false, "test_the_new_api", 16, "If you are reading this I forgot to delete this test, please let me know", 72, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 212 }, { PROC_LINKS(theme_lister, 0), true, "theme_lister", 12, "Opens an interactive list of all registered themes.", 51, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 784 }, { PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 567 }, { PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 554 }, @@ -743,37 +741,36 @@ static i32 fcoder_metacmd_ID_snippet_lister = 214; static i32 fcoder_metacmd_ID_string_repeat = 215; static i32 fcoder_metacmd_ID_suppress_mouse = 216; static i32 fcoder_metacmd_ID_swap_panels = 217; -static i32 fcoder_metacmd_ID_test_the_new_api = 218; -static i32 fcoder_metacmd_ID_theme_lister = 219; -static i32 fcoder_metacmd_ID_to_lowercase = 220; -static i32 fcoder_metacmd_ID_to_uppercase = 221; -static i32 fcoder_metacmd_ID_toggle_filebar = 222; -static i32 fcoder_metacmd_ID_toggle_fps_meter = 223; -static i32 fcoder_metacmd_ID_toggle_fullscreen = 224; -static i32 fcoder_metacmd_ID_toggle_highlight_enclosing_scopes = 225; -static i32 fcoder_metacmd_ID_toggle_highlight_line_at_cursor = 226; -static i32 fcoder_metacmd_ID_toggle_line_numbers = 227; -static i32 fcoder_metacmd_ID_toggle_line_wrap = 228; -static i32 fcoder_metacmd_ID_toggle_mouse = 229; -static i32 fcoder_metacmd_ID_toggle_paren_matching_helper = 230; -static i32 fcoder_metacmd_ID_toggle_show_whitespace = 231; -static i32 fcoder_metacmd_ID_toggle_virtual_whitespace = 232; -static i32 fcoder_metacmd_ID_tutorial_maximize = 233; -static i32 fcoder_metacmd_ID_tutorial_minimize = 234; -static i32 fcoder_metacmd_ID_uncomment_line = 235; -static i32 fcoder_metacmd_ID_undo = 236; -static i32 fcoder_metacmd_ID_undo_all_buffers = 237; -static i32 fcoder_metacmd_ID_view_buffer_other_panel = 238; -static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 239; -static i32 fcoder_metacmd_ID_word_complete = 240; -static i32 fcoder_metacmd_ID_word_complete_drop_down = 241; -static i32 fcoder_metacmd_ID_write_block = 242; -static i32 fcoder_metacmd_ID_write_hack = 243; -static i32 fcoder_metacmd_ID_write_note = 244; -static i32 fcoder_metacmd_ID_write_space = 245; -static i32 fcoder_metacmd_ID_write_text_and_auto_indent = 246; -static i32 fcoder_metacmd_ID_write_text_input = 247; -static i32 fcoder_metacmd_ID_write_todo = 248; -static i32 fcoder_metacmd_ID_write_underscore = 249; -static i32 fcoder_metacmd_ID_write_zero_struct = 250; +static i32 fcoder_metacmd_ID_theme_lister = 218; +static i32 fcoder_metacmd_ID_to_lowercase = 219; +static i32 fcoder_metacmd_ID_to_uppercase = 220; +static i32 fcoder_metacmd_ID_toggle_filebar = 221; +static i32 fcoder_metacmd_ID_toggle_fps_meter = 222; +static i32 fcoder_metacmd_ID_toggle_fullscreen = 223; +static i32 fcoder_metacmd_ID_toggle_highlight_enclosing_scopes = 224; +static i32 fcoder_metacmd_ID_toggle_highlight_line_at_cursor = 225; +static i32 fcoder_metacmd_ID_toggle_line_numbers = 226; +static i32 fcoder_metacmd_ID_toggle_line_wrap = 227; +static i32 fcoder_metacmd_ID_toggle_mouse = 228; +static i32 fcoder_metacmd_ID_toggle_paren_matching_helper = 229; +static i32 fcoder_metacmd_ID_toggle_show_whitespace = 230; +static i32 fcoder_metacmd_ID_toggle_virtual_whitespace = 231; +static i32 fcoder_metacmd_ID_tutorial_maximize = 232; +static i32 fcoder_metacmd_ID_tutorial_minimize = 233; +static i32 fcoder_metacmd_ID_uncomment_line = 234; +static i32 fcoder_metacmd_ID_undo = 235; +static i32 fcoder_metacmd_ID_undo_all_buffers = 236; +static i32 fcoder_metacmd_ID_view_buffer_other_panel = 237; +static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 238; +static i32 fcoder_metacmd_ID_word_complete = 239; +static i32 fcoder_metacmd_ID_word_complete_drop_down = 240; +static i32 fcoder_metacmd_ID_write_block = 241; +static i32 fcoder_metacmd_ID_write_hack = 242; +static i32 fcoder_metacmd_ID_write_note = 243; +static i32 fcoder_metacmd_ID_write_space = 244; +static i32 fcoder_metacmd_ID_write_text_and_auto_indent = 245; +static i32 fcoder_metacmd_ID_write_text_input = 246; +static i32 fcoder_metacmd_ID_write_todo = 247; +static i32 fcoder_metacmd_ID_write_underscore = 248; +static i32 fcoder_metacmd_ID_write_zero_struct = 249; #endif diff --git a/custom/generated/system_api.cpp b/custom/generated/system_api.cpp index e28dee6b..8d364069 100644 --- a/custom/generated/system_api.cpp +++ b/custom/generated/system_api.cpp @@ -54,9 +54,8 @@ vtable->set_fullscreen = system_set_fullscreen; vtable->is_fullscreen = system_is_fullscreen; vtable->get_keyboard_modifiers = system_get_keyboard_modifiers; vtable->set_key_mode = system_set_key_mode; -vtable->play_clip = system_play_clip; -vtable->audio_is_playing = system_audio_is_playing; -vtable->audio_stop = system_audio_stop; +vtable->set_source_mixer = system_set_source_mixer; +vtable->set_destination_mixer = system_set_destination_mixer; } #if defined(DYNAMIC_LINK_API) function void @@ -115,9 +114,8 @@ system_set_fullscreen = vtable->set_fullscreen; system_is_fullscreen = vtable->is_fullscreen; system_get_keyboard_modifiers = vtable->get_keyboard_modifiers; system_set_key_mode = vtable->set_key_mode; -system_play_clip = vtable->play_clip; -system_audio_is_playing = vtable->audio_is_playing; -system_audio_stop = vtable->audio_stop; +system_set_source_mixer = vtable->set_source_mixer; +system_set_destination_mixer = vtable->set_destination_mixer; } #undef DYNAMIC_LINK_API #endif diff --git a/custom/generated/system_api.h b/custom/generated/system_api.h index ce1d2a12..0c3cc455 100644 --- a/custom/generated/system_api.h +++ b/custom/generated/system_api.h @@ -52,9 +52,8 @@ #define system_is_fullscreen_sig() b32 system_is_fullscreen(void) #define system_get_keyboard_modifiers_sig() Input_Modifier_Set system_get_keyboard_modifiers(Arena* arena) #define system_set_key_mode_sig() void system_set_key_mode(Key_Mode mode) -#define system_play_clip_sig() void system_play_clip(Audio_Clip clip, Audio_Control* control) -#define system_audio_is_playing_sig() b32 system_audio_is_playing(Audio_Control* control) -#define system_audio_stop_sig() void system_audio_stop(Audio_Control* control) +#define system_set_source_mixer_sig() void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func) +#define system_set_destination_mixer_sig() void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func) typedef String_Const_u8 system_get_path_type(Arena* arena, System_Path_Code path_code); typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name); typedef File_List system_get_file_list_type(Arena* arena, String_Const_u8 directory); @@ -109,9 +108,8 @@ typedef b32 system_set_fullscreen_type(b32 full_screen); typedef b32 system_is_fullscreen_type(void); typedef Input_Modifier_Set system_get_keyboard_modifiers_type(Arena* arena); typedef void system_set_key_mode_type(Key_Mode mode); -typedef void system_play_clip_type(Audio_Clip clip, Audio_Control* control); -typedef b32 system_audio_is_playing_type(Audio_Control* control); -typedef void system_audio_stop_type(Audio_Control* control); +typedef void system_set_source_mixer_type(void* ctx, Audio_Mix_Sources_Function* mix_func); +typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func); struct API_VTable_system{ system_get_path_type *get_path; system_get_canonical_type *get_canonical; @@ -167,9 +165,8 @@ system_set_fullscreen_type *set_fullscreen; system_is_fullscreen_type *is_fullscreen; system_get_keyboard_modifiers_type *get_keyboard_modifiers; system_set_key_mode_type *set_key_mode; -system_play_clip_type *play_clip; -system_audio_is_playing_type *audio_is_playing; -system_audio_stop_type *audio_stop; +system_set_source_mixer_type *set_source_mixer; +system_set_destination_mixer_type *set_destination_mixer; }; #if defined(STATIC_LINK_API) internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code); @@ -226,9 +223,8 @@ internal b32 system_set_fullscreen(b32 full_screen); internal b32 system_is_fullscreen(void); internal Input_Modifier_Set system_get_keyboard_modifiers(Arena* arena); internal void system_set_key_mode(Key_Mode mode); -internal void system_play_clip(Audio_Clip clip, Audio_Control* control); -internal b32 system_audio_is_playing(Audio_Control* control); -internal void system_audio_stop(Audio_Control* control); +internal void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func); +internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func); #undef STATIC_LINK_API #elif defined(DYNAMIC_LINK_API) global system_get_path_type *system_get_path = 0; @@ -285,8 +281,7 @@ global system_set_fullscreen_type *system_set_fullscreen = 0; global system_is_fullscreen_type *system_is_fullscreen = 0; global system_get_keyboard_modifiers_type *system_get_keyboard_modifiers = 0; global system_set_key_mode_type *system_set_key_mode = 0; -global system_play_clip_type *system_play_clip = 0; -global system_audio_is_playing_type *system_audio_is_playing = 0; -global system_audio_stop_type *system_audio_stop = 0; +global system_set_source_mixer_type *system_set_source_mixer = 0; +global system_set_destination_mixer_type *system_set_destination_mixer = 0; #undef DYNAMIC_LINK_API #endif diff --git a/custom/generated/system_api_constructor.cpp b/custom/generated/system_api_constructor.cpp index 80290dce..4fc4933b 100644 --- a/custom/generated/system_api_constructor.cpp +++ b/custom/generated/system_api_constructor.cpp @@ -246,17 +246,13 @@ API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_ke api_param(arena, call, "Key_Mode", "mode"); } { -API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("play_clip"), string_u8_litexpr("void"), string_u8_litexpr("")); -api_param(arena, call, "Audio_Clip", "clip"); -api_param(arena, call, "Audio_Control*", "control"); +API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_source_mixer"), string_u8_litexpr("void"), string_u8_litexpr("")); +api_param(arena, call, "void*", "ctx"); +api_param(arena, call, "Audio_Mix_Sources_Function*", "mix_func"); } { -API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("audio_is_playing"), string_u8_litexpr("b32"), string_u8_litexpr("")); -api_param(arena, call, "Audio_Control*", "control"); -} -{ -API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("audio_stop"), string_u8_litexpr("void"), string_u8_litexpr("")); -api_param(arena, call, "Audio_Control*", "control"); +API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_destination_mixer"), string_u8_litexpr("void"), string_u8_litexpr("")); +api_param(arena, call, "Audio_Mix_Destination_Function*", "mix_func"); } return(result); } diff --git a/custom/generated/system_api_master_list.h b/custom/generated/system_api_master_list.h index 11839fd4..da8ae63a 100644 --- a/custom/generated/system_api_master_list.h +++ b/custom/generated/system_api_master_list.h @@ -52,6 +52,5 @@ api(system) function b32 set_fullscreen(b32 full_screen); api(system) function b32 is_fullscreen(void); api(system) function Input_Modifier_Set get_keyboard_modifiers(Arena* arena); api(system) function void set_key_mode(Key_Mode mode); -api(system) function void play_clip(Audio_Clip clip, Audio_Control* control); -api(system) function b32 audio_is_playing(Audio_Control* control); -api(system) function void audio_stop(Audio_Control* control); +api(system) function void set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func); +api(system) function void set_destination_mixer(Audio_Mix_Destination_Function* mix_func); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index 8ebc8d5e..cbfa1c28 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -179,9 +179,12 @@ struct Win32_Vars{ HWND window_handle; f32 screen_scale_factor; - Audio_System audio_system; DWORD audio_thread_id; + void *volatile audio_mix_ctx; + Audio_Mix_Sources_Function *volatile audio_mix_sources; + Audio_Mix_Destination_Function *volatile audio_mix_destination; + f64 count_per_usecond; b32 first; i32 running_cli; @@ -1812,7 +1815,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS win32_resize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); // NOTE(allen): Audio Init - win32vars.audio_thread_id = win32_audio_init(&win32vars.audio_system); + win32vars.audio_thread_id = win32_audio_init(); // NOTE(allen): Misc Init if (!AddClipboardFormatListener(win32vars.window_handle)){ diff --git a/platform_win32/win32_audio.cpp b/platform_win32/win32_audio.cpp index a9861b3d..1c8f3b46 100644 --- a/platform_win32/win32_audio.cpp +++ b/platform_win32/win32_audio.cpp @@ -1,164 +1,96 @@ //////////////////////////////// -// NOTE(allen): Win32 Audio Helpers +// NOTE(allen): Quick Mutex + +// TODO(allen): intrinsics wrappers +#include function u32 AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend) { // NOTE(casey): Returns the original value _prior_ to adding - u32 Result = _InterlockedExchangeAdd(Value, Addend); + u32 Result = _InterlockedExchangeAdd((long volatile*)Value, (long)Addend); return(Result); } +global volatile u32 win32_audio_ticket = 0; +global volatile u32 win32_audio_serving = 0; + function void -win32_begin_ticket_mutex(Audio_System *Crunky) +win32_audio_begin_ticket_mutex(void) { - u32 Ticket = AtomicAddU32AndReturnOriginal(&Crunky->ticket, 1); - while(Ticket != Crunky->serving) {_mm_pause();} + u32 Ticket = AtomicAddU32AndReturnOriginal(&win32_audio_ticket, 1); + while(Ticket != win32_audio_serving) {_mm_pause();} +} +function void +win32_audio_end_ticket_mutex(void) +{ + AtomicAddU32AndReturnOriginal(&win32_audio_serving, 1); +} + +//////////////////////////////// +// NOTE(allen): Fallback Mixers + +function void +win32_default_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count){ } function void -win32_end_ticket_mutex(Audio_System *Crunky) -{ - AtomicAddU32AndReturnOriginal(&Crunky->serving, 1); +win32_default_mix_destination(i16 *dst, f32 *src, u32 sample_count){ + u32 opl = sample_count*2; + for(u32 i = 0; i < sample_count; i += 1){ + dst[i] = (i16)src[i]; + } } //////////////////////////////// // NOTE(allen): Win32 Audio System API internal -system_play_clip_sig(){ - clip.control = control; - Audio_System *Crunky = &win32vars.audio_system; - win32_begin_ticket_mutex(Crunky); - if (Crunky->pending_clip_count < ArrayCount(Crunky->pending_clips)) - { - Crunky->pending_clips[Crunky->pending_clip_count++] = clip; - } - win32_end_ticket_mutex(Crunky); +system_set_source_mixer_sig(){ + win32_audio_begin_ticket_mutex(); + win32vars.audio_mix_ctx = ctx; + win32vars.audio_mix_sources = mix_func; + win32_audio_end_ticket_mutex(); } internal -system_audio_is_playing_sig(){ - Audio_System *Crunky = (Audio_System *)&win32vars.audio_system; - b32 result = (Crunky->generation - control->generation < 2); - return(result); -} - -internal -system_audio_stop_sig(){ - Audio_System *Crunky = (Audio_System *)&win32vars.audio_system; - win32_begin_ticket_mutex(Crunky); - - Audio_Clip *clip = Crunky->playing_clips; - for(u32 i = 0; - i < ArrayCount(Crunky->playing_clips); - i += 1, clip += 1){ - if (clip->control == control){ - clip->at_sample_index = clip->sample_count; - } - } - control->loop = false; - - win32_end_ticket_mutex(Crunky); +system_set_destination_mixer_sig(){ + win32_audio_begin_ticket_mutex(); + win32vars.audio_mix_destination = mix_func; + win32_audio_end_ticket_mutex(); } //////////////////////////////// // NOTE(allen): Win32 Audio Loop -function void -win32_mix_audio(Audio_System *Crunky, u32 SampleCount, i16 *Dest, void *mix_buffer_memory){ - // NOTE(casey): Clear the output buffer - u32 MixBufferSize = SampleCount*2*sizeof(f32); - f32 *MixBuffer = (f32 *)mix_buffer_memory; - memset(MixBuffer, 0, MixBufferSize); - - win32_begin_ticket_mutex(Crunky); - // NOTE(casey): Move pending sounds into the playing list - { - Crunky->generation += 1; - u32 PendIndex = 0; - Audio_Clip *clip = Crunky->playing_clips; - for(u32 DestIndex = 0; - (DestIndex < ArrayCount(Crunky->playing_clips)) && (PendIndex < Crunky->pending_clip_count); - DestIndex += 1, clip += 1) - { - if (clip->at_sample_index == clip->sample_count) - { - Audio_Control *control = clip->control; - if (control == 0 || !control->loop){ - *clip = Crunky->pending_clips[PendIndex++]; - } - } - } - Crunky->pending_clip_count = 0; - } - win32_end_ticket_mutex(Crunky); - - // NOTE(casey): Mix all sounds into the output buffer - { - Audio_Clip *clip = Crunky->playing_clips; - for(u32 SoundIndex = 0; - SoundIndex < ArrayCount(Crunky->playing_clips); - SoundIndex += 1, clip += 1) - { - Audio_Control *control = clip->control; - if (control != 0 && control->loop && clip->at_sample_index == clip->sample_count){ - clip->at_sample_index = 0; - } - - // NOTE(casey): Determine how many samples are left to play in this - // sound (possible none) - u32 SamplesToMix = Min((clip->sample_count - clip->at_sample_index), SampleCount); - clip->at_sample_index += SamplesToMix; - - // NOTE(casey): Load the volume out of the control if there is one, - // and if there is, update the generation and sample index so - // external controllers can take action - f32 LeftVol = clip->channel_volume[0]; - f32 RightVol = clip->channel_volume[1]; - if(SamplesToMix && control != 0) - { - LeftVol *= control->channel_volume[0]; - RightVol *= control->channel_volume[1]; - control->generation = Crunky->generation; - control->last_played_sample_index = clip->at_sample_index; - } - - // NOTE(casey): Mix samples - for(u32 SampleIndex = 0; - SampleIndex < SamplesToMix; - ++SampleIndex) - { - u32 src_index = 2*(clip->at_sample_index + SampleIndex); - f32 Left = LeftVol*(f32)clip->samples[src_index + 0]; - f32 Right = RightVol*(f32)clip->samples[src_index + 1]; - - u32 dst_index = 2*SampleIndex; - MixBuffer[dst_index + 0] += Left; - MixBuffer[dst_index + 1] += Right; - } - } - - for(u32 SampleIndex = 0; - SampleIndex < SampleCount; - ++SampleIndex) - { - f32 Left = MixBuffer[2*SampleIndex + 0]; - f32 Right = MixBuffer[2*SampleIndex + 1]; - - Dest[2*SampleIndex + 0] = (i16)Left; - Dest[2*SampleIndex + 1] = (i16)Right; - } - } -} - function b32 -win32_submit_audio(Audio_System *Crunky, HWAVEOUT WaveOut, WAVEHDR *Header, u32 SampleCount, void *mix_buffer){ +win32_submit_audio(HWAVEOUT WaveOut, WAVEHDR *Header, u32 SampleCount, f32 *mix_buffer){ b32 Result = false; + // NOTE(allen): prep buffers + u32 mix_buffer_size = SampleCount*2*sizeof(f32); + memset(mix_buffer, 0, mix_buffer_size); i16 *Samples = (i16 *)Header->lpData; - win32_mix_audio(Crunky, SampleCount, Samples, mix_buffer); + // NOTE(allen): prep mixer pointers + win32_audio_begin_ticket_mutex(); + void *audio_mix_ctx = win32vars.audio_mix_ctx; + Audio_Mix_Sources_Function *audio_mix_sources = win32vars.audio_mix_sources; + Audio_Mix_Destination_Function *audio_mix_destination = win32vars.audio_mix_destination; + win32_audio_end_ticket_mutex(); + + if (audio_mix_sources == 0){ + audio_mix_sources = win32_default_mix_sources; + } + if (audio_mix_destination == 0){ + audio_mix_destination = win32_default_mix_destination; + } + + // NOTE(allen): mix + audio_mix_sources(audio_mix_ctx, mix_buffer, SampleCount); + audio_mix_destination(Samples, mix_buffer, SampleCount); + + // NOTE(allen): send final samples to win32 DWORD Error = waveOutPrepareHeader(WaveOut, Header, sizeof(*Header)); if(Error == MMSYSERR_NOERROR) { @@ -175,8 +107,6 @@ win32_submit_audio(Audio_System *Crunky, HWAVEOUT WaveOut, WAVEHDR *Header, u32 function DWORD WINAPI win32_audio_loop(void *Passthrough){ - Audio_System *Crunky = (Audio_System *)Passthrough; - // // NOTE(casey): Set up our audio output buffer // @@ -206,6 +136,8 @@ win32_audio_loop(void *Passthrough){ Format.nBlockAlign = (Format.nChannels*Format.wBitsPerSample)/8; Format.nAvgBytesPerSec = Format.nBlockAlign * Format.nSamplesPerSec; + b32 quit = false; + void *MixBuffer = 0; void *AudioBufferMemory = 0; if(waveOutOpen(&WaveOut, WAVE_MAPPER, &Format, GetCurrentThreadId(), 0, CALLBACK_THREAD) == MMSYSERR_NOERROR) @@ -227,17 +159,19 @@ win32_audio_loop(void *Passthrough){ At += TotalBufferSize; - win32_submit_audio(Crunky, WaveOut, Header, SamplesPerBuffer, MixBuffer); + win32_submit_audio(WaveOut, Header, SamplesPerBuffer, (f32*)MixBuffer); } } else { - Crunky->quit = true; + // TODO(allen): audio error + quit = true; } } else { - Crunky->quit = true; + // TODO(allen): audio error + quit = true; } // @@ -245,7 +179,7 @@ win32_audio_loop(void *Passthrough){ // SetTimer(0, 0, 100, 0); - while(!Crunky->quit) + for (;!quit;) { MSG Message = {}; GetMessage(&Message, 0, 0, 0); @@ -259,7 +193,7 @@ win32_audio_loop(void *Passthrough){ waveOutUnprepareHeader(WaveOut, Header, sizeof(*Header)); - win32_submit_audio(Crunky, WaveOut, Header, SamplesPerBuffer, MixBuffer); + win32_submit_audio(WaveOut, Header, SamplesPerBuffer, (f32*)MixBuffer); } } @@ -277,9 +211,9 @@ win32_audio_loop(void *Passthrough){ } function DWORD -win32_audio_init(Audio_System *audio_system){ +win32_audio_init(void){ DWORD thread_id = 0; - HANDLE handle = CreateThread(0, 0, win32_audio_loop, audio_system, 0, &thread_id); + HANDLE handle = CreateThread(0, 0, win32_audio_loop, 0, 0, &thread_id); CloseHandle(handle); return(thread_id); }