From fb0c68a916e28f8d98e1fec71999c4a6e7b2c61e Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Fri, 28 Feb 2020 05:08:50 +1100 Subject: [PATCH] update DivaSound source --- .../source/plugins/DivaSound/src/dllmain.cpp | 61 ++++-- .../source/plugins/DivaSound/src/framework.h | 180 ++++++++++++------ 2 files changed, 170 insertions(+), 71 deletions(-) diff --git a/source-code/source/plugins/DivaSound/src/dllmain.cpp b/source-code/source/plugins/DivaSound/src/dllmain.cpp index 9d4dbcb..d90cf4d 100644 --- a/source-code/source/plugins/DivaSound/src/dllmain.cpp +++ b/source-code/source/plugins/DivaSound/src/dllmain.cpp @@ -32,18 +32,36 @@ void NopBytes(void* address, unsigned int num) void resizeInternalBuffers(int frames) { float* oldMixbuffer = divaAudioMixCls->mixbuffer; - float* oldState2buffer = divaAudioMixCls->state2->buffer; divaBufSizeInFrames = frames; divaAudioMixCls->mixbuffer = (float*)malloc(divaBufSizeInFrames * 4 * 4); divaAudioMixCls->mixbuffer_size = divaBufSizeInFrames * 4 * 4; - divaAudioMixCls->state2->buffer = (float*)malloc(divaBufSizeInFrames * 4 * 4); - divaAudioMixCls->state2->buffer_size = divaBufSizeInFrames * 4 * 4; + free(oldMixbuffer); + + for (int i = 0; i < divaAudioMixCls->streamingChannels_len; i++) + { + float* oldChannelBuffer = divaAudioMixCls->streamingChannels[i].buffer; + if (oldChannelBuffer != nullptr) + { + if (divaAudioMixCls->streamingChannels[i].playing == 0) + { + divaAudioMixCls->streamingChannels[i].buffer = (float*)malloc(divaBufSizeInFrames * 4 * 4); + divaAudioMixCls->streamingChannels[i].buffer_size = divaBufSizeInFrames * 4 * 4; + free(oldChannelBuffer); + } + else if (divaAudioMixCls->streamingChannels[i].mutex != nullptr && mtx_lock_0(&divaAudioMixCls->streamingChannels[i].mutex) == 0) + { + divaAudioMixCls->streamingChannels[i].buffer = (float*)malloc(divaBufSizeInFrames * 4 * 4); + divaAudioMixCls->streamingChannels[i].buffer_size = divaBufSizeInFrames * 4 * 4; + free(oldChannelBuffer); + mtx_unlock(&divaAudioMixCls->streamingChannels[i].mutex); + //printf("[DivaSound] %d\n", i); + } + } + } divaAudCls->buffer_size = divaBufSizeInFrames; - free(oldMixbuffer); - free(oldState2buffer); printf("[DivaSound] Resized internal buffers to %d frames\n", frames); } @@ -52,12 +70,12 @@ void resizeTestLoop() bool dir = true; while (true) { - Sleep(5000); + Sleep(3000); if (dir) - resizeInternalBuffers(divaBufSizeInFrames + 3000); + resizeInternalBuffers(divaBufSizeInFrames + 10000); else - resizeInternalBuffers(divaBufSizeInFrames - 3000); + resizeInternalBuffers(divaBufSizeInFrames - 10000); dir = !dir; } @@ -442,13 +460,28 @@ void hookedAudioInit(initClass *cls, uint64_t unk, uint64_t unk2) { if (!maInit()) return; - maInternalBufferSizeInMilliseconds = device.playback.internalBufferSizeInFrames * 1000 / device.playback.internalSampleRate; // because miniaudio doesn't seem to have this - printf("[DivaSound] Output buffer size: %d (%dms at %dHz)\n", device.playback.internalBufferSizeInFrames, maInternalBufferSizeInMilliseconds, device.playback.internalSampleRate); - printf("[DivaSound] Buffer periods: %d\n", device.playback.internalPeriods); + if (device.playback.internalSampleRate) + { + maInternalBufferSizeInMilliseconds = device.playback.internalBufferSizeInFrames * 1000 / device.playback.internalSampleRate; // because miniaudio doesn't seem to have this + printf("[DivaSound] Output buffer size: %d (%dms at %dHz)\n", device.playback.internalBufferSizeInFrames, maInternalBufferSizeInMilliseconds, device.playback.internalSampleRate); + printf("[DivaSound] Buffer periods: %d\n", device.playback.internalPeriods); - divaBufSizeInFrames = device.playback.internalBufferSizeInFrames * device.sampleRate / device.playback.internalSampleRate; // +128; // 128 is just a bit extra in case resampling needs it or something. idk - divaBufSizeInMilliseconds = divaBufSizeInFrames * 1000 / device.sampleRate; - printf("[DivaSound] PDAFT buffer size: %d (%dms at %dHz)\n", divaBufSizeInFrames, divaBufSizeInMilliseconds, device.sampleRate); + divaBufSizeInFrames = device.playback.internalBufferSizeInFrames * device.sampleRate / device.playback.internalSampleRate; // +128; // 128 is just a bit extra in case resampling needs it or something. idk + divaBufSizeInMilliseconds = divaBufSizeInFrames * 1000 / device.sampleRate; + printf("[DivaSound] PDAFT buffer size: %d (%dms at %dHz)\n", divaBufSizeInFrames, divaBufSizeInMilliseconds, device.sampleRate); + } + else + { + printf("[DivaSound] Unable to determine output sample rate. Assuming 44100Hz.\n"); + + maInternalBufferSizeInMilliseconds = device.playback.internalBufferSizeInFrames * 1000 / 44100; // because miniaudio doesn't seem to have this + printf("[DivaSound] Output buffer size: %d (%dms at %dHz)\n", device.playback.internalBufferSizeInFrames, maInternalBufferSizeInMilliseconds, 44100); + printf("[DivaSound] Buffer periods: %d\n", device.playback.internalPeriods); + + divaBufSizeInFrames = device.playback.internalBufferSizeInFrames * device.sampleRate / 44100; + divaBufSizeInMilliseconds = divaBufSizeInFrames * 1000 / device.sampleRate; + printf("[DivaSound] PDAFT buffer size: %d (%dms at %dHz)\n", divaBufSizeInFrames, divaBufSizeInMilliseconds, device.sampleRate); + } divaAudioAllocMixer(divaAudioMixCls, unk, unk2, divaBufSizeInFrames); diff --git a/source-code/source/plugins/DivaSound/src/framework.h b/source-code/source/plugins/DivaSound/src/framework.h index 8af41b9..6c8f289 100644 --- a/source-code/source/plugins/DivaSound/src/framework.h +++ b/source-code/source/plugins/DivaSound/src/framework.h @@ -12,43 +12,127 @@ #include #include -void (__cdecl* divaAudioInit)(void* cls, uint64_t unk, uint64_t unk2) = (void(__cdecl*)(void* cls, uint64_t unk, uint64_t unk2))0x1406269F0; +void (*divaAudioInit)(void* cls, uint64_t unk, uint64_t unk2) = (void(*)(void* cls, uint64_t unk, uint64_t unk2))0x1406269F0; -void (__cdecl* divaAudioFillbuffer)(void* mixer, int16_t* buf, uint64_t nFrames, bool disableHpVol, bool invertPhase) = (void(__cdecl*)(void* mixer, int16_t* buf, uint64_t nFrames, bool disableHpVol, bool invertPhase))0x140627370; +void (*divaAudioFillbuffer)(void* mixer, int16_t* buf, uint64_t nFrames, bool disableHpVol, bool invertPhase) = (void(*)(void* mixer, int16_t* buf, uint64_t nFrames, bool disableHpVol, bool invertPhase))0x140627370; // mixer is a pointer to an audioMixer (from audio init's cls + 0x70) // disableHpVol uses speaker volume for headphones (only works in 4ch mode) // invertPhase inverts the output signal (only works if disableHpVol == false) -int (__cdecl* divaAudioAllocMixer)(void* cls, uint64_t unk, uint64_t unk2, int64_t nFrames) = (int(__cdecl*)(void* cls, uint64_t unk, uint64_t unk2, int64_t nFrames))0x140626710; +int (*divaAudioAllocMixer)(void* cls, uint64_t unk, uint64_t unk2, int64_t nFrames) = (int(*)(void* cls, uint64_t unk, uint64_t unk2, int64_t nFrames))0x140626710; // unks are the same as from the init call. they seem to set the internal mixing channel counts(?) // cls is the same as mixer in divaAudioFillbuffer // nFrames is number of audio frames to hold in the mixing buffers (only used when divaAudioFillbuffer is called). Internally this is multiplied by 16 (buffers are built using 32bit floats) -int(__cdecl* mtx_init)(void* mutex, int type) = (int(__cdecl*)(void* mutex, int type))0x14081DEF4; +int(*mtx_init)(void* mutex, int type) = (int(*)(void* mutex, int type))0x14081DEF4; +int(*mtx_lock_0)(void* mutex) = (int(*)(void* mutex))0x14081DF50; +int(*mtx_unlock)(void* mutex) = (int(*)(void* mutex))0x14081DFD4; + +typedef void streamingCallback(float* buffer, int64_t nFrames, void* userdata); #pragma pack(push, 1) -struct _50 { - byte padding00[0x50]; -}; -struct _70 { - byte padding00[0x70]; -}; +struct initClass; // define these earlier so they can be used in other structs +struct audioMixer; + +// known streaming channel variables +// + 0x00 = pointer to mixer class +// + 0x08 = buffer pointer (float) +// + 0x10 = buffer size (frame count * 16) +// + 0x18 = playing (32 bits, set to 0 for pause) +// + 0x1c = reset (32 bits, set to 0 to kill channel) +// + 0x20 = mutex pointer +// + 0x28 = master volume float (multiply other volumes by this) +// + 0x2c = ch1 volume +// + 0x30 = ch2 volume +// + 0x34 = ch3 volume +// + 0x38 = ch4 volume +// +// + 0x40 = callback func +// + 0x48 = callback userdata pointer +struct streamingChannel { + audioMixer* mixer; -struct streamingState { - std::vector<_50>* state; float* buffer; - uint64_t buffer_size; + uint64_t buffer_size; // in bytes + + uint32_t playing; // set to 0 for pause (usually ==1) + uint32_t reset; // set to 1 to kill (usually ==0) + + void* mutex; + + float volume_master; + float volume_channels[4]; + byte padding3c[0x4]; + + streamingCallback callback; + void* userdata; }; -struct initClass; +// known SE channel variables +// + 0x00 = pointer to mixer class +// + 0x08 = some kind of toggle (is playing)? +// + 0x10 = mutex pointer +// + 0x18 = master volume float (multiply other volumes by this) +// + 0x1c = ch1 volume +// + 0x20 = ch2 volume +// + 0x24 = ch3 volume +// + 0x28 = ch4 volume + +// + 0x30 = buffer pointer (float) +// + 0x38 = buffer size????? (frame count * 16)??? (buffers seem to hold whole sounds) +// + 0x40 = num channels +// + 0x48 = num frames +// + 0x50 = sample rate??? +// + 0x58 = loop start frame??? +// + 0x60 = loop end frame??? +// + 0x68 = current playback time +struct seChannel { + audioMixer* mixer; + + uint32_t unk1; // toggle on/off? + byte padding0c[0x4]; + + void* mutex; + + float volume_master; + float volume_channels[4]; + byte padding2c[0x4]; + + float* buffer; + byte padding38[0x8]; // probably buffer size + + int64_t nChannels; // seems to affect mapping + + uint64_t length; // in frames + byte padding50[0x8]; // sample rate? + uint64_t loop_start; // ? + uint64_t loop_end; // ? + uint64_t curTime; +}; + +// known internal audio mixer variables (used by divaAudioFillbuffer and divaAudioAllocMixer) +// cls + 0x00 = pointer to main audio/init class +// cls + 0x08 = SE channels pointer +// cls + 0x10 = SE channels count +// cls + 0x18 = streaming channels pointer +// cls + 0x20 = streaming channels count +// cls + 0x28 = mixing buffer pointer (when a buffer is generated, this is filled with 32bit floats (four per frame) +// cls + 0x30 = mixing buffer size (frame count * 16) +// +// cls + 0x38 = mutex lock for volume +// cls + 0x40 = master volume float (multiply other volumes by this) +// cls + 0x44 = ch1 volume +// cls + 0x48 = ch2 volume +// cls + 0x4c = ch3 volume +// cls + 0x50 = ch4 volume struct audioMixer { initClass* audioClass; - std::vector<_70>** state1; - uint64_t state1_len; - streamingState* state2; - uint64_t state2_len; + seChannel* seChannels; + uint64_t seChannels_len; + streamingChannel* streamingChannels; + uint64_t streamingChannels_len; float* mixbuffer; uint64_t mixbuffer_size; @@ -60,6 +144,27 @@ struct audioMixer { byte padding54[4]; }; +// known main/init audio class variables (used by divaAudioInit) +// cls + 0x0 = WAVEFORMATEXTENSIBLE wave_format (null with old method) (length 0x28) +// cls + 0x28 = IMMDeviceEnumerator *pEnumerator +// cls + 0x30 = IMMDevice *pDevice (default device) +// cls + 0x38 = IAudioClient *pAudioClient +// +// cls + 0x40 = buffer size in frames +// +// cls + 0x48 = IAudioRenderClient *pRenderClient +// +// cls + 0x50 = HANDLE hEvent (for original WASAPI buffer timing) +// +// cls + 0x58 = number of output channels +// cls + 0x60 = audio sample rate +// cls + 0x68 = audio bit depth (only 16bit works) +// +// cls + 0x70 = pointer to mixer class +// +// cls + 0x78 = HANDLE* hCallback (handle to original callback thread) +// +// cls + 0x80 = break flag dword (becomes 1 on exit) struct initClass { WAVEFORMATEXTENSIBLE wave_format; IMMDeviceEnumerator *pEnumerator; @@ -83,45 +188,6 @@ struct initClass { }; #pragma pack(pop) -// known internal audio mixer variables (used by divaAudioFillbuffer and divaAudioAllocMixer) -// cls + 0x00 = pointer to main audio/init class -// cls + 0x08 = internal state 1 (SE?) vector pointer (or full class?) -// cls + 0x10 = internal state 1 (SE?) length (channels?) -// cls + 0x18 = internal state 2 (streaming?) vector pointer (or full class?) -// cls + 0x20 = internal state 2 (streaming?) length (channels?) -// cls + 0x28 = mixing buffer pointer (when a buffer is generated, this is filled with 32bit floats (four per frame) -// cls + 0x30 = mixing buffer size (frame count * 16) -// -// cls + 0x38 = mutex lock for volume -// cls + 0x40 = master volume float (multiply other volumes by this) -// cls + 0x44 = ch1 volume -// cls + 0x48 = ch2 volume -// cls + 0x4c = ch3 volume -// cls + 0x50 = ch4 volume -// -// -// known main/init audio class variables (used by divaAudioInit) -// cls + 0x0 = WAVEFORMATEXTENSIBLE wave_format (null with old method) (length 0x28) -// cls + 0x28 = IMMDeviceEnumerator *pEnumerator -// cls + 0x30 = IMMDevice *pDevice (default device) -// cls + 0x38 = IAudioClient *pAudioClient -// -// cls + 0x40 = buffer size in frames -// -// cls + 0x48 = IAudioRenderClient *pRenderClient -// -// cls + 0x50 = HANDLE hEvent (for original WASAPI buffer timing) -// -// cls + 0x58 = number of output channels -// cls + 0x60 = audio sample rate -// cls + 0x68 = audio bit depth (only 16bit works) -// -// cls + 0x70 = pointer to mixer class -// -// cls + 0x78 = HANDLE* hCallback (handle to original callback thread) -// -// cls + 0x80 = break flag dword (becomes 1 on exit) - initClass *divaAudCls; audioMixer *divaAudioMixCls;