Code more of less complete.
[jack2.git] / common / JackAC3Encoder.cpp
blob71a9deb1f25157c5d3d0a196683757125d4db18c
1 /*
2 Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack)
3 Copyright (C) 2012 Grame
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.
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.
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.
21 #include "JackAC3Encoder.h"
22 #include "JackError.h"
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdio.h>
27 #define max(x,y) (((x)>(y)) ? (x) : (y))
28 #define min(x,y) (((x)<(y)) ? (x) : (y))
30 namespace Jack
33 JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams& params)
35 aften_set_defaults(&fAftenContext);
37 fAftenContext.channels = params.channels;
38 fAftenContext.samplerate = params.sample_rate;
39 fAftenContext.params.bitrate = params.bitrate;
41 int acmod = A52_ACMOD_MONO;
42 int lfe = params.lfe;
44 switch (params.channels) {
46 case 1: acmod = A52_ACMOD_MONO; break;
47 case 2: acmod = A52_ACMOD_STEREO; break;
48 case 3: acmod = A52_ACMOD_3_0; break;
49 case 4: acmod = A52_ACMOD_2_2; break;
50 case 5: acmod = A52_ACMOD_3_2; break;
51 break;
53 default:
54 break;
57 if (lfe) {
58 fAftenContext.channels += 1;
61 fAftenContext.acmod = acmod;
62 fAftenContext.lfe = lfe;
63 fAftenContext.sample_format = A52_SAMPLE_FMT_FLT;
64 fAftenContext.verbose = 1;
66 fAftenContext.system.n_threads = 1;
68 // create interleaved framebuffer for MAX_AC3_CHANNELS
69 fSampleBuffer = new float[MAX_AC3_CHANNELS * A52_SAMPLES_PER_FRAME];
71 // create AC3 buffer
72 fAC3Buffer = new unsigned char[A52_MAX_CODED_FRAME_SIZE];
73 memset(fAC3Buffer, 0, A52_MAX_CODED_FRAME_SIZE);
75 fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE];
76 memset(fZeroBuffer, 0, SPDIF_FRAME_SIZE);
78 fRingBuffer = jack_ringbuffer_create(32768);
80 fOutSizeByte = 0;
81 fFramePos = 0;
83 fSampleRate = 0;
84 fByteRate = 0;
87 bool JackAC3Encoder::Init(jack_nframes_t sample_rate)
89 fSampleRate = sample_rate;
90 fByteRate = fSampleRate * sizeof(short) * 2;
91 return (aften_encode_init(&fAftenContext) == 0);
94 JackAC3Encoder::~JackAC3Encoder()
96 aften_encode_close(&fAftenContext);
98 delete [] fSampleBuffer;
99 delete [] fAC3Buffer;
100 delete [] fZeroBuffer;
102 if (fRingBuffer) {
103 jack_ringbuffer_free(fRingBuffer);
107 void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int nframes)
109 // fill and process frame buffers as appropriate
110 jack_nframes_t frames_left = A52_SAMPLES_PER_FRAME - fFramePos;
111 jack_nframes_t offset = 0;
113 while (offset < nframes)
115 if ((nframes - offset) >= frames_left) {
117 // copy only frames_left more data
118 jack_nframes_t pos = fFramePos * fAftenContext.channels;
119 for (jack_nframes_t spos = offset; spos < offset + frames_left; ++spos) {
120 for (size_t i = 0; i < fAftenContext.channels; ++i) {
121 fSampleBuffer[pos + i] = inputs_buffer[i][spos];
123 pos += fAftenContext.channels;
126 // use interleaved version
127 int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer);
128 if (res < 0) {
129 jack_error("aften_encode_frame error !!");
130 return;
133 fOutSizeByte = res;
135 FillSpdifHeader(fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
137 // push AC3 output to SPDIF ring buffer
138 float calc_ac3byterate = (fOutSizeByte * fSampleRate / (float) A52_SAMPLES_PER_FRAME);
139 jack_nframes_t silencebytes = (jack_nframes_t) (fOutSizeByte * (fByteRate / calc_ac3byterate)) - fOutSizeByte - SPDIF_HEADER_SIZE;
141 jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
143 // write the proper remainder of zero padding (inefficient, should be memsetting)
144 jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes);
146 offset += frames_left;
147 frames_left = A52_SAMPLES_PER_FRAME;
148 fFramePos = 0;
150 } else {
152 // copy incoming data into frame buffers without processing
153 jack_nframes_t pos = fFramePos * fAftenContext.channels;
154 for (jack_nframes_t spos = offset; spos < nframes; ++spos) {
155 for (size_t i = 0; i < fAftenContext.channels; ++i) {
156 fSampleBuffer[pos + i] = inputs_buffer[i][spos];
158 pos += fAftenContext.channels;
161 fFramePos += (nframes - offset);
162 offset += (nframes-offset);
166 Output2Driver(outputs_buffer, nframes);
169 void JackAC3Encoder::FillSpdifHeader(unsigned char* buf, int outsize)
171 // todo, use outsize and not assume the fixed frame size?
172 int ac3outsize = outsize - SPDIF_HEADER_SIZE;
174 buf[0] = 0x72; buf[1] = 0xf8; /* spdif syncword */
175 buf[2] = 0x1f; buf[3] = 0x4e; /* .............. */
176 buf[4] = 0x01; /* AC3 data */
177 buf[5] = buf[13] & 7; /* bsmod, stream = 0 */
178 buf[6] = (ac3outsize << 3) & 0xff;
179 buf[7] = (ac3outsize >> 5) & 0xff;
181 #if !IS_BIGENDIAN
182 swab(buf+SPDIF_HEADER_SIZE, buf + SPDIF_HEADER_SIZE, ac3outsize);
183 #endif
186 int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes)
188 int wrotebytes = 0;
189 jack_nframes_t nframes_left = nframes;
191 if (jack_ringbuffer_read_space(fRingBuffer) == 0) {
193 // just write silence
194 memset(outputs[0], 0, nframes * sizeof(jack_default_audio_sample_t));
195 memset(outputs[1], 0, nframes * sizeof(jack_default_audio_sample_t));
197 } else {
199 jack_ringbuffer_data_t rb_data[2];
201 jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
203 while (nframes_left > 0 && rb_data[0].len > 4) {
205 jack_nframes_t towrite_frames = (rb_data[0].len) / (sizeof(short) * 2);
206 towrite_frames = min(towrite_frames, nframes_left);
208 // write and deinterleave into the two channels
209 #if 1
210 sample_move_dS_s16(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
211 sample_move_dS_s16(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
212 #else
213 sample_move_dS_s16_24ph(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
214 sample_move_dS_s16_24ph(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
215 #endif
216 wrotebytes = towrite_frames * sizeof(short) * 2;
217 nframes_left -= towrite_frames;
219 jack_ringbuffer_read_advance(fRingBuffer, wrotebytes);
220 jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
223 if (nframes_left > 0) {
224 // write silence
225 memset(outputs[0] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
226 memset(outputs[1] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
230 return wrotebytes;
233 void JackAC3Encoder::sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
235 /* ALERT: signed sign-extension portability !!! */
236 while (nsamples--) {
237 *dst = (*((short *) src)) / SAMPLE_MAX_16BIT;
238 dst++;
239 src += src_skip;
243 void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
245 /* ALERT: signed sign-extension portability !!! */
246 while (nsamples--) {
247 *dst = (((int)(*((short *) src))) << 8) / SAMPLE_MAX_24BIT;
248 dst++;
249 src += src_skip;
253 void JackAC3Encoder::GetChannelName(const char* name, const char* alias, char* portname, int channel)
256 * 2 channels = L, R
257 * 3 channels = L, C, R
258 * 4 channels = L, R, LS, RS
259 * 5 ch = L, C, R, LS, RS
260 * 6 ch = L, C, R, LS, RS, LFE
263 const char* AC3_name = "";
265 switch (channel) {
267 case 0:
268 AC3_name = "AC3_1_Left";
269 break;
271 case 1:
272 if (fAftenContext.channels == 2 || fAftenContext.channels == 4) {
273 AC3_name = "AC3_2_Right";
274 } else {
275 AC3_name = "AC3_2_Center";
277 break;
279 case 2:
280 if (fAftenContext.channels == 4) {
281 AC3_name = "AC3_3_LeftSurround";
282 } else {
283 AC3_name = "AC3_3_Right";
285 break;
287 case 3:
288 if (fAftenContext.channels == 4) {
289 AC3_name = "AC3_4_RightSurround";
290 } else {
291 AC3_name = "AC3_4_LeftSurround";
293 break;
295 case 4:
296 if (fAftenContext.channels > 4) {
297 AC3_name = "AC3_5_RightSurround";
299 break;
301 default:
302 break;
305 // Last channel
306 if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) {
307 sprintf(portname, "%s:%s:AC3_%d_LFE", name, alias, fAftenContext.channels);
308 } else {
309 sprintf(portname, "%s:%s:%s", name, alias, AC3_name);
313 } // end of namespace