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"
27 #define max(x,y) (((x)>(y)) ? (x) : (y))
28 #define min(x,y) (((x)<(y)) ? (x) : (y))
35 JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams
& params
)
37 aften_set_defaults(&fAftenContext
);
39 fAftenContext
.channels
= params
.channels
;
40 fAftenContext
.samplerate
= params
.sample_rate
;
41 fAftenContext
.params
.bitrate
= params
.bitrate
;
43 int acmod
= A52_ACMOD_MONO
;
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;
57 fAftenContext
.channels
+= 1;
60 fAftenContext
.acmod
= acmod
;
61 fAftenContext
.lfe
= lfe
;
62 fAftenContext
.sample_format
= A52_SAMPLE_FMT_FLT
;
63 fAftenContext
.verbose
= 1;
65 fAftenContext
.system
.n_threads
= 1;
67 // create interleaved framebuffer for MAX_AC3_CHANNELS
68 fSampleBuffer
= new float[MAX_AC3_CHANNELS
* A52_SAMPLES_PER_FRAME
];
71 fAC3Buffer
= new unsigned char[A52_MAX_CODED_FRAME_SIZE
];
72 memset(fAC3Buffer
, 0, A52_MAX_CODED_FRAME_SIZE
);
74 fZeroBuffer
= new unsigned char[SPDIF_FRAME_SIZE
];
75 memset(fZeroBuffer
, 0, SPDIF_FRAME_SIZE
);
77 fRingBuffer
= jack_ringbuffer_create(32768);
86 bool JackAC3Encoder::Init(jack_nframes_t sample_rate
)
88 fSampleRate
= sample_rate
;
89 fByteRate
= fSampleRate
* sizeof(short) * 2;
90 return (aften_encode_init(&fAftenContext
) == 0);
93 JackAC3Encoder::~JackAC3Encoder()
95 aften_encode_close(&fAftenContext
);
97 delete [] fSampleBuffer
;
99 delete [] fZeroBuffer
;
102 jack_ringbuffer_free(fRingBuffer
);
106 void JackAC3Encoder::Process(float** inputs_buffer
, float** outputs_buffer
, int nframes
)
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;
112 while (offset
< nframes
)
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
];
121 pos
+= fAftenContext
.channels
;
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
);
130 // released version 0.0.8 hasn't the 'count' parameter
131 int res
= aften_encode_frame(&fAftenContext
, fAC3Buffer
+ SPDIF_HEADER_SIZE
, fSampleBuffer
);
135 jack_error("aften_encode_frame error !!");
141 FillSpdifHeader(fAC3Buffer
, fOutSizeByte
+ SPDIF_HEADER_SIZE
);
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
;
147 jack_ringbuffer_write(fRingBuffer
, (const char *)fAC3Buffer
, fOutSizeByte
+ SPDIF_HEADER_SIZE
);
149 // write the proper remainder of zero padding (inefficient, should be memsetting)
150 jack_ringbuffer_write(fRingBuffer
, (const char *)fZeroBuffer
, silencebytes
);
152 offset
+= frames_left
;
153 frames_left
= A52_SAMPLES_PER_FRAME
;
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
];
162 pos
+= fAftenContext
.channels
;
165 fFramePos
+= (nframes
- offset
);
166 offset
+= (nframes
-offset
);
170 Output2Driver(outputs_buffer
, nframes
);
173 void JackAC3Encoder::FillSpdifHeader(unsigned char* buf
, int outsize
)
175 // todo, use outsize and not assume the fixed frame size?
176 int ac3outsize
= outsize
- SPDIF_HEADER_SIZE
;
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;
186 swab(buf
+SPDIF_HEADER_SIZE
, buf
+ SPDIF_HEADER_SIZE
, ac3outsize
);
190 int JackAC3Encoder::Output2Driver(float** outputs
, jack_nframes_t nframes
)
193 jack_nframes_t nframes_left
= nframes
;
195 if (jack_ringbuffer_read_space(fRingBuffer
) == 0) {
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
));
203 jack_ringbuffer_data_t rb_data
[2];
205 jack_ringbuffer_get_read_vector(fRingBuffer
, rb_data
);
207 while (nframes_left
> 0 && rb_data
[0].len
> 4) {
209 jack_nframes_t towrite_frames
= (rb_data
[0].len
) / (sizeof(short) * 2);
210 towrite_frames
= min(towrite_frames
, nframes_left
);
212 // write and deinterleave into the two channels
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);
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);
220 wrotebytes
= towrite_frames
* sizeof(short) * 2;
221 nframes_left
-= towrite_frames
;
223 jack_ringbuffer_read_advance(fRingBuffer
, wrotebytes
);
224 jack_ringbuffer_get_read_vector(fRingBuffer
, rb_data
);
227 if (nframes_left
> 0) {
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
));
237 void JackAC3Encoder::sample_move_dS_s16(jack_default_audio_sample_t
* dst
, char *src
, jack_nframes_t nsamples
, unsigned long src_skip
)
239 /* ALERT: signed sign-extension portability !!! */
241 *dst
= (*((short *) src
)) / SAMPLE_MAX_16BIT
;
247 void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t
* dst
, char *src
, jack_nframes_t nsamples
, unsigned long src_skip
)
249 /* ALERT: signed sign-extension portability !!! */
251 *dst
= (((int)(*((short *) src
))) << 8) / SAMPLE_MAX_24BIT
;
257 void JackAC3Encoder::GetChannelName(const char* name
, const char* alias
, char* portname
, int channel
)
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
267 const char* AC3_name
= "";
272 AC3_name
= "AC3_1_Left";
276 if (fAftenContext
.channels
== 2 || fAftenContext
.channels
== 4) {
277 AC3_name
= "AC3_2_Right";
279 AC3_name
= "AC3_2_Center";
284 if (fAftenContext
.channels
== 4) {
285 AC3_name
= "AC3_3_LeftSurround";
287 AC3_name
= "AC3_3_Right";
292 if (fAftenContext
.channels
== 4) {
293 AC3_name
= "AC3_4_RightSurround";
295 AC3_name
= "AC3_4_LeftSurround";
300 if (fAftenContext
.channels
> 4) {
301 AC3_name
= "AC3_5_RightSurround";
310 if (fAftenContext
.lfe
&& (channel
== fAftenContext
.channels
- 1)) {
311 sprintf(portname
, "%s:%s:AC3_%d_LFE", name
, alias
, fAftenContext
.channels
);
313 sprintf(portname
, "%s:%s:%s", name
, alias
, AC3_name
);
319 } // end of namespace