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

KonstantinSource codes8c4603c

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