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