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 */
@ -286,14 +286,14 @@ static ReturnCode Codebook_DecodeSetup(struct VorbisState* ctx, struct Codebook*
if (c->LookupType == 0) return 0; if (c->LookupType == 0) return 0;
if (c->LookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP; if (c->LookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP;
c->MinValue = float32_unpack(ctx); c->MinValue = float32_unpack(ctx);
c->DeltaValue = float32_unpack(ctx); c->DeltaValue = float32_unpack(ctx);
Int32 valueBits = Vorbis_ReadBits(ctx, 4); valueBits++; Int32 valueBits = Vorbis_ReadBits(ctx, 4); valueBits++;
c->SequenceP = Vorbis_ReadBits(ctx, 1); c->SequenceP = Vorbis_ReadBits(ctx, 1);
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;
} }
@ -1311,11 +1311,11 @@ Int32 Vorbis_OutputFrame(struct VorbisState* ctx, Int16* data) {
/* So for example, consider a short block overlapping with a long block /* So for example, consider a short block overlapping with a long block
a) we need to chop off 'prev' before its halfway point a) we need to chop off 'prev' before its halfway point
b) then need to chop off the 'cur' before the halfway point of 'prev' b) then need to chop off the 'cur' before the halfway point of 'prev'
|- ********|***** |- ********| |- ********|***** |- ********|
-| - * | *** | - * | -| - * | *** | - * |
- | # | *** ===> | # | - | # | *** ===> | # |
- | * - | *** | * - | - | * - | *** | * - |
******-***|* - | *** |* - | ******-***|* - | *** |* - |
*/ */
@ -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] = {