Implement volume for C client

This commit is contained in:
UnknownShadow200 2018-08-22 22:27:06 +10:00
parent 912067ac99
commit 74a7c39a28
8 changed files with 98 additions and 90 deletions

View File

@ -13,6 +13,33 @@
#include "Chat.h" #include "Chat.h"
StringsBuffer files; StringsBuffer files;
static void Volume_Mix16(Int16* samples, Int32 count, Int32 volume) {
Int32 i;
for (i = 0; i < (count & ~0x07); i += 8, samples += 8) {
samples[0] = (samples[0] * volume / 100);
samples[1] = (samples[1] * volume / 100);
samples[2] = (samples[2] * volume / 100);
samples[3] = (samples[3] * volume / 100);
samples[4] = (samples[4] * volume / 100);
samples[5] = (samples[5] * volume / 100);
samples[6] = (samples[6] * volume / 100);
samples[7] = (samples[7] * volume / 100);
}
for (; i < count; i++, samples++) {
samples[0] = (samples[0] * volume / 100);
}
}
static void Volume_Mix8(UInt8* samples, Int32 count, Int32 volume) {
Int32 i;
for (i = 0; i < count; i++, samples++) {
samples[0] = (127 + (samples[0] - 127) * volume / 100);
}
}
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------Soundboard---------------------------------------------------------* *------------------------------------------------------Soundboard---------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
@ -153,15 +180,36 @@ struct Sound* Soundboard_PickRandom(struct Soundboard* board, UInt8 type) {
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------------Sounds-----------------------------------------------------------* *--------------------------------------------------------Sounds-----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
struct Soundboard digBoard, stepBoard; struct SoundOutput { AudioHandle Handle; void* Buffer; UInt32 BufferSize; };
#define AUDIO_MAX_HANDLES 6 #define AUDIO_MAX_HANDLES 6
AudioHandle monoOutputs[AUDIO_MAX_HANDLES] = { -1, -1, -1, -1, -1, -1 }; #define HANDLE_INV -1
AudioHandle stereoOutputs[AUDIO_MAX_HANDLES] = { -1, -1, -1, -1, -1, -1 }; #define SOUND_INV { HANDLE_INV, NULL, 0 }
static void Sounds_PlayRaw(AudioHandle output, struct Sound* snd, struct AudioFormat* fmt, Real32 volume) { struct Soundboard digBoard, stepBoard;
Audio_SetVolume(output, volume); struct SoundOutput monoOutputs[AUDIO_MAX_HANDLES] = { SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV };
Audio_SetFormat(output, fmt); struct SoundOutput stereoOutputs[AUDIO_MAX_HANDLES] = { SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV };
Audio_PlayData(output, 0, snd->Data, snd->DataSize);
static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, struct AudioFormat* fmt, Int32 volume) {
Audio_SetFormat(output->Handle, fmt);
void* buffer = snd->Data;
/* copy to temp buffer to apply volume */
if (volume < 100) {
if (output->BufferSize < snd->DataSize) {
UInt32 expandBy = snd->DataSize - output->BufferSize;
Utils_Resize(&output->Buffer, &output->BufferSize, 1, 0, expandBy);
}
buffer = output->Buffer;
Mem_Copy(buffer, snd->Data, snd->DataSize);
if (fmt->BitsPerSample == 8) {
Volume_Mix8(buffer, snd->DataSize, volume);
} else {
Volume_Mix16(buffer, snd->DataSize / 2, volume);
}
}
Audio_PlayData(output->Handle, 0, buffer, snd->DataSize);
/* TODO: handle errors here */ /* TODO: handle errors here */
} }
@ -171,32 +219,28 @@ static void Sounds_Play(UInt8 type, struct Soundboard* board) {
if (snd == NULL) return; if (snd == NULL) return;
struct AudioFormat fmt = snd->Format; struct AudioFormat fmt = snd->Format;
Real32 volume = Game_SoundsVolume / 100.0f; Int32 volume = Game_SoundsVolume;
if (board == &digBoard) { if (board == &digBoard) {
if (type == SOUND_METAL) fmt.SampleRate = (fmt.SampleRate * 6) / 5; if (type == SOUND_METAL) fmt.SampleRate = (fmt.SampleRate * 6) / 5;
else fmt.SampleRate = (fmt.SampleRate * 4) / 5; else fmt.SampleRate = (fmt.SampleRate * 4) / 5;
} else { } else {
volume *= 0.50f; volume /= 2;
if (type == SOUND_METAL) fmt.SampleRate = (fmt.SampleRate * 7) / 5; if (type == SOUND_METAL) fmt.SampleRate = (fmt.SampleRate * 7) / 5;
} }
AudioHandle* outputs = NULL; struct SoundOutput* outputs = fmt.Channels == 1 ? monoOutputs : stereoOutputs;
if (fmt.Channels == 1) outputs = monoOutputs;
if (fmt.Channels == 2) outputs = stereoOutputs;
if (outputs == NULL) return; /* TODO: > 2 channel sound?? */
Int32 i; Int32 i;
/* Try to play on fresh device, or device with same data format */ /* Try to play on fresh device, or device with same data format */
for (i = 0; i < AUDIO_MAX_HANDLES; i++) { for (i = 0; i < AUDIO_MAX_HANDLES; i++) {
AudioHandle output = outputs[i]; struct SoundOutput* output = &outputs[i];
if (output == -1) { if (output->Handle == HANDLE_INV) {
Audio_Init(&output, 1); Audio_Init(&output->Handle, 1);
outputs[i] = output;
} }
if (!Audio_IsFinished(output)) continue; if (!Audio_IsFinished(output->Handle)) continue;
struct AudioFormat* l = Audio_GetFormat(output); struct AudioFormat* l = Audio_GetFormat(output->Handle);
if (l->Channels == 0 || AudioFormat_Eq(l, &fmt)) { if (l->Channels == 0 || AudioFormat_Eq(l, &fmt)) {
Sounds_PlayRaw(output, snd, &fmt, volume); return; Sounds_PlayRaw(output, snd, &fmt, volume); return;
} }
@ -204,8 +248,8 @@ static void Sounds_Play(UInt8 type, struct Soundboard* board) {
/* Try again with all devices, even if need to recreate one (expensive) */ /* Try again with all devices, even if need to recreate one (expensive) */
for (i = 0; i < AUDIO_MAX_HANDLES; i++) { for (i = 0; i < AUDIO_MAX_HANDLES; i++) {
AudioHandle output = outputs[i]; struct SoundOutput* output = &outputs[i];
if (!Audio_IsFinished(output)) continue; if (!Audio_IsFinished(output->Handle)) continue;
Sounds_PlayRaw(output, snd, &fmt, volume); return; Sounds_PlayRaw(output, snd, &fmt, volume); return;
} }
@ -219,23 +263,26 @@ static void Audio_PlayBlockSound(void* obj, Vector3I coords, BlockID oldBlock, B
} }
} }
static void Sounds_FreeOutputs(AudioHandle* outputs) { static void Sounds_FreeOutputs(struct SoundOutput* outputs) {
bool anyPlaying = true; bool anyPlaying = true;
Int32 i; Int32 i;
while (anyPlaying) { while (anyPlaying) {
anyPlaying = false; anyPlaying = false;
for (i = 0; i < AUDIO_MAX_HANDLES; i++) { for (i = 0; i < AUDIO_MAX_HANDLES; i++) {
if (outputs[i] == -1) continue; if (outputs[i].Handle == HANDLE_INV) continue;
anyPlaying |= !Audio_IsFinished(outputs[i]); anyPlaying |= !Audio_IsFinished(outputs[i].Handle);
} }
if (anyPlaying) Thread_Sleep(1); if (anyPlaying) Thread_Sleep(1);
} }
for (i = 0; i < AUDIO_MAX_HANDLES; i++) { for (i = 0; i < AUDIO_MAX_HANDLES; i++) {
if (outputs[i] == -1) continue; if (outputs[i].Handle == HANDLE_INV) continue;
Audio_Free(outputs[i]); Audio_Free(outputs[i].Handle);
outputs[i] = -1; outputs[i].Handle = HANDLE_INV;
Mem_Free(&outputs[i].Buffer);
outputs[i].BufferSize = 0;
} }
} }
@ -286,9 +333,10 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
fmt.BitsPerSample = 16; fmt.BitsPerSample = 16;
Audio_SetFormat(music_out, &fmt); Audio_SetFormat(music_out, &fmt);
/* largest possible vorbis frame decodes to blocksize1 samples */ /* largest possible vorbis frame decodes to blocksize1 * channels samples */
/* so we may end up decoding slightly over a second of audio */ /* so we may end up decoding slightly over a second of audio */
Int32 chunkSize = (fmt.SampleRate + vorbis.BlockSizes[1]) * fmt.Channels; Int32 chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]);
Int32 samplesPerSecond = fmt.Channels * fmt.SampleRate;
Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output"); Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output");
for (;;) { for (;;) {
@ -304,15 +352,16 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
Int16* base = data + (chunkSize * next); Int16* base = data + (chunkSize * next);
Int32 samples = 0; Int32 samples = 0;
while (samples < fmt.SampleRate) { while (samples < samplesPerSecond) {
res = Vorbis_DecodeFrame(&vorbis); res = Vorbis_DecodeFrame(&vorbis);
if (res) break; if (res) break;
Int16* cur = &base[samples * fmt.Channels]; Int16* cur = &base[samples];
samples += Vorbis_OutputFrame(&vorbis, cur); samples += Vorbis_OutputFrame(&vorbis, cur);
} }
Audio_PlayData(music_out, next, base, samples * fmt.Channels * sizeof(Int16)); if (Game_MusicVolume < 100) { Volume_Mix16(base, samples, Game_MusicVolume); }
Audio_PlayData(music_out, next, base, samples * sizeof(Int16));
/* need to specially handle last bit of audio */ /* need to specially handle last bit of audio */
if (res) break; if (res) break;
} }
@ -368,8 +417,7 @@ static void Music_RunLoop(void) {
} }
static void Music_Init(void) { static void Music_Init(void) {
if (music_thread) { Audio_SetVolume(music_out, Game_MusicVolume / 100.0f); return; } if (music_thread) return;
music_pendingStop = false; music_pendingStop = false;
Audio_Init(&music_out, AUDIO_MAX_CHUNKS); Audio_Init(&music_out, AUDIO_MAX_CHUNKS);
music_thread = Thread_Start(Music_RunLoop); music_thread = Thread_Start(Music_RunLoop);

View File

@ -748,7 +748,6 @@ void Game_Run(Int32 width, Int32 height, STRING_REF String* title, struct Displa
/* TODO: fix all these stubs.... */ /* TODO: fix all these stubs.... */
#include "Builder.h" #include "Builder.h"
void AdvLightingBuilder_SetActive(void) { NormalBuilder_SetActive(); } void AdvLightingBuilder_SetActive(void) { NormalBuilder_SetActive(); }
void Audio_SetVolume(AudioHandle handle, Real32 volume) { }
/* TODO: Initalise Shell, see https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx /* TODO: Initalise Shell, see https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx
https://stackoverflow.com/questions/24590059/c-opening-a-url-in-default-browser-on-windows-without-admin-privileges */ https://stackoverflow.com/questions/24590059/c-opening-a-url-in-default-browser-on-windows-without-admin-privileges */
ReturnCode Platform_StartShell(STRING_PURE String* args) { return 0; } ReturnCode Platform_StartShell(STRING_PURE String* args) { return 0; }

View File

@ -273,12 +273,6 @@ void BoxDesc_TexOrigin(struct BoxDesc* desc, Int32 x, Int32 y) {
desc->TexX = x; desc->TexY = y; desc->TexX = x; desc->TexY = y;
} }
void BoxDesc_SetBounds(struct BoxDesc* desc, Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2) {
desc->X1 = x1 / 16.0f; desc->X2 = x2 / 16.0f;
desc->Y1 = y1 / 16.0f; desc->Y2 = y2 / 16.0f;
desc->Z1 = z1 / 16.0f; desc->Z2 = z2 / 16.0f;
}
void BoxDesc_Expand(struct BoxDesc* desc, Real32 amount) { void BoxDesc_Expand(struct BoxDesc* desc, Real32 amount) {
amount /= 16.0f; amount /= 16.0f;
desc->X1 -= amount; desc->X2 += amount; desc->X1 -= amount; desc->X2 += amount;
@ -286,33 +280,10 @@ void BoxDesc_Expand(struct BoxDesc* desc, Real32 amount) {
desc->Z1 -= amount; desc->Z2 += amount; desc->Z1 -= amount; desc->Z2 += amount;
} }
void BoxDesc_Scale(struct BoxDesc* desc, Real32 scale) {
desc->X1 *= scale; desc->X2 *= scale;
desc->Y1 *= scale; desc->Y2 *= scale;
desc->Z1 *= scale; desc->Z2 *= scale;
desc->RotX *= scale; desc->RotY *= scale; desc->RotZ *= scale;
}
void BoxDesc_RotOrigin(struct BoxDesc* desc, Int8 x, Int8 y, Int8 z) {
desc->RotX = (Real32)x / 16.0f;
desc->RotY = (Real32)y / 16.0f;
desc->RotZ = (Real32)z / 16.0f;
}
void BoxDesc_MirrorX(struct BoxDesc* desc) { void BoxDesc_MirrorX(struct BoxDesc* desc) {
Real32 temp = desc->X1; desc->X1 = desc->X2; desc->X2 = temp; Real32 temp = desc->X1; desc->X1 = desc->X2; desc->X2 = temp;
} }
void BoxDesc_Box(struct BoxDesc* desc, Int32 x1, Int32 y1, Int32 z1, Int32 x2, Int32 y2, Int32 z2) {
BoxDesc_TexOrigin(desc, 0, 0);
BoxDesc_RotOrigin(desc, 0, 0, 0);
BoxDesc_SetBounds(desc, (Real32)x1, (Real32)y1, (Real32)z1, (Real32)x2, (Real32)y2, (Real32)z2);
desc->SizeZ = Math_AbsI(z2 - z1);
desc->SizeX = Math_AbsI(x2 - x1);
desc->SizeY = Math_AbsI(y2 - y1);
}
void BoxDesc_BuildBox(struct ModelPart* part, struct BoxDesc* desc) { void BoxDesc_BuildBox(struct ModelPart* part, struct BoxDesc* desc) {
Int32 sidesW = desc->SizeZ, bodyW = desc->SizeX, bodyH = desc->SizeY; Int32 sidesW = desc->SizeZ, bodyW = desc->SizeX, bodyH = desc->SizeY;

View File

@ -91,20 +91,11 @@ struct BoxDesc {
/* Sets the texture origin for this part within the texture atlas. */ /* Sets the texture origin for this part within the texture atlas. */
void BoxDesc_TexOrigin(struct BoxDesc* desc, Int32 x, Int32 y); void BoxDesc_TexOrigin(struct BoxDesc* desc, Int32 x, Int32 y);
/* Sets the the two corners of this box, in pixel coordinates. */
void BoxDesc_SetBounds(struct BoxDesc* desc, Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2);
/* Expands the corners of this box outwards by the given amount in pixel coordinates. */ /* Expands the corners of this box outwards by the given amount in pixel coordinates. */
void BoxDesc_Expand(struct BoxDesc* desc, Real32 amount); void BoxDesc_Expand(struct BoxDesc* desc, Real32 amount);
/* Scales the corners of this box outwards by the given amounts. */
void BoxDesc_Scale(struct BoxDesc* desc, Real32 scale);
/* Sets the coordinate that this box is rotated around, in pixel coordinates. */
void BoxDesc_RotOrigin(struct BoxDesc* desc, Int8 x, Int8 y, Int8 z);
/* Swaps the min and max X around, resulting in the part being drawn mirrored. */ /* Swaps the min and max X around, resulting in the part being drawn mirrored. */
void BoxDesc_MirrorX(struct BoxDesc* desc); void BoxDesc_MirrorX(struct BoxDesc* desc);
/* Constructs a description of the given box, from two corners. */
void BoxDesc_Box(struct BoxDesc* desc, Int32 x1, Int32 y1, Int32 z1, Int32 x2, Int32 y2, Int32 z2);
/* Builds a box model assuming the follow texture layout: /* Builds a box model assuming the follow texture layout:
let SW = sides width, BW = body width, BH = body height let SW = sides width, BW = body width, BH = body height
********************************************************************************************* *********************************************************************************************

View File

@ -894,7 +894,7 @@ ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle) {
} }
*handle = InternetOpenUrlA(hInternet, url.buffer, headers.buffer, headers.length, *handle = InternetOpenUrlA(hInternet, url.buffer, headers.buffer, headers.length,
INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD, NULL); INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD, 0);
return Win_Return(*handle); return Win_Return(*handle);
} }
@ -935,7 +935,7 @@ ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void*
while (left > 0) { while (left > 0) {
UInt32 toRead = left, avail = 0; UInt32 toRead = left, avail = 0;
/* only read as much data that is pending */ /* only read as much data that is pending */
if (InternetQueryDataAvailable(handle, &avail, 0, NULL)) { if (InternetQueryDataAvailable(handle, &avail, 0, 0)) {
toRead = min(toRead, avail); toRead = min(toRead, avail);
} }
@ -1025,7 +1025,7 @@ void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format) {
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
if (waveOutGetNumDevs() == 0u) ErrorHandler_Fail("No audio devices found"); if (waveOutGetNumDevs() == 0u) ErrorHandler_Fail("No audio devices found");
ReturnCode result = waveOutOpen(&ctx->Handle, WAVE_MAPPER, &fmt, NULL, NULL, CALLBACK_NULL); ReturnCode result = waveOutOpen(&ctx->Handle, WAVE_MAPPER, &fmt, 0, 0, CALLBACK_NULL);
ErrorHandler_CheckOrFail(result, "Audio - opening device"); ErrorHandler_CheckOrFail(result, "Audio - opening device");
ctx->Format = *format; ctx->Format = *format;
} }

View File

@ -117,7 +117,7 @@ ReturnCode Http_FreeRequest(void* handle);
ReturnCode Http_Free(void); ReturnCode Http_Free(void);
#define AUDIO_MAX_CHUNKS 4 #define AUDIO_MAX_CHUNKS 4
struct AudioFormat { UInt8 Channels, BitsPerSample; Int32 SampleRate; }; struct AudioFormat { UInt16 Channels, BitsPerSample; Int32 SampleRate; };
#define AudioFormat_Eq(a, b) ((a)->Channels == (b)->Channels && (a)->BitsPerSample == (b)->BitsPerSample && (a)->SampleRate == (b)->SampleRate) #define AudioFormat_Eq(a, b) ((a)->Channels == (b)->Channels && (a)->BitsPerSample == (b)->BitsPerSample && (a)->SampleRate == (b)->SampleRate)
typedef Int32 AudioHandle; typedef Int32 AudioHandle;
@ -125,7 +125,6 @@ void Audio_Init(AudioHandle* handle, Int32 buffers);
void Audio_Free(AudioHandle handle); void Audio_Free(AudioHandle handle);
struct AudioFormat* Audio_GetFormat(AudioHandle handle); struct AudioFormat* Audio_GetFormat(AudioHandle handle);
void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format); void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format);
void Audio_SetVolume(AudioHandle handle, Real32 volume);
void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize); void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize);
bool Audio_IsCompleted(AudioHandle handle, Int32 idx); bool Audio_IsCompleted(AudioHandle handle, Int32 idx);
bool Audio_IsFinished(AudioHandle handle); bool Audio_IsFinished(AudioHandle handle);

View File

@ -92,7 +92,7 @@ int main(void) {
String title = String_FromConst(PROGRAM_APP_NAME); String title = String_FromConst(PROGRAM_APP_NAME);
String rawArgs = Platform_GetCommandLineArgs(); String rawArgs = Platform_GetCommandLineArgs();
/* NOTE: Make sure to comment this out before pushing a commit */ /* NOTE: Make sure to comment this out before pushing a commit */
rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565"); //rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
String args[5]; Int32 argsCount = Array_Elems(args); String args[5]; Int32 argsCount = Array_Elems(args);
String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount); String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount);

View File

@ -172,7 +172,7 @@ static UInt32 Codebook_Pow(UInt32 base, UInt32 exp) {
return result; return result;
} }
static UInt32 lookup1_values(UInt32 entries, UInt32 dimensions) { static UInt32 Codebook_Lookup1Values(UInt32 entries, UInt32 dimensions) {
UInt32 i; UInt32 i;
/* the greatest integer value for which [value] to the power of [dimensions] is less than or equal to [entries] */ /* the greatest integer value for which [value] to the power of [dimensions] is less than or equal to [entries] */
/* TODO: verify this */ /* TODO: verify this */
@ -293,7 +293,7 @@ static ReturnCode Codebook_DecodeSetup(struct VorbisState* ctx, struct Codebook*
UInt32 lookupValues; UInt32 lookupValues;
if (c->LookupType == 1) { if (c->LookupType == 1) {
lookupValues = lookup1_values(c->Entries, c->Dimensions); lookupValues = Codebook_Lookup1Values(c->Entries, c->Dimensions);
} else { } else {
lookupValues = c->Entries * c->Dimensions; lookupValues = c->Entries * c->Dimensions;
} }
@ -1350,7 +1350,7 @@ Int32 Vorbis_OutputFrame(struct VorbisState* ctx, Int16* data) {
} }
ctx->PrevBlockSize = ctx->CurBlockSize; ctx->PrevBlockSize = ctx->CurBlockSize;
return prevQrtr + curQrtr; return (prevQrtr + curQrtr) * ctx->Channels;
} }
static Real32 floor1_inverse_dB_table[256] = { static Real32 floor1_inverse_dB_table[256] = {