Bayonne 3 - API
 All Classes Namespaces Files Functions Variables Typedefs Macros
audiostream.cpp
Go to the documentation of this file.
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>
21 #include <bayonne.h>
22 
23 using namespace BAYONNE_NAMESPACE;
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
Definition: bayonne.h:25
GNU Bayonne library namespace.