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
7.0 KiB234 linesraw
1#include "stdafx.h"
2#if BUILD_BOTH_VERSIONS
3#include "../API/iContext.cl.h"
4#include "convertThings.h"
5using namespace Whisper;
6
7sFullParams makeNewParams( const whisper_full_params& wfp )
8{
9	assert( nullptr == wfp.encoder_begin_callback );
10	assert( nullptr == wfp.new_segment_callback );
11
12	sFullParams res;
13	memset( &res, 0, sizeof( res ) );
14
15	res.strategy = (eSamplingStrategy)wfp.strategy;
16	res.cpuThreads = wfp.n_threads;
17	res.n_max_text_ctx = wfp.n_max_text_ctx;
18	res.offset_ms = wfp.offset_ms;
19	res.duration_ms = wfp.duration_ms;
20
21	// flags
22	uint32_t flags = 0;
23	if( wfp.translate ) flags |= (uint32_t)eFullParamsFlags::Translate;
24	if( wfp.no_context ) flags |= (uint32_t)eFullParamsFlags::NoContext;
25	if( wfp.single_segment ) flags |= (uint32_t)eFullParamsFlags::SingleSegment;
26	if( wfp.print_special ) flags |= (uint32_t)eFullParamsFlags::PrintSpecial;
27	if( wfp.print_progress ) flags |= (uint32_t)eFullParamsFlags::PrintProgress;
28	if( wfp.print_realtime ) flags |= (uint32_t)eFullParamsFlags::PrintRealtime;
29	if( wfp.print_timestamps ) flags |= (uint32_t)eFullParamsFlags::PrintTimestamps;
30	if( wfp.token_timestamps ) flags |= (uint32_t)eFullParamsFlags::TokenTimestamps;
31	if( wfp.speed_up ) flags |= (uint32_t)eFullParamsFlags::SpeedupAudio;
32	res.flags = (eFullParamsFlags)flags;
33
34	res.language = findLanguageKeyA( wfp.language );
35	res.thold_pt = wfp.thold_pt;
36	res.thold_ptsum = wfp.thold_ptsum;
37	res.max_len = wfp.max_len;
38	res.greedy.n_past = wfp.greedy.n_past;
39	res.beam_search.n_past = wfp.beam_search.n_past;
40	res.beam_search.beam_width = wfp.beam_search.beam_width;
41	res.beam_search.n_best = wfp.beam_search.n_best;
42	res.audio_ctx = wfp.audio_ctx;
43	res.prompt_tokens = wfp.prompt_tokens;
44	res.prompt_n_tokens = wfp.prompt_n_tokens;
45
46	return res;
47}
48
49namespace
50{
51	class NewParamsTemp
52	{
53		char language[ 5 ];
54		iContext* newContext;
55		pfnNewSegment newSegment;
56		pfnEncoderBegin encoderBegin;
57
58		static bool encBegin( struct whisper_context* ctx, void* user_data );
59		static void newSeg( struct whisper_context* ctx, int n_new, void* user_data );
60
61	public:
62
63		void initialize( whisper_full_params& res, const Whisper::sFullParams& rsi, Whisper::iContext* context )
64		{
65			*(uint32_t*)( &language[ 0 ] ) = rsi.language;
66			language[ 4 ] = '\0';
67			res.language = language;
68
69			newContext = context;
70
71			if( nullptr != rsi.encoder_begin_callback )
72			{
73				encoderBegin = rsi.encoder_begin_callback;
74				res.encoder_begin_callback = &encBegin;
75				res.encoder_begin_callback_user_data = rsi.encoder_begin_callback_user_data;
76			}
77			else
78			{
79				encoderBegin = nullptr;
80				res.encoder_begin_callback = nullptr;
81				res.encoder_begin_callback_user_data = nullptr;
82			}
83
84			if( nullptr != rsi.new_segment_callback )
85			{
86				newSegment = rsi.new_segment_callback;
87				res.new_segment_callback = &newSeg;
88				res.new_segment_callback_user_data = rsi.new_segment_callback_user_data;
89			}
90			else
91			{
92				newSegment = nullptr;
93				res.new_segment_callback = nullptr;
94				res.new_segment_callback_user_data = nullptr;
95			}
96		}
97	};
98
99	static thread_local NewParamsTemp npTemp;
100
101	bool NewParamsTemp::encBegin( struct whisper_context* ctx, void* user_data )
102	{
103		const NewParamsTemp& tmp = npTemp;
104		HRESULT hr = tmp.encoderBegin( tmp.newContext, user_data );
105		if( SUCCEEDED( hr ) )
106			return S_OK == hr;
107		throw hr;
108	}
109
110	void NewParamsTemp::newSeg( struct whisper_context* ctx, int n_new, void* user_data )
111	{
112		assert( n_new >= 0 );
113		const NewParamsTemp& tmp = npTemp;
114		HRESULT hr = tmp.newSegment( tmp.newContext, (uint32_t)n_new, user_data );
115		if( SUCCEEDED( hr ) )
116			return;
117		throw hr;
118	}
119}
120
121whisper_full_params makeOldParams( const Whisper::sFullParams& rsi, Whisper::iContext* context )
122{
123	whisper_full_params res;
124	memset( &res, 0, sizeof( res ) );
125
126	res.strategy = (whisper_sampling_strategy)rsi.strategy;
127	res.n_threads = rsi.cpuThreads;
128	res.n_max_text_ctx = rsi.n_max_text_ctx;
129	res.offset_ms = rsi.offset_ms;
130	res.duration_ms = rsi.duration_ms;
131
132	// flags
133	const uint32_t flags = (uint32_t)rsi.flags;
134	auto hasFlag = [ = ]( eFullParamsFlags bit ) { return 0 != ( flags & (uint32_t)bit ); };
135
136	res.translate = hasFlag( eFullParamsFlags::Translate );
137	res.no_context = hasFlag( eFullParamsFlags::NoContext );
138	res.single_segment = hasFlag( eFullParamsFlags::SingleSegment );
139	res.print_special = hasFlag( eFullParamsFlags::PrintSpecial );
140	res.print_progress = hasFlag( eFullParamsFlags::PrintProgress );
141	res.print_realtime = hasFlag( eFullParamsFlags::PrintRealtime );
142	res.print_timestamps = hasFlag( eFullParamsFlags::PrintTimestamps );
143	res.token_timestamps = hasFlag( eFullParamsFlags::TokenTimestamps );
144	res.speed_up = hasFlag( eFullParamsFlags::SpeedupAudio );
145
146	res.thold_pt = rsi.thold_pt;
147	res.thold_ptsum = rsi.thold_ptsum;
148	res.max_len = rsi.max_len;
149	res.greedy.n_past = rsi.greedy.n_past;
150	res.beam_search.n_past = rsi.beam_search.n_past;
151	res.beam_search.beam_width = rsi.beam_search.beam_width;
152	res.beam_search.n_best = rsi.beam_search.n_best;
153	res.audio_ctx = rsi.audio_ctx;
154	res.prompt_tokens = rsi.prompt_tokens;
155	res.prompt_n_tokens = rsi.prompt_n_tokens;
156
157	NewParamsTemp& tmp = npTemp;
158	tmp.initialize( res, rsi, context );
159	return res;
160}
161
162#include "../Whisper/TranscribeResult.h"
163#include <mfapi.h>
164
165namespace
166{
167	inline sTimeSpan time( int64_t wt )
168	{
169		int64_t ticks = MFllMulDiv( wt, 10'000'000, 100, 0 );
170		return sTimeSpan{ (uint64_t)ticks };
171	}
172
173	void makeNewResults( whisper_context* ctx, Whisper::eResultFlags flags, TranscribeResult& res )
174	{
175		const bool makeTokens = 0 != ( flags & eResultFlags::Tokens );
176		res.segments.clear();
177		res.tokens.clear();
178
179		const int countSegments = whisper_full_n_segments( ctx );
180		res.segments.resize( countSegments );
181		const int tokenEot = whisper_token_eot( ctx );
182		for( int i = 0; i < countSegments; i++ )
183		{
184			sSegment& seg = res.segments[ i ];
185			seg.text = whisper_full_get_segment_text( ctx, i );
186			seg.time.begin = time( whisper_full_get_segment_t0( ctx, i ) );
187			seg.time.end = time( whisper_full_get_segment_t1( ctx, i ) );
188
189			seg.firstToken = (uint32_t)res.tokens.size();
190			seg.countTokens = 0;
191			if( !makeTokens )
192				continue;
193
194			const int countTokens = whisper_full_n_tokens( ctx, i );
195			seg.countTokens = countTokens;
196			res.tokens.resize( res.tokens.size() + countTokens );
197			for( int t = 0; t < countTokens; t++ )
198			{
199				sToken& tok = res.tokens[ seg.firstToken + t ];
200				tok.text = whisper_full_get_token_text( ctx, i, t );
201
202				const whisper_token_data src = whisper_full_get_token_data( ctx, i, t );
203				tok.time.begin = time( src.t0 );
204				tok.time.end = time( src.t1 );
205				tok.probability = src.p;
206				tok.probabilityTimestamp = src.pt;
207				tok.ptsum = src.ptsum;
208				tok.vlen = src.vlen;
209				tok.id = src.id;
210				uint32_t flags = 0;
211				if( src.id >= tokenEot )
212					flags |= eTokenFlags::Special;
213				tok.flags = (eTokenFlags)flags;
214			}
215		}
216	}
217}
218
219HRESULT makeNewResults( whisper_context* ctx, Whisper::eResultFlags flags, Whisper::iTranscribeResult** pp )
220{
221	static TranscribeResultStatic trs;
222	if( flags & eResultFlags::NewObject )
223	{
224		return E_NOTIMPL;
225	}
226	else
227	{
228		makeNewResults( ctx, flags, trs );
229		*pp = &trs;
230		( *pp )->AddRef();
231		return S_OK;
232	}
233}
234#endif