0f6580e27d3eefaa222b64e4b32d708264f49294
[reactos.git] / base / applications / sndrec32 / audio_membuffer.cpp
1 /*
2 * PROJECT: ReactOS Sound Record Application
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/sndrec32/audio_membuffer.cpp
5 * PURPOSE: Audio MemBuffer
6 * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
7 */
8
9 #include "stdafx.h"
10 #include "audio_membuffer.hpp"
11
12 _AUDIO_NAMESPACE_START_
13
14
15 void
16 audio_membuffer::alloc_mem_( unsigned int bytes )
17 {
18
19 //
20 // Some checking
21 //
22
23 if ( bytes == 0 )
24 return;
25
26
27
28
29
30 //
31 // Checks previsiously alloc'd memory
32 // and frees it.
33 //
34
35 if ( audio_data )
36 delete[] audio_data;
37
38
39
40 //
41 // Allocs new memory and zeros it.
42 //
43
44 audio_data = new BYTE[ bytes ];
45
46
47 memset( audio_data, 0, bytes * sizeof( BYTE ));
48
49
50
51 //
52 // Sets the correct buffer size
53 //
54
55 buf_size = bytes;
56
57
58 init_size = bytes;
59
60
61
62 }
63
64
65 void
66 audio_membuffer::free_mem_( void )
67 {
68
69 if ( audio_data )
70 delete[] audio_data;
71
72 buf_size = 0;
73 audio_data = 0;
74
75 }
76
77
78 void
79 audio_membuffer::resize_mem_( unsigned int new_size )
80 {
81
82
83 if ( new_size == 0 )
84 return;
85
86
87 //
88 // The new_size, cannot be <= of the
89 // `bytes_received' member value of the
90 // parent class `audio_receiver'.
91 // We cannot touch received audio data,
92 // so we have to alloc at least
93 // bytes_received+1 bytes.
94 //
95 // But we can truncate unused memory, so
96 // `new_size' can be < of `buf_size'.
97 //
98
99 if ( new_size <= bytes_received )
100 return;
101
102
103
104
105 BYTE * new_mem;
106
107
108
109 //
110 // Allocs new memory and zeros it.
111 //
112
113
114 new_mem = new BYTE[ new_size ];
115
116 memset( new_mem, 0, new_size * sizeof( BYTE ));
117
118
119
120 if ( audio_data )
121 {
122
123
124 //
125 // Copies received audio data, and discard
126 // unused memory.
127 //
128
129 memcpy( new_mem, audio_data, bytes_received );
130
131
132
133 //
134 // Frees old memory.
135 //
136
137 delete[] audio_data;
138
139
140
141
142
143 //
144 // Commit new memory.
145 //
146
147 audio_data = new_mem;
148 buf_size = new_size;
149
150
151
152
153 } else {
154
155 audio_data = new_mem;
156 buf_size = new_size;
157 }
158
159
160 if ( buffer_resized )
161 buffer_resized( new_size );
162
163 }
164
165
166
167
168 void
169 audio_membuffer::truncate_( void )
170 {
171
172 //
173 // If `buf_size' is already = to the
174 // `bytes_received' of audio data, then
175 // this operation is useless; simply return.
176 //
177
178 if ( bytes_received == buf_size )
179 return;
180
181
182
183 if ( audio_data )
184 {
185
186
187 //
188 // Allocs a new buffer.
189 //
190
191 BYTE * newbuf = new BYTE[ bytes_received ];
192
193
194
195
196 //
197 // Copies audio data.
198 //
199
200 memcpy( newbuf, audio_data, bytes_received );
201
202
203
204 //
205 // Frees old memory.
206 //
207
208 delete[] audio_data;
209
210
211
212 //
213 // Commit the new buffer.
214 //
215
216 audio_data = newbuf;
217 buf_size = bytes_received;
218
219
220
221 //
222 // Buffer truncation successfull.
223 // Now the buffer size is exactly big
224 // as much audio data was received.
225 //
226
227
228 }
229
230
231 }
232
233
234
235
236
237
238 //////////////////////////////////////
239 /////// Public Functions ///////////
240 //////////////////////////////////////
241
242
243
244
245 void
246 audio_membuffer::clear( void )
247 {
248
249 free_mem_();
250
251 bytes_received = 0;
252 }
253
254
255
256 void
257 audio_membuffer::reset( void )
258 {
259
260
261 //
262 // Frees memory and reset
263 // to initial state.
264 //
265
266 clear();
267
268
269
270 //
271 // Alloc memory of size specified
272 // at the constructor.
273 //
274
275 alloc_mem_( init_size );
276
277
278 }
279
280 void
281 audio_membuffer::alloc_bytes( unsigned int bytes )
282 {
283
284 alloc_mem_( bytes );
285
286 }
287
288
289
290
291 void
292 audio_membuffer::alloc_seconds( unsigned int secs )
293 {
294
295 alloc_mem_( aud_info.byte_rate() * secs );
296
297 }
298
299
300 void
301 audio_membuffer::alloc_seconds( float secs )
302 {
303
304 alloc_mem_(( unsigned int )(( float ) aud_info.byte_rate() * secs ));
305
306 }
307
308
309
310
311 void
312 audio_membuffer::resize_bytes( unsigned int bytes )
313 {
314
315 resize_mem_( bytes );
316
317 }
318
319
320
321 void
322 audio_membuffer::resize_seconds( unsigned int secs )
323 {
324
325 resize_mem_( aud_info.byte_rate() * secs );
326
327 }
328
329
330 void
331 audio_membuffer::resize_seconds( float secs )
332 {
333
334 resize_mem_(( unsigned int )
335 (( float )aud_info.byte_rate() * secs )
336 );
337
338 }
339
340
341
342
343
344
345 ///////////////////////////////////////
346 /////// Inherited Functions /////////
347 ///////////////////////////////////////
348
349
350
351
352
353
354
355 void
356 audio_membuffer::audio_receive
357 ( unsigned char * data, unsigned int size )
358 {
359
360
361 //
362 // If there isn't a buffer, allocs memory for
363 // it of size*2, and copies audio data arrival.
364 //
365
366 if (( audio_data == 0 ) || ( buf_size == 0 ))
367 {
368 alloc_mem_( size * 2 );
369
370 memcpy( audio_data, data, size );
371
372 return;
373
374 }
375
376
377
378
379
380 //
381 // If buffer's free memory is < of `size',
382 // we have to realloc buffer memory of
383 // buf_size*2, while free memory is enough
384 // to contain `size' bytes.
385 //
386 // In this case free memory is represented
387 // by `buf_size - bytes_recorded'.
388 //
389
390 unsigned int tot_mem = buf_size,
391 free_mem = buf_size - bytes_received;
392
393
394 if ( free_mem < size )
395 {
396
397 //
398 // Calcs new buffer size.
399 // TODO: flags for other behaviour?
400
401 while ( free_mem < size )
402 {
403 tot_mem *= 2;
404
405 free_mem = tot_mem - bytes_received;
406 }
407
408
409
410 //
411 // Resize buffer memory.
412 //
413
414 resize_mem_( tot_mem );
415
416 }
417
418
419 //
420 // Now we have enough free space in the
421 // buffer, so let's copy audio data arrivals.
422 //
423
424 memcpy( audio_data + bytes_received, data, size );
425
426
427
428
429 if ( audio_arrival )
430 audio_arrival( aud_info.samples_in_bytes( size ));
431
432
433
434 }
435
436
437 unsigned int
438 audio_membuffer::read( BYTE * out_buf, unsigned int bytes )
439 {
440
441 //
442 // Some checking
443 //
444
445 if ( !audio_data )
446 return 0;
447
448
449 if ( bytes_played_ >= bytes_received )
450 return 0;
451
452
453
454 unsigned int to_play =
455 bytes_received - bytes_played_;
456
457
458 unsigned int to_copy =
459 bytes > to_play ? to_play : bytes;
460
461
462 //
463 // Copies the audio data out.
464 //
465
466 if (( out_buf ) && ( to_copy ) && ( audio_data ))
467 memcpy( out_buf, audio_data + bytes_played_, to_copy );
468
469
470 //
471 // Increments the number of total bytes
472 // played (audio data gone out from the
473 // `audio_producer' object).
474 //
475
476 bytes_played_ += bytes;
477
478
479 if ( audio_arrival )
480 audio_arrival( aud_info.samples_in_bytes( bytes ));
481
482
483 //
484 // Returns the exact size of audio data
485 // produced.
486 //
487
488 return to_copy;
489 }
490
491
492 bool
493 audio_membuffer::finished( void )
494 {
495 if ( bytes_played_ < bytes_received )
496 return false;
497 else
498 return true;
499 }
500
501 _AUDIO_NAMESPACE_END_