From f41071c25b2c2c38d3950d51843b31ffcb677b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sch=C2=84fer?= Date: Sun, 5 May 2024 09:26:18 +0200 Subject: [PATCH] Implemented audio for OS/2 by using KAI --- misc/os2/Makefile | 2 +- src/AudioBackend.c | 104 +++++++++++++++++---------------------------- 2 files changed, 41 insertions(+), 65 deletions(-) diff --git a/misc/os2/Makefile b/misc/os2/Makefile index 0fc6be7a1..e472d17eb 100644 --- a/misc/os2/Makefile +++ b/misc/os2/Makefile @@ -43,7 +43,7 @@ APP_AUTHOR := UnknownShadow200 CC := gcc CFLAGS := -pipe -fno-math-errno -O3 -g -mtune=pentium4 -msse2 -march=i686 -idirafter /@unixroot/usr/include/os2tk45 -DOS2 LDFLAGS := -Zhigh-mem -Zomf -Zargs-wild -Zargs-resp -Zlinker DISABLE -Zlinker 1121 -LIBS := -lcx -lmmpm2 -lpthread +LIBS := -lcx -lmmpm2 -lpthread /@unixroot/usr/local/lib/kai.a $(TARGET).exe: $(BUILD_DIR) $(OBJECTS) $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS) diff --git a/src/AudioBackend.c b/src/AudioBackend.c index 5af8d4b8e..3b5c6ebad 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -1544,7 +1544,7 @@ struct AudioContext { HKAI hkai; void *buffers[AUDIO_MAX_BUFFERS]; cc_uint32 bufferSize[AUDIO_MAX_BUFFERS]; - int fillBuffer, playbackBuffer; + int fillBuffer, drainBuffer; int indexIntoBuffer; }; @@ -1555,66 +1555,38 @@ CC_INLINE void getNextBuffer(int count, int *bufferIndex) { ULONG APIENTRY kaiCallback(PVOID data, PVOID buffer, ULONG size) { struct AudioContext *ctx = (struct AudioContext*)data; - void* dest = buffer; - void* src = ctx->buffers[ctx->playbackBuffer]; - cc_uint32 len = 0; - cc_uint32 bufferRemaining = ctx->bufferSize[ctx->playbackBuffer] - ctx->indexIntoBuffer; - - if (src == NULL) {// Current buffer is empty - int inUse = 0; - Audio_Poll(ctx, &inUse); - if (inUse == 0) { - // No more buffers, we are done. - printf("Short Done\n"); - return 0; - } - //Search for next buffer - for(inUse = 0; inUse < ctx->count; inUse++) { - getNextBuffer(ctx->count, &ctx->playbackBuffer); - if (ctx->buffers[ctx->playbackBuffer] != NULL) { - src = ctx->buffers[ctx->playbackBuffer]; - bufferRemaining = ctx->bufferSize[ctx->playbackBuffer] - ctx->indexIntoBuffer; - break; - } - } - } - - len = min(bufferRemaining, size); - Mem_Copy(dest, src, len); + char* dst = buffer; + void* src = ctx->buffers[ctx->drainBuffer]; + cc_uint32 read = 0; - // We have to fill the buffer completely, or KAI will stop playback - if (len < size) { - cc_uint32 len2 = size - len; - // Reset the current buffer - ctx->bufferSize[ctx->playbackBuffer] = 0; - ctx->buffers[ctx->playbackBuffer] = NULL; - // Begin at the next buffer and go to it// Goto next buffer - ctx->indexIntoBuffer = 0; - getNextBuffer(ctx->count, &ctx->playbackBuffer); - src = ctx->buffers[ctx->playbackBuffer]; - // Most likely we are done - if (src == NULL) return len; + if (!src) return 0; // Reached end of playable queue + + while (size) { + cc_uint32 bufferLeft = ctx->bufferSize[ctx->drainBuffer] - ctx->indexIntoBuffer; + cc_uint32 len = min(bufferLeft, size); - Mem_Copy(dest + len, src, len2); - len += len2; - ctx->indexIntoBuffer += len2; + Mem_Copy(dst, src + ctx->indexIntoBuffer, len); + + dst += len; + read += len; + size -= len; + ctx->indexIntoBuffer += len; + + // Finished current buffer + if (ctx->indexIntoBuffer >= ctx->bufferSize[ctx->drainBuffer]) { + // Reset the current buffer + ctx->bufferSize[ctx->drainBuffer] = 0; + ctx->buffers[ctx->drainBuffer] = NULL; + // Begin at the next buffer and go to it + ctx->drainBuffer = (ctx->drainBuffer + 1) % ctx->count; + ctx->indexIntoBuffer = 0; + src = ctx->buffers[ctx->drainBuffer]; + if (!src) break; // Reached end of playable queue + } } - - //printf("callback %d %d %d %d\n",size,ctx->count,ctx->bufferSize,len); - //printf("copied %d index %d buffer# %d\n", len, ctx->indexIntoBuffer, ctx->playbackBuffer); - ctx->indexIntoBuffer += len; - if (ctx->indexIntoBuffer >= ctx->bufferSize[ctx->playbackBuffer]) { - // Reset the current buffer - ctx->bufferSize[ctx->playbackBuffer] = 0; - ctx->buffers[ctx->playbackBuffer] = NULL; - // Begin at the next buffer and go to it - ctx->indexIntoBuffer = 0; - getNextBuffer(ctx->count, &ctx->playbackBuffer); - } - if (len < size) printf("Done\n"); - return len; -} + return read; +} cc_bool AudioBackend_Init(void) { KAISPEC ksWanted, ksObtained; @@ -1641,13 +1613,14 @@ cc_result Audio_Init(struct AudioContext* ctx, int buffers) { ctx->bufferSize[i] = 0; } ctx->fillBuffer = 0; - ctx->playbackBuffer = 0; + ctx->drainBuffer = 0; ctx->indexIntoBuffer = 0; return 0; } void Audio_Close(struct AudioContext* ctx) { printf("Audio_CLose\n"); + ctx->count = 0; if (ctx->hkai > 0) { kaiStop(ctx->hkai); kaiClose(ctx->hkai); @@ -1664,8 +1637,8 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate ksWanted.ulSamplingRate = Audio_AdjustSampleRate(sampleRate, playbackRate); ksWanted.ulDataFormat = 0; ksWanted.ulChannels = channels; - ksWanted.ulNumBuffers = ctx->count; - ksWanted.ulBufferSize = 4096*8; + ksWanted.ulNumBuffers = 0; + ksWanted.ulBufferSize = 0; ksWanted.fShareable = TRUE; ksWanted.pfnCallBack = kaiCallback; ksWanted.pCallBackData = (PVOID)ctx; @@ -1676,8 +1649,8 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate ctx->hkai = 0; return rc; } - - kaiSetSoundState(ctx->hkai, MCI_SET_AUDIO_ALL, true); + + kaiSetSoundState(ctx->hkai, MCI_SET_AUDIO_ALL, true); return 0; } @@ -1687,10 +1660,13 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { } cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { + if (ctx->buffers[ctx->fillBuffer]) + return ERR_INVALID_ARGUMENT; // tried to queue data while either playing or queued still + //printf("-> select buffer %d\n", ctx->fillBuffer); - ctx->buffers[ctx->fillBuffer] = chunk; + ctx->buffers[ctx->fillBuffer] = chunk; ctx->bufferSize[ctx->fillBuffer] = size; - getNextBuffer(ctx->count, &ctx->fillBuffer); + ctx->fillBuffer = (ctx->fillBuffer + 1) % ctx->count; //printf("<- select buffer %d\n", ctx->fillBuffer); return 0; }