From ffb26ec077271a77f2c7f61f7a30aba1c7a7e55c Mon Sep 17 00:00:00 2001 From: jiegeaiai Date: Sun, 29 Sep 2024 00:29:59 +0800 Subject: [PATCH] add first --- AudioRender.sln | 31 ++++ ...b7341f62-5739-4a30-9c07-29cbb18288f4.vsidx | Bin 0 -> 7465 bytes AudioRender/.vs/AudioRender/v17/.suo | Bin 0 -> 18432 bytes AudioRender/.vs/AudioRender/v17/Browse.VC.db | Bin 0 -> 450560 bytes .../.vs/AudioRender/v17/DocumentLayout.json | 12 ++ AudioRender/AudioRender.cpp | 27 ++++ AudioRender/AudioRender.h | 21 +++ AudioRender/AudioRender.vcxproj | 150 ++++++++++++++++++ AudioRender/AudioRender.vcxproj.filters | 54 +++++++ AudioRender/AudioRender.vcxproj.user | 4 + AudioRender/AudioRenderStd.cpp | 7 + AudioRender/AudioRenderStd.h | 12 ++ AudioRender/IAudioRender.h | 30 ++++ AudioRender/Windows/CoreAudioRender.cpp | 1 + AudioRender/Windows/CoreAudioRender.h | 7 + AudioRender/Windows/SectionLock.cpp | 22 +++ AudioRender/Windows/SectionLock.h | 35 ++++ AudioRender/Windows/WavAudioRender.cpp | 144 +++++++++++++++++ AudioRender/Windows/WavAudioRender.h | 31 ++++ 19 files changed, 588 insertions(+) create mode 100644 AudioRender.sln create mode 100644 AudioRender/.vs/AudioRender/FileContentIndex/b7341f62-5739-4a30-9c07-29cbb18288f4.vsidx create mode 100644 AudioRender/.vs/AudioRender/v17/.suo create mode 100644 AudioRender/.vs/AudioRender/v17/Browse.VC.db create mode 100644 AudioRender/.vs/AudioRender/v17/DocumentLayout.json create mode 100644 AudioRender/AudioRender.cpp create mode 100644 AudioRender/AudioRender.h create mode 100644 AudioRender/AudioRender.vcxproj create mode 100644 AudioRender/AudioRender.vcxproj.filters create mode 100644 AudioRender/AudioRender.vcxproj.user create mode 100644 AudioRender/AudioRenderStd.cpp create mode 100644 AudioRender/AudioRenderStd.h create mode 100644 AudioRender/IAudioRender.h create mode 100644 AudioRender/Windows/CoreAudioRender.cpp create mode 100644 AudioRender/Windows/CoreAudioRender.h create mode 100644 AudioRender/Windows/SectionLock.cpp create mode 100644 AudioRender/Windows/SectionLock.h create mode 100644 AudioRender/Windows/WavAudioRender.cpp create mode 100644 AudioRender/Windows/WavAudioRender.h diff --git a/AudioRender.sln b/AudioRender.sln new file mode 100644 index 0000000..db98028 --- /dev/null +++ b/AudioRender.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35303.130 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioRender", "AudioRender\AudioRender.vcxproj", "{095FA653-16F9-4AAE-87E9-3E467A5E8564}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Debug|x64.ActiveCfg = Debug|x64 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Debug|x64.Build.0 = Debug|x64 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Debug|x86.ActiveCfg = Debug|Win32 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Debug|x86.Build.0 = Debug|Win32 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Release|x64.ActiveCfg = Release|x64 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Release|x64.Build.0 = Release|x64 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Release|x86.ActiveCfg = Release|Win32 + {095FA653-16F9-4AAE-87E9-3E467A5E8564}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {50A43890-42B5-46B3-AF83-E4977344D4B1} + EndGlobalSection +EndGlobal diff --git a/AudioRender/.vs/AudioRender/FileContentIndex/b7341f62-5739-4a30-9c07-29cbb18288f4.vsidx b/AudioRender/.vs/AudioRender/FileContentIndex/b7341f62-5739-4a30-9c07-29cbb18288f4.vsidx new file mode 100644 index 0000000000000000000000000000000000000000..36e4e0b144b3a2e5e77e996ef7d838d63ec1cc50 GIT binary patch literal 7465 zcma)=1$dlQ7KZ;q3&kn!GB_nkBTdpynldw)NhV~H5NQJxZ3`4Dlol(+-QC?~g>_ff zmvvv(optwJ_WRC#Gn<9y*@wLrCW%T}x$S$^8G<*Qzc-FVj0b52*&#^YCTdGhbTs{6o*pdU4v!87chw zfoWN`UY6B0mt}iI$(C8BN99RhVWe8AoE1kAralVNlVul8i9BmEj+)3bX^NRbO|_GQ zN)$ZRN|QsXsy9i6(t4A+e`=ztqmwLJ1nPcDqqB$fRC z=JHXKG>z(16DU>5RarJYLZy-vN>z#`Tl$L3Up>ZDlAKcxYObg5nSw}Dxiq;+)hfNp zIk_bx7q6;SdZ}SOelk+4dR09K8L5eeBhRUBa#oc}^k|RiRZnu0=Veizn=Bch^ih=x z)g*P1S|wFsDo?L+P_!4KU)gm}`N&p$siIANrj{gs)hdYWq{&dB!pgoTderM)5l22L ztg7lGlAViM8S+eznrrN`r`D=%s#RffPKGp{!8BcZoi;fw^3TPS(o=bAnEX?G+47N{ zp43Zc%)m>_vUXz`2P$)fVd&qy*vdyyiH#5O8>R)vdwps?KLtmlx+W>9| z9mC}t!HwZ2a8u|m?YBAH0xGL0*MNds!L8voa9g+?+#c=#cZ55^o#8IfKQ!)tH@G|8 z1MUemQQ@b>3GNN|f&0S!;QsIccp#h&4}uM_5jMd&P^%pMwZK-`2Is7Vokrmp)O8o-{!792 zi{S)33?2@TfJ@+!@F;jRJO&;MkAq9$GPoQb4^Mz6!WHl&crrW%o(fNcE8*$z47duO z30K24@GN*XJO`c&&x32>`EVV)0A2_$f)~R};HB^~csaZRUJ0*)SHo-IweUK4J-h+l z2ycQn!&~63@HTimyaV0|?}B&3d*HqBK6pQT06qvGf)B$-;G^&{_&9t5J_(WWoG<*Sm27VTP4t^ef0e%sF34R%V1%4HN4SpSd1AY^}2)_lt4Zj1w z3%>`y4}SoE2!8~B41WTD3V#M)fU@z>0RoD*?fdjAx2jLJL zhKIrtI10z$I9vo5!wGm8JRBYYm%t<8QSfMZ3_KPd2baQSa5+34o&ZmTE8t1+WOxcZ z6`lrH!qedya1}fgu7+#iS@3Ll4m=m02iL;$;W~H$ybxXlFNT-EOW|eka(D&25?%$b zhS$Jr;dStOcmuo<-UM%kx4>KBZSZz@2fP#B1@DIUzN8w}e zargv$5LOZ4I&)TYQbG9z5oU|><+m-d4 z$fG&(@?6-jMc-y+TZlGYk;j}UElB4oix$nxh}7@aR%wsM)uKF$(uzK<8dWznt*UF6 z-4W%^tX1N+*>uJlI5T^-snm8Uv?9)xPn*=eSpAdb7pM|?F${(e(|WgV?5pRF3Dai zA8UK)yog>?E?y6xD6gw`T-t?R#k32&e+wFySKU56^7ZUDhC0HSMpeibNqsuorQUNz zW!4gH8l>JAUac{yYpg^1_NYZsW1K7X4lHVngVLJvw}ExPw#nM}!Vwbei%1ga(%8KCV z1IntD&WWD-Lx)0#L+$C6 zv96PPrmZ7V=Voho5SdbWF&TRMBQIeA{Kn(Y5Q zhy8l@O8FOMOzIW!j__XbN~YCIb7UP*iRZvQ`II_SYgM0tSdRh4nLNp!L)*@5Fxq<8 zRinphc4+KA&#X`TMAol}MX6WGC%+upt9BlVHTBUX+iN!vtK*d$mOZLt|zht%@$)_SO_1$6hIq~fhnBvF%y#?ELq%*!HY?cZ^9r`XRlKN<9L{ZU|iv>T=h6%=S$0<9Zv8 z`#aso)}9zox@#xG+qb88y>&$DoQKt;)idO~)wOPI^^ABgd7aYkuj$=uU(1H zF80atnH!aQ_j!-l(_^x_WGK$P=fQWJXW73J>9+PvGrf1Wqbcyy#^jnIztQ zV%xXB@2|YnF?>7MqVIvwk@y{2q`Z7*re8&C`o$ZIUDYJ@zH{z9QfK5dkdNPzO8k~| dNd5PRZ|A1?d(bjn-z|7M6|S3+jF+}b{10CFSR4QV literal 0 HcmV?d00001 diff --git a/AudioRender/.vs/AudioRender/v17/.suo b/AudioRender/.vs/AudioRender/v17/.suo new file mode 100644 index 0000000000000000000000000000000000000000..9a9b853a7c241065b68fae927d0771c843f032ff GIT binary patch literal 18432 zcmeI3Pi)*r6~|}O1`-M_At68#Qj?@K(AtUZjpH%v zt={kN%uT;ZHEFRCkJ!*;W=(B~WL)H=S{^TyA%{3(IznB$*ug~y?| zY+f*@p+3jeu(?s^E2Xcun+*l}5_{>}%6Azas|^BAUv#gUEG@{HSulkxromZPtm<)} z*^mgkyK2GU#W2@TM#gl`T!Tv1EWp2TKA=3rlUz`*(xvEsf)^XWxcpC3*4y<1T)!7G z5L|cgZZr5

=U;-UZ6u1s~>m3n=}Cc#5sA9xt-2akY{fgz8_ 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 literal 0 HcmV?d00001 diff --git a/AudioRender/.vs/AudioRender/v17/Browse.VC.db b/AudioRender/.vs/AudioRender/v17/Browse.VC.db new file mode 100644 index 0000000000000000000000000000000000000000..65fd0a023690ad466598d97508796bca6ae2814c GIT binary patch literal 450560 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 +#include + +#include "IAudioRender.h" + +static std::unique_ptr audiosRender_; +bool __stdcall Initialize(const char* sender_name, const char* receiver_name) { + assert(!audiosRender_); + audiosRender_.reset(IAudioRender::Create()); + return true; +} + +bool __stdcall Write(const unsigned char* data, unsigned int len) { + assert(audiosRender_); + + std::vector audio(len, 0); + memcpy(&audio[0], data, len); + AudioFrame frame = { audio, 0 }; + return audiosRender_->Write(frame); +} + +void __stdcall Uninitialize() { + assert(audiosRender_); + audiosRender_.reset(); +} diff --git a/AudioRender/AudioRender.h b/AudioRender/AudioRender.h new file mode 100644 index 0000000..8cdcacd --- /dev/null +++ b/AudioRender/AudioRender.h @@ -0,0 +1,21 @@ +#pragma once + +#if defined(WIN32) +#ifdef AUDIO_RENDER_LIB +#define AUDIO_RENDER_EXPORT __declspec( dllexport ) +#else +#define AUDIO_RENDER_EXPORT __declspec( dllimport ) +#endif +#endif // WIN32 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + AUDIO_RENDER_EXPORT bool __stdcall Initialize(const char* sender_name, const char* receiver_name); + AUDIO_RENDER_EXPORT bool __stdcall Write(const unsigned char* data, unsigned int len); + AUDIO_RENDER_EXPORT void __stdcall Uninitialize(); + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/AudioRender/AudioRender.vcxproj b/AudioRender/AudioRender.vcxproj new file mode 100644 index 0000000..a1a1d84 --- /dev/null +++ b/AudioRender/AudioRender.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {095fa653-16f9-4aae-87e9-3e467a5e8564} + AudioRender + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;WIN32;AUDIO_RENDER_LIB;%(PreprocessorDefinitions) + true + D:\Project\AudioRender\AudioRender;%(AdditionalIncludeDirectories) + + + Console + true + Winmm.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;WIN32;AUDIO_RENDER_LIB;%(PreprocessorDefinitions) + true + + + Console + true + true + true + Winmm.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AudioRender/AudioRender.vcxproj.filters b/AudioRender/AudioRender.vcxproj.filters new file mode 100644 index 0000000..616cc85 --- /dev/null +++ b/AudioRender/AudioRender.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git a/AudioRender/AudioRender.vcxproj.user b/AudioRender/AudioRender.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/AudioRender/AudioRender.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/AudioRender/AudioRenderStd.cpp b/AudioRender/AudioRenderStd.cpp new file mode 100644 index 0000000..575ae75 --- /dev/null +++ b/AudioRender/AudioRenderStd.cpp @@ -0,0 +1,7 @@ +#include "AudioRenderStd.h" + +#include "Windows/WavAudioRender.h" + +IAudioRender* IAudioRender::Create() { + return new WavAudioRender; +} \ No newline at end of file diff --git a/AudioRender/AudioRenderStd.h b/AudioRender/AudioRenderStd.h new file mode 100644 index 0000000..aea7328 --- /dev/null +++ b/AudioRender/AudioRenderStd.h @@ -0,0 +1,12 @@ +#pragma once + +#include "IAudioRender.h" + +class AudioRenderStd : public IAudioRender { +public: + ~AudioRenderStd() override = default; + uint64 GetClock() override { + return 0; + } +}; + diff --git a/AudioRender/IAudioRender.h b/AudioRender/IAudioRender.h new file mode 100644 index 0000000..30b126c --- /dev/null +++ b/AudioRender/IAudioRender.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +using int8 = char; +using uint8 = unsigned char; +using int16 = short; +using uint16 = unsigned short; +using int32 = int; +using uint32 = unsigned int; +using int64 = long long; +using uint64 = unsigned long long; + + +struct AudioFrame { + std::vector data_; + uint64 dts_{ 0 }; +}; + + +class IAudioRender { +public: + static IAudioRender* Create(); + +public: + virtual ~IAudioRender() = default; + virtual uint64 GetClock() = 0; + virtual bool Write(const AudioFrame& audioFrame) = 0; + +}; diff --git a/AudioRender/Windows/CoreAudioRender.cpp b/AudioRender/Windows/CoreAudioRender.cpp new file mode 100644 index 0000000..1c6ef2d --- /dev/null +++ b/AudioRender/Windows/CoreAudioRender.cpp @@ -0,0 +1 @@ +#include "CoreAudioRender.h" diff --git a/AudioRender/Windows/CoreAudioRender.h b/AudioRender/Windows/CoreAudioRender.h new file mode 100644 index 0000000..1e60dc7 --- /dev/null +++ b/AudioRender/Windows/CoreAudioRender.h @@ -0,0 +1,7 @@ +#pragma once + +#include "IAudioRender.h" + +class CoreAudioRender : public IAudioRender { +}; + diff --git a/AudioRender/Windows/SectionLock.cpp b/AudioRender/Windows/SectionLock.cpp new file mode 100644 index 0000000..da9304f --- /dev/null +++ b/AudioRender/Windows/SectionLock.cpp @@ -0,0 +1,22 @@ +#include "Windows/SectionLock.h" + +SectionLock::SectionLock() noexcept { + InitializeCriticalSection(§ion_); +} + +SectionLock::~SectionLock() { + DeleteCriticalSection(§ion_); +} + +void SectionLock::Lock() { + EnterCriticalSection(§ion_); +} + +bool SectionLock::TryLock() { + bool success = TryEnterCriticalSection(§ion_); + return success; +} + +void SectionLock::UnLock() { + LeaveCriticalSection(§ion_); +} diff --git a/AudioRender/Windows/SectionLock.h b/AudioRender/Windows/SectionLock.h new file mode 100644 index 0000000..1b702ca --- /dev/null +++ b/AudioRender/Windows/SectionLock.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +class SectionLock { +public: + explicit SectionLock() noexcept; + explicit SectionLock(const SectionLock& ) = delete; + SectionLock& operator= (const SectionLock&) = delete; + ~SectionLock(); + + void Lock(); + bool TryLock(); + void UnLock(); + +private: + CRITICAL_SECTION section_; +}; + +template +class Locker { +public: + explicit Locker(Lock& lock) noexcept : lock_(lock) { + lock_.Lock(); + } + explicit Locker(const Locker&) = delete; + Locker& operator= (const Locker&) = delete; + ~Locker() { + lock_.UnLock(); + } + +private: + Lock& lock_; +}; + diff --git a/AudioRender/Windows/WavAudioRender.cpp b/AudioRender/Windows/WavAudioRender.cpp new file mode 100644 index 0000000..d5c5239 --- /dev/null +++ b/AudioRender/Windows/WavAudioRender.cpp @@ -0,0 +1,144 @@ +#include "Windows/WavAudioRender.h" + +#include +#include + +static WAVEHDR* AllocateBlocks(uint32 size, int32 count) { + uint32 totalBufferSize = (size + sizeof(WAVEHDR)) * count; + + uint8* buffer{ nullptr }; + if ((buffer = reinterpret_cast(HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + totalBufferSize + ))) == NULL) { + ExitProcess(1); + } + + WAVEHDR* blocks = reinterpret_cast(buffer); + buffer += sizeof(WAVEHDR) * count; + for (int32 index = 0; index < count; ++index) { + blocks[index].dwBufferLength = size; + blocks[index].lpData = (LPSTR)buffer; + blocks[index].dwFlags = 0; + buffer += size; + } + return blocks; +} + +static void FreeBlocks(WAVEHDR* blockArray) { + HeapFree(GetProcessHeap(), 0, blockArray); +} + +WavAudioRender::WavAudioRender() noexcept { + HWAVEOUT hWaveOut = nullptr; + + waveBlocks_ = AllocateBlocks(BlockSize_, BlockCount_); + + constexpr int32 rate = 16000; + constexpr int32 channel = 1; + constexpr int32 bitePerSample = 16; + + WAVEFORMATEX waveform; + waveform.wFormatTag = WAVE_FORMAT_PCM; + waveform.nChannels = channel; + waveform.nSamplesPerSec = rate; + waveform.nAvgBytesPerSec = rate * channel * 2; + waveform.nBlockAlign = channel * 2; + waveform.wBitsPerSample = bitePerSample; + waveform.cbSize = 0; + + + MMRESULT hr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveform, + reinterpret_cast(WavAudioRender::waveOutProc), + reinterpret_cast(this), CALLBACK_FUNCTION); + if (MMSYSERR_NOERROR == hr) { + return; + } + + hWavout_ = std::move(hWaveOut); +} + +WavAudioRender::~WavAudioRender() { + if (nullptr == hWavout_) { + return; + } + waveOutReset(hWavout_); + for (int i = 0; i < BlockCount_; i++) { + if (waveBlocks_[i].dwFlags & WHDR_PREPARED) { + waveOutUnprepareHeader(hWavout_, &waveBlocks_[i], sizeof(WAVEHDR)); + } + } + + do { + MMRESULT ret = waveOutClose(hWavout_); + if (MMSYSERR_NOERROR == ret) { + break; + } else if (WAVERR_STILLPLAYING == ret) { + ::Sleep(1); + } else if (MMSYSERR_NOMEM == ret) { + break; + } else { + break; + } + } while (true); + FreeBlocks(waveBlocks_); +} + +bool WavAudioRender::Write(const AudioFrame& audioFrame) { + if (nullptr == hWavout_) { + return false; + } + + WAVEHDR* current; + int32 remain; + current = &waveBlocks_[waveCurrentBlock_]; + uint64 size = audioFrame.data_.size(); + const uint8* data = audioFrame.data_.data(); + while (size > 0) { + if (current->dwFlags & WHDR_PREPARED) { + waveOutUnprepareHeader(hWavout_, current, sizeof(WAVEHDR)); + } + if (size < (int)(BlockSize_ - current->dwUser)) { + memcpy(current->lpData + current->dwUser, data, size); + current->dwUser += size; + break; + } + remain = BlockSize_ - static_cast(current->dwUser); + memcpy(current->lpData + current->dwUser, data, remain); + size -= remain; + data += remain; + current->dwBufferLength = BlockSize_; + waveOutPrepareHeader(hWavout_, current, sizeof(WAVEHDR)); + waveOutWrite(hWavout_, current, sizeof(WAVEHDR)); + { + Locker locker(lock_); + --freeBlockCounter_; + } + + while (!freeBlockCounter_) { + Sleep(1); + } + + ++waveCurrentBlock_; + waveCurrentBlock_ %= BlockCount_; + current = &waveBlocks_[waveCurrentBlock_]; + current->dwUser = 0; + } + return true; +} + +void CALLBACK WavAudioRender::waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, + DWORD_PTR dwParam1, DWORD_PTR dwParam2) { + WavAudioRender* self = reinterpret_cast(dwInstance); + + if (uMsg != WOM_DONE) + return; + + self->FreeBlock(); +} + +void WavAudioRender::FreeBlock() { + Locker locker(lock_); + ++freeBlockCounter_; +} diff --git a/AudioRender/Windows/WavAudioRender.h b/AudioRender/Windows/WavAudioRender.h new file mode 100644 index 0000000..5c48dec --- /dev/null +++ b/AudioRender/Windows/WavAudioRender.h @@ -0,0 +1,31 @@ +#pragma once + +#include "AudioRenderStd.h" + +#include "Windows/SectionLock.h" + +class WavAudioRender : public AudioRenderStd { +public: + explicit WavAudioRender() noexcept; + ~WavAudioRender() override; + + bool Write(const AudioFrame& audioFrame) override; + +private: + static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, + DWORD_PTR dwParam1, DWORD_PTR dwParam2); + void FreeBlock(); + +private: + int64_t audioPts_{ 0 }; + + static constexpr int BlockSize_{ 6400 }; + static constexpr int BlockCount_{ 10 }; + + SectionLock lock_; + uint32 freeBlockCounter_{ BlockCount_ }; + uint32 waveCurrentBlock_{ 0 }; + + WAVEHDR* waveBlocks_{ nullptr }; + HWAVEOUT hWavout_{ nullptr }; +};