Add audio backend function for allocating audio chunks

Also try to fix stick drift on 3DS (Thanks camthesaxman)
This commit is contained in:
UnknownShadow200 2024-01-19 18:33:24 +11:00
parent 3945e4e938
commit c156484de2
6 changed files with 76 additions and 33 deletions

View File

@ -248,14 +248,14 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
return 0; return 0;
} }
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 size) { cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) {
ALuint buffer; ALuint buffer;
ALenum err; ALenum err;
if (!ctx->free) return ERR_INVALID_ARGUMENT; if (!ctx->free) return ERR_INVALID_ARGUMENT;
buffer = ctx->freeIDs[--ctx->free]; buffer = ctx->freeIDs[--ctx->free];
_alBufferData(buffer, ctx->channels, data, size, ctx->sampleRate); _alBufferData(buffer, ctx->channels, chunk, size, ctx->sampleRate);
if ((err = _alGetError())) return err; if ((err = _alGetError())) return err;
_alSourceQueueBuffers(ctx->source, 1, &buffer); _alSourceQueueBuffers(ctx->source, 1, &buffer);
if ((err = _alGetError())) return err; if ((err = _alGetError())) return err;
@ -299,7 +299,7 @@ cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
data->sampleRate = Audio_AdjustSampleRate(data); data->sampleRate = Audio_AdjustSampleRate(data);
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res; if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
if ((res = Audio_QueueData(ctx, data->data, data->size))) return res; if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
if ((res = Audio_Play(ctx))) return res; if ((res = Audio_Play(ctx))) return res;
return 0; return 0;
} }
@ -322,6 +322,14 @@ cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
if (err) String_AppendConst(dst, err); if (err) String_AppendConst(dst, err);
return err != NULL; return err != NULL;
} }
void* Audio_AllocChunk(cc_uint32 size) {
return Mem_TryAlloc(size, 1);
}
void Audio_FreeChunk(void* data) {
Mem_Free(data);
}
#elif defined CC_BUILD_WINMM #elif defined CC_BUILD_WINMM
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------WinMM backend------------------------------------------------------* *------------------------------------------------------WinMM backend------------------------------------------------------*
@ -448,7 +456,7 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
return res; return res;
} }
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 dataSize) { cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) {
cc_result res = 0; cc_result res = 0;
WAVEHDR* hdr; WAVEHDR* hdr;
int i; int i;
@ -458,7 +466,7 @@ cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 dataSi
if (!(hdr->dwFlags & WHDR_DONE)) continue; if (!(hdr->dwFlags & WHDR_DONE)) continue;
Mem_Set(hdr, 0, sizeof(WAVEHDR)); Mem_Set(hdr, 0, sizeof(WAVEHDR));
hdr->lpData = (LPSTR)data; hdr->lpData = (LPSTR)chunk;
hdr->dwBufferLength = dataSize; hdr->dwBufferLength = dataSize;
hdr->dwLoops = 1; hdr->dwLoops = 1;
@ -504,7 +512,7 @@ cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
data->sampleRate = Audio_AdjustSampleRate(data); data->sampleRate = Audio_AdjustSampleRate(data);
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res; if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
if ((res = Audio_QueueData(ctx, data->data, data->size))) return res; if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
return 0; return 0;
} }
@ -516,6 +524,14 @@ cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
String_AppendConst(dst, buffer); String_AppendConst(dst, buffer);
return true; return true;
} }
void* Audio_AllocChunk(cc_uint32 size) {
return Mem_TryAlloc(size, 1);
}
void Audio_FreeChunk(void* data) {
Mem_Free(data);
}
#elif defined CC_BUILD_OPENSLES #elif defined CC_BUILD_OPENSLES
/*########################################################################################################################* /*########################################################################################################################*
*----------------------------------------------------OpenSL ES backend----------------------------------------------------* *----------------------------------------------------OpenSL ES backend----------------------------------------------------*
@ -676,8 +692,8 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
return 0; return 0;
} }
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 size) { cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) {
return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, data, size); return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, chunk, size);
} }
static cc_result Audio_Pause(struct AudioContext* ctx) { static cc_result Audio_Pause(struct AudioContext* ctx) {
@ -712,7 +728,7 @@ cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
/* rate is in milli, so 1000 = normal rate */ /* rate is in milli, so 1000 = normal rate */
if ((res = (*ctx->playerRate)->SetRate(ctx->playerRate, data->rate * 10))) return res; if ((res = (*ctx->playerRate)->SetRate(ctx->playerRate, data->rate * 10))) return res;
if ((res = Audio_QueueData(ctx, data->data, data->size))) return res; if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
if ((res = Audio_Play(ctx))) return res; if ((res = Audio_Play(ctx))) return res;
return 0; return 0;
} }
@ -744,6 +760,14 @@ cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
if (err) String_AppendConst(dst, err); if (err) String_AppendConst(dst, err);
return err != NULL; return err != NULL;
} }
void* Audio_AllocChunk(cc_uint32 size) {
return Mem_TryAlloc(size, 1);
}
void Audio_FreeChunk(void* data) {
Mem_Free(data);
}
#elif defined CC_BUILD_3DS #elif defined CC_BUILD_3DS
/*########################################################################################################################* /*########################################################################################################################*
*-------------------------------------------------------3DS backend-------------------------------------------------------* *-------------------------------------------------------3DS backend-------------------------------------------------------*
@ -804,7 +828,7 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate
return 0; return 0;
} }
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 dataSize) { cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) {
ndspWaveBuf* buf; ndspWaveBuf* buf;
for (int i = 0; i < ctx->count; i++) for (int i = 0; i < ctx->count; i++)
@ -814,7 +838,7 @@ cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 dataSi
if (buf->status == NDSP_WBUF_QUEUED || buf->status == NDSP_WBUF_PLAYING) if (buf->status == NDSP_WBUF_QUEUED || buf->status == NDSP_WBUF_PLAYING)
continue; continue;
buf->data_pcm16 = data; buf->data_pcm16 = chunk;
buf->nsamples = dataSize / 2; // 16 bit samples buf->nsamples = dataSize / 2; // 16 bit samples
//Platform_Log1("PLAYING ON: %i", &ctx->chanID); //Platform_Log1("PLAYING ON: %i", &ctx->chanID);
ndspChnWaveBufAdd(ctx->chanID, buf); ndspChnWaveBufAdd(ctx->chanID, buf);
@ -858,7 +882,7 @@ cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) {
cc_result res; cc_result res;
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res; if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate))) return res;
if ((res = Audio_QueueData(ctx, data->data, data->size))) return res; if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res;
return 0; return 0;
} }
@ -892,7 +916,7 @@ void Audio_Close(struct AudioContext* ctx) {
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) { cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) {
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
} }
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 size) { cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) {
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
} }
cc_result Audio_Play(struct AudioContext* ctx) { return ERR_NOT_SUPPORTED; } cc_result Audio_Play(struct AudioContext* ctx) { return ERR_NOT_SUPPORTED; }
@ -922,6 +946,14 @@ cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
String_AppendUtf8(dst, buffer, len); String_AppendUtf8(dst, buffer, len);
return len > 0; return len > 0;
} }
void* Audio_AllocChunk(cc_uint32 size) {
return Mem_TryAlloc(size, 1);
}
void Audio_FreeChunk(void* data) {
Mem_Free(data);
}
#endif #endif
/*########################################################################################################################* /*########################################################################################################################*
@ -1032,7 +1064,7 @@ static cc_result Sound_ReadWaveData(struct Stream* stream, struct Sound* snd) {
if (bitsPerSample != 16) return WAV_ERR_SAMPLE_BITS; if (bitsPerSample != 16) return WAV_ERR_SAMPLE_BITS;
size -= WAV_FMT_SIZE; size -= WAV_FMT_SIZE;
} else if (fourCC == WAV_FourCC('d','a','t','a')) { } else if (fourCC == WAV_FourCC('d','a','t','a')) {
snd->data = Mem_TryAlloc(size, 1); snd->data = Audio_AllocChunk(size);
snd->size = size; snd->size = size;
if (!snd->data) return ERR_OUT_OF_MEMORY; if (!snd->data) return ERR_OUT_OF_MEMORY;
@ -1310,7 +1342,7 @@ static cc_result Music_Buffer(cc_int16* data, int maxSamples, struct VorbisState
} }
if (Audio_MusicVolume < 100) { ApplyVolume(data, samples, Audio_MusicVolume); } if (Audio_MusicVolume < 100) { ApplyVolume(data, samples, Audio_MusicVolume); }
res2 = Audio_QueueData(&music_ctx, data, samples * 2); res2 = Audio_QueueChunk(&music_ctx, data, samples * 2);
if (res2) { music_stopping = true; return res2; } if (res2) { music_stopping = true; return res2; }
return res; return res;
} }
@ -1339,7 +1371,7 @@ static cc_result Music_PlayOgg(struct Stream* source) {
samplesPerSecond = channels * sampleRate; samplesPerSecond = channels * sampleRate;
cur = 0; cur = 0;
data = (cc_int16*)Mem_TryAlloc(chunkSize * AUDIO_MAX_BUFFERS, 2); data = (cc_int16*)Audio_AllocChunk(chunkSize * AUDIO_MAX_BUFFERS * 2);
if (!data) { res = ERR_OUT_OF_MEMORY; goto cleanup; } if (!data) { res = ERR_OUT_OF_MEMORY; goto cleanup; }
/* fill up with some samples before playing */ /* fill up with some samples before playing */

View File

@ -48,11 +48,11 @@ void Audio_Close(struct AudioContext* ctx);
/* Sets the format of the audio data to be played. */ /* Sets the format of the audio data to be played. */
/* NOTE: Changing the format can be expensive, depending on the backend. */ /* NOTE: Changing the format can be expensive, depending on the backend. */
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate); cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate);
/* Queues the given audio data for playing. */ /* Queues the given audio chunk for playing. */
/* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */ /* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */
/* NOTE: Some backends directly read from the data - therefore you MUST NOT modify it */ /* NOTE: Some backends directly read from the data - therefore you MUST NOT modify it */
cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 size); cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size);
/* Begins playing audio. Audio_QueueData must have been used before this. */ /* Begins playing audio. Audio_QueueChunk must have been used before this. */
cc_result Audio_Play(struct AudioContext* ctx); cc_result Audio_Play(struct AudioContext* ctx);
/* Polls the audio context and then potentially unqueues buffer */ /* Polls the audio context and then potentially unqueues buffer */
/* Returns the number of buffers being played or queued */ /* Returns the number of buffers being played or queued */
@ -65,4 +65,9 @@ cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data);
cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data); cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data);
/* Outputs more detailed information about errors with audio. */ /* Outputs more detailed information about errors with audio. */
cc_bool Audio_DescribeError(cc_result res, cc_string* dst); cc_bool Audio_DescribeError(cc_result res, cc_string* dst);
/* Allocates a chunk of data to store audio samples */
void* Audio_AllocChunk(cc_uint32 size);
/* Frees a previously allocated chunk of data */
void Audio_FreeChunk(void* chunk);
#endif #endif

View File

@ -708,7 +708,7 @@ static cc_result HttpClient_SendRequest(struct HttpClientState* state) {
HttpClient_Serialise(state); HttpClient_Serialise(state);
/* TODO check that wrote is >= inputMsg.length */ /* TODO check that wrote is >= inputMsg.length */
return HttpConnection_Write(state->conn, inputBuffer, inputMsg.length, &wrote); return HttpConnection_Write(state->conn, (cc_uint8*)inputBuffer, inputMsg.length, &wrote);
} }
@ -763,7 +763,8 @@ static int HttpClient_BeginBody(struct HttpRequest* req, struct HttpClientState*
static int HttpClient_GetChunkLength(const cc_string* line) { static int HttpClient_GetChunkLength(const cc_string* line) {
int length = 0, i, part; int length = 0, i, part;
for (i = 0; i < line->length; i++) { for (i = 0; i < line->length; i++)
{
char c = line->buffer[i]; char c = line->buffer[i];
/* RFC 7230, section 4.1.1 - Chunk Extensions */ /* RFC 7230, section 4.1.1 - Chunk Extensions */
if (c == ';') break; if (c == ';') break;
@ -786,7 +787,8 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
case HTTP_RESPONSE_STATE_HEADER: case HTTP_RESPONSE_STATE_HEADER:
{ {
for (; offset < total;) { for (; offset < total;)
{
char c = buffer[offset++]; char c = buffer[offset++];
if (c == '\r') continue; if (c == '\r') continue;
if (c != '\n') { if (c != '\n') {
@ -837,7 +839,8 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
/* RFC 7230, section 4.1 - Chunked Transfer Coding */ /* RFC 7230, section 4.1 - Chunked Transfer Coding */
case HTTP_RESPONSE_STATE_CHUNK_HEADER: case HTTP_RESPONSE_STATE_CHUNK_HEADER:
{ {
for (; offset < total;) { for (; offset < total;)
{
char c = buffer[offset++]; char c = buffer[offset++];
if (c == '\r') continue; if (c == '\r') continue;
if (c != '\n') { String_Append(&state->header, c); continue; } if (c != '\n') { String_Append(&state->header, c); continue; }
@ -874,7 +877,8 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
/* RFC 7230, section 4.1.2 - Chunked Trailer Part */ /* RFC 7230, section 4.1.2 - Chunked Trailer Part */
case HTTP_RESPONSE_STATE_CHUNK_TRAILERS: case HTTP_RESPONSE_STATE_CHUNK_TRAILERS:
{ {
for (; offset < total;) { for (; offset < total;)
{
char c = buffer[offset++]; char c = buffer[offset++];
if (c == '\r') continue; if (c == '\r') continue;
if (c != '\n') { String_Append(&state->header, c); continue; } if (c != '\n') { String_Append(&state->header, c); continue; }
@ -904,7 +908,8 @@ static cc_result HttpClient_ParseResponse(struct HttpClientState* state) {
cc_uint32 total; cc_uint32 total;
cc_result res; cc_result res;
for (;;) { for (;;)
{
dst = state->dataLeft > INPUT_BUFFER_LEN ? (req->data + req->size) : buffer; dst = state->dataLeft > INPUT_BUFFER_LEN ? (req->data + req->size) : buffer;
res = HttpConnection_Read(state->conn, dst, INPUT_BUFFER_LEN, &total); res = HttpConnection_Read(state->conn, dst, INPUT_BUFFER_LEN, &total);

View File

@ -19,11 +19,12 @@ struct Vec4 { float x, y, z, w; };
/* 4x4 matrix. (for vertex transformations) */ /* 4x4 matrix. (for vertex transformations) */
struct Matrix { struct Vec4 row1, row2, row3, row4; }; struct Matrix { struct Vec4 row1, row2, row3, row4; };
#define Matrix_IdentityValue { \ #define Matrix_IdentityValue \
1.0f, 0.0f, 0.0f, 0.0f, \ { \
0.0f, 1.0f, 0.0f, 0.0f, \ { 1.0f, 0.0f, 0.0f, 0.0f }, \
0.0f, 0.0f, 1.0f, 0.0f, \ { 0.0f, 1.0f, 0.0f, 0.0f }, \
0.0f, 0.0f, 0.0f, 1.0f \ { 0.0f, 0.0f, 1.0f, 0.0f }, \
{ 0.0f, 0.0f, 0.0f, 1.0f } \
} }
/* Identity matrix. (A * Identity = A) */ /* Identity matrix. (A * Identity = A) */

View File

@ -103,8 +103,8 @@ static void ProcessJoystickInput(circlePosition* pos, double delta) {
float scale = (delta * 60.0) / 8.0f; float scale = (delta * 60.0) / 8.0f;
// May not be exactly 0 on actual hardware // May not be exactly 0 on actual hardware
if (Math_AbsI(pos->dx) <= 8) pos->dx = 0; if (Math_AbsI(pos->dx) <= 16) pos->dx = 0;
if (Math_AbsI(pos->dy) <= 8) pos->dy = 0; if (Math_AbsI(pos->dy) <= 16) pos->dy = 0;
Event_RaiseRawMove(&PointerEvents.RawMoved, pos->dx * scale, -pos->dy * scale); Event_RaiseRawMove(&PointerEvents.RawMoved, pos->dx * scale, -pos->dy * scale);
} }

View File

@ -272,7 +272,7 @@ static void AppendVRAMStats(cc_string* info) {
} }
void Gfx_GetApiInfo(cc_string* info) { void Gfx_GetApiInfo(cc_string* info) {
GLint depthBits; GLint depthBits = 0;
int pointerSize = sizeof(void*) * 8; int pointerSize = sizeof(void*) * 8;
glGetIntegerv(GL_DEPTH_BITS, &depthBits); glGetIntegerv(GL_DEPTH_BITS, &depthBits);