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