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