Hack in new audio system contributed by casey; win32 only for now
parent
45ab2afe61
commit
a9a1931e34
|
@ -303,6 +303,12 @@ define_api(Arena *arena){
|
|||
api_param(arena, call, "Key_Mode", "mode");
|
||||
}
|
||||
|
||||
{
|
||||
API_Call *call = api_call(arena, api, "play_clip", "void");
|
||||
api_param(arena, call, "Audio_Clip", "clip");
|
||||
api_param(arena, call, "Audio_Control*", "control");
|
||||
}
|
||||
|
||||
return(api);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
////////////////////////////////
|
||||
// NOTE(allen): Load Clip
|
||||
|
||||
#if !defined(FCODER_SKIP_WAV)
|
||||
#define FCODER_SKIP_WAV
|
||||
#pragma pack(push, 1)
|
||||
struct wave_fmt_data
|
||||
{
|
||||
u16 wFormatTag;
|
||||
u16 wChannels;
|
||||
u32 dwSamplesPerSec;
|
||||
u32 dwAvgBytesPerSec;
|
||||
u16 wBlockAlign;
|
||||
u16 wBitsPerSample;
|
||||
};
|
||||
|
||||
struct riff_header
|
||||
{
|
||||
u32 ID;
|
||||
u32 DataSize;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
function Audio_Clip
|
||||
audio_clip_from_wav_data(String_Const_u8 data){
|
||||
Audio_Clip Result = {};
|
||||
|
||||
if (data.size >= 4 && *(u32 *)data.str == *(u32 *)"RIFF"){
|
||||
// NOTE(casey): This ROM is in WAV format
|
||||
|
||||
riff_header *RootHeader = (riff_header *)data.str;
|
||||
|
||||
wave_fmt_data *Format = 0;
|
||||
u32 SampleDataSize = 0;
|
||||
i16 *Samples = 0;
|
||||
|
||||
u32 At = sizeof(riff_header);
|
||||
u32 LastAt = At + ((RootHeader->DataSize + 1) & ~1);
|
||||
if ((*(u32 *)(data.str + At) == *(u32 *)"WAVE") &&
|
||||
(LastAt <= data.size)){
|
||||
At += sizeof(u32);
|
||||
while (At < LastAt){
|
||||
riff_header *Header = (riff_header *)(data.str + At);
|
||||
u32 DataAt = At + sizeof(riff_header);
|
||||
u32 EndAt = DataAt + ((Header->DataSize + 1) & ~1);
|
||||
if(EndAt <= data.size)
|
||||
{
|
||||
void *Data = (data.str + DataAt);
|
||||
if(Header->ID == *(u32 *)"fmt ")
|
||||
{
|
||||
Format = (wave_fmt_data *)Data;
|
||||
}
|
||||
else if(Header->ID == *(u32 *)"data")
|
||||
{
|
||||
SampleDataSize = Header->DataSize;
|
||||
Samples = (i16 *)Data;
|
||||
}
|
||||
}
|
||||
|
||||
At = EndAt;
|
||||
}
|
||||
}
|
||||
|
||||
if (Format &&
|
||||
Samples &&
|
||||
(Format->wFormatTag == 1) &&
|
||||
(Format->wChannels == 2) &&
|
||||
(Format->wBitsPerSample == 16) &&
|
||||
(Format->dwSamplesPerSec == 48000)){
|
||||
Result.sample_count = SampleDataSize / (Format->wChannels*Format->wBitsPerSample/8);
|
||||
Result.samples = (i16 *)Samples;
|
||||
}
|
||||
else{
|
||||
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
||||
}
|
||||
}
|
||||
else{
|
||||
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
||||
}
|
||||
|
||||
return(Result);
|
||||
}
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
function Audio_Clip
|
||||
audio_clip_from_wav_file_name(char *file_name){
|
||||
String_Const_u8 data = {};
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
if (file != 0){
|
||||
fseek(file, 0, SEEK_END);
|
||||
data.size = ftell(file);
|
||||
data.str = (u8*)malloc(data.size);
|
||||
if (data.str != 0 && data.size > 0){
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(data.str, data.size, 1, file);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
Audio_Clip result = audio_clip_from_wav_data(data);
|
||||
return(result);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/* date = November 23rd 2020 1:18 pm */
|
||||
|
||||
#ifndef FCODER_AUDIO_H
|
||||
#define FCODER_AUDIO_H
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Load Clip
|
||||
|
||||
function Audio_Clip audio_clip_from_wav_data(String_Const_u8 data);
|
||||
|
||||
#endif //4CODER_AUDIO_H
|
|
@ -18,6 +18,15 @@ CUSTOM_DOC("Default command for responding to a startup event")
|
|||
load_project(app);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
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;
|
||||
system_play_clip(test_clip, &test_control);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(default_try_exit)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#endif
|
||||
|
||||
#include "4coder_variables.h"
|
||||
#include "4coder_audio.h"
|
||||
#include "4coder_profile.h"
|
||||
#include "4coder_async_tasks.h"
|
||||
#include "4coder_token.h"
|
||||
|
@ -129,6 +130,7 @@
|
|||
#include "4coder_doc_commands.cpp"
|
||||
#include "4coder_docs.cpp"
|
||||
#include "4coder_variables.cpp"
|
||||
#include "4coder_audio.cpp"
|
||||
|
||||
#include "4coder_examples.cpp"
|
||||
|
||||
|
|
|
@ -787,4 +787,39 @@ struct Process_State{
|
|||
i64 return_code;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
api(custom)
|
||||
struct Audio_Control{
|
||||
#define AUDIO_PRODUCER_KNOB_ONE 256
|
||||
volatile u32 left_volume_knob;
|
||||
volatile u32 right_volume_knob;
|
||||
volatile u32 generation;
|
||||
volatile u32 last_played_sample_index;;
|
||||
};
|
||||
|
||||
api(custom)
|
||||
struct Audio_Clip{
|
||||
i16 *samples;
|
||||
Audio_Control *control;
|
||||
|
||||
u32 sample_count;
|
||||
u32 at_sample_index;
|
||||
};
|
||||
|
||||
api(custom)
|
||||
struct Audio_System{
|
||||
volatile u32 quit;
|
||||
volatile u32 ticket;
|
||||
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
|
||||
volatile u32 pending_clip_count;
|
||||
Audio_Clip pending_clips[64];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -307,8 +307,8 @@ static Command_Metadata fcoder_metacmd_table[248] = {
|
|||
{ 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, 23 },
|
||||
{ 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, 67 },
|
||||
{ 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(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 },
|
||||
|
|
|
@ -54,6 +54,7 @@ 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;
|
||||
}
|
||||
#if defined(DYNAMIC_LINK_API)
|
||||
function void
|
||||
|
@ -112,6 +113,7 @@ 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;
|
||||
}
|
||||
#undef DYNAMIC_LINK_API
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#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)
|
||||
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);
|
||||
|
@ -106,6 +107,7 @@ 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);
|
||||
struct API_VTable_system{
|
||||
system_get_path_type *get_path;
|
||||
system_get_canonical_type *get_canonical;
|
||||
|
@ -161,6 +163,7 @@ 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;
|
||||
};
|
||||
#if defined(STATIC_LINK_API)
|
||||
internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code);
|
||||
|
@ -217,6 +220,7 @@ 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);
|
||||
#undef STATIC_LINK_API
|
||||
#elif defined(DYNAMIC_LINK_API)
|
||||
global system_get_path_type *system_get_path = 0;
|
||||
|
@ -273,5 +277,6 @@ 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;
|
||||
#undef DYNAMIC_LINK_API
|
||||
#endif
|
||||
|
|
|
@ -245,5 +245,10 @@ api_param(arena, call, "Arena*", "arena");
|
|||
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_key_mode"), string_u8_litexpr("void"), string_u8_litexpr(""));
|
||||
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");
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -52,3 +52,4 @@ 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);
|
||||
|
|
|
@ -179,6 +179,9 @@ struct Win32_Vars{
|
|||
HWND window_handle;
|
||||
f32 screen_scale_factor;
|
||||
|
||||
Audio_System audio_system;
|
||||
DWORD audio_thread_id;
|
||||
|
||||
f64 count_per_usecond;
|
||||
b32 first;
|
||||
i32 running_cli;
|
||||
|
@ -259,6 +262,7 @@ handle_type_ptr(void *ptr){
|
|||
////////////////////////////////
|
||||
|
||||
#include "win32_4ed_functions.cpp"
|
||||
#include "win32_audio.cpp"
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
|
@ -355,9 +359,16 @@ system_set_key_mode_sig(){
|
|||
win32vars.key_mode = mode;
|
||||
}
|
||||
|
||||
//
|
||||
// Clipboard
|
||||
//
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Audio
|
||||
|
||||
internal
|
||||
system_play_clip_sig(){
|
||||
win32_play_clip(clip, control);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Clipboard
|
||||
|
||||
internal String_Const_u8
|
||||
win32_read_clipboard_contents(Thread_Context *tctx, Arena *arena){
|
||||
|
@ -1783,10 +1794,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Window and GL Initialization
|
||||
//
|
||||
|
||||
// NOTE(allen): Window Init
|
||||
RECT window_rect = {};
|
||||
if (plat_settings.set_window_size){
|
||||
window_rect.right = plat_settings.window_w;
|
||||
|
@ -1811,10 +1819,10 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
GetClientRect(win32vars.window_handle, &window_rect);
|
||||
win32_resize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top);
|
||||
|
||||
//
|
||||
// Misc System Initializations
|
||||
//
|
||||
// NOTE(allen): Audio Init
|
||||
win32vars.audio_thread_id = win32_audio_init(&win32vars.audio_system);
|
||||
|
||||
// NOTE(allen): Misc Init
|
||||
if (!AddClipboardFormatListener(win32vars.window_handle)){
|
||||
Scratch_Block scratch(win32vars.tctx);
|
||||
win32_output_error_string(scratch, ErrorString_UseLog);
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
////////////////////////////////
|
||||
// NOTE(allen): Win32 Audio Functions
|
||||
|
||||
function u32
|
||||
AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend)
|
||||
{
|
||||
// NOTE(casey): Returns the original value _prior_ to adding
|
||||
u32 Result = _InterlockedExchangeAdd(Value, Addend);
|
||||
return(Result);
|
||||
}
|
||||
|
||||
function void
|
||||
win32_begin_ticket_mutex(Audio_System *Crunky)
|
||||
{
|
||||
u32 Ticket = AtomicAddU32AndReturnOriginal(&Crunky->ticket, 1);
|
||||
while(Ticket != Crunky->serving) {_mm_pause();}
|
||||
}
|
||||
|
||||
function void
|
||||
win32_end_ticket_mutex(Audio_System *Crunky)
|
||||
{
|
||||
AtomicAddU32AndReturnOriginal(&Crunky->serving, 1);
|
||||
}
|
||||
|
||||
function void
|
||||
win32_play_clip(Audio_Clip clip, Audio_Control *control){
|
||||
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);
|
||||
}
|
||||
|
||||
function void
|
||||
win32_mix_audio(Audio_System *Crunky, u32 SampleCount, i16 *Dest){
|
||||
// NOTE(casey): Move pending sounds into the playing list
|
||||
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];
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
for(u32 SampleIndex = 0;
|
||||
SampleIndex < SamplesToMix;
|
||||
++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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function b32
|
||||
win32_submit_audio(Audio_System *Crunky, HWAVEOUT WaveOut, WAVEHDR *Header){
|
||||
b32 Result = false;
|
||||
|
||||
u32 SampleCount = Header->dwBufferLength/4;
|
||||
i16 *Samples = (i16 *)Header->lpData;
|
||||
win32_mix_audio(Crunky, SampleCount, Samples);
|
||||
|
||||
DWORD Error = waveOutPrepareHeader(WaveOut, Header, sizeof(*Header));
|
||||
if(Error == MMSYSERR_NOERROR)
|
||||
{
|
||||
Error = waveOutWrite(WaveOut, Header, sizeof(*Header));
|
||||
if(Error == MMSYSERR_NOERROR)
|
||||
{
|
||||
// NOTE(casey): Success
|
||||
Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return(Result);
|
||||
}
|
||||
|
||||
function DWORD WINAPI
|
||||
win32_audio_loop(void *Passthrough){
|
||||
Audio_System *Crunky = (Audio_System *)Passthrough;
|
||||
|
||||
//
|
||||
// NOTE(casey): Set up our audio output buffer
|
||||
//
|
||||
u32 SamplesPerSecond = 48000;
|
||||
u32 SamplesPerBuffer = 16*SamplesPerSecond/1000;
|
||||
u32 ChannelCount = 2;
|
||||
u32 BytesPerChannelValue = 2;
|
||||
u32 BytesPerSample = ChannelCount*BytesPerChannelValue;
|
||||
|
||||
u32 BufferCount = 3;
|
||||
u32 BufferSize = SamplesPerBuffer*BytesPerSample;
|
||||
u32 HeaderSize = sizeof(WAVEHDR);
|
||||
u32 TotalBufferSize = (BufferSize+HeaderSize);
|
||||
u32 TotalAudioMemorySize = BufferCount*TotalBufferSize;
|
||||
|
||||
//
|
||||
// NOTE(casey): Initialize audio out
|
||||
//
|
||||
HWAVEOUT WaveOut = {};
|
||||
|
||||
WAVEFORMATEX Format = {};
|
||||
Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
Format.nChannels = (WORD)ChannelCount;
|
||||
Format.wBitsPerSample = (WORD)(8*BytesPerChannelValue);
|
||||
Format.nSamplesPerSec = SamplesPerSecond;
|
||||
Format.nBlockAlign = (Format.nChannels*Format.wBitsPerSample)/8;
|
||||
Format.nAvgBytesPerSec = Format.nBlockAlign * Format.nSamplesPerSec;
|
||||
|
||||
if(waveOutOpen(&WaveOut, WAVE_MAPPER, &Format, GetCurrentThreadId(), 0, CALLBACK_THREAD) == MMSYSERR_NOERROR)
|
||||
{
|
||||
void *AudioBufferMemory = VirtualAlloc(0, TotalAudioMemorySize, MEM_COMMIT, PAGE_READWRITE);
|
||||
if(AudioBufferMemory)
|
||||
{
|
||||
u8 *At = (u8 *)AudioBufferMemory;
|
||||
for(u32 BufferIndex = 0;
|
||||
BufferIndex < BufferCount;
|
||||
++BufferIndex)
|
||||
{
|
||||
WAVEHDR *Header = (WAVEHDR *)At;
|
||||
At += sizeof(WAVEHDR);
|
||||
Header->lpData = (char *)At;
|
||||
Header->dwBufferLength = TotalBufferSize;
|
||||
|
||||
At += TotalBufferSize;
|
||||
|
||||
win32_submit_audio(Crunky, WaveOut, Header);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Crunky->quit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Crunky->quit = true;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE(casey): Serve audio forever (until we are told to stop)
|
||||
//
|
||||
// SetTimer(0, 0, 100, 0);
|
||||
while(!Crunky->quit)
|
||||
{
|
||||
MSG Message = {};
|
||||
GetMessage(&Message, 0, 0, 0);
|
||||
if(Message.message == MM_WOM_DONE)
|
||||
{
|
||||
WAVEHDR *Header = (WAVEHDR *)Message.lParam;
|
||||
if(Header->dwFlags & WHDR_DONE)
|
||||
{
|
||||
Header->dwFlags &= ~WHDR_DONE;
|
||||
}
|
||||
|
||||
waveOutUnprepareHeader(WaveOut, Header, sizeof(*Header));
|
||||
|
||||
win32_submit_audio(Crunky, WaveOut, Header);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
function DWORD
|
||||
win32_audio_init(Audio_System *audio_system){
|
||||
DWORD thread_id = 0;
|
||||
HANDLE handle = CreateThread(0, 0, win32_audio_loop, audio_system, 0, &thread_id);
|
||||
CloseHandle(handle);
|
||||
return(thread_id);
|
||||
}
|
Loading…
Reference in New Issue