jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
9.0KB

  1. /*
  2. Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack)
  3. Copyright (C) 2012 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackAC3Encoder.h"
  17. #include "JackError.h"
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <stdio.h>
  21. #define max(x,y) (((x)>(y)) ? (x) : (y))
  22. #define min(x,y) (((x)<(y)) ? (x) : (y))
  23. namespace Jack
  24. {
  25. #ifndef __ppc__
  26. JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams& params)
  27. {
  28. aften_set_defaults(&fAftenContext);
  29. fAftenContext.channels = params.channels;
  30. fAftenContext.samplerate = params.sample_rate;
  31. fAftenContext.params.bitrate = params.bitrate;
  32. int acmod = A52_ACMOD_MONO;
  33. int lfe = params.lfe;
  34. switch (params.channels) {
  35. case 1: acmod = A52_ACMOD_MONO; break;
  36. case 2: acmod = A52_ACMOD_STEREO; break;
  37. case 3: acmod = A52_ACMOD_3_0; break;
  38. case 4: acmod = A52_ACMOD_2_2; break;
  39. case 5: acmod = A52_ACMOD_3_2; break;
  40. default:
  41. break;
  42. }
  43. if (lfe) {
  44. fAftenContext.channels += 1;
  45. }
  46. fAftenContext.acmod = acmod;
  47. fAftenContext.lfe = lfe;
  48. fAftenContext.sample_format = A52_SAMPLE_FMT_FLT;
  49. fAftenContext.verbose = 1;
  50. fAftenContext.system.n_threads = 1;
  51. // create interleaved framebuffer for MAX_AC3_CHANNELS
  52. fSampleBuffer = new float[MAX_AC3_CHANNELS * A52_SAMPLES_PER_FRAME];
  53. // create AC3 buffer
  54. fAC3Buffer = new unsigned char[A52_MAX_CODED_FRAME_SIZE];
  55. memset(fAC3Buffer, 0, A52_MAX_CODED_FRAME_SIZE);
  56. fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE];
  57. memset(fZeroBuffer, 0, SPDIF_FRAME_SIZE);
  58. fRingBuffer = jack_ringbuffer_create(32768);
  59. fOutSizeByte = 0;
  60. fFramePos = 0;
  61. fSampleRate = 0;
  62. fByteRate = 0;
  63. }
  64. bool JackAC3Encoder::Init(jack_nframes_t sample_rate)
  65. {
  66. fSampleRate = sample_rate;
  67. fByteRate = fSampleRate * sizeof(short) * 2;
  68. return (aften_encode_init(&fAftenContext) == 0);
  69. }
  70. JackAC3Encoder::~JackAC3Encoder()
  71. {
  72. aften_encode_close(&fAftenContext);
  73. delete [] fSampleBuffer;
  74. delete [] fAC3Buffer;
  75. delete [] fZeroBuffer;
  76. if (fRingBuffer) {
  77. jack_ringbuffer_free(fRingBuffer);
  78. }
  79. }
  80. void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int nframes)
  81. {
  82. // fill and process frame buffers as appropriate
  83. jack_nframes_t frames_left = A52_SAMPLES_PER_FRAME - fFramePos;
  84. jack_nframes_t offset = 0;
  85. while (offset < nframes)
  86. {
  87. if ((nframes - offset) >= frames_left) {
  88. // copy only frames_left more data
  89. jack_nframes_t pos = fFramePos * fAftenContext.channels;
  90. for (jack_nframes_t spos = offset; spos < offset + frames_left; ++spos) {
  91. for (size_t i = 0; i < fAftenContext.channels; ++i) {
  92. fSampleBuffer[pos + i] = inputs_buffer[i][spos];
  93. }
  94. pos += fAftenContext.channels;
  95. }
  96. // use interleaved version
  97. #ifdef HAVE_AFTEN_NEW_API
  98. // note additional parameter 'nframes'
  99. // added in commit e1cbb66628de8aa496a75092d8d694234c67aa95 git://aften.git.sourceforge.net/gitroot/aften/aften
  100. int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer, nframes);
  101. #else
  102. // released version 0.0.8 hasn't the 'count' parameter
  103. int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer);
  104. #endif
  105. if (res < 0) {
  106. jack_error("aften_encode_frame error !!");
  107. return;
  108. }
  109. fOutSizeByte = res;
  110. FillSpdifHeader(fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
  111. // push AC3 output to SPDIF ring buffer
  112. float calc_ac3byterate = (fOutSizeByte * fSampleRate / (float) A52_SAMPLES_PER_FRAME);
  113. jack_nframes_t silencebytes = (jack_nframes_t) (fOutSizeByte * (fByteRate / calc_ac3byterate)) - fOutSizeByte - SPDIF_HEADER_SIZE;
  114. jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
  115. // write the proper remainder of zero padding (inefficient, should be memsetting)
  116. jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes);
  117. offset += frames_left;
  118. frames_left = A52_SAMPLES_PER_FRAME;
  119. fFramePos = 0;
  120. } else {
  121. // copy incoming data into frame buffers without processing
  122. jack_nframes_t pos = fFramePos * fAftenContext.channels;
  123. for (jack_nframes_t spos = offset; spos < nframes; ++spos) {
  124. for (size_t i = 0; i < fAftenContext.channels; ++i) {
  125. fSampleBuffer[pos + i] = inputs_buffer[i][spos];
  126. }
  127. pos += fAftenContext.channels;
  128. }
  129. fFramePos += (nframes - offset);
  130. offset += (nframes-offset);
  131. }
  132. }
  133. Output2Driver(outputs_buffer, nframes);
  134. }
  135. void JackAC3Encoder::FillSpdifHeader(unsigned char* buf, int outsize)
  136. {
  137. // todo, use outsize and not assume the fixed frame size?
  138. int ac3outsize = outsize - SPDIF_HEADER_SIZE;
  139. buf[0] = 0x72; buf[1] = 0xf8; /* spdif syncword */
  140. buf[2] = 0x1f; buf[3] = 0x4e; /* .............. */
  141. buf[4] = 0x01; /* AC3 data */
  142. buf[5] = buf[13] & 7; /* bsmod, stream = 0 */
  143. buf[6] = (ac3outsize << 3) & 0xff;
  144. buf[7] = (ac3outsize >> 5) & 0xff;
  145. #if !IS_BIGENDIAN
  146. swab(buf+SPDIF_HEADER_SIZE, buf + SPDIF_HEADER_SIZE, ac3outsize);
  147. #endif
  148. }
  149. int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes)
  150. {
  151. int wrotebytes = 0;
  152. jack_nframes_t nframes_left = nframes;
  153. if (jack_ringbuffer_read_space(fRingBuffer) == 0) {
  154. // just write silence
  155. memset(outputs[0], 0, nframes * sizeof(jack_default_audio_sample_t));
  156. memset(outputs[1], 0, nframes * sizeof(jack_default_audio_sample_t));
  157. } else {
  158. jack_ringbuffer_data_t rb_data[2];
  159. jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
  160. while (nframes_left > 0 && rb_data[0].len > 4) {
  161. jack_nframes_t towrite_frames = (rb_data[0].len) / (sizeof(short) * 2);
  162. towrite_frames = min(towrite_frames, nframes_left);
  163. // write and deinterleave into the two channels
  164. #if 1
  165. sample_move_dS_s16(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
  166. sample_move_dS_s16(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
  167. #else
  168. sample_move_dS_s16_24ph(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
  169. sample_move_dS_s16_24ph(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
  170. #endif
  171. wrotebytes = towrite_frames * sizeof(short) * 2;
  172. nframes_left -= towrite_frames;
  173. jack_ringbuffer_read_advance(fRingBuffer, wrotebytes);
  174. jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
  175. }
  176. if (nframes_left > 0) {
  177. // write silence
  178. memset(outputs[0] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
  179. memset(outputs[1] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
  180. }
  181. }
  182. return wrotebytes;
  183. }
  184. void JackAC3Encoder::sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
  185. {
  186. /* ALERT: signed sign-extension portability !!! */
  187. while (nsamples--) {
  188. *dst = (*((short *) src)) / SAMPLE_MAX_16BIT;
  189. dst++;
  190. src += src_skip;
  191. }
  192. }
  193. void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
  194. {
  195. /* ALERT: signed sign-extension portability !!! */
  196. while (nsamples--) {
  197. *dst = (((int)(*((short *) src))) << 8) / SAMPLE_MAX_24BIT;
  198. dst++;
  199. src += src_skip;
  200. }
  201. }
  202. void JackAC3Encoder::GetChannelName(const char* name, const char* alias, char* portname, int channel)
  203. {
  204. /*
  205. * 2 channels = L, R
  206. * 3 channels = L, C, R
  207. * 4 channels = L, R, LS, RS
  208. * 5 ch = L, C, R, LS, RS
  209. * 6 ch = L, C, R, LS, RS, LFE
  210. */
  211. const char* AC3_name = "";
  212. switch (channel) {
  213. case 0:
  214. AC3_name = "AC3_1_Left";
  215. break;
  216. case 1:
  217. if (fAftenContext.channels == 2 || fAftenContext.channels == 4) {
  218. AC3_name = "AC3_2_Right";
  219. } else {
  220. AC3_name = "AC3_2_Center";
  221. }
  222. break;
  223. case 2:
  224. if (fAftenContext.channels == 4) {
  225. AC3_name = "AC3_3_LeftSurround";
  226. } else {
  227. AC3_name = "AC3_3_Right";
  228. }
  229. break;
  230. case 3:
  231. if (fAftenContext.channels == 4) {
  232. AC3_name = "AC3_4_RightSurround";
  233. } else {
  234. AC3_name = "AC3_4_LeftSurround";
  235. }
  236. break;
  237. case 4:
  238. if (fAftenContext.channels > 4) {
  239. AC3_name = "AC3_5_RightSurround";
  240. }
  241. break;
  242. default:
  243. break;
  244. }
  245. // Last channel
  246. if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) {
  247. sprintf(portname, "%s:%s:AC3_%d_LFE", name, alias, fAftenContext.channels);
  248. } else {
  249. sprintf(portname, "%s:%s:%s", name, alias, AC3_name);
  250. }
  251. }
  252. #endif
  253. } // end of namespace