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
670f889
master
1#include "stdafx.h" 2#include "LoadModelDlg.h" 3#include "Utils/miscUtils.h" 4#include "Utils/logger.h" 5#include "ModelAdvancedDlg.h" 6 7constexpr int progressMaxInteger = 1024 * 8 ; 8 9HRESULT LoadModelDlg ::show () 10{ 11auto res = DoModal (nullptr ); 12if (res == -1 ) 13return HRESULT_FROM_WIN32 (GetLastError () ); 14if (res == IDOK ) 15 { 16HRESULT hr = appState .lastScreenLoad (); 17switch (hr ) 18 { 19case SCREEN_TRANSCRIBE : 20case SCREEN_CAPTURE : 21return hr ; 22default : 23return SCREEN_TRANSCRIBE ; 24 } 25 } 26return S_OK ; 27} 28 29LRESULT LoadModelDlg ::OnInitDialog (UINT nMessage ,WPARAM wParam ,LPARAM lParam ,BOOL & bHandled ) 30{ 31// First DDX call, hooks up variables to controls. 32DoDataExchange ( false ); 33 34cbConsole .initialize (m_hWnd ,IDC_CONSOLE ,appState ); 35implPopulateCombobox (cbModelType ,appState .source .impl ); 36modelPath .SetWindowTextW (appState .source .path ); 37 38HRESULT hr = work .create (this ); 39if (FAILED (hr ) ) 40 { 41CString text = L"CreateThreadpoolWork failed\n" ; 42text += formatErrorMessage (hr ); 43 ::MessageBox (m_hWnd ,text ,L"Unable to load the model" ,MB_OK |MB_ICONWARNING ); 44return TRUE; 45 } 46 47editorsWindows .reserve (6 ); 48editorsWindows = {modelPath ,cbModelType ,GetDlgItem (IDC_BROWSE ),GetDlgItem (IDC_MODEL_ADV ),GetDlgItem (IDOK ),GetDlgItem (IDCANCEL ) }; 49pendingWindows .reserve (2 ); 50pendingWindows = {GetDlgItem (IDC_PENDING_TEXT ),progressBar }; 51 52progressBar .SetRange32 (0 ,progressMaxInteger ); 53progressBar .SetStep (1 ); 54 55appState .setupIcon (this ); 56ATLVERIFY (CenterWindow () ); 57if ( !appState .source .found || !appState .automaticallyLoadModel ) 58return 0 ; 59 60// AppState.findModelSource() method has located model parameters in registry; 61// Post a notification identical to the "OK" button click event. 62PostMessage (WM_COMMAND ,IDOK , (LPARAM )(GetDlgItem (IDOK ).m_hWnd ) ); 63 64return 0 ; 65} 66 67LRESULT LoadModelDlg ::OnBrowse (UINT ,INT ,HWND ,BOOL & bHandled ) 68{ 69bHandled = TRUE; 70 71CString path ; 72modelPath .GetWindowText (path ); 73if ( !getOpenFileName (m_hWnd ,L"Select a GGML Model File" ,L"Binary files (*.bin)\0*.bin\0\0" ,path ) ) 74return 0 ; 75 76modelPath .SetWindowText (path ); 77appState .source .path = path ; 78return 0 ; 79} 80 81LRESULT LoadModelDlg ::validationError (LPCTSTR message ) 82{ 83reportError (m_hWnd ,message ,L"Unable to load the model" ); 84return 0 ; 85} 86 87LRESULT LoadModelDlg ::validationError (LPCTSTR message ,HRESULT hr ) 88{ 89reportError (m_hWnd ,message ,L"Unable to load the model" ,hr ); 90return 0 ; 91} 92 93void LoadModelDlg ::setPending (bool nowPending ) 94{ 95const BOOL enable = nowPending ? FALSE : TRUE; 96for (HWND w :editorsWindows ) 97 ::EnableWindow (w ,enable ); 98 99const int show = nowPending ?SW_NORMAL :SW_HIDE ; 100for (HWND w :pendingWindows ) 101 ::ShowWindow (w ,show ); 102 103if (nowPending ) 104progressBar .SetMarquee ( TRUE,0 ); 105else 106progressBar .SetMarquee ( FALSE,0 ); 107} 108 109LRESULT LoadModelDlg ::OnOk (UINT ,INT ,HWND ,BOOL & bHandled ) 110{ 111modelPath .GetWindowText (path ); 112if (path .GetLength () <=0 ) 113return validationError (L"Please select a model GGML file" ); 114 115 { 116CAtlFile file ; 117HRESULT hr = file .Create (path ,GENERIC_READ ,FILE_SHARE_READ ,OPEN_EXISTING ); 118if (FAILED (hr ) ) 119return validationError (L"Unable to open the model file" ,hr ); 120 121ULONGLONG cb = 0 ; 122file .GetSize (cb ); 123appState .source .sizeInBytes = cb ; 124 } 125 126impl = implGetValue (cbModelType ); 127if (impl == (Whisper ::eModelImplementation )0 ) 128return validationError (L"Please select a model type" ); 129 130setPending ( true ); 131work .post (); 132return 0 ; 133} 134 135void __stdcallLoadModelDlg ::poolCallback ()noexcept 136{ 137CComPtr < Whisper ::iModel > model ; 138clearLastError (); 139loadError = L"" ; 140Whisper ::sLoadModelCallbacks lmcb ; 141lmcb .cancel = nullptr ; 142lmcb .progress = & LoadModelDlg ::progressCallback ; 143lmcb .pv = this ; 144const uint32_t flags = appState .gpuFlagsLoad (); 145HRESULT hr = Whisper ::loadModel (path ,impl ,flags ,& lmcb ,& model ); 146if (SUCCEEDED (hr ) ) 147appState .model = model ; 148else 149getLastError (loadError ); 150 151this -> PostMessage (WM_CALLBACK_STATUS , (WPARAM )hr ); 152} 153 154HRESULT __stdcallLoadModelDlg ::progressCallback (double val ,void * pv )noexcept 155{ 156LoadModelDlg & dialog = * (LoadModelDlg * )pv ; 157constexpr double mul = progressMaxInteger ; 158int pos = lround (mul * val ); 159dialog .progressBar .PostMessage (PBM_SETPOS ,pos ,0 ); 160return S_OK ; 161} 162 163LRESULT LoadModelDlg ::OnCallbackStatus (UINT ,WPARAM wParam ,LPARAM ,BOOL & bHandled ) 164{ 165setPending ( false ); 166 167bHandled = TRUE; 168const HRESULT hr = (HRESULT )wParam ; 169if (FAILED (hr ) ) 170 { 171LPCTSTR failMessage = L"Error loading the model" ; 172if (loadError .GetLength ()> 0 ) 173 { 174CString tmp = failMessage ; 175tmp += L"\n" ; 176tmp += loadError ; 177return validationError (tmp ,hr ); 178 } 179else 180return validationError (failMessage ,hr ); 181 } 182 183appState .source .path = path ; 184appState .source .impl = impl ; 185appState .saveModelSource (); 186 187EndDialog (IDOK ); 188return 0 ; 189} 190 191LRESULT LoadModelDlg ::OnHyperlink (int idCtrl ,LPNMHDR pnmh ,BOOL & bHandled ) 192{ 193const UINT code = pnmh -> code ; 194switch (code ) 195 { 196case NM_CLICK : 197case NM_RETURN : 198break ; 199default : 200return 0 ; 201 } 202 203PNMLINK pNMLink = (PNMLINK )pnmh ; 204LPCTSTR url = pNMLink -> item .szUrl ; 205ShellExecute (NULL ,L"open" ,url ,NULL ,NULL ,SW_SHOW ); 206bHandled = TRUE; 207return 0 ; 208} 209 210void LoadModelDlg ::onModelAdvanced () 211{ 212ModelAdvancedDlg dlg {appState }; 213dlg .show (m_hWnd ); 214}