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
5.8 KiB254 linesraw
1#include "stdafx.h"
2#include "miscUtils.h"
3
4namespace
5{
6	wchar_t* formatMessage( HRESULT hr )
7	{
8		wchar_t* err;
9		if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
10			NULL,
11			hr,
12			MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
13			(LPTSTR)&err,
14			0,
15			NULL ) )
16			return err;
17		return nullptr;
18	}
19}
20
21CString formatErrorMessage( HRESULT hr )
22{
23	CString message;
24	const wchar_t* err = formatMessage( hr );
25	if( nullptr != err )
26	{
27		message = err;
28		LocalFree( (HLOCAL)err );
29		message.TrimRight();
30	}
31	else
32		message.Format( L"Error code %i (0x%08X)", hr, hr );
33
34	return message;
35}
36
37void reportFatalError( const char* what, HRESULT hr )
38{
39	CString message;
40	message.Format( L"%S\n%S\n", "Unable to start the application.", what );
41	message += formatErrorMessage( hr );
42	::MessageBox( nullptr, message, L"Whisper Desktop Startup", MB_OK | MB_ICONERROR );
43}
44
45namespace
46{
47	using Whisper::eModelImplementation;
48
49	struct sImplString
50	{
51		eModelImplementation val;
52		LPCTSTR str;
53	};
54	static const std::array<sImplString, 3> s_implStrings =
55	{
56		sImplString{ eModelImplementation::GPU, L"GPU" },
57		sImplString{ eModelImplementation::Hybrid, L"Hybrid" },
58		sImplString{ eModelImplementation::Reference, L"Reference" },
59	};
60}
61
62HRESULT implParse( const CString& s, eModelImplementation& rdi )
63{
64	for( const auto& is : s_implStrings )
65	{
66		if( 0 != s.CompareNoCase( is.str ) )
67			continue;
68		rdi = is.val;;
69		return S_OK;
70	}
71	return E_INVALIDARG;
72}
73
74LPCTSTR implString( eModelImplementation i )
75{
76	for( const auto& is : s_implStrings )
77		if( is.val == i )
78			return is.str;
79	return nullptr;
80}
81
82void implPopulateCombobox( CComboBox& cb, Whisper::eModelImplementation impl )
83{
84	int curSel = 0;
85	int idx = 0;
86	for( const auto& is : s_implStrings )
87	{
88		cb.AddString( is.str );
89		if( is.val == impl )
90			curSel = idx;
91		idx++;
92	}
93	cb.SetCurSel( curSel );
94}
95
96Whisper::eModelImplementation implGetValue( CComboBox& cb )
97{
98	int curSel = cb.GetCurSel();
99	if( curSel < 0 )
100		return (Whisper::eModelImplementation)0;
101	return s_implStrings[ curSel ].val;
102}
103
104ThreadPoolWork::~ThreadPoolWork()
105{
106	if( nullptr != work )
107	{
108		CloseThreadpoolWork( work );
109		work = nullptr;
110	}
111}
112
113void __stdcall ThreadPoolWork::callback( PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work )
114{
115	iThreadPoolCallback* cb = (iThreadPoolCallback*)Context;
116	cb->poolCallback();
117}
118
119HRESULT ThreadPoolWork::create( iThreadPoolCallback* cb )
120{
121	if( nullptr == cb )
122		return E_POINTER;
123	if( nullptr != work )
124		return HRESULT_FROM_WIN32( ERROR_ALREADY_INITIALIZED );
125
126	work = CreateThreadpoolWork( &callback, cb, nullptr );
127	if( nullptr != work )
128		return S_OK;
129
130	return HRESULT_FROM_WIN32( GetLastError() );
131}
132
133HRESULT ThreadPoolWork::post()
134{
135	if( nullptr == work )
136		return OLE_E_BLANK;
137	SubmitThreadpoolWork( work );
138	return S_OK;
139}
140
141void makeUtf16( CString& rdi, const char* utf8 )
142{
143	const size_t length = strlen( utf8 );
144	int count = MultiByteToWideChar( CP_UTF8, 0, utf8, (int)length, nullptr, 0 );
145	wchar_t* p = rdi.GetBufferSetLength( count );
146	MultiByteToWideChar( CP_UTF8, 0, utf8, (int)length, p, count );
147	rdi.ReleaseBuffer();
148}
149
150void makeUtf8( CStringA& rdi, const CString& utf16 )
151{
152	int count = WideCharToMultiByte( CP_UTF8, 0, utf16, utf16.GetLength(), nullptr, 0, nullptr, nullptr );
153	char* s = rdi.GetBufferSetLength( count + 1 );
154	count = WideCharToMultiByte( CP_UTF8, 0, utf16, utf16.GetLength(), s, count, nullptr, nullptr );
155	rdi.ReleaseBufferSetLength( count );
156}
157
158constexpr int ofnBufferLength = 2048;
159
160bool getOpenFileName( HWND owner, LPCTSTR title, LPCTSTR filter, CString& path )
161{
162	wchar_t buffer[ ofnBufferLength ];
163	buffer[ 0 ] = 0;
164	OPENFILENAME ofn;
165	memset( &ofn, 0, sizeof( ofn ) );
166	ofn.lStructSize = sizeof( OPENFILENAME );
167	ofn.hwndOwner = owner;
168	ofn.lpstrFilter = filter;
169	ofn.lpstrTitle = title;
170	ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
171	ofn.lpstrFile = buffer;
172	ofn.nMaxFile = ofnBufferLength - 1;
173
174	CString dir;
175	if( path.GetLength() > 0 && path.GetLength() < ofnBufferLength )
176		wcsncpy_s( buffer, path, path.GetLength() );
177
178	if( !GetOpenFileName( &ofn ) )
179	{
180		path = L"";
181		return false;
182	}
183	else
184	{
185		path = ofn.lpstrFile;
186		return true;
187	}
188}
189
190bool getSaveFileName( HWND owner, LPCTSTR title, LPCTSTR filter, CString& path, DWORD* filterIndex )
191{
192	wchar_t buffer[ ofnBufferLength ];
193	buffer[ 0 ] = 0;
194
195	OPENFILENAME ofn;
196	memset( &ofn, 0, sizeof( ofn ) );
197	ofn.lStructSize = sizeof( OPENFILENAME );
198	ofn.hwndOwner = owner;
199	ofn.lpstrFilter = filter;
200	ofn.lpstrTitle = title;
201	ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST;
202	ofn.lpstrFile = buffer;
203	ofn.nMaxFile = ofnBufferLength - 1;
204	if( nullptr != filterIndex )
205		ofn.nFilterIndex = *filterIndex + 1;
206
207	if( path.GetLength() > 0 && path.GetLength() < ofnBufferLength )
208		wcsncpy_s( buffer, path, path.GetLength() );
209
210	if( !GetSaveFileName( &ofn ) )
211		return false;
212
213	path = ofn.lpstrFile;
214
215	if( nullptr != filterIndex )
216		*filterIndex = ofn.nFilterIndex - 1;
217
218	return true;
219}
220
221void reportError( HWND owner, LPCTSTR text, LPCTSTR title, HRESULT hr )
222{
223	if( nullptr == title )
224		title = L"Operation Failed";
225
226	CString message = text;
227	message.TrimRight();
228	if( FAILED( hr ) )
229	{
230		message += L"\n";
231		message += formatErrorMessage( hr );
232	}
233
234	::MessageBox( owner, message, title, MB_OK | MB_ICONWARNING );
235}
236
237HRESULT writeUtf8Bom( CAtlFile& file )
238{
239	const std::array<uint8_t, 3> bom = { 0xEF, 0xBB, 0xBF };
240	return file.Write( bom.data(), 3 );
241}
242
243bool isInvalidTranslate( HWND owner, uint32_t lang, bool translate )
244{
245	if( !translate )
246		return false;
247	constexpr uint32_t english = 0x6E65;
248	if( lang != english )
249		return false;
250
251	LPCTSTR message = L"The translate feature translates speech to English.\nIt’s not available when the audio language is already English.";
252	MessageBox( owner, message, L"Incompatible parameters", MB_OK | MB_ICONINFORMATION );
253	return true;
254}