sox_ng/libdolbyb/dolbyb.c
Martin Guy e7190574aa Sync with libdolbyb-1.1
One change: from #include "configure.h" to "../src/soxconfig.h"
2026-02-20 22:44:21 +01:00

150 lines
4.6 KiB
C

/*
* dolbyb.c - the main program to drive libdolbyb as a stand-alone program.
*
* Copyright (C) 2025 Martin Guy <martinwguy@gmail.com>
* based on dolbybcsoftwaredecode/DolbyBi64.PP by Richard Evans 2018.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. See COPYING for details.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "dolbyb.h"
#include <stdlib.h>
#include <stdio.h>
#include <sndfile.h>
#include <sndfile.h>
#if DEBUG
#include "Param.h"
#endif
static void
usage(void)
{
fprintf(stderr, "Usage: dolbyb [options] in.wav out.wav\n");
fprintf(stderr, "-d Decode a Dolby B-encoded recording (this is the default action)\n");
fprintf(stderr, "-e Encode instead of decoding\n");
fprintf(stderr, "-p Show a progress meter\n");
fprintf(stderr, "-u N Upsample the high-pass filter N times\n");
fprintf(stderr, " (defaults to the right value for at least 200kHz)\n");
fprintf(stderr, "-h Process absolutely everything at the upsampled rate\n");
fprintf(stderr, "-t N Set the threshold gain to N dB (float, default 0.0)\n");
fprintf(stderr, "-a N Set the decode accuracy in dB (float, default -5.0)\n");
fprintf(stderr, "-f N Use filter type N (1-4, default 4)\n");
}
#define HANDFUL 1024
int
main(int argc, char *argv[])
{
dolbyb_t dolbyb;
SNDFILE *sf_in, *sf_out;
SF_INFO sfinfo;
short *buf_in, *buf_out;
sf_count_t n_read;
int Encode = 0;
int Progress = 0;
char *progname;
char *errmsg;
dolbyb_init(&dolbyb);
/* Process commandline arguments */
progname = argv[0];
argv++; argc--; /* Skip program name */
while (argc > 0 && argv[0][0] == '-') {
char arg = 0;
char *numarg;
switch (argv[0][1]) {
case 'd': Encode = 0; break;
case 'e': Encode = 1; break;
case 'p': Progress = 1; break;
case 'h': dolbyb.AllHig = 1; break;
case 'f':
case 'u':
case 't':
case 'a': arg = argv[0][1];
numarg = argv[0][2] ? &argv[0][2] : (--argc, *++argv);
break;
default: usage(); exit(1);
}
switch (arg) {
case 'f': dolbyb.FltTyp = *numarg - '0'; break;
case 'u': dolbyb.UpSamp = atol(numarg); break;
case 't': dolbyb.ThGndB = atof(numarg); break;
case 'a': dolbyb.DecAdB = atof(numarg); break;
}
argv++; argc--;
}
if (argc != 2) { usage(); exit(1); }
sf_in = sf_open(argv[0], SFM_READ, &sfinfo);
if (sf_in == NULL) exit(1);
sf_out = sf_open(argv[1], SFM_WRITE, &sfinfo);
if (sf_out == NULL) exit(1);
buf_in = calloc(sfinfo.channels * sizeof(short), HANDFUL);
buf_out = calloc(sfinfo.channels * sizeof(short), HANDFUL);
if (buf_in == NULL || buf_out == NULL) exit(1);
if (Progress) fprintf(stderr, "Calibrating...");
dolbyb.SmpSec = sfinfo.samplerate;
dolbyb.NumChn = sfinfo.channels;
dolbyb.BDepth = 16;
if ((errmsg = dolbyb_start(&dolbyb))) {
fprintf(stderr, "%s: %s\n", progname, errmsg);
exit(1);
}
if ((errmsg = dolbyb_restart(&dolbyb))) {
fprintf(stderr, "%s: %s\n", progname, errmsg);
exit(1);
}
while ((n_read = sf_readf_short(sf_in, buf_in, (sf_count_t)HANDFUL)) > 0) {
if (Encode) errmsg = dolbyb_encode(&dolbyb, buf_in, buf_out, (size_t)n_read);
else errmsg = dolbyb_decode(&dolbyb, buf_in, buf_out, (size_t)n_read);
if (errmsg) {
fprintf(stderr, "%s: %s\n", progname, errmsg);
break;
}
if (sf_writef_short(sf_out, buf_out, n_read) != n_read) {
fprintf(stderr, "Write error on the output file.\n");
break;
}
if (Progress) {
/* Show progress as minutes:seconds coded */
static unsigned total = 0;
unsigned h, m, s;
static unsigned oldh = 1, oldm, olds;
total += n_read;
s = total / sfinfo.samplerate;
m = s / 60; s %= 60;
h = m / 60; m %= 60;
if (h != oldh || m != oldm || s != olds) {
fprintf(stderr, "\rProcessed %02u:%02u:%02u", h, m, s);
oldh = h; oldm = m; olds = s;
}
}
}
if (Progress) putc('\n', stderr);
#if DEBUG
dolbyb_dumpparam(&dolbyb);
#endif
dolbyb_free(&dolbyb);
sf_close(sf_out);
sf_close(sf_in);
return 0;
}