|
|
@@ -29,93 +29,89 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
|
|
|
|
|
|
namespace Jack |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
#ifndef __ppc__ |
|
|
|
|
|
|
|
JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams& params) |
|
|
|
{ |
|
|
|
aften_set_defaults(&fAftenContext); |
|
|
|
|
|
|
|
fAftenContext.channels = params.channels; |
|
|
|
aften_set_defaults(&fAftenContext); |
|
|
|
|
|
|
|
fAftenContext.channels = params.channels; |
|
|
|
fAftenContext.samplerate = params.sample_rate; |
|
|
|
fAftenContext.params.bitrate = params.bitrate; |
|
|
|
|
|
|
|
int acmod = A52_ACMOD_MONO; |
|
|
|
int lfe = params.lfe; |
|
|
|
|
|
|
|
|
|
|
|
switch (params.channels) { |
|
|
|
|
|
|
|
case 1: acmod = A52_ACMOD_MONO; break; |
|
|
|
case 2: acmod = A52_ACMOD_STEREO; break; |
|
|
|
case 3: acmod = A52_ACMOD_3_0; break; |
|
|
|
case 4: acmod = A52_ACMOD_2_2; break; |
|
|
|
case 5: acmod = A52_ACMOD_3_2; break; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
case 1: acmod = A52_ACMOD_MONO; break; |
|
|
|
case 2: acmod = A52_ACMOD_STEREO; break; |
|
|
|
case 3: acmod = A52_ACMOD_3_0; break; |
|
|
|
case 4: acmod = A52_ACMOD_2_2; break; |
|
|
|
case 5: acmod = A52_ACMOD_3_2; break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (lfe) { |
|
|
|
fAftenContext.channels += 1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fAftenContext.acmod = acmod; |
|
|
|
fAftenContext.lfe = lfe; |
|
|
|
fAftenContext.sample_format = A52_SAMPLE_FMT_FLT; |
|
|
|
fAftenContext.verbose = 1; |
|
|
|
|
|
|
|
fAftenContext.system.n_threads = 1; |
|
|
|
|
|
|
|
// create interleaved framebuffer for MAX_AC3_CHANNELS |
|
|
|
|
|
|
|
// create interleaved framebuffer for MAX_AC3_CHANNELS |
|
|
|
fSampleBuffer = new float[MAX_AC3_CHANNELS * A52_SAMPLES_PER_FRAME]; |
|
|
|
|
|
|
|
// create AC3 buffer |
|
|
|
|
|
|
|
// create AC3 buffer |
|
|
|
fAC3Buffer = new unsigned char[A52_MAX_CODED_FRAME_SIZE]; |
|
|
|
memset(fAC3Buffer, 0, A52_MAX_CODED_FRAME_SIZE); |
|
|
|
|
|
|
|
fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE]; |
|
|
|
|
|
|
|
fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE]; |
|
|
|
memset(fZeroBuffer, 0, SPDIF_FRAME_SIZE); |
|
|
|
|
|
|
|
fRingBuffer = jack_ringbuffer_create(32768); |
|
|
|
|
|
|
|
fRingBuffer = jack_ringbuffer_create(32768); |
|
|
|
|
|
|
|
fOutSizeByte = 0; |
|
|
|
fFramePos = 0; |
|
|
|
|
|
|
|
fSampleRate = 0; |
|
|
|
fByteRate = 0; |
|
|
|
fOutSizeByte = 0; |
|
|
|
fFramePos = 0; |
|
|
|
|
|
|
|
fSampleRate = 0; |
|
|
|
fByteRate = 0; |
|
|
|
} |
|
|
|
|
|
|
|
bool JackAC3Encoder::Init(jack_nframes_t sample_rate) |
|
|
|
{ |
|
|
|
fSampleRate = sample_rate; |
|
|
|
fSampleRate = sample_rate; |
|
|
|
fByteRate = fSampleRate * sizeof(short) * 2; |
|
|
|
return (aften_encode_init(&fAftenContext) == 0); |
|
|
|
return (aften_encode_init(&fAftenContext) == 0); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JackAC3Encoder::~JackAC3Encoder() |
|
|
|
{ |
|
|
|
aften_encode_close(&fAftenContext); |
|
|
|
|
|
|
|
delete [] fSampleBuffer; |
|
|
|
delete [] fAC3Buffer; |
|
|
|
delete [] fZeroBuffer; |
|
|
|
|
|
|
|
if (fRingBuffer) { |
|
|
|
jack_ringbuffer_free(fRingBuffer); |
|
|
|
} |
|
|
|
aften_encode_close(&fAftenContext); |
|
|
|
|
|
|
|
delete [] fSampleBuffer; |
|
|
|
delete [] fAC3Buffer; |
|
|
|
delete [] fZeroBuffer; |
|
|
|
|
|
|
|
if (fRingBuffer) { |
|
|
|
jack_ringbuffer_free(fRingBuffer); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int nframes) |
|
|
|
{ |
|
|
|
// fill and process frame buffers as appropriate |
|
|
|
// fill and process frame buffers as appropriate |
|
|
|
jack_nframes_t frames_left = A52_SAMPLES_PER_FRAME - fFramePos; |
|
|
|
jack_nframes_t offset = 0; |
|
|
|
|
|
|
|
while (offset < nframes) |
|
|
|
{ |
|
|
|
if ((nframes - offset) >= frames_left) { |
|
|
|
|
|
|
|
// copy only frames_left more data |
|
|
|
jack_nframes_t pos = fFramePos * fAftenContext.channels; |
|
|
|
for (jack_nframes_t spos = offset; spos < offset + frames_left; ++spos) { |
|
|
@@ -135,30 +131,28 @@ void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int |
|
|
|
int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer); |
|
|
|
#endif |
|
|
|
|
|
|
|
if (res < 0) { |
|
|
|
jack_error("aften_encode_frame error !!"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
fOutSizeByte = res; |
|
|
|
|
|
|
|
if (res < 0) { |
|
|
|
jack_error("aften_encode_frame error !!"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
fOutSizeByte = res; |
|
|
|
|
|
|
|
FillSpdifHeader(fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
// push AC3 output to SPDIF ring buffer |
|
|
|
float calc_ac3byterate = (fOutSizeByte * fSampleRate / (float) A52_SAMPLES_PER_FRAME); |
|
|
|
jack_nframes_t silencebytes = (jack_nframes_t) (fOutSizeByte * (fByteRate / calc_ac3byterate)) - fOutSizeByte - SPDIF_HEADER_SIZE; |
|
|
|
|
|
|
|
jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE); |
|
|
|
|
|
|
|
// write the proper remainder of zero padding (inefficient, should be memsetting) |
|
|
|
jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes); |
|
|
|
|
|
|
|
jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE); |
|
|
|
|
|
|
|
// write the proper remainder of zero padding (inefficient, should be memsetting) |
|
|
|
jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes); |
|
|
|
|
|
|
|
offset += frames_left; |
|
|
|
frames_left = A52_SAMPLES_PER_FRAME; |
|
|
|
fFramePos = 0; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// copy incoming data into frame buffers without processing |
|
|
|
jack_nframes_t pos = fFramePos * fAftenContext.channels; |
|
|
|
for (jack_nframes_t spos = offset; spos < nframes; ++spos) { |
|
|
@@ -180,7 +174,7 @@ void JackAC3Encoder::FillSpdifHeader(unsigned char* buf, int outsize) |
|
|
|
{ |
|
|
|
// todo, use outsize and not assume the fixed frame size? |
|
|
|
int ac3outsize = outsize - SPDIF_HEADER_SIZE; |
|
|
|
|
|
|
|
|
|
|
|
buf[0] = 0x72; buf[1] = 0xf8; /* spdif syncword */ |
|
|
|
buf[2] = 0x1f; buf[3] = 0x4e; /* .............. */ |
|
|
|
buf[4] = 0x01; /* AC3 data */ |
|
|
@@ -197,24 +191,24 @@ int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes) |
|
|
|
{ |
|
|
|
int wrotebytes = 0; |
|
|
|
jack_nframes_t nframes_left = nframes; |
|
|
|
|
|
|
|
|
|
|
|
if (jack_ringbuffer_read_space(fRingBuffer) == 0) { |
|
|
|
|
|
|
|
|
|
|
|
// just write silence |
|
|
|
memset(outputs[0], 0, nframes * sizeof(jack_default_audio_sample_t)); |
|
|
|
memset(outputs[1], 0, nframes * sizeof(jack_default_audio_sample_t)); |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
jack_ringbuffer_data_t rb_data[2]; |
|
|
|
|
|
|
|
jack_ringbuffer_data_t rb_data[2]; |
|
|
|
|
|
|
|
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data); |
|
|
|
|
|
|
|
|
|
|
|
while (nframes_left > 0 && rb_data[0].len > 4) { |
|
|
|
|
|
|
|
|
|
|
|
jack_nframes_t towrite_frames = (rb_data[0].len) / (sizeof(short) * 2); |
|
|
|
towrite_frames = min(towrite_frames, nframes_left); |
|
|
|
|
|
|
|
|
|
|
|
// write and deinterleave into the two channels |
|
|
|
#if 1 |
|
|
|
sample_move_dS_s16(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2); |
|
|
@@ -225,7 +219,7 @@ int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes) |
|
|
|
#endif |
|
|
|
wrotebytes = towrite_frames * sizeof(short) * 2; |
|
|
|
nframes_left -= towrite_frames; |
|
|
|
|
|
|
|
|
|
|
|
jack_ringbuffer_read_advance(fRingBuffer, wrotebytes); |
|
|
|
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data); |
|
|
|
} |
|
|
@@ -262,64 +256,64 @@ void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, c |
|
|
|
|
|
|
|
void JackAC3Encoder::GetChannelName(const char* name, const char* alias, char* portname, int channel) |
|
|
|
{ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* 2 channels = L, R |
|
|
|
* 3 channels = L, C, R |
|
|
|
* 4 channels = L, R, LS, RS |
|
|
|
* 5 ch = L, C, R, LS, RS |
|
|
|
* 6 ch = L, C, R, LS, RS, LFE |
|
|
|
*/ |
|
|
|
|
|
|
|
const char* AC3_name = ""; |
|
|
|
|
|
|
|
switch (channel) { |
|
|
|
|
|
|
|
case 0: |
|
|
|
AC3_name = "AC3_1_Left"; |
|
|
|
break; |
|
|
|
|
|
|
|
case 1: |
|
|
|
if (fAftenContext.channels == 2 || fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_2_Right"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_2_Center"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
if (fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_3_LeftSurround"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_3_Right"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 3: |
|
|
|
if (fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_4_RightSurround"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_4_LeftSurround"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 4: |
|
|
|
if (fAftenContext.channels > 4) { |
|
|
|
AC3_name = "AC3_5_RightSurround"; |
|
|
|
|
|
|
|
const char* AC3_name = ""; |
|
|
|
|
|
|
|
switch (channel) { |
|
|
|
|
|
|
|
case 0: |
|
|
|
AC3_name = "AC3_1_Left"; |
|
|
|
break; |
|
|
|
|
|
|
|
case 1: |
|
|
|
if (fAftenContext.channels == 2 || fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_2_Right"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_2_Center"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
if (fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_3_LeftSurround"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_3_Right"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 3: |
|
|
|
if (fAftenContext.channels == 4) { |
|
|
|
AC3_name = "AC3_4_RightSurround"; |
|
|
|
} else { |
|
|
|
AC3_name = "AC3_4_LeftSurround"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// Last channel |
|
|
|
if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) { |
|
|
|
sprintf(portname, "%s:%s:AC3_%d_LFE", name, alias, fAftenContext.channels); |
|
|
|
} else { |
|
|
|
sprintf(portname, "%s:%s:%s", name, alias, AC3_name); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 4: |
|
|
|
if (fAftenContext.channels > 4) { |
|
|
|
AC3_name = "AC3_5_RightSurround"; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// Last channel |
|
|
|
if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) { |
|
|
|
sprintf(portname, "%s:%s:AC3_%d_LFE", name, alias, fAftenContext.channels); |
|
|
|
} else { |
|
|
|
sprintf(portname, "%s:%s:%s", name, alias, AC3_name); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} // end of namespace |
|
|
|
} // end of namespace |