e30065daec5899b53fa29d194da6b479697c614d
[reactos.git] / reactos / base / applications / sndrec32 / audio_resampler_acm.cpp
1 /*
2 * PROJECT: ReactOS Sound Record Application
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/sndrec32/audio_resampler_acm.cpp
5 * PURPOSE: Audio Resampler
6 * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
7 */
8
9 #include "stdafx.h"
10 #include "audio_resampler_acm.hpp"
11 #include <stdio.h>
12
13
14
15 _AUDIO_NAMESPACE_START_
16
17
18 /////////////////////////////////////////
19 /////// Private Functions ////////
20 /////////////////////////////////////////
21
22
23 void
24 audio_resampler_acm::init_( void )
25 {
26
27
28
29 //
30 // Zeroing structures
31 //
32
33 ZeroMemory( &acm_header, sizeof( ACMSTREAMHEADER ));
34 ZeroMemory( &wformat_src, sizeof( WAVEFORMATEX ));
35 ZeroMemory( &wformat_dst, sizeof( WAVEFORMATEX ));
36
37
38
39
40 //
41 // Setting structures sizes
42 //
43
44 acm_header.cbStruct = sizeof( ACMSTREAMHEADER );
45 wformat_src.cbSize = sizeof( WAVEFORMATEX );
46 wformat_dst.cbSize = sizeof( WAVEFORMATEX );
47
48
49
50
51 //
52 // Setting WAVEFORMATEX structure parameters
53 // according to `audio_format' in/out classes
54 //
55
56 wformat_src.wFormatTag = WAVE_FORMAT_PCM;
57 wformat_src.nSamplesPerSec = audfmt_in.sample_rate();
58 wformat_src.nChannels = audfmt_in.channels();
59 wformat_src.wBitsPerSample = audfmt_in.bits();
60 wformat_src.nAvgBytesPerSec = audfmt_in.byte_rate();
61 wformat_src.nBlockAlign = audfmt_in.block_align();
62
63
64 wformat_dst.wFormatTag = WAVE_FORMAT_PCM;
65 wformat_dst.nSamplesPerSec = audfmt_out.sample_rate();
66 wformat_dst.nChannels = audfmt_out.channels();
67 wformat_dst.wBitsPerSample = audfmt_out.bits();
68 wformat_dst.nAvgBytesPerSec = audfmt_out.byte_rate();
69 wformat_dst.nBlockAlign = audfmt_out.block_align();
70
71
72
73 //
74 // Init acm structures completed successfull
75 //
76 }
77
78
79
80
81
82
83
84
85
86
87
88 /////////////////////////////////////////
89 /////// Public Functions ////////
90 /////////////////////////////////////////
91
92
93
94
95 void
96 audio_resampler_acm::open( void )
97 {
98
99
100 MMRESULT err;
101
102
103 //
104 // Opens ACM stream
105 //
106
107 err = acmStreamOpen( &acm_stream, 0, &wformat_src, &wformat_dst,
108 0, 0, 0, ACM_STREAMOPENF_NONREALTIME );
109
110
111 if ( err != MMSYSERR_NOERROR )
112 {
113 //TODO: throw error
114 MessageBox( 0, _T("acmOpen error: %i"), _T("ERROR"), MB_ICONERROR );
115
116 }
117
118
119
120 //
121 // Calcs source buffer lenght
122 //
123
124 src_buflen = ( unsigned int )
125 (( float )audfmt_in.byte_rate() * ( float )buf_secs );
126
127
128
129
130
131
132 //
133 // Calcs destination source buffer lenght
134 // with help of ACM apis
135 //
136
137 err = acmStreamSize( acm_stream,
138 src_buflen, &dst_buflen, ACM_STREAMSIZEF_SOURCE );
139
140
141 if ( err != MMSYSERR_NOERROR )
142 {
143 //TODO: throw error
144 MessageBox( 0, _T("acmStreamSize error"), _T("ERROR"), MB_ICONERROR );
145
146
147 }
148
149
150
151 //
152 // Initialize ACMSTREAMHEADER structure,
153 // and alloc memory for source and destination
154 // buffers.
155 //
156
157 acm_header.fdwStatus = 0;
158 acm_header.dwUser = 0;
159
160
161 acm_header.pbSrc = ( LPBYTE ) new BYTE [ src_buflen ];
162 acm_header.cbSrcLength = src_buflen;
163 acm_header.cbSrcLengthUsed = 0;
164 acm_header.dwSrcUser = src_buflen;
165
166
167 acm_header.pbDst = ( LPBYTE ) new BYTE [ dst_buflen ];
168 acm_header.cbDstLength = dst_buflen;
169 acm_header.cbDstLengthUsed = 0;
170 acm_header.dwDstUser = dst_buflen;
171
172
173
174
175 //
176 // Give ACMSTREAMHEADER initialized correctly to the
177 // driver.
178 //
179
180 err = acmStreamPrepareHeader( acm_stream, &acm_header, 0L );
181
182 if ( err != MMSYSERR_NOERROR )
183 {
184 //TODO: throw error
185 MessageBox( 0, _T("acmStreamPrepareHeader error"), _T("ERROR"), MB_ICONERROR );
186
187
188 }
189
190
191
192
193 //
194 // ACM stream successfully opened.
195 //
196
197 stream_opened = true;
198
199 }
200
201
202
203
204 void
205 audio_resampler_acm::close( void )
206 {
207
208
209 MMRESULT err;
210
211
212 if ( acm_stream )
213 {
214
215 if ( acm_header.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED )
216 {
217
218 acm_header.cbSrcLength = src_buflen;
219 acm_header.cbDstLength = dst_buflen;
220
221 err = acmStreamUnprepareHeader( acm_stream, &acm_header, 0L );
222
223
224 if ( err != MMSYSERR_NOERROR )
225 {
226
227 //
228 // Free buffer memory
229 //
230
231 if ( acm_header.pbSrc != 0 )
232 delete[] acm_header.pbSrc;
233
234 if ( acm_header.pbDst != 0 )
235 delete[] acm_header.pbDst;
236
237
238 //
239 // Re-init structures
240 //
241
242 init_();
243
244 //
245 // Updating status
246 //
247
248 stream_opened = false;
249
250
251 //TODO: throw error
252 MessageBox( 0, _T("acmStreamUnPrepareHeader error"), _T("ERROR"), MB_ICONERROR );
253
254
255 }
256 }
257
258
259 err = acmStreamClose( acm_stream, 0 );
260 acm_stream = 0;
261
262 if ( err != MMSYSERR_NOERROR )
263 {
264
265 //
266 // Free buffer memory
267 //
268
269 if ( acm_header.pbSrc != 0 )
270 delete[] acm_header.pbSrc;
271
272 if ( acm_header.pbDst != 0 )
273 delete[] acm_header.pbDst;
274
275
276 //
277 // Re-init structures
278 //
279
280 init_();
281
282
283 //
284 // Updating status
285 //
286
287 stream_opened = false;
288
289
290 //TODO: throw error!
291
292 MessageBox( 0, _T("acmStreamClose error"), _T("ERROR"), MB_ICONERROR );
293
294
295 }
296
297
298 }//if acm_stream != 0
299
300
301
302
303
304
305 //
306 // Free buffer memory
307 //
308
309 if ( acm_header.pbSrc != 0 )
310 delete[] acm_header.pbSrc;
311
312 if ( acm_header.pbDst != 0 )
313 delete[] acm_header.pbDst;
314
315
316 //
317 // Re-init structures
318 //
319
320 init_();
321
322
323 //
324 // Updating status
325 //
326
327 stream_opened = false;
328
329
330
331 //
332 // ACM sream successfully closed.
333 //
334
335
336 }
337
338
339
340
341 void
342 audio_resampler_acm::audio_receive( unsigned char * data, unsigned int size )
343 {
344
345 MMRESULT err;
346
347 //
348 // Checking for acm stream opened
349 //
350
351 if ( stream_opened )
352 {
353
354
355 //
356 // Copy audio data from extern to
357 // internal source buffer
358 //
359
360 memcpy( acm_header.pbSrc, data, size );
361
362
363 acm_header.cbSrcLength = size;
364 acm_header.cbDstLengthUsed = 0;
365
366 err = acmStreamConvert( acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN );
367
368 if ( err != MMSYSERR_NOERROR )
369 {
370 //TODO: throw error
371 MessageBox( 0, _T("acmStreamConvert error"), _T("ERROR"), MB_ICONERROR );
372
373
374 }
375
376
377 //
378 // Wait for sound conversion
379 //
380
381 while(( ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus ) == 0 );
382
383
384 //printf("Processed successfully %i bytes of audio.\n", acm_header.cbDstLengthUsed );
385
386
387
388 //
389 // Copy resampled audio, to destination buffer.
390 //
391
392 //memcpy( pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed );
393
394
395 }
396
397 }
398
399
400 _AUDIO_NAMESPACE_END_