yum-archive/TaSTT-Whisper
High-performance GPGPU inference of OpenAI's Whisper automatic speech recognition (ASR) model
git clone https://git.yummers.dev/yum-archive/TaSTT-Whisper
8c4603c
master
1#include "stdafx.h" 2#include <atlstr.h> 3#include <mfapi.h> 4#include <mfidl.h> 5#include <mfreadwrite.h> 6#include "AudioCapture.h" 7#include "../API/iMediaFoundation.cl.h" 8#include "../ComLightLib/comLightServer.h" 9#pragma comment(lib, "Mf.lib") 10 11namespace 12{ 13struct Strings 14 { 15CString displayName ,endpoint ; 16 }; 17 18HRESULT getAllocString (IMFActivate * activate ,const GUID & id ,CString & rdi ) 19 { 20wchar_t * pointer = nullptr ; 21UINT32 cchName ; 22HRESULT hr = activate -> GetAllocatedString (id ,& pointer ,& cchName ); 23if (SUCCEEDED (hr ) ) 24rdi .SetString (pointer ,cchName ); 25CoTaskMemFree (pointer ); 26return hr ; 27 } 28 29HRESULT getInfo (IMFActivate * activate ,Strings & rdi ) 30 { 31CHECK (getAllocString (activate ,MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME ,rdi .displayName ) ); 32CHECK (getAllocString (activate ,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID ,rdi .endpoint ) ); 33return S_OK ; 34 } 35 36HRESULT __stdcallsupplyDevices (Whisper ::pfnFoundCaptureDevices pfn ,void * pv ,IMFActivate ** ppDevices ,UINT32 count ) 37 { 38if (ppDevices == nullptr || count == 0 ) 39return pfn (0 ,nullptr ,pv ); 40 41 std::vector < Strings > strings ; 42strings .reserve (count ); 43 44for (UINT i = 0 ;i < count ;i ++ ) 45 { 46IMFActivate * const activate = ppDevices [i ]; 47if (nullptr == activate ) 48continue ; 49Strings info ; 50HRESULT hr = getInfo (activate ,info ); 51if (FAILED (hr ) ) 52continue ; 53 54strings .emplace_back ( std::move (info ) ); 55 } 56 57const size_t len = strings .size (); 58if (0 == len ) 59return pfn (0 ,nullptr ,pv ); 60 61 std::vector < Whisper ::sCaptureDevice > pointers ; 62pointers .resize (len ); 63for (size_t i = 0 ;i < len ;i ++ ) 64 { 65const auto & src = strings [i ]; 66auto & dest = pointers [i ]; 67dest .displayName = src .displayName ; 68dest .endpoint = src .endpoint ; 69 } 70return pfn ( (int )len ,pointers .data (),pv ); 71 } 72} 73 74HRESULT __stdcallWhisper ::captureDeviceList (pfnFoundCaptureDevices pfn ,void * pv ) 75{ 76// Create an attribute store to hold the search criteria. 77CComPtr < IMFAttributes > attrs ; 78CHECK (MFCreateAttributes (& attrs ,1 ) ); 79// Request audio capture devices 80CHECK (attrs -> SetGUID (MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE ,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID ) ); 81 82// Enumerate the devices 83IMFActivate ** ppDevices = nullptr ; 84UINT32 count = 0 ; 85CHECK (MFEnumDeviceSources (attrs ,& ppDevices ,& count ) ); 86 87// Feed the data to the caller 88HRESULT hr = supplyDevices (pfn ,pv ,ppDevices ,count ); 89 90// Free the memory 91for (DWORD i = 0 ;i < count ;i ++ ) 92ppDevices [i ]-> Release (); 93CoTaskMemFree (ppDevices ); 94 95return hr ; 96} 97 98namespace 99{ 100using namespace Whisper ; 101 102class Capture :public ComLight ::ObjectRoot < iAudioCapture > 103 { 104CComPtr < IMFSourceReader > reader ; 105CComPtr < iMediaFoundation > mediaFoundation ; 106sCaptureParams captureParams ; 107 108HRESULT COMLIGHTCALL getReader (IMFSourceReader ** pp )const noexcept override final 109 { 110if (pp == nullptr ) 111return E_POINTER ; 112CComPtr < IMFSourceReader > res = reader ; 113* pp = res .Detach ();; 114return S_OK ; 115 } 116const sCaptureParams & COMLIGHTCALL getParams ()const noexcept override final 117 { 118return captureParams ; 119 } 120public : 121HRESULT open (iMediaFoundation * owner ,const wchar_t * endpoint ,const sCaptureParams & cp ); 122 }; 123 124HRESULT Capture ::open (iMediaFoundation * owner ,const wchar_t * endpoint ,const sCaptureParams & cp ) 125 { 126// Create an attribute store to hold the search criteria. 127CComPtr < IMFAttributes > attrs ; 128CHECK (MFCreateAttributes (& attrs ,2 ) ); 129// Request audio capture devices 130CHECK (attrs -> SetGUID (MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE ,MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID ) ); 131CHECK (attrs -> SetString (MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID ,endpoint ) ); 132 133CComPtr < IMFMediaSource > source ; 134HRESULT hr = MFCreateDeviceSource (attrs ,& source ); 135if (FAILED (hr ) ) 136 { 137logErrorHr (hr ,u8"MFCreateDeviceSource" ); 138return hr ; 139 } 140 141// TODO: implement IMFSourceReaderCallback, pass into MF_SOURCE_READER_ASYNC_CALLBACK attribute 142// This is to support cancellation 143hr = MFCreateSourceReaderFromMediaSource (source ,nullptr ,& reader ); 144if (FAILED (hr ) ) 145 { 146logErrorHr (hr ,u8"MFCreateSourceReaderFromMediaSource" ); 147return hr ; 148 } 149 150captureParams = cp ; 151mediaFoundation = owner ; 152return S_OK ; 153 } 154} 155 156HRESULT __stdcallWhisper ::captureOpen (iMediaFoundation * owner ,const wchar_t * endpoint ,const sCaptureParams & captureParams ,iAudioCapture ** pp )noexcept 157{ 158if (nullptr == endpoint || nullptr == pp ) 159return E_POINTER ; 160 161ComLight ::CComPtr < ComLight ::Object < Capture >> res ; 162CHECK (ComLight ::Object < Capture > ::create (res ) ); 163CHECK (res -> open (owner ,endpoint ,captureParams ) ); 164 165res .detach (pp ); 166return S_OK ; 167}