diff options
author | Javier <dev.git@javispedro.com> | 2022-02-05 15:43:59 +0100 |
---|---|---|
committer | Javier <dev.git@javispedro.com> | 2022-02-05 15:43:59 +0100 |
commit | 774984e2f00b4ea81060adf7a0625706ddaa42a5 (patch) | |
tree | b28bc676598432953ce1002b93b0d7b584500df2 /Emu8000.cpp | |
parent | 176ec23dd48c50c87e5394b702e2cf0fe72957db (diff) | |
download | vmusic-774984e2f00b4ea81060adf7a0625706ddaa42a5.tar.gz vmusic-774984e2f00b4ea81060adf7a0625706ddaa42a5.zip |
increment the emu's sample count between audio callbacks as per the virtual clock, to aid programs that poll it
Diffstat (limited to 'Emu8000.cpp')
-rw-r--r-- | Emu8000.cpp | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/Emu8000.cpp b/Emu8000.cpp index 86dcb11..4e3fd01 100644 --- a/Emu8000.cpp +++ b/Emu8000.cpp @@ -132,9 +132,12 @@ typedef struct { bool volatile fShutdown; /** Flag from render thread indicated it has shutdown (e.g. due to error or timeout). */ bool volatile fStopped; - /** (System clock) timestamp of last OPL chip access. */ + /** (System clock) timestamp of last port write. */ uint64_t tmLastWrite; + /** (Virtual clock) timestamp of last frame rendered. */ + uint64_t tmLastRender; + /** To protect access to opl3_chip from the render thread and main thread. */ RTCRITSECT critSect; /** Handle to emu8k. */ @@ -148,18 +151,26 @@ typedef EMUSTATE *PEMUSTATE; #ifndef VBOX_DEVICE_STRUCT_TESTCASE -static inline uint64_t emuCalculateFramesFromMilli(PEMUSTATE pThis, uint64_t milli) +DECLINLINE(uint64_t) emuCalculateFramesFromMilli(PEMUSTATE pThis, uint64_t milli) { uint64_t rate = pThis->uSampleRate; return (rate * milli) / 1000; } -static inline size_t emuCalculateBytesFromFrames(PEMUSTATE pThis, uint64_t frames) +DECLINLINE(uint64_t) emuCalculateFramesFromNano(PEMUSTATE pThis, uint64_t nano) +{ + uint64_t rate = pThis->uSampleRate; + return (rate * nano) / 1000000000; +} + +DECLINLINE(size_t) emuCalculateBytesFromFrames(PEMUSTATE pThis, uint64_t frames) { NOREF(pThis); return frames * sizeof(uint16_t) * EMU_NUM_CHANNELS; } + + /** * The render thread calls into the emulator to render audio frames, and then pushes them * on the PCM output device. @@ -172,7 +183,8 @@ static inline size_t emuCalculateBytesFromFrames(PEMUSTATE pThis, uint64_t frame static DECLCALLBACK(int) emuRenderThread(RTTHREAD ThreadSelf, void *pvUser) { RT_NOREF(ThreadSelf); - PEMUSTATE pThis = (PEMUSTATE)pvUser; + PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser; + PEMUSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PEMUSTATE); PCMOutBackend *pPcmOut = &pThis->pcmOut; // Compute the max number of frames we can store on our temporary buffer. @@ -190,6 +202,7 @@ static DECLCALLBACK(int) emuRenderThread(RTTHREAD ThreadSelf, void *pvUser) RTCritSectEnter(&pThis->critSect); emu8k_render(pThis->emu, buf, buf_frames); + pThis->tmLastRender = PDMDevHlpTMTimeVirtGetNano(pDevIns); RTCritSectLeave(&pThis->critSect); Log9(("writing %lld frames\n", buf_frames)); @@ -275,7 +288,7 @@ static void emuWakeRenderThread(PPDMDEVINS pDevIns) Log3(("Creating render thread\n")); - int rc = RTThreadCreateF(&pThis->hRenderThread, emuRenderThread, pThis, 0, + int rc = RTThreadCreateF(&pThis->hRenderThread, emuRenderThread, pDevIns, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "emu%u_render", pDevIns->iInstance); AssertLogRelRCReturnVoid(rc); @@ -291,6 +304,10 @@ static DECLCALLBACK(VBOXSTRICTRC) emuIoPortRead(PPDMDEVINS pDevIns, void *pvUser PEMUSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PEMUSTATE); + RTCritSectEnter(&pThis->critSect); + uint64_t frames_since_last_render = emuCalculateFramesFromNano(pThis, PDMDevHlpTMTimeVirtGetNano(pDevIns) - pThis->tmLastRender); + emu8k_update_virtual_sample_count(pThis->emu, frames_since_last_render); + switch (cb) { case sizeof(uint8_t): *pu32 = emu8k_inb(pThis->emu, port); @@ -307,6 +324,8 @@ static DECLCALLBACK(VBOXSTRICTRC) emuIoPortRead(PPDMDEVINS pDevIns, void *pvUser break; } + RTCritSectLeave(&pThis->critSect); + Log9Func(("read port 0x%X (%u): %#04x\n", port, cb, *pu32)); return VINF_SUCCESS; @@ -397,6 +416,7 @@ static DECLCALLBACK(void) emuR3Reset(PPDMDEVINS pDevIns) RTCritSectEnter(&pThis->critSect); emu8k_reset(pThis->emu); + pThis->tmLastRender = PDMDevHlpTMTimeVirtGetNano(pDevIns); RTCritSectLeave(&pThis->critSect); } |