1 // Copyright (C) 2008-2011 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU Bayonne.
4 //
5 // GNU Bayonne is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU Bayonne is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with GNU Bayonne. If not, see <http://www.gnu.org/licenses/>.
17
18 #include <config.h>
19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
22
24 using namespace UCOMMON_NAMESPACE;
25
26 AudioStream::AudioStream() : AudioFile()
27 {
28 codec = NULL;
29 framebuf = NULL;
30 bufferFrame = NULL;
31 encBuffer = NULL;
32 decBuffer = NULL;
33 encSize = decSize = 0;
34 bufferPosition = 0;
35 }
36
37 AudioStream::AudioStream(const char *fname, mode_t m, timeout_t framing) :
38 AudioFile()
39 {
40 codec = NULL;
41 framebuf = NULL;
42 bufferFrame = NULL;
43 bufferPosition = 0;
44
45 open(fname, m, framing);
46 }
47
48 AudioStream::AudioStream(const char *fname, info_t& info, timeout_t framing) :
49 AudioFile()
50 {
51 codec = NULL;
52 framebuf = NULL;
53 bufferFrame = NULL;
54 bufferPosition = 0;
55
56 create(fname, info, framing);
57 }
58
59 AudioStream::~AudioStream()
60 {
61 AudioStream::close();
62 AudioFile::clear();
63 }
64
65 ssize_t AudioStream::getBuffer(encoded_t data, size_t request)
66 {
67 if(!request)
68 return getPacket(data);
69
70 return AudioFile::getBuffer(data, request);
71 }
72
73 ssize_t AudioStream::getPacket(encoded_t data)
74 {
75 size_t count;
76 unsigned status = 0;
77
78 if(!is_streamable())
79 return AudioFile::getBuffer(data, 0);
80
81 for(;;)
82 {
83 count = codec->getEstimated();
84 if(count)
85 status = AudioFile::getBuffer(framebuf, count);
86 if(count && (size_t)status != count)
87 return 0;
88
89 status = codec->getPacket(data, framebuf, status);
90 if(status == Audio::ndata)
91 break;
92
93 if(status)
94 return status;
95 }
96
97 return 0;
98 }
99
100 bool AudioStream::is_streamable(void)
101 {
102 if(!is_open())
103 return false;
104
105 if(!streamable)
106 return false;
107
108 return true;
109 }
110
111 void AudioStream::flush(void)
112 {
113 unsigned fpos;
114
115 if(!bufferFrame)
116 return;
117
118 if(bufferPosition) {
119 for(fpos = bufferPosition; fpos < getCount() * bufferChannels; ++fpos)
120 bufferFrame[fpos] = 0;
121 if(bufferChannels == 1)
122 putMono(bufferFrame, 1);
123 else
124 putStereo(bufferFrame, 1);
125 }
126
127 delete[] bufferFrame;
128 bufferFrame = NULL;
129 bufferPosition = 0;
130 }
131
132 void AudioStream::close(void)
133 {
134 flush();
135
136 if(codec)
137 AudioCodec::release(codec);
138
139 if(framebuf)
140 delete[] framebuf;
141
142 if(encBuffer)
143 delete[] encBuffer;
144
145 if(decBuffer)
146 delete[] decBuffer;
147
148 encSize = decSize = 0;
149 encBuffer = decBuffer = NULL;
150 framebuf = NULL;
151 codec = NULL;
152 AudioFile::close();
153 }
154
155 void AudioStream::create(const char *fname, info_t& info, timeout_t framing)
156 {
157 if(!framing)
158 framing = 20;
159
160 close();
161 AudioFile::create(fname, info, framing);
162 if(!is_open())
163 return;
164
165 streamable = true;
166
167 if(is_linear(AudioFile::info.encoding))
168 return;
169
170 codec = AudioCodec::get(AudioFile::info);
171 if(!codec) {
172 streamable = false;
173 return;
174 }
175 framebuf = new unsigned char[maxFramesize(AudioFile::info)];
176 }
177
178 void AudioStream::open(const char *fname, mode_t m, timeout_t framing)
179 {
180 if(!framing)
181 framing = 20;
182
183 close();
184 AudioFile::open(fname, m, framing);
185 if(!is_open())
186 return;
187
188 streamable = true;
189
190 if(is_linear(info.encoding))
191 return;
192
193 codec = AudioCodec::get(info);
194 if(!codec)
195 streamable = false;
196 else
197 framebuf = new unsigned char[maxFramesize(info)];
198 }
199
200 unsigned AudioStream::getCount(void)
201 {
202 if(!is_streamable())
203 return 0;
204
205 return info.framecount;
206 }
207
208 unsigned AudioStream::getMono(linear_t buffer, unsigned frames)
209 {
210 unsigned char *iobuf = (unsigned char *)buffer;
211 unsigned count, offset, copied = 0;
212 ssize_t len;
213 linear_t dbuf = NULL;
214
215 if(!is_streamable())
216 return 0;
217
218 if(!frames)
219 ++frames;
220
221 count = frames * getCount();
222
223 if(is_stereo(info.encoding))
224 dbuf = new sample_t[count * 2];
225 if(codec)
226 iobuf = framebuf;
227 else if(dbuf)
228 iobuf = (unsigned char *)dbuf;
229
230 while(frames--) {
231 len = AudioFile::getBuffer(iobuf); // packet read
232 if(len < (ssize_t)info.framesize)
233 break;
234 ++copied;
235 if(codec) {
236 codec->decode(buffer, iobuf, info.framecount);
237 goto stereo;
238 }
239
240 if(dbuf)
241 swapEndian(info, dbuf, info.framecount);
242 else
243 swapEndian(info, buffer, info.framecount);
244
245 stereo:
246 if(!dbuf) {
247 buffer += info.framecount;
248 continue;
249 }
250
251 for(offset = 0; offset < info.framecount; ++offset)
252 buffer[offset] =
253 dbuf[offset * 2] / 2 + dbuf[offset * 2 + 1] / 2;
254
255 buffer += info.framecount;
256 }
257
258 if(dbuf)
259 delete[] dbuf;
260
261 return copied;
262 }
263
264 unsigned AudioStream::getStereo(linear_t buffer, unsigned frames)
265 {
266 unsigned char *iobuf = (unsigned char *)buffer;
267 unsigned offset, copied = 0;
268 ssize_t len;
269
270 if(!is_streamable())
271 return 0;
272
273 if(!frames)
274 ++frames;
275
276 if(codec)
277 iobuf = framebuf;
278
279 while(frames--) {
280 len = AudioFile::getBuffer(iobuf); // packet read
281 if(len < (ssize_t)info.framesize)
282 break;
283 ++copied;
284
285 if(codec) {
286 codec->decode(buffer, iobuf, info.framecount);
287 goto stereo;
288 }
289 swapEndian(info, buffer, info.framecount);
290
291 stereo:
292 if(is_stereo(info.encoding)) {
293 buffer += (info.framecount * 2);
294 continue;
295 }
296 offset = info.framecount;
297 while(offset--) {
298 buffer[offset * 2] = buffer[offset];
299 buffer[offset * 2 + 1] = buffer[offset];
300 }
301 buffer += (info.framecount * 2);
302 }
303 return copied;
304 }
305
306 unsigned AudioStream::putMono(linear_t buffer, unsigned frames)
307 {
308 linear_t iobuf = buffer, dbuf = NULL;
309 unsigned offset, copied = 0;
310 ssize_t len;
311
312 if(!is_streamable())
313 return 0;
314
315 if(!frames)
316 ++frames;
317
318 if(is_stereo(info.encoding)) {
319 dbuf = new sample_t[info.framecount * 2];
320 iobuf = dbuf;
321 }
322
323 while(frames--) {
324 if(dbuf) {
325 for(offset = 0; offset < info.framecount; ++offset)
326 dbuf[offset * 2] = dbuf[offset * 2 + 1] = buffer[offset];
327 }
328
329 if(codec) {
330 codec->encode(iobuf, framebuf, info.framecount);
331 len = putBuffer(framebuf);
332 if(len < (ssize_t)info.framesize)
333 break;
334 ++copied;
335 buffer += info.framecount;
336 continue;
337 }
338 swapEndian(info, iobuf, info.framecount);
339 len = putBuffer((encoded_t)iobuf);
340 if(len < (ssize_t)info.framesize)
341 break;
342 ++copied;
343 buffer += info.framecount;
344 }
345 if(dbuf)
346 delete[] dbuf;
347
348 return copied;
349 }
350
351 unsigned AudioStream::putStereo(linear_t buffer, unsigned frames)
352 {
353 linear_t iobuf = buffer, mbuf = NULL;
354 unsigned offset, copied = 0;
355 ssize_t len;
356
357 if(!is_streamable())
358 return 0;
359
360 if(!frames)
361 ++frames;
362
363 if(!is_stereo(info.encoding)) {
364 mbuf = new sample_t[info.framecount];
365 iobuf = mbuf;
366 }
367
368 while(frames--) {
369 if(mbuf) {
370 for(offset = 0; offset < info.framecount; ++offset)
371 mbuf[offset] = buffer[offset * 2] / 2 + buffer[offset * 2 + 1] / 2;
372 }
373
374 if(codec) {
375 codec->encode(iobuf, framebuf, info.framecount);
376 len = putBuffer(framebuf);
377 if(len < (ssize_t)info.framesize)
378 break;
379 ++copied;
380 buffer += info.framecount;
381 continue;
382 }
383 swapEndian(info, iobuf, info.framecount);
384 len = putBuffer((encoded_t)iobuf);
385 if(len < (ssize_t)info.framesize)
386 break;
387 ++copied;
388 }
389 if(mbuf)
390 delete[] mbuf;
391
392 return copied;
393 }
394
395 unsigned AudioStream::bufMono(linear_t samples, unsigned count)
396 {
397 unsigned size = getCount();
398
399 if(bufferChannels != 1)
400 flush();
401
402 if(!bufferFrame) {
403 bufferFrame = new sample_t[size];
404 bufferChannels = 1;
405 bufferPosition = 0;
406 }
407 return bufAudio(samples, count, size);
408 }
409
410 unsigned AudioStream::bufStereo(linear_t samples, unsigned count)
411 {
412 unsigned size = getCount() * 2;
413
414 if(bufferChannels != 2)
415 flush();
416
417 if(!bufferFrame) {
418 bufferFrame = new sample_t[size];
419 bufferChannels = 2;
420 bufferPosition = 0;
421 }
422 return bufAudio(samples, count * 2, size);
423 }
424
425 unsigned AudioStream::bufAudio(linear_t samples, unsigned count, unsigned size)
426 {
427 unsigned fill = 0;
428 unsigned frames = 0, copy, result;
429
430 if(bufferPosition)
431 fill = size - bufferPosition;
432 else if(count < size)
433 fill = count;
434
435 if(fill > count)
436 fill = count;
437
438 if(fill) {
439 memcpy(&bufferFrame[bufferPosition], samples, fill * 2);
440 bufferPosition += fill;
441 samples += fill;
442 count -= fill;
443 }
444
445 if(bufferPosition == size) {
446 if(bufferChannels == 1)
447 frames = putMono(bufferFrame, 1);
448 else
449 frames = putStereo(bufferFrame, 1);
450 bufferPosition = 0;
451 if(!frames)
452 return 0;
453 }
454
455 if(!count)
456 return frames;
457
458 if(count >= size) {
459 copy = (count / size);
460 if(bufferChannels == 1)
461 result = putMono(samples, copy);
462 else
463 result = putStereo(samples, copy);
464
465 if(result < copy)
466 return frames + result;
467
468 samples += copy * size;
469 count -= copy * size;
470 frames += result;
471 }
472 if(count) {
473 memcpy(bufferFrame, samples, count * 2);
474 bufferPosition = count;
475 }
476 return frames;
477 }
478
479 unsigned AudioStream::getEncoded(encoded_t addr, unsigned frames)
480 {
481 unsigned count = 0, len;
482
483 if(is_linear(info.encoding))
484 return getMono((linear_t)addr, frames);
485
486 while(frames--) {
487 len = AudioFile::getBuffer(addr); // packet read
488 if(len < info.framesize)
489 break;
490 addr += info.framesize;
491 ++count;
492 }
493 return count;
494 }
495
496 unsigned AudioStream::putEncoded(encoded_t addr, unsigned frames)
497 {
498 unsigned count = 0;
499 ssize_t len;
500
501 if(is_linear(info.encoding))
502 return putMono((linear_t)addr, frames);
503
504 while(frames--) {
505 len = putBuffer(addr);
506 if(len < (ssize_t)info.framesize)
507 break;
508 addr += info.framesize;
509 ++count;
510 }
511 return count;
512 }
513
514 unsigned AudioStream::getEncoded(
AudioCodec *codec, encoded_t addr,
unsigned frames)
515 {
516 Info ci;
517 unsigned count = 0;
518 unsigned bufsize = 0;
519 unsigned used = 0;
520 bool eof = false;
521
522 if(!codec)
523 return getEncoded(addr, frames);
524
525 ci = codec->getInfo();
526
527 if(ci.encoding == info.encoding && ci.framecount == info.framecount)
528 return getEncoded(addr, frames);
529
530 if(!is_streamable())
531 return 0;
532
533 while(bufsize < ci.framesize)
534 bufsize += info.framesize;
535
536 if(encSize != bufsize) {
537 if(encBuffer)
538 delete[] encBuffer;
539
540 encBuffer = new sample_t[bufsize];
541 encSize = bufsize;
542 }
543
544 while(count < frames && !eof) {
545 while(used < ci.framesize) {
546 if(getMono(encBuffer + used, 1) < 1) {
547 eof = true;
548 break;
549 }
550 used += info.framesize;
551 }
552 codec->encode(encBuffer, addr, ci.framesize);
553 if(ci.framesize < used)
554 memcpy(encBuffer, encBuffer + ci.framesize, used - ci.framesize);
555 used -= ci.framesize;
556 }
557 return count;
558 }
559
560 unsigned AudioStream::putEncoded(
AudioCodec *codec, encoded_t addr,
unsigned frames)
561 {
562 Info ci;
563 unsigned count = 0;
564
565 if(!codec)
566 return putEncoded(addr, frames);
567
568 ci = codec->getInfo();
569 if(ci.encoding == info.encoding && ci.framecount == info.framecount)
570 return putEncoded(addr, frames);
571
572 if(!is_streamable())
573 return 0;
574
575 if(ci.framecount != decSize) {
576 if(decBuffer)
577 delete[] decBuffer;
578 decBuffer = new sample_t[ci.framecount];
579 decSize = ci.framecount;
580 }
581
582 while(count < frames) {
583 codec->decode(decBuffer, addr, ci.framecount);
584 if(bufMono(decBuffer, ci.framecount) < ci.framecount)
585 break;
586 ++count;
587 addr += ci.framesize;
588 }
589
590 return count;
591 }
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.