tools & cpp: Add support of asymetric frame sizes of a stereo stream

This commit is contained in:
Antoine Soulier
2024-01-10 14:44:49 -08:00
parent 71ffd784d5
commit 4d014e33e7
7 changed files with 166 additions and 97 deletions

View File

@@ -31,6 +31,8 @@
#include "lc3bin.h"
#include "wave.h"
#define MAX_CHANNELS 2
#ifndef MIN
#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
#endif
@@ -158,15 +160,15 @@ int main(int argc, char *argv[])
/* --- Check parameters --- */
int frame_us, srate_hz, nch, nsamples;
int frame_us, srate_hz, nchannels, nsamples;
bool hrmode;
if (lc3bin_read_header(fp_in,
&frame_us, &srate_hz, &hrmode, &nch, &nsamples) < 0)
&frame_us, &srate_hz, &hrmode, &nchannels, &nsamples) < 0)
error(EINVAL, "LC3 binary input file");
if (nch < 1 || nch > 2)
error(EINVAL, "Number of channels %d", nch);
if (nchannels < 1 || nchannels > MAX_CHANNELS)
error(EINVAL, "Number of channels %d", nchannels);
if (!LC3_CHECK_DT_US(frame_us))
error(EINVAL, "Frame duration");
@@ -186,7 +188,7 @@ int main(int argc, char *argv[])
((int64_t)nsamples * pcm_srate_hz) / srate_hz;
wave_write_header(fp_out,
pcm_sbits, pcm_sbytes, pcm_srate_hz, nch, pcm_samples);
pcm_sbits, pcm_sbytes, pcm_srate_hz, nchannels, pcm_samples);
/* --- Setup decoding --- */
@@ -200,7 +202,7 @@ int main(int argc, char *argv[])
enum lc3_pcm_format pcm_fmt =
pcm_sbits == 24 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16;
for (int ich = 0; ich < nch; ich++) {
for (int ich = 0; ich < nchannels; ich++) {
dec[ich] = lc3_hr_setup_decoder(
hrmode, frame_us, srate_hz, p.srate_hz,
malloc(lc3_hr_decoder_size(hrmode, frame_us, pcm_srate_hz)));
@@ -214,11 +216,12 @@ int main(int argc, char *argv[])
static const char *dash_line = "========================================";
int nsec = 0;
int nerr = 0;
unsigned t0 = clock_us();
for (int i = 0; i * frame_samples < encode_samples; i++) {
int frame_bytes = lc3bin_read_data(fp_in, nch, in);
int block_bytes = lc3bin_read_data(fp_in, nchannels, in);
if (floorf(i * frame_us * 1e-6) > nsec) {
@@ -231,19 +234,28 @@ int main(int argc, char *argv[])
nsec = rint(i * frame_us * 1e-6);
}
if (frame_bytes <= 0)
memset(pcm, 0, nch * frame_samples * pcm_sbytes);
else
for (int ich = 0; ich < nch; ich++)
lc3_decode(dec[ich],
in + ich * frame_bytes, frame_bytes,
pcm_fmt, pcm + ich * pcm_sbytes, nch);
if (block_bytes <= 0)
memset(pcm, 0, nchannels * frame_samples * pcm_sbytes);
else {
const uint8_t *in_ptr = in;
for (int ich = 0; ich < nchannels; ich++) {
int frame_bytes = block_bytes / nchannels
+ (ich < block_bytes % nchannels);
int res = lc3_decode(dec[ich], in_ptr, frame_bytes,
pcm_fmt, pcm + ich * pcm_sbytes, nchannels);
nerr += (res != 0);
in_ptr += frame_bytes;
}
}
int pcm_offset = i > 0 ? 0 : encode_samples - pcm_samples;
int pcm_nwrite = MIN(frame_samples - pcm_offset,
encode_samples - i*frame_samples);
wave_write_pcm(fp_out, pcm_sbytes, pcm, nch, pcm_offset, pcm_nwrite);
wave_write_pcm(fp_out,
pcm_sbytes, pcm, nchannels, pcm_offset, pcm_nwrite);
}
unsigned t = (clock_us() - t0) / 1000;
@@ -252,9 +264,12 @@ int main(int argc, char *argv[])
fprintf(stderr, "%02d:%02d Decoded in %d.%03d seconds %20s\n",
nsec / 60, nsec % 60, t / 1000, t % 1000, "");
if (nerr)
fprintf(stderr, "Warning: Decoding of %d frames failed!\n", nerr);
/* --- Cleanup --- */
for (int ich = 0; ich < nch; ich++)
for (int ich = 0; ich < nchannels; ich++)
free(dec[ich]);
if (fp_in != stdin)

View File

@@ -31,6 +31,8 @@
#include "lc3bin.h"
#include "wave.h"
#define MAX_CHANNELS 2
/**
* Error handling
@@ -158,11 +160,11 @@ int main(int argc, char *argv[])
/* --- Check parameters --- */
int frame_us = p.frame_ms * 1000;
int srate_hz, nch, nsamples;
int srate_hz, nchannels, nsamples;
int pcm_sbits, pcm_sbytes;
if (wave_read_header(fp_in,
&pcm_sbits, &pcm_sbytes, &srate_hz, &nch, &nsamples) < 0)
&pcm_sbits, &pcm_sbytes, &srate_hz, &nchannels, &nsamples) < 0)
error(EINVAL, "Bad or unsupported WAVE input file");
if (p.bitrate <= 0)
@@ -181,8 +183,8 @@ int main(int argc, char *argv[])
(pcm_sbits == 24 && pcm_sbytes != 24/8 && pcm_sbytes != 32/8))
error(EINVAL, "Sample storage on %d bytes", pcm_sbytes);
if (nch < 1 || nch > 2)
error(EINVAL, "Number of channels %d", nch);
if (nchannels < 1 || nchannels > MAX_CHANNELS)
error(EINVAL, "Number of channels %d", nchannels);
if (p.srate_hz && (!LC3_HR_CHECK_SR_HZ(p.hrmode, p.srate_hz) ||
p.srate_hz > srate_hz ))
@@ -192,9 +194,18 @@ int main(int argc, char *argv[])
int enc_samples = !p.srate_hz ? nsamples :
((int64_t)nsamples * enc_srate_hz) / srate_hz;
int block_bytes = lc3_hr_frame_block_bytes(
p.hrmode, frame_us, srate_hz, nchannels, p.bitrate);
int bitrate = lc3_hr_resolve_bitrate(
p.hrmode, frame_us, srate_hz, block_bytes);
if (bitrate != p.bitrate)
fprintf(stderr, "Bitrate adjusted to %d bps\n", bitrate);
lc3bin_write_header(fp_out,
frame_us, enc_srate_hz, p.hrmode,
p.bitrate, nch, enc_samples);
bitrate, nchannels, enc_samples);
/* --- Setup encoding --- */
@@ -202,8 +213,6 @@ int main(int argc, char *argv[])
uint8_t out[2 * LC3_HR_MAX_FRAME_BYTES];
lc3_encoder_t enc[2];
int frame_bytes = lc3_hr_frame_bytes(
p.hrmode, frame_us, srate_hz, p.bitrate / nch);
int frame_samples = lc3_hr_frame_samples(
p.hrmode, frame_us, srate_hz);
int encode_samples = nsamples + lc3_hr_delay_samples(
@@ -212,7 +221,7 @@ int main(int argc, char *argv[])
pcm_sbytes == 32/8 ? LC3_PCM_FORMAT_S24 :
pcm_sbytes == 24/8 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16;
for (int ich = 0; ich < nch; ich++) {
for (int ich = 0; ich < nchannels; ich++) {
enc[ich] = lc3_hr_setup_encoder(
p.hrmode, frame_us, enc_srate_hz, srate_hz,
malloc(lc3_hr_encoder_size(p.hrmode, frame_us, srate_hz)));
@@ -230,10 +239,10 @@ int main(int argc, char *argv[])
for (int i = 0; i * frame_samples < encode_samples; i++) {
int nread = wave_read_pcm(fp_in, pcm_sbytes, nch, frame_samples, pcm);
int nread = wave_read_pcm(fp_in, pcm_sbytes, nchannels, frame_samples, pcm);
memset(pcm + nread * nch * pcm_sbytes, 0,
nch * (frame_samples - nread) * pcm_sbytes);
memset(pcm + nread * nchannels * pcm_sbytes, 0,
nchannels * (frame_samples - nread) * pcm_sbytes);
if (floorf(i * frame_us * 1e-6) > nsec) {
float progress = fminf(
@@ -246,12 +255,19 @@ int main(int argc, char *argv[])
nsec = (int)(i * frame_us * 1e-6);
}
for (int ich = 0; ich < nch; ich++)
lc3_encode(enc[ich],
pcm_fmt, pcm + ich * pcm_sbytes, nch,
frame_bytes, out + ich * frame_bytes);
uint8_t *out_ptr = out;
for (int ich = 0; ich < nchannels; ich++) {
int frame_bytes = block_bytes / nchannels
+ (ich < block_bytes % nchannels);
lc3bin_write_data(fp_out, out, nch, frame_bytes);
lc3_encode(enc[ich],
pcm_fmt, pcm + ich * pcm_sbytes, nchannels,
frame_bytes, out_ptr);
out_ptr += frame_bytes;
}
lc3bin_write_data(fp_out, out, block_bytes);
}
unsigned t = (clock_us() - t0) / 1000;
@@ -262,7 +278,7 @@ int main(int argc, char *argv[])
/* --- Cleanup --- */
for (int ich = 0; ich < nch; ich++)
for (int ich = 0; ich < nchannels; ich++)
free(enc[ich]);
if (fp_in != stdin)

View File

@@ -80,12 +80,11 @@ int lc3bin_read_data(FILE *fp, int nchannels, void *buffer)
uint16_t nbytes;
if (fread(&nbytes, sizeof(nbytes), 1, fp) < 1
|| nbytes > nchannels * LC3_MAX_FRAME_BYTES
|| nbytes % nchannels
|| nbytes > nchannels * LC3_HR_MAX_FRAME_BYTES
|| fread(buffer, nbytes, 1, fp) < 1)
return -1;
return nbytes / nchannels;
return nbytes;
}
/**
@@ -118,11 +117,10 @@ void lc3bin_write_header(FILE *fp,
/**
* Write LC3 block of data
*/
void lc3bin_write_data(FILE *fp,
const void *data, int nchannels, int frame_bytes)
void lc3bin_write_data(FILE *fp, const void *data, int nbytes)
{
uint16_t nbytes = nchannels * frame_bytes;
fwrite(&nbytes, sizeof(nbytes), 1, fp);
uint16_t hdr_nbytes = nbytes;
fwrite(&hdr_nbytes, sizeof(hdr_nbytes), 1, fp);
fwrite(data, 1, nbytes, fp);
}

View File

@@ -42,8 +42,8 @@ int lc3bin_read_header(FILE *fp,
* Read LC3 block of data
* fp Opened file
* nchannels Number of channels
* buffer Output buffer of `nchannels * LC3_MAX_FRAME_BYTES`
* return Size of each 'nchannels` frames, -1 on error
* buffer Output buffer of `nchannels * LC3_HR_MAX_FRAME_BYTES`
* return Size of the frames block, -1 on error
*/
int lc3bin_read_data(FILE *fp, int nchannels, void *buffer);
@@ -65,11 +65,9 @@ void lc3bin_write_header(FILE *fp,
* Write LC3 block of data
* fp Opened file
* data The frames data
* nchannels Number of channels
* frame_bytes Size of each `nchannels` frames
* nbytes Size of the frames block
*/
void lc3bin_write_data(FILE *fp,
const void *data, int nchannels, int frame_bytes);
void lc3bin_write_data(FILE *fp, const void *data, int nbytes);
#endif /* __LC3BIN_H */