diff --git a/4ed_system_api.cpp b/4ed_system_api.cpp index 81e11430..198d6913 100644 --- a/4ed_system_api.cpp +++ b/4ed_system_api.cpp @@ -309,6 +309,16 @@ define_api(Arena *arena){ api_param(arena, call, "Audio_Control*", "control"); } + { + 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"); + } + return(api); } diff --git a/custom/4coder_audio.cpp b/custom/4coder_audio.cpp index c68ce7d3..a12173f6 100644 --- a/custom/4coder_audio.cpp +++ b/custom/4coder_audio.cpp @@ -68,6 +68,9 @@ audio_clip_from_wav_data(String_Const_u8 data){ (Format->wChannels == 2) && (Format->wBitsPerSample == 16) && (Format->dwSamplesPerSec == 48000)){ + for (u32 i = 0; i < 2; i += 1){ + Result.channel_volume[i] = 1.f; + } Result.sample_count = SampleDataSize / (Format->wChannels*Format->wBitsPerSample/8); Result.samples = (i16 *)Samples; } diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index e5f1d968..ecdd794f 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -23,8 +23,8 @@ CUSTOM_DOC("Default command for responding to a startup event") 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.left_volume_knob = AUDIO_PRODUCER_KNOB_ONE; - test_control.right_volume_knob = AUDIO_PRODUCER_KNOB_ONE; + test_control.channel_volume[0] = 1.f; + test_control.channel_volume[1] = 1.f; system_play_clip(test_clip, &test_control); } } diff --git a/custom/4coder_examples.cpp b/custom/4coder_examples.cpp index 9d3763be..c11f74f7 100644 --- a/custom/4coder_examples.cpp +++ b/custom/4coder_examples.cpp @@ -262,6 +262,55 @@ CUSTOM_DOC("If you are reading this I forgot to delete this test, please let me } +global Audio_Control the_music_control = {}; + +CUSTOM_COMMAND_SIG(music_start) +CUSTOM_DOC("Starts the music.") +{ + local_persist Audio_Clip the_music_clip = {}; + local_persist b32 initialized = false; + if (!initialized){ + initialized = true; + the_music_clip = audio_clip_from_wav_file_name("W:\\4ed\\audio_test\\chtulthu.wav"); + } + + if (!system_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); + } +} + +CUSTOM_COMMAND_SIG(music_stop) +CUSTOM_DOC("Stops the music.") +{ + system_audio_stop(&the_music_control); +} + +CUSTOM_COMMAND_SIG(hit_sfx) +CUSTOM_DOC("Play the hit sound effect") +{ + local_persist Audio_Clip the_hit_clip = {}; + local_persist b32 initialized = false; + if (!initialized){ + initialized = true; + the_hit_clip = audio_clip_from_wav_file_name("W:\\4ed\\audio_test\\hit.wav"); + } + + local_persist u32 index = 0; + local_persist Audio_Control controls[8] = {}; + + Audio_Control *control = &controls[index%8]; + if (!system_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); + index += 1; + } +} + // BOTTOM diff --git a/custom/4coder_types.h b/custom/4coder_types.h index 2d2c8826..b48d551e 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -791,17 +791,17 @@ struct Process_State{ api(custom) struct Audio_Control{ -#define AUDIO_PRODUCER_KNOB_ONE 256 - volatile u32 left_volume_knob; - volatile u32 right_volume_knob; + volatile f32 channel_volume[2]; volatile u32 generation; - volatile u32 last_played_sample_index;; + 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; @@ -814,7 +814,6 @@ struct Audio_System{ volatile u32 serving; volatile u32 generation; - u32 next_playing_clip_index; Audio_Clip playing_clips[64]; // NOTE(casey): Requests to play sounds are written to a pending array to avoid long locking diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index d14706b1..3c0e996d 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 248 +#define command_one_past_last_id 251 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -74,6 +74,7 @@ CUSTOM_COMMAND_SIG(goto_prev_jump); CUSTOM_COMMAND_SIG(goto_prev_jump_no_skips); CUSTOM_COMMAND_SIG(hide_filebar); CUSTOM_COMMAND_SIG(hide_scrollbar); +CUSTOM_COMMAND_SIG(hit_sfx); CUSTOM_COMMAND_SIG(hms_demo_tutorial); CUSTOM_COMMAND_SIG(if0_off); CUSTOM_COMMAND_SIG(if_read_only_goto_position); @@ -148,6 +149,8 @@ CUSTOM_COMMAND_SIG(move_up_to_blank_line_skip_whitespace); CUSTOM_COMMAND_SIG(multi_paste); CUSTOM_COMMAND_SIG(multi_paste_interactive); CUSTOM_COMMAND_SIG(multi_paste_interactive_quick); +CUSTOM_COMMAND_SIG(music_start); +CUSTOM_COMMAND_SIG(music_stop); CUSTOM_COMMAND_SIG(open_all_code); CUSTOM_COMMAND_SIG(open_all_code_recursive); CUSTOM_COMMAND_SIG(open_file_in_quotes); @@ -269,7 +272,7 @@ char *source_name; i32 source_name_len; i32 line_number; }; -static Command_Metadata fcoder_metacmd_table[248] = { +static Command_Metadata fcoder_metacmd_table[251] = { { 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 }, @@ -335,6 +338,7 @@ static Command_Metadata fcoder_metacmd_table[248] = { { 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(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 }, @@ -409,6 +413,8 @@ static Command_Metadata fcoder_metacmd_table[248] = { { 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(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 }, @@ -584,187 +590,190 @@ static i32 fcoder_metacmd_ID_goto_prev_jump = 61; static i32 fcoder_metacmd_ID_goto_prev_jump_no_skips = 62; static i32 fcoder_metacmd_ID_hide_filebar = 63; static i32 fcoder_metacmd_ID_hide_scrollbar = 64; -static i32 fcoder_metacmd_ID_hms_demo_tutorial = 65; -static i32 fcoder_metacmd_ID_if0_off = 66; -static i32 fcoder_metacmd_ID_if_read_only_goto_position = 67; -static i32 fcoder_metacmd_ID_if_read_only_goto_position_same_panel = 68; -static i32 fcoder_metacmd_ID_increase_face_size = 69; -static i32 fcoder_metacmd_ID_interactive_kill_buffer = 70; -static i32 fcoder_metacmd_ID_interactive_new = 71; -static i32 fcoder_metacmd_ID_interactive_open = 72; -static i32 fcoder_metacmd_ID_interactive_open_or_new = 73; -static i32 fcoder_metacmd_ID_interactive_switch_buffer = 74; -static i32 fcoder_metacmd_ID_jump_to_definition = 75; -static i32 fcoder_metacmd_ID_jump_to_definition_at_cursor = 76; -static i32 fcoder_metacmd_ID_jump_to_last_point = 77; -static i32 fcoder_metacmd_ID_keyboard_macro_finish_recording = 78; -static i32 fcoder_metacmd_ID_keyboard_macro_replay = 79; -static i32 fcoder_metacmd_ID_keyboard_macro_start_recording = 80; -static i32 fcoder_metacmd_ID_kill_buffer = 81; -static i32 fcoder_metacmd_ID_kill_tutorial = 82; -static i32 fcoder_metacmd_ID_left_adjust_view = 83; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 84; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 85; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 86; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 87; -static i32 fcoder_metacmd_ID_list_all_locations = 88; -static i32 fcoder_metacmd_ID_list_all_locations_case_insensitive = 89; -static i32 fcoder_metacmd_ID_list_all_locations_of_identifier = 90; -static i32 fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 91; -static i32 fcoder_metacmd_ID_list_all_locations_of_selection = 92; -static i32 fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 93; -static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition = 94; -static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 95; -static i32 fcoder_metacmd_ID_list_all_substring_locations = 96; -static i32 fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 97; -static i32 fcoder_metacmd_ID_load_project = 98; -static i32 fcoder_metacmd_ID_load_theme_current_buffer = 99; -static i32 fcoder_metacmd_ID_load_themes_default_folder = 100; -static i32 fcoder_metacmd_ID_load_themes_hot_directory = 101; -static i32 fcoder_metacmd_ID_make_directory_query = 102; -static i32 fcoder_metacmd_ID_miblo_decrement_basic = 103; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 104; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 105; -static i32 fcoder_metacmd_ID_miblo_increment_basic = 106; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 107; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 108; -static i32 fcoder_metacmd_ID_mouse_wheel_change_face_size = 109; -static i32 fcoder_metacmd_ID_mouse_wheel_scroll = 110; -static i32 fcoder_metacmd_ID_move_down = 111; -static i32 fcoder_metacmd_ID_move_down_10 = 112; -static i32 fcoder_metacmd_ID_move_down_textual = 113; -static i32 fcoder_metacmd_ID_move_down_to_blank_line = 114; -static i32 fcoder_metacmd_ID_move_down_to_blank_line_end = 115; -static i32 fcoder_metacmd_ID_move_down_to_blank_line_skip_whitespace = 116; -static i32 fcoder_metacmd_ID_move_left = 117; -static i32 fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 118; -static i32 fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 119; -static i32 fcoder_metacmd_ID_move_left_token_boundary = 120; -static i32 fcoder_metacmd_ID_move_left_whitespace_boundary = 121; -static i32 fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 122; -static i32 fcoder_metacmd_ID_move_line_down = 123; -static i32 fcoder_metacmd_ID_move_line_up = 124; -static i32 fcoder_metacmd_ID_move_right = 125; -static i32 fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 126; -static i32 fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 127; -static i32 fcoder_metacmd_ID_move_right_token_boundary = 128; -static i32 fcoder_metacmd_ID_move_right_whitespace_boundary = 129; -static i32 fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 130; -static i32 fcoder_metacmd_ID_move_up = 131; -static i32 fcoder_metacmd_ID_move_up_10 = 132; -static i32 fcoder_metacmd_ID_move_up_to_blank_line = 133; -static i32 fcoder_metacmd_ID_move_up_to_blank_line_end = 134; -static i32 fcoder_metacmd_ID_move_up_to_blank_line_skip_whitespace = 135; -static i32 fcoder_metacmd_ID_multi_paste = 136; -static i32 fcoder_metacmd_ID_multi_paste_interactive = 137; -static i32 fcoder_metacmd_ID_multi_paste_interactive_quick = 138; -static i32 fcoder_metacmd_ID_open_all_code = 139; -static i32 fcoder_metacmd_ID_open_all_code_recursive = 140; -static i32 fcoder_metacmd_ID_open_file_in_quotes = 141; -static i32 fcoder_metacmd_ID_open_in_other = 142; -static i32 fcoder_metacmd_ID_open_long_braces = 143; -static i32 fcoder_metacmd_ID_open_long_braces_break = 144; -static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 145; -static i32 fcoder_metacmd_ID_open_matching_file_cpp = 146; -static i32 fcoder_metacmd_ID_open_panel_hsplit = 147; -static i32 fcoder_metacmd_ID_open_panel_vsplit = 148; -static i32 fcoder_metacmd_ID_page_down = 149; -static i32 fcoder_metacmd_ID_page_up = 150; -static i32 fcoder_metacmd_ID_paste = 151; -static i32 fcoder_metacmd_ID_paste_and_indent = 152; -static i32 fcoder_metacmd_ID_paste_next = 153; -static i32 fcoder_metacmd_ID_paste_next_and_indent = 154; -static i32 fcoder_metacmd_ID_place_in_scope = 155; -static i32 fcoder_metacmd_ID_play_with_a_counter = 156; -static i32 fcoder_metacmd_ID_profile_clear = 157; -static i32 fcoder_metacmd_ID_profile_disable = 158; -static i32 fcoder_metacmd_ID_profile_enable = 159; -static i32 fcoder_metacmd_ID_profile_inspect = 160; -static i32 fcoder_metacmd_ID_project_command_lister = 161; -static i32 fcoder_metacmd_ID_project_fkey_command = 162; -static i32 fcoder_metacmd_ID_project_go_to_root_directory = 163; -static i32 fcoder_metacmd_ID_query_replace = 164; -static i32 fcoder_metacmd_ID_query_replace_identifier = 165; -static i32 fcoder_metacmd_ID_query_replace_selection = 166; -static i32 fcoder_metacmd_ID_quick_swap_buffer = 167; -static i32 fcoder_metacmd_ID_redo = 168; -static i32 fcoder_metacmd_ID_redo_all_buffers = 169; -static i32 fcoder_metacmd_ID_rename_file_query = 170; -static i32 fcoder_metacmd_ID_reopen = 171; -static i32 fcoder_metacmd_ID_replace_in_all_buffers = 172; -static i32 fcoder_metacmd_ID_replace_in_buffer = 173; -static i32 fcoder_metacmd_ID_replace_in_range = 174; -static i32 fcoder_metacmd_ID_reverse_search = 175; -static i32 fcoder_metacmd_ID_reverse_search_identifier = 176; -static i32 fcoder_metacmd_ID_save = 177; -static i32 fcoder_metacmd_ID_save_all_dirty_buffers = 178; -static i32 fcoder_metacmd_ID_save_to_query = 179; -static i32 fcoder_metacmd_ID_search = 180; -static i32 fcoder_metacmd_ID_search_identifier = 181; -static i32 fcoder_metacmd_ID_seek_beginning_of_line = 182; -static i32 fcoder_metacmd_ID_seek_beginning_of_textual_line = 183; -static i32 fcoder_metacmd_ID_seek_end_of_line = 184; -static i32 fcoder_metacmd_ID_seek_end_of_textual_line = 185; -static i32 fcoder_metacmd_ID_select_all = 186; -static i32 fcoder_metacmd_ID_select_next_scope_absolute = 187; -static i32 fcoder_metacmd_ID_select_next_scope_after_current = 188; -static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 189; -static i32 fcoder_metacmd_ID_select_prev_top_most_scope = 190; -static i32 fcoder_metacmd_ID_select_surrounding_scope = 191; -static i32 fcoder_metacmd_ID_select_surrounding_scope_maximal = 192; -static i32 fcoder_metacmd_ID_set_eol_mode_from_contents = 193; -static i32 fcoder_metacmd_ID_set_eol_mode_to_binary = 194; -static i32 fcoder_metacmd_ID_set_eol_mode_to_crlf = 195; -static i32 fcoder_metacmd_ID_set_eol_mode_to_lf = 196; -static i32 fcoder_metacmd_ID_set_face_size = 197; -static i32 fcoder_metacmd_ID_set_face_size_this_buffer = 198; -static i32 fcoder_metacmd_ID_set_mark = 199; -static i32 fcoder_metacmd_ID_set_mode_to_notepad_like = 200; -static i32 fcoder_metacmd_ID_set_mode_to_original = 201; -static i32 fcoder_metacmd_ID_setup_build_bat = 202; -static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 203; -static i32 fcoder_metacmd_ID_setup_build_sh = 204; -static i32 fcoder_metacmd_ID_setup_new_project = 205; -static i32 fcoder_metacmd_ID_show_filebar = 206; -static i32 fcoder_metacmd_ID_show_scrollbar = 207; -static i32 fcoder_metacmd_ID_show_the_log_graph = 208; -static i32 fcoder_metacmd_ID_snipe_backward_whitespace_or_token_boundary = 209; -static i32 fcoder_metacmd_ID_snipe_forward_whitespace_or_token_boundary = 210; -static i32 fcoder_metacmd_ID_snippet_lister = 211; -static i32 fcoder_metacmd_ID_string_repeat = 212; -static i32 fcoder_metacmd_ID_suppress_mouse = 213; -static i32 fcoder_metacmd_ID_swap_panels = 214; -static i32 fcoder_metacmd_ID_test_the_new_api = 215; -static i32 fcoder_metacmd_ID_theme_lister = 216; -static i32 fcoder_metacmd_ID_to_lowercase = 217; -static i32 fcoder_metacmd_ID_to_uppercase = 218; -static i32 fcoder_metacmd_ID_toggle_filebar = 219; -static i32 fcoder_metacmd_ID_toggle_fps_meter = 220; -static i32 fcoder_metacmd_ID_toggle_fullscreen = 221; -static i32 fcoder_metacmd_ID_toggle_highlight_enclosing_scopes = 222; -static i32 fcoder_metacmd_ID_toggle_highlight_line_at_cursor = 223; -static i32 fcoder_metacmd_ID_toggle_line_numbers = 224; -static i32 fcoder_metacmd_ID_toggle_line_wrap = 225; -static i32 fcoder_metacmd_ID_toggle_mouse = 226; -static i32 fcoder_metacmd_ID_toggle_paren_matching_helper = 227; -static i32 fcoder_metacmd_ID_toggle_show_whitespace = 228; -static i32 fcoder_metacmd_ID_toggle_virtual_whitespace = 229; -static i32 fcoder_metacmd_ID_tutorial_maximize = 230; -static i32 fcoder_metacmd_ID_tutorial_minimize = 231; -static i32 fcoder_metacmd_ID_uncomment_line = 232; -static i32 fcoder_metacmd_ID_undo = 233; -static i32 fcoder_metacmd_ID_undo_all_buffers = 234; -static i32 fcoder_metacmd_ID_view_buffer_other_panel = 235; -static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 236; -static i32 fcoder_metacmd_ID_word_complete = 237; -static i32 fcoder_metacmd_ID_word_complete_drop_down = 238; -static i32 fcoder_metacmd_ID_write_block = 239; -static i32 fcoder_metacmd_ID_write_hack = 240; -static i32 fcoder_metacmd_ID_write_note = 241; -static i32 fcoder_metacmd_ID_write_space = 242; -static i32 fcoder_metacmd_ID_write_text_and_auto_indent = 243; -static i32 fcoder_metacmd_ID_write_text_input = 244; -static i32 fcoder_metacmd_ID_write_todo = 245; -static i32 fcoder_metacmd_ID_write_underscore = 246; -static i32 fcoder_metacmd_ID_write_zero_struct = 247; +static i32 fcoder_metacmd_ID_hit_sfx = 65; +static i32 fcoder_metacmd_ID_hms_demo_tutorial = 66; +static i32 fcoder_metacmd_ID_if0_off = 67; +static i32 fcoder_metacmd_ID_if_read_only_goto_position = 68; +static i32 fcoder_metacmd_ID_if_read_only_goto_position_same_panel = 69; +static i32 fcoder_metacmd_ID_increase_face_size = 70; +static i32 fcoder_metacmd_ID_interactive_kill_buffer = 71; +static i32 fcoder_metacmd_ID_interactive_new = 72; +static i32 fcoder_metacmd_ID_interactive_open = 73; +static i32 fcoder_metacmd_ID_interactive_open_or_new = 74; +static i32 fcoder_metacmd_ID_interactive_switch_buffer = 75; +static i32 fcoder_metacmd_ID_jump_to_definition = 76; +static i32 fcoder_metacmd_ID_jump_to_definition_at_cursor = 77; +static i32 fcoder_metacmd_ID_jump_to_last_point = 78; +static i32 fcoder_metacmd_ID_keyboard_macro_finish_recording = 79; +static i32 fcoder_metacmd_ID_keyboard_macro_replay = 80; +static i32 fcoder_metacmd_ID_keyboard_macro_start_recording = 81; +static i32 fcoder_metacmd_ID_kill_buffer = 82; +static i32 fcoder_metacmd_ID_kill_tutorial = 83; +static i32 fcoder_metacmd_ID_left_adjust_view = 84; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 85; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 86; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 87; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 88; +static i32 fcoder_metacmd_ID_list_all_locations = 89; +static i32 fcoder_metacmd_ID_list_all_locations_case_insensitive = 90; +static i32 fcoder_metacmd_ID_list_all_locations_of_identifier = 91; +static i32 fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 92; +static i32 fcoder_metacmd_ID_list_all_locations_of_selection = 93; +static i32 fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 94; +static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition = 95; +static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 96; +static i32 fcoder_metacmd_ID_list_all_substring_locations = 97; +static i32 fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 98; +static i32 fcoder_metacmd_ID_load_project = 99; +static i32 fcoder_metacmd_ID_load_theme_current_buffer = 100; +static i32 fcoder_metacmd_ID_load_themes_default_folder = 101; +static i32 fcoder_metacmd_ID_load_themes_hot_directory = 102; +static i32 fcoder_metacmd_ID_make_directory_query = 103; +static i32 fcoder_metacmd_ID_miblo_decrement_basic = 104; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 105; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 106; +static i32 fcoder_metacmd_ID_miblo_increment_basic = 107; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 108; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 109; +static i32 fcoder_metacmd_ID_mouse_wheel_change_face_size = 110; +static i32 fcoder_metacmd_ID_mouse_wheel_scroll = 111; +static i32 fcoder_metacmd_ID_move_down = 112; +static i32 fcoder_metacmd_ID_move_down_10 = 113; +static i32 fcoder_metacmd_ID_move_down_textual = 114; +static i32 fcoder_metacmd_ID_move_down_to_blank_line = 115; +static i32 fcoder_metacmd_ID_move_down_to_blank_line_end = 116; +static i32 fcoder_metacmd_ID_move_down_to_blank_line_skip_whitespace = 117; +static i32 fcoder_metacmd_ID_move_left = 118; +static i32 fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 119; +static i32 fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 120; +static i32 fcoder_metacmd_ID_move_left_token_boundary = 121; +static i32 fcoder_metacmd_ID_move_left_whitespace_boundary = 122; +static i32 fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 123; +static i32 fcoder_metacmd_ID_move_line_down = 124; +static i32 fcoder_metacmd_ID_move_line_up = 125; +static i32 fcoder_metacmd_ID_move_right = 126; +static i32 fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 127; +static i32 fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 128; +static i32 fcoder_metacmd_ID_move_right_token_boundary = 129; +static i32 fcoder_metacmd_ID_move_right_whitespace_boundary = 130; +static i32 fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 131; +static i32 fcoder_metacmd_ID_move_up = 132; +static i32 fcoder_metacmd_ID_move_up_10 = 133; +static i32 fcoder_metacmd_ID_move_up_to_blank_line = 134; +static i32 fcoder_metacmd_ID_move_up_to_blank_line_end = 135; +static i32 fcoder_metacmd_ID_move_up_to_blank_line_skip_whitespace = 136; +static i32 fcoder_metacmd_ID_multi_paste = 137; +static i32 fcoder_metacmd_ID_multi_paste_interactive = 138; +static i32 fcoder_metacmd_ID_multi_paste_interactive_quick = 139; +static i32 fcoder_metacmd_ID_music_start = 140; +static i32 fcoder_metacmd_ID_music_stop = 141; +static i32 fcoder_metacmd_ID_open_all_code = 142; +static i32 fcoder_metacmd_ID_open_all_code_recursive = 143; +static i32 fcoder_metacmd_ID_open_file_in_quotes = 144; +static i32 fcoder_metacmd_ID_open_in_other = 145; +static i32 fcoder_metacmd_ID_open_long_braces = 146; +static i32 fcoder_metacmd_ID_open_long_braces_break = 147; +static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 148; +static i32 fcoder_metacmd_ID_open_matching_file_cpp = 149; +static i32 fcoder_metacmd_ID_open_panel_hsplit = 150; +static i32 fcoder_metacmd_ID_open_panel_vsplit = 151; +static i32 fcoder_metacmd_ID_page_down = 152; +static i32 fcoder_metacmd_ID_page_up = 153; +static i32 fcoder_metacmd_ID_paste = 154; +static i32 fcoder_metacmd_ID_paste_and_indent = 155; +static i32 fcoder_metacmd_ID_paste_next = 156; +static i32 fcoder_metacmd_ID_paste_next_and_indent = 157; +static i32 fcoder_metacmd_ID_place_in_scope = 158; +static i32 fcoder_metacmd_ID_play_with_a_counter = 159; +static i32 fcoder_metacmd_ID_profile_clear = 160; +static i32 fcoder_metacmd_ID_profile_disable = 161; +static i32 fcoder_metacmd_ID_profile_enable = 162; +static i32 fcoder_metacmd_ID_profile_inspect = 163; +static i32 fcoder_metacmd_ID_project_command_lister = 164; +static i32 fcoder_metacmd_ID_project_fkey_command = 165; +static i32 fcoder_metacmd_ID_project_go_to_root_directory = 166; +static i32 fcoder_metacmd_ID_query_replace = 167; +static i32 fcoder_metacmd_ID_query_replace_identifier = 168; +static i32 fcoder_metacmd_ID_query_replace_selection = 169; +static i32 fcoder_metacmd_ID_quick_swap_buffer = 170; +static i32 fcoder_metacmd_ID_redo = 171; +static i32 fcoder_metacmd_ID_redo_all_buffers = 172; +static i32 fcoder_metacmd_ID_rename_file_query = 173; +static i32 fcoder_metacmd_ID_reopen = 174; +static i32 fcoder_metacmd_ID_replace_in_all_buffers = 175; +static i32 fcoder_metacmd_ID_replace_in_buffer = 176; +static i32 fcoder_metacmd_ID_replace_in_range = 177; +static i32 fcoder_metacmd_ID_reverse_search = 178; +static i32 fcoder_metacmd_ID_reverse_search_identifier = 179; +static i32 fcoder_metacmd_ID_save = 180; +static i32 fcoder_metacmd_ID_save_all_dirty_buffers = 181; +static i32 fcoder_metacmd_ID_save_to_query = 182; +static i32 fcoder_metacmd_ID_search = 183; +static i32 fcoder_metacmd_ID_search_identifier = 184; +static i32 fcoder_metacmd_ID_seek_beginning_of_line = 185; +static i32 fcoder_metacmd_ID_seek_beginning_of_textual_line = 186; +static i32 fcoder_metacmd_ID_seek_end_of_line = 187; +static i32 fcoder_metacmd_ID_seek_end_of_textual_line = 188; +static i32 fcoder_metacmd_ID_select_all = 189; +static i32 fcoder_metacmd_ID_select_next_scope_absolute = 190; +static i32 fcoder_metacmd_ID_select_next_scope_after_current = 191; +static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 192; +static i32 fcoder_metacmd_ID_select_prev_top_most_scope = 193; +static i32 fcoder_metacmd_ID_select_surrounding_scope = 194; +static i32 fcoder_metacmd_ID_select_surrounding_scope_maximal = 195; +static i32 fcoder_metacmd_ID_set_eol_mode_from_contents = 196; +static i32 fcoder_metacmd_ID_set_eol_mode_to_binary = 197; +static i32 fcoder_metacmd_ID_set_eol_mode_to_crlf = 198; +static i32 fcoder_metacmd_ID_set_eol_mode_to_lf = 199; +static i32 fcoder_metacmd_ID_set_face_size = 200; +static i32 fcoder_metacmd_ID_set_face_size_this_buffer = 201; +static i32 fcoder_metacmd_ID_set_mark = 202; +static i32 fcoder_metacmd_ID_set_mode_to_notepad_like = 203; +static i32 fcoder_metacmd_ID_set_mode_to_original = 204; +static i32 fcoder_metacmd_ID_setup_build_bat = 205; +static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 206; +static i32 fcoder_metacmd_ID_setup_build_sh = 207; +static i32 fcoder_metacmd_ID_setup_new_project = 208; +static i32 fcoder_metacmd_ID_show_filebar = 209; +static i32 fcoder_metacmd_ID_show_scrollbar = 210; +static i32 fcoder_metacmd_ID_show_the_log_graph = 211; +static i32 fcoder_metacmd_ID_snipe_backward_whitespace_or_token_boundary = 212; +static i32 fcoder_metacmd_ID_snipe_forward_whitespace_or_token_boundary = 213; +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; #endif diff --git a/custom/generated/system_api.cpp b/custom/generated/system_api.cpp index 724f0b82..e28dee6b 100644 --- a/custom/generated/system_api.cpp +++ b/custom/generated/system_api.cpp @@ -55,6 +55,8 @@ 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; } #if defined(DYNAMIC_LINK_API) function void @@ -114,6 +116,8 @@ 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; } #undef DYNAMIC_LINK_API #endif diff --git a/custom/generated/system_api.h b/custom/generated/system_api.h index 5d39f00f..ce1d2a12 100644 --- a/custom/generated/system_api.h +++ b/custom/generated/system_api.h @@ -53,6 +53,8 @@ #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) 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); @@ -108,6 +110,8 @@ 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); struct API_VTable_system{ system_get_path_type *get_path; system_get_canonical_type *get_canonical; @@ -164,6 +168,8 @@ 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; }; #if defined(STATIC_LINK_API) internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code); @@ -221,6 +227,8 @@ 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); #undef STATIC_LINK_API #elif defined(DYNAMIC_LINK_API) global system_get_path_type *system_get_path = 0; @@ -278,5 +286,7 @@ 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; #undef DYNAMIC_LINK_API #endif diff --git a/custom/generated/system_api_constructor.cpp b/custom/generated/system_api_constructor.cpp index 152a3c58..80290dce 100644 --- a/custom/generated/system_api_constructor.cpp +++ b/custom/generated/system_api_constructor.cpp @@ -250,5 +250,13 @@ API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("play_c 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("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"); +} return(result); } diff --git a/custom/generated/system_api_master_list.h b/custom/generated/system_api_master_list.h index 3ed646ff..11839fd4 100644 --- a/custom/generated/system_api_master_list.h +++ b/custom/generated/system_api_master_list.h @@ -53,3 +53,5 @@ 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); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index 2b1f7774..8ebc8d5e 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -359,14 +359,6 @@ system_set_key_mode_sig(){ win32vars.key_mode = mode; } -//////////////////////////////// -// NOTE(allen): Audio - -internal -system_play_clip_sig(){ - win32_play_clip(clip, control); -} - //////////////////////////////// // NOTE(allen): Clipboard diff --git a/platform_win32/win32_audio.cpp b/platform_win32/win32_audio.cpp index 9d1e3ca2..a9861b3d 100644 --- a/platform_win32/win32_audio.cpp +++ b/platform_win32/win32_audio.cpp @@ -1,5 +1,5 @@ //////////////////////////////// -// NOTE(allen): Win32 Audio Functions +// NOTE(allen): Win32 Audio Helpers function u32 AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend) @@ -22,8 +22,11 @@ win32_end_ticket_mutex(Audio_System *Crunky) AtomicAddU32AndReturnOriginal(&Crunky->serving, 1); } -function void -win32_play_clip(Audio_Clip clip, Audio_Control *control){ +//////////////////////////////// +// 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); @@ -34,60 +37,127 @@ win32_play_clip(Audio_Clip clip, Audio_Control *control){ win32_end_ticket_mutex(Crunky); } -function void -win32_mix_audio(Audio_System *Crunky, u32 SampleCount, i16 *Dest){ - // NOTE(casey): Move pending sounds into the playing list +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); - ++Crunky->generation; - for(u32 PendIndex = 0; - PendIndex < Crunky->pending_clip_count; - ++PendIndex) - { - u32 DestIndex = Crunky->next_playing_clip_index++ % ArrayCount(Crunky->playing_clips); - Crunky->playing_clips[DestIndex] = Crunky->pending_clips[PendIndex]; + + 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); +} + +//////////////////////////////// +// 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; } - Crunky->pending_clip_count = 0; win32_end_ticket_mutex(Crunky); - memset(Dest, 0, SampleCount*4); - for(u32 SoundIndex = 0; - SoundIndex < ArrayCount(Crunky->playing_clips); - ++SoundIndex) + // NOTE(casey): Mix all sounds into the output buffer { - Audio_Clip Sound = Crunky->playing_clips[SoundIndex]; - u32 SamplesToMix = Min((Sound.sample_count - Sound.at_sample_index), SampleCount); - Crunky->playing_clips[SoundIndex].at_sample_index += SamplesToMix; - - i32 LeftVol = AUDIO_PRODUCER_KNOB_ONE; - i32 RightVol = AUDIO_PRODUCER_KNOB_ONE; - if(SamplesToMix && Sound.control) - { - LeftVol = Sound.control->left_volume_knob; - RightVol = Sound.control->right_volume_knob; - Sound.control->generation = Crunky->generation; - Sound.control->last_played_sample_index = Crunky->playing_clips[SoundIndex].at_sample_index; - } - + 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 < SamplesToMix; + SampleIndex < SampleCount; ++SampleIndex) { - u32 src_base_indx = 2*(Sound.at_sample_index + SampleIndex); - u32 dst_base_indx = 2*SampleIndex; - Dest[dst_base_indx + 0] += (i16)(LeftVol*(i32)Sound.samples[src_base_indx + 0]/AUDIO_PRODUCER_KNOB_ONE); - Dest[dst_base_indx + 1] += (i16)(RightVol*(i32)Sound.samples[src_base_indx + 1]/AUDIO_PRODUCER_KNOB_ONE); + 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){ +win32_submit_audio(Audio_System *Crunky, HWAVEOUT WaveOut, WAVEHDR *Header, u32 SampleCount, void *mix_buffer){ b32 Result = false; - u32 SampleCount = Header->dwBufferLength/4; i16 *Samples = (i16 *)Header->lpData; - win32_mix_audio(Crunky, SampleCount, Samples); + win32_mix_audio(Crunky, SampleCount, Samples, mix_buffer); DWORD Error = waveOutPrepareHeader(WaveOut, Header, sizeof(*Header)); if(Error == MMSYSERR_NOERROR) @@ -120,7 +190,8 @@ win32_audio_loop(void *Passthrough){ u32 BufferSize = SamplesPerBuffer*BytesPerSample; u32 HeaderSize = sizeof(WAVEHDR); u32 TotalBufferSize = (BufferSize+HeaderSize); - u32 TotalAudioMemorySize = BufferCount*TotalBufferSize; + u32 MixBufferSize = (SamplesPerBuffer*ChannelCount*sizeof(f32)); + u32 TotalAudioMemorySize = BufferCount*TotalBufferSize + MixBufferSize; // // NOTE(casey): Initialize audio out @@ -135,24 +206,28 @@ win32_audio_loop(void *Passthrough){ Format.nBlockAlign = (Format.nChannels*Format.wBitsPerSample)/8; Format.nAvgBytesPerSec = Format.nBlockAlign * Format.nSamplesPerSec; + void *MixBuffer = 0; + void *AudioBufferMemory = 0; if(waveOutOpen(&WaveOut, WAVE_MAPPER, &Format, GetCurrentThreadId(), 0, CALLBACK_THREAD) == MMSYSERR_NOERROR) { - void *AudioBufferMemory = VirtualAlloc(0, TotalAudioMemorySize, MEM_COMMIT, PAGE_READWRITE); + AudioBufferMemory = VirtualAlloc(0, TotalAudioMemorySize, MEM_COMMIT, PAGE_READWRITE); if(AudioBufferMemory) { u8 *At = (u8 *)AudioBufferMemory; + MixBuffer = At; + At += MixBufferSize; + for(u32 BufferIndex = 0; BufferIndex < BufferCount; ++BufferIndex) { WAVEHDR *Header = (WAVEHDR *)At; - At += sizeof(WAVEHDR); - Header->lpData = (char *)At; - Header->dwBufferLength = TotalBufferSize; + Header->lpData = (char *)(Header + 1); + Header->dwBufferLength = BufferSize; At += TotalBufferSize; - win32_submit_audio(Crunky, WaveOut, Header); + win32_submit_audio(Crunky, WaveOut, Header, SamplesPerBuffer, MixBuffer); } } else @@ -168,7 +243,8 @@ win32_audio_loop(void *Passthrough){ // // NOTE(casey): Serve audio forever (until we are told to stop) // - // SetTimer(0, 0, 100, 0); + + SetTimer(0, 0, 100, 0); while(!Crunky->quit) { MSG Message = {}; @@ -183,10 +259,20 @@ win32_audio_loop(void *Passthrough){ waveOutUnprepareHeader(WaveOut, Header, sizeof(*Header)); - win32_submit_audio(Crunky, WaveOut, Header); + win32_submit_audio(Crunky, WaveOut, Header, SamplesPerBuffer, MixBuffer); } } + if(WaveOut) + { + waveOutClose(WaveOut); + } + + if(AudioBufferMemory) + { + VirtualFree(AudioBufferMemory, 0, MEM_RELEASE); + } + return(0); }