ref: 0826f2e98f06d05257d66b9bd7368eda5802a534
dir: /frontend/aacenc.c/
/*
* FAAC - Freeware Advanced Audio Coder
* Copyright (C) 2001 Menno Bakker
* Copyright (C) 2002-2017 Krzysztof Nikiel
* Copyright (C) 2004 Dan Villiom P. Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <faac.h>
static Biobuf out;
static int
done(void*, char*)
{
Bflush(&out);
return 0;
}
static void
usage(void)
{
fprint(2, "usage: %s [-b] [-c CHAN] [-q QUANT] [-r RATE] [-t low|main|ltp] [-B BITRATE]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
int nch, srate, type, brate, sz, n, r, q, i, nobuffer;
ulong insamples, outsz, insz;
faacEncConfigurationPtr fmt;
u8int *obuf, ph[7+1+4+8];
faacEncHandle e;
s16int *pcm;
Biobuf in;
uvlong ns;
char *s;
nobuffer = 0;
brate = 0;
srate = 44100;
nch = 2;
type = LOW;
q = 0;
ARGBEGIN{
case 'b':
nobuffer = 1;
break;
case 'B':
if((brate = atoi(EARGF(usage()))) < 0)
sysfatal("invalid bitrate %d", brate);
break;
case 'c':
if((nch = atoi(EARGF(usage()))) < 1 || nch > 64)
sysfatal("invalid number of channels %d", nch);
break;
case 'r':
if((srate = atoi(EARGF(usage()))) < 1)
sysfatal("invalid samplerate %d", srate);
break;
case 'q':
if((q = atoi(EARGF(usage()))) < 1)
sysfatal("invalid quantization quality %d", q);
break;
case 't':
s = EARGF(usage());
if(cistrcmp(s, "low") == 0)
type = LOW;
else if(cistrcmp(s, "main") == 0)
type = MAIN;
else if(cistrcmp(s, "ltp") == 0)
type = LTP;
else
sysfatal("invalid type %s", s);
break;
default:
usage();
}ARGEND
if(argc != 0)
usage();
if(Binit(&in, 0, OREAD) != 0 || Binit(&out, 1, OWRITE) != 0)
sysfatal("io init failed");
setfcr(getfcr() & ~(FPINVAL|FPOVFL));
if((e = faacEncOpen(srate, nch, &insamples, &outsz)) == nil)
sysfatal("faacEncOpen");
insz = insamples * sizeof(*pcm);
if((pcm = malloc(insz)) == nil)
sysfatal("memory");
if((obuf = malloc(outsz)) == nil)
sysfatal("memory");
fmt = faacEncGetCurrentConfiguration(e);
fmt->inputFormat = FAAC_INPUT_16BIT;
fmt->mpegVersion = MPEG2;
fmt->outputFormat = ADTS_STREAM;
fmt->aacObjectType = type;
if(brate > 0)
fmt->bitRate = brate / nch;
if(q > 0)
fmt->quantqual = q;
if(!faacEncSetConfiguration(e, fmt))
sysfatal("invalid encoder configuration");
atnotify(done, 1);
ns = nsec();
for(;;){
for(n = 0; n == 0 || (n & (sizeof(*pcm)-1)) != 0; n += r){
if((r = Bread(&in, pcm+n, insz-n)) <= 0)
break;
}
if(n == 0)
break;
if((sz = faacEncEncode(e, pcm, n/sizeof(*pcm), obuf, outsz)) < 0)
sysfatal("faacEncEncode");
else if(sz == 0)
continue;
if(ns != 0){
memmove(ph, obuf, 7);
/* set frame size */
ph[3] &= ~3;
ph[4] = sizeof(ph)>>3;
ph[5] = (ph[5]&~0xe0) | sizeof(ph)<<5;
ph[7] = 0x04; /* DSE */
ph[8] = 'n';
ph[9] = 's';
ph[10] = 'e';
ph[11] = 'c';
for(i = 0; i < 8; i++, ns >>= 8)
ph[12+i] = ns;
ns = 0;
if(Bwrite(&out, ph, sizeof(ph)) < 0)
break;
Bflush(&out);
}
if(Bwrite(&out, obuf, sz) < 0)
break;
if(nobuffer)
Bflush(&out);
}
Bflush(&out);
exits(nil);
}