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