~ft/aacdec

4a95346b4ecd076e699968623bb9d4da71e54d0c — Sigrid Solveig Haflínudóttir 1 year, 7 days ago cb1b7ef master
update plan 9 build
M .gitignore => .gitignore +2 -0
@@ 1,1 1,3 @@
bazel-*
[a0125678vqki].*
*.[ao0125678vqki]

M config_plan9.h => config_plan9.h +1 -0
@@ 1,3 1,4 @@
//#define DRM_SUPPORT 1
#define HAVE_STRCHR 1
#define HAVE_MEMCPY 1
#define FLT_MAX 3.40282347e+38

M frontend/aacdec.c => frontend/aacdec.c +160 -1326
@@ 28,1356 28,190 @@
** $Id: main.c,v 1.89 2015/01/19 09:46:12 knik Exp $
**/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h>
#ifndef __MINGW32__
#define off_t __int64
#endif
#elif !defined(__plan9__)
#include <time.h>
#endif

#ifdef __plan9__
#include <u.h>
#include <libc.h>
#else
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#endif
#include <stdio.h>
#include "unicode_support.h"

#include <bio.h>
#include <neaacdec.h>

#include "audio.h"
#include "mp4read.h"

#ifndef min
#define min(a,b) ( (a) < (b) ? (a) : (b) )
#endif
#define min(a,b) ((a)<=(b)?(a):(b))

#define MAX_CHANNELS 6 /* make this higher to support files with
                          more channels */

#define MAX_PERCENTS 384

static int quiet = 0;

static void faad_fprintf(FILE *stream, const char *fmt, ...)
{
    va_list ap;

    if (!quiet)
    {
        va_start(ap, fmt);
        vfprintf(stream, fmt, ap);
        va_end(ap);
    }

#ifdef _WIN32
    if (!_isatty(_fileno(stream)))
    {
        fflush(stream); /*ensure real-time progress output on Win32*/
    }
#endif
}
#define MAX_CHANNELS 6 /* make this higher to support files with more channels */

/* FAAD file buffering routines */
typedef struct {
    unsigned long bytes_into_buffer;
    unsigned long bytes_consumed;
    unsigned long file_offset;
    unsigned char *buffer;
    FILE *infile;
    int at_eof;
} aac_buffer;


static int fill_buffer(aac_buffer *b)
{
    unsigned long bread;

    if (b->bytes_consumed > 0)
    {
        if (b->bytes_into_buffer)
        {
            memmove((void*)b->buffer, (void*)(b->buffer + b->bytes_consumed),
                b->bytes_into_buffer*sizeof(unsigned char));
        }

        if (!b->at_eof)
        {
            bread = (unsigned long)fread((void*)(b->buffer + b->bytes_into_buffer), 1,
                b->bytes_consumed, b->infile);

            if (bread != b->bytes_consumed)
                b->at_eof = 1;

            b->bytes_into_buffer += bread;
        }

        b->bytes_consumed = 0;

        if (b->bytes_into_buffer > 3)
        {
            if (memcmp(b->buffer, "TAG", 3) == 0)
                b->bytes_into_buffer = 0;
        }
        if (b->bytes_into_buffer > 11)
        {
            if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0)
                b->bytes_into_buffer = 0;
        }
        if (b->bytes_into_buffer > 8)
        {
            if (memcmp(b->buffer, "APETAGEX", 8) == 0)
                b->bytes_into_buffer = 0;
        }
    }

    return 1;
}

static void advance_buffer(aac_buffer *b, unsigned int bytes)
{
    while ((b->bytes_into_buffer > 0) && (bytes > 0))
    {
        unsigned int chunk = bytes;
        if (b->bytes_into_buffer < chunk)
            chunk = (unsigned int)b->bytes_into_buffer;

        bytes -= chunk;
        b->file_offset += chunk;
        b->bytes_consumed = chunk;
        b->bytes_into_buffer -= chunk;

        if (b->bytes_into_buffer == 0)
            fill_buffer(b);
    }
}

static void lookforheader(aac_buffer *b)
{
    int i = 0;
    while (!b->at_eof )
    {
        if (b->bytes_into_buffer > 4)
        {
            if( ((b->buffer[0+i] == 0xff) && ((b->buffer[1+i] & 0xf6) == 0xf0)) ||
                (b->buffer[0+i] == 'A'    && b->buffer[1+i] == 'D' && b->buffer[2+i] == 'I' && b->buffer[3+i] == 'F'))
            {
                fill_buffer(b);
                break;
            } else {
                i++;
                b->file_offset       += 1;
                b->bytes_consumed    += 1;
                b->bytes_into_buffer -= 1;
            }
        }
        else
        {
            fill_buffer(b);
            i = 0;
        }
    }
}

static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0};

static int adts_parse(aac_buffer *b, int *bitrate, float *length)
{
    size_t frames;
    unsigned int frame_length;
    size_t t_framelength = 0;
    int samplerate = 0;
    float frames_per_sec, bytes_per_frame;

    /* Read all frames to ensure correct time and bitrate */
    for (frames = 0; /* */; frames++)
    {
        fill_buffer(b);

        if (b->bytes_into_buffer > 7)
        {
            /* check syncword */
            if (!((b->buffer[0] == 0xFF)&&((b->buffer[1] & 0xF6) == 0xF0)))
                break;

            if (frames == 0)
                samplerate = adts_sample_rates[(b->buffer[2]&0x3c)>>2];

            frame_length = ((((unsigned int)b->buffer[3] & 0x3)) << 11)
                | (((unsigned int)b->buffer[4]) << 3) | (b->buffer[5] >> 5);
            if (frame_length == 0)
                break;

            t_framelength += frame_length;

            if (frame_length > b->bytes_into_buffer)
                break;

            advance_buffer(b, frame_length);
        } else {
            break;
        }
    }

    frames_per_sec = (float)samplerate/1024.0f;
    if (frames != 0)
        bytes_per_frame = (float)t_framelength/(float)(frames*1000);
    else
        bytes_per_frame = 0;
    *bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
    if (frames_per_sec != 0)
        *length = (float)frames/frames_per_sec;
    else
        *length = 1;

    return 1;
}

/* MicroSoft channel definitions */
#define SPEAKER_FRONT_LEFT             0x1
#define SPEAKER_FRONT_RIGHT            0x2
#define SPEAKER_FRONT_CENTER           0x4
#define SPEAKER_LOW_FREQUENCY          0x8
#define SPEAKER_BACK_LEFT              0x10
#define SPEAKER_BACK_RIGHT             0x20
#define SPEAKER_FRONT_LEFT_OF_CENTER   0x40
#define SPEAKER_FRONT_RIGHT_OF_CENTER  0x80
#define SPEAKER_BACK_CENTER            0x100
#define SPEAKER_SIDE_LEFT              0x200
#define SPEAKER_SIDE_RIGHT             0x400
#define SPEAKER_TOP_CENTER             0x800
#define SPEAKER_TOP_FRONT_LEFT         0x1000
#define SPEAKER_TOP_FRONT_CENTER       0x2000
#define SPEAKER_TOP_FRONT_RIGHT        0x4000
#define SPEAKER_TOP_BACK_LEFT          0x8000
#define SPEAKER_TOP_BACK_CENTER        0x10000
#define SPEAKER_TOP_BACK_RIGHT         0x20000
#define SPEAKER_RESERVED               0x80000000

static long aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo *hInfo)
{
    if (hInfo->channels == 6 && hInfo->num_lfe_channels)
    {
        return SPEAKER_FRONT_LEFT + SPEAKER_FRONT_RIGHT +
            SPEAKER_FRONT_CENTER + SPEAKER_LOW_FREQUENCY +
            SPEAKER_BACK_LEFT + SPEAKER_BACK_RIGHT;
    } else {
        return 0;
    }
}

static char *position2string(int position)
{
    switch (position)
    {
    case FRONT_CHANNEL_CENTER: return "Center front";
    case FRONT_CHANNEL_LEFT:   return "Left front";
    case FRONT_CHANNEL_RIGHT:  return "Right front";
    case SIDE_CHANNEL_LEFT:    return "Left side";
    case SIDE_CHANNEL_RIGHT:   return "Right side";
    case BACK_CHANNEL_LEFT:    return "Left back";
    case BACK_CHANNEL_RIGHT:   return "Right back";
    case BACK_CHANNEL_CENTER:  return "Center back";
    case LFE_CHANNEL:          return "LFE";
    case UNKNOWN_CHANNEL:      return "Unknown";
    default: return "";
    }

    // return "";
	long bytes_into_buffer;
	long bytes_consumed;
	long file_offset;
	unsigned char *buffer;
	int at_eof;
}aac_buffer;

static Biobuf stdin, stdout;

static int
fill_buffer(aac_buffer *b)
{
	int bread;

	if(b->bytes_consumed > 0){
		if(b->bytes_into_buffer)
			memmove(b->buffer, b->buffer + b->bytes_consumed, b->bytes_into_buffer);

		if(!b->at_eof){
			bread = Bread(&stdin, (void*)(b->buffer + b->bytes_into_buffer), b->bytes_consumed);
			if(bread != b->bytes_consumed)
				b->at_eof = 1;
			b->bytes_into_buffer += bread;
		}

		b->bytes_consumed = 0;

		if(b->bytes_into_buffer > 3 && memcmp(b->buffer, "TAG", 3) == 0)
			b->bytes_into_buffer = 0;
		if(b->bytes_into_buffer > 11 && memcmp(b->buffer, "LYRICSBEGIN", 11) == 0)
			b->bytes_into_buffer = 0;
		if(b->bytes_into_buffer > 8 && memcmp(b->buffer, "APETAGEX", 8) == 0)
			b->bytes_into_buffer = 0;
	}

	return 1;
}

static void print_channel_info(NeAACDecFrameInfo *frameInfo)
static void
advance_buffer(aac_buffer *b, int bytes)
{
    /* print some channel info */
    int i;
    long channelMask = aacChannelConfig2wavexChannelMask(frameInfo);

    faad_fprintf(stderr, "  ---------------------\n");
    if (frameInfo->num_lfe_channels > 0)
    {
        faad_fprintf(stderr, " | Config: %2d.%d Ch     |", frameInfo->channels-frameInfo->num_lfe_channels, frameInfo->num_lfe_channels);
    } else {
        faad_fprintf(stderr, " | Config: %2d Ch       |", frameInfo->channels);
    }
    if (channelMask)
        faad_fprintf(stderr, " WARNING: channels are reordered according to\n");
    else
        faad_fprintf(stderr, "\n");
    faad_fprintf(stderr, "  ---------------------");
    if (channelMask)
        faad_fprintf(stderr, "  MS defaults defined in WAVE_FORMAT_EXTENSIBLE\n");
    else
        faad_fprintf(stderr, "\n");
    faad_fprintf(stderr, " | Ch |    Position    |\n");
    faad_fprintf(stderr, "  ---------------------\n");
    for (i = 0; i < frameInfo->channels; i++)
    {
        faad_fprintf(stderr, " | %.2d | %-14s |\n", i, position2string((int)frameInfo->channel_position[i]));
    }
    faad_fprintf(stderr, "  ---------------------\n");
    faad_fprintf(stderr, "\n");
}
	while(b->bytes_into_buffer > 0 && bytes > 0){
		int chunk = min(bytes, b->bytes_into_buffer);

static int FindAdtsSRIndex(int sr)
{
    int i;
		bytes -= chunk;
		b->file_offset += chunk;
		b->bytes_consumed = chunk;
		b->bytes_into_buffer -= chunk;

    for (i = 0; i < 16; i++)
    {
        if (sr == adts_sample_rates[i])
            return i;
    }
    return 16 - 1;
		if(b->bytes_into_buffer == 0)
			fill_buffer(b);
	}
}

static unsigned char *MakeAdtsHeader(int *dataSize, NeAACDecFrameInfo *hInfo, unsigned char old_format)
{
    unsigned char *data;
    int profile = (hInfo->object_type - 1) & 0x3;
    int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ?
        FindAdtsSRIndex(hInfo->samplerate / 2) : FindAdtsSRIndex(hInfo->samplerate);
    int skip = (old_format) ? 8 : 7;
    int framesize = skip + hInfo->bytesconsumed;

    if (hInfo->header_type == ADTS)
        framesize -= skip;

    *dataSize = 7;

    data = malloc(*dataSize * sizeof(unsigned char));
    memset(data, 0, *dataSize * sizeof(unsigned char));

    data[0] += 0xFF; /* 8b: syncword */

    data[1] += 0xF0; /* 4b: syncword */
    /* 1b: mpeg id = 0 */
    /* 2b: layer = 0 */
    data[1] += 1; /* 1b: protection absent */

    data[2] += ((profile << 6) & 0xC0); /* 2b: profile */
    data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */
    /* 1b: private = 0 */
    data[2] += ((hInfo->channels >> 2) & 0x1); /* 1b: channel_configuration */

    data[3] += ((hInfo->channels << 6) & 0xC0); /* 2b: channel_configuration */
    /* 1b: original */
    /* 1b: home */
    /* 1b: copyright_id */
    /* 1b: copyright_id_start */
    data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */

    data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */

    data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */
    data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */

    data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */
    /* 2b: num_raw_data_blocks */

    return data;
static int
decode(void)
{
	NeAACDecHandle hDecoder;
	NeAACDecFrameInfo frameInfo;
	NeAACDecConfigurationPtr config;
	unsigned long samplerate;
	unsigned char channels;
	void *sample_buffer;
	int bread;
	aac_buffer b;

	memset(&b, 0, sizeof(b));
	if((b.buffer = malloc(FAAD_MIN_STREAMSIZE*MAX_CHANNELS)) == nil)
		return -1;
	memset(b.buffer, 0, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);

	bread = Bread(&stdin, b.buffer, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
	b.bytes_into_buffer = bread;
	b.bytes_consumed = 0;
	b.file_offset = 0;

	if(bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS)
		b.at_eof = 1;

	hDecoder = NeAACDecOpen();

	config = NeAACDecGetCurrentConfiguration(hDecoder);
	config->defSampleRate = 44100;
	config->defObjectType = LC;
	config->outputFormat = FAAD_FMT_16BIT;
	config->downMatrix = 0;
	config->useOldADTSFormat = 0;
	NeAACDecSetConfiguration(hDecoder, config);

	fill_buffer(&b);
	if((bread = NeAACDecInit(hDecoder, b.buffer, b.bytes_into_buffer, &samplerate, &channels)) < 0){
		sysfatal("NeAACDecInit failed: %d", bread);
		if(b.buffer)
			free(b.buffer);
		NeAACDecClose(hDecoder);
		return -1;
	}
	advance_buffer(&b, bread);
	fill_buffer(&b);

	if(samplerate != 44100 || channels != 2){
		int pfd[2], pid;
		char fmt[32];

		pid = -1;
		if(pipe(pfd) < 0 || (pid = fork()) < 0)
			sysfatal("%r");
		if(pid == 0){
			dup(pfd[1], 0);
			close(pfd[1]);
			close(pfd[0]);
			snprint(fmt, sizeof(fmt), "s16c%dr%ld", channels, samplerate);
			execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, nil);
			sysfatal("%r");
		}
		close(pfd[1]);
		Binit(&stdout, pfd[0], OWRITE);
	}

	for(;;){
		sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, b.buffer, b.bytes_into_buffer);

		/* update buffer indices */
		advance_buffer(&b, frameInfo.bytesconsumed);

		if(frameInfo.error != 0)
			sysfatal("%s: %d", NeAACDecGetErrorMessage(frameInfo.error), frameInfo.error);

		if(frameInfo.samples > 0 && Bwrite(&stdout, sample_buffer, frameInfo.samples*2) != frameInfo.samples*2)
			break;

		fill_buffer(&b);

		if(b.bytes_into_buffer == 0)
			break;
	}

	NeAACDecClose(hDecoder);

	if(b.buffer)
		free(b.buffer);

	return frameInfo.error;
}

/* globals */
char *progName;

static const char *file_ext[] =
{
    NULL,
    ".wav",
    ".aif",
    ".au",
    ".au",
    ".pcm",
    NULL
};

static void usage(void)
static void
usage(void)
{
    faad_fprintf(stdout, "\nUsage:\n");
    faad_fprintf(stdout, "%s [options] infile.aac\n", progName);
    faad_fprintf(stdout, "Options:\n");
    faad_fprintf(stdout, " -h    Shows this help screen.\n");
    faad_fprintf(stdout, " -i    Shows info about the input file.\n");
    faad_fprintf(stdout, " -a X  Write MPEG-4 AAC ADTS output file.\n");
    faad_fprintf(stdout, " -t    Assume old ADTS format.\n");
    faad_fprintf(stdout, " -o X  Set output filename.\n");
    faad_fprintf(stdout, " -f X  Set output format. Valid values for X are:\n");
    faad_fprintf(stdout, "        1:  Microsoft WAV format (default).\n");
    faad_fprintf(stdout, "        2:  RAW PCM data.\n");
    faad_fprintf(stdout, " -b X  Set output sample format. Valid values for X are:\n");
    faad_fprintf(stdout, "        1:  16 bit PCM data (default).\n");
    faad_fprintf(stdout, "        2:  24 bit PCM data.\n");
    faad_fprintf(stdout, "        3:  32 bit PCM data.\n");
    faad_fprintf(stdout, "        4:  32 bit floating point data.\n");
    faad_fprintf(stdout, "        5:  64 bit floating point data.\n");
    faad_fprintf(stdout, " -s X  Force the samplerate to X (for RAW files).\n");
    faad_fprintf(stdout, " -l X  Set object type. Supported object types:\n");
    faad_fprintf(stdout, "        1:  Main object type.\n");
    faad_fprintf(stdout, "        2:  LC (Low Complexity) object type.\n");
    faad_fprintf(stdout, "        4:  LTP (Long Term Prediction) object type.\n");
    faad_fprintf(stdout, "        23: LD (Low Delay) object type.\n");
    faad_fprintf(stdout, " -d    Down matrix 5.1 to 2 channels\n");
    faad_fprintf(stdout, " -w    Write output to stdio instead of a file.\n");
    faad_fprintf(stdout, " -g    Disable gapless decoding.\n");
    faad_fprintf(stdout, " -q    Quiet - suppresses status messages.\n");
    faad_fprintf(stdout, " -j X  Jump - start output X seconds into track (MP4 files only).\n");
    faad_fprintf(stdout, "Example:\n");
    faad_fprintf(stdout, "       %s infile.aac\n", progName);
    faad_fprintf(stdout, "       %s infile.mp4\n", progName);
    faad_fprintf(stdout, "       %s -o outfile.wav infile.aac\n", progName);
    faad_fprintf(stdout, "       %s -w infile.aac > outfile.wav\n", progName);
    faad_fprintf(stdout, "       %s -a outfile.aac infile.aac\n", progName);
    return;
	fprint(2, "usage: %s\n", argv0);
	exits("usage");
}

static int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout,
                  int def_srate, unsigned char object_type, unsigned char outputFormat, int fileType,
                  unsigned char downMatrix, int infoOnly, int adts_out, unsigned char old_format,
                  float *song_length)
void
main(int argc, char **argv)
{
    int tagsize;
    unsigned long samplerate;
    unsigned char channels;
    void *sample_buffer;

    audio_file *aufile = NULL;

    FILE *adtsFile = NULL;
    unsigned char *adtsData;
    int adtsDataSize;

    NeAACDecHandle hDecoder;
    NeAACDecFrameInfo frameInfo;
    NeAACDecConfigurationPtr config;

    char percents[MAX_PERCENTS];
    int percent, old_percent = -1;
    int fileread;
    unsigned long bread;
    long bused;
    int header_type = 0;
    int bitrate = 0;
    float length = 0;

    int first_time = 1;
    int retval;
    int streaminput = 0;

    aac_buffer b;

    memset(&b, 0, sizeof(aac_buffer));

    if (adts_out)
    {
        adtsFile = faad_fopen(adts_fn, "wb");
        if (adtsFile == NULL)
        {
            faad_fprintf(stderr, "Error opening file: %s\n", adts_fn);
            return 1;
        }
    }

    if (0 == strcmp(aacfile, "-"))
    {
        b.infile = stdin;
#ifdef _WIN32
        _setmode(_fileno(stdin), O_BINARY);
#endif

    }
    else
    {
        b.infile = faad_fopen(aacfile, "rb");
        if (b.infile == NULL)
        {
            /* unable to open file */
            faad_fprintf(stderr, "Error opening file: %s\n", aacfile);
            return 1;
        }
    }

    retval = fseek(b.infile, 0, SEEK_END);
#ifdef _WIN32
    if (0 == strcmp(aacfile, "-")) {
        retval = -1;
    }
#endif
    if (retval )
    {
        faad_fprintf(stderr, "Input not seekable %s\n", aacfile);
        fileread = -1;
        streaminput = 1;
    } else {
        fileread = ftell(b.infile);
        fseek(b.infile, 0, SEEK_SET);
    };

    b.buffer = (unsigned char*)malloc(FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
    if (!b.buffer)
    {
        faad_fprintf(stderr, "Memory allocation error\n");
        return 0;
    }
    memset(b.buffer, 0, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);

    bread = (unsigned long)fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile);
    b.bytes_into_buffer = bread;
    b.bytes_consumed = 0;
    b.file_offset = 0;

    if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS)
        b.at_eof = 1;

    tagsize = 0;
    if (!memcmp(b.buffer, "ID3", 3))
    {
        /* high bit is not used */
        tagsize = (b.buffer[6] << 21) | (b.buffer[7] << 14) |
            (b.buffer[8] <<  7) | (b.buffer[9] <<  0);

        tagsize += 10;
        advance_buffer(&b, tagsize);
        fill_buffer(&b);
    }

    hDecoder = NeAACDecOpen();

    /* Set the default object type and samplerate */
    /* This is useful for RAW AAC files */
    config = NeAACDecGetCurrentConfiguration(hDecoder);
    if (def_srate)
        config->defSampleRate = def_srate;
    config->defObjectType = object_type;
    config->outputFormat = outputFormat;
    config->downMatrix = downMatrix;
    config->useOldADTSFormat = old_format;
    //config->dontUpSampleImplicitSBR = 1;
    NeAACDecSetConfiguration(hDecoder, config);

    /* get AAC infos for printing */
    header_type = 0;
    if (streaminput == 1)
        lookforheader(&b);

    if ((b.buffer[0] == 0xFF) && ((b.buffer[1] & 0xF6) == 0xF0))
    {
        if (streaminput == 1)
        {
            int /*frames,*/ frame_length;
            float frames_per_sec, bytes_per_frame;
            channels = 2;
            samplerate = adts_sample_rates[(b.buffer[2]&0x3c)>>2];
            frame_length = ((((unsigned int)b.buffer[3] & 0x3)) << 11)
                | (((unsigned int)b.buffer[4]) << 3) | (b.buffer[5] >> 5);
            frames_per_sec = (float)samplerate/1024.0f;
            bytes_per_frame = (float)frame_length/(float)(1000);
            bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
            length = 1;
            faad_fprintf(stderr, "Streamed input format  samplerate %d channels %d.\n", samplerate, channels);
        } else {
            adts_parse(&b, &bitrate, &length);
            fseek(b.infile, tagsize, SEEK_SET);

            bread = (unsigned long)fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile);
            if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS)
                b.at_eof = 1;
            else
                b.at_eof = 0;
            b.bytes_into_buffer = bread;
            b.bytes_consumed = 0;
            b.file_offset = tagsize;
        }

        header_type = 1;
    }
    else if (memcmp(b.buffer, "ADIF", 4) == 0)
    {
        int skip_size = (b.buffer[4] & 0x80) ? 9 : 0;
        bitrate = ((unsigned int)(b.buffer[4 + skip_size] & 0x0F)<<19) |
            ((unsigned int)b.buffer[5 + skip_size]<<11) |
            ((unsigned int)b.buffer[6 + skip_size]<<3) |
            ((unsigned int)b.buffer[7 + skip_size] & 0xE0);

        length = (float)fileread;
        if (length != 0)
        {
            length = ((float)length*8.f)/((float)bitrate) + 0.5f;
        }

        bitrate = (int)((float)bitrate/1000.0f + 0.5f);

        header_type = 2;
    }

    *song_length = length;

    fill_buffer(&b);
    bused = NeAACDecInit(hDecoder, b.buffer, b.bytes_into_buffer, &samplerate, &channels);
    if (bused < 0)
    {
        /* If some error initializing occured, skip the file */
        faad_fprintf(stderr, "Error initializing decoder library.\n");
        if (b.buffer)
            free(b.buffer);
        NeAACDecClose(hDecoder);
        if (b.infile != stdin)
            fclose(b.infile);
        return 1;
    }
    advance_buffer(&b, bused);
    fill_buffer(&b);

    /* print AAC file info */
    faad_fprintf(stderr, "%s file info:\n", aacfile);
    switch (header_type)
    {
    case 0:
        faad_fprintf(stderr, "RAW\n\n");
        break;
    case 1:
        faad_fprintf(stderr, "ADTS, %.3f sec, %d kbps, %d Hz\n\n",
            length, bitrate, samplerate);
        break;
    case 2:
        faad_fprintf(stderr, "ADIF, %.3f sec, %d kbps, %d Hz\n\n",
            length, bitrate, samplerate);
        break;
    }

    // Override the logic of skipping 0-th output frame.
    NeAACDecPostSeekReset(hDecoder, 1);

    if (infoOnly)
    {
        NeAACDecClose(hDecoder);
        if (b.infile != stdin)
            fclose(b.infile);
        if (b.buffer)
            free(b.buffer);
        return 0;
    }
	int n;

    do
    {
        sample_buffer = NeAACDecDecode(hDecoder, &frameInfo,
            b.buffer, b.bytes_into_buffer);
	ARGBEGIN{
	case 's': /* FIXME seeking isn't implemented yet */
		break;
	default:
		usage();
	}ARGEND

        if (adts_out == 1)
        {
            int skip = (old_format) ? 8 : 7;
            adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo, old_format);
	if(argc != 0)
		usage();

            /* write the adts header */
            fwrite(adtsData, 1, adtsDataSize, adtsFile);
	Binit(&stdin, 0, OREAD);
	Binit(&stdout, 1, OWRITE);

            /* write the frame data */
            if (frameInfo.header_type == ADTS)
                fwrite(b.buffer + skip, 1, frameInfo.bytesconsumed - skip, adtsFile);
            else
                fwrite(b.buffer, 1, frameInfo.bytesconsumed, adtsFile);
        }
	n = decode();
	Bterm(&stdout);
	waitpid();

        /* update buffer indices */
        advance_buffer(&b, frameInfo.bytesconsumed);

        /* check if the inconsistent number of channels */
        if (aufile != NULL && frameInfo.channels != aufile->channels)
            frameInfo.error = 12;

        if (frameInfo.error > 0)
        {
            faad_fprintf(stderr, "Error: %s\n",
                NeAACDecGetErrorMessage(frameInfo.error));
        }

        /* open the sound file now that the number of channels are known */
        if (first_time && !frameInfo.error)
        {
            /* print some channel info */
            print_channel_info(&frameInfo);

            if (!adts_out)
            {
                /* open output file */
                if (!to_stdout)
                {
                    aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
                        (int)outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
                } else {
                    aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
                        (int)outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
                }
                if (aufile == NULL)
                {
                    if (b.buffer)
                        free(b.buffer);
                    NeAACDecClose(hDecoder);
                    if (b.infile != stdin)
                        fclose(b.infile);
                    return 0;
                }
            } else {
                faad_fprintf(stderr, "Writing output MPEG-4 AAC ADTS file.\n\n");
            }
            first_time = 0;
        }

        percent = min((int)(b.file_offset*100)/fileread, 100);
        if (percent > old_percent)
        {
            old_percent = percent;
            snprintf(percents, MAX_PERCENTS, "%d%% decoding %s.", percent, aacfile);
            faad_fprintf(stderr, "%s\r", percents);
#ifdef _WIN32
            SetConsoleTitle(percents);
#endif
        }

        if ((frameInfo.error == 0) && (frameInfo.samples > 0) && (!adts_out))
        {
            if (write_audio_file(aufile, sample_buffer, frameInfo.samples) == 0)
                break;
        }

        /* fill buffer */
        fill_buffer(&b);

        if (b.bytes_into_buffer == 0)
            sample_buffer = NULL; /* to make sure it stops now */

    } while (sample_buffer != NULL);

    NeAACDecClose(hDecoder);

    if (adts_out == 1)
    {
        fclose(adtsFile);
    }

    if (b.infile != stdin)
        fclose(b.infile);

    if (!first_time && !adts_out)
        close_audio_file(aufile);

    if (b.buffer)
        free(b.buffer);

    return frameInfo.error;
}

static int decodeMP4file(char *mp4file, char *sndfile, char *adts_fn, int to_stdout,
                  unsigned char outputFormat, int fileType, unsigned char downMatrix, int noGapless,
                  int infoOnly, int adts_out, float *song_length, float seek_to)
{
    /*int track;*/
    unsigned long samplerate;
    unsigned char channels;
    void *sample_buffer;

    uint32_t sampleId, startSampleId;

    audio_file *aufile = NULL;

    FILE *adtsFile = NULL;
    unsigned char *adtsData;
    int adtsDataSize;

    NeAACDecHandle hDecoder;
    NeAACDecConfigurationPtr config;
    NeAACDecFrameInfo frameInfo = {0};  // should no-frames situation be flagged as an error?
    mp4AudioSpecificConfig mp4ASC = {0};

    char percents[MAX_PERCENTS];
    int percent, old_percent = -1;

    int first_time = 1;

    /* for gapless decoding */
    unsigned int useAacLength = 1;
    unsigned int framesize;
    unsigned decoded;

    if (strcmp(mp4file, "-") == 0 ) {
        faad_fprintf(stderr, "Cannot open stdin for MP4 input \n");
        return 1;
    }

    if (!quiet)
    {
        mp4config.verbose.header = 1;
        mp4config.verbose.tags = 1;
    }
    if (mp4read_open(mp4file))
    {
        /* unable to open file */
        faad_fprintf(stderr, "Error opening file: %s\n", mp4file);
        return 1;
    }

    hDecoder = NeAACDecOpen();

    /* Set configuration */
    config = NeAACDecGetCurrentConfiguration(hDecoder);
    config->outputFormat = outputFormat;
    config->downMatrix = downMatrix;
    //config->dontUpSampleImplicitSBR = 1;
    NeAACDecSetConfiguration(hDecoder, config);

    if (adts_out)
    {
        adtsFile = faad_fopen(adts_fn, "wb");
        if (adtsFile == NULL)
        {
            faad_fprintf(stderr, "Error opening file: %s\n", adts_fn);
            return 1;
        }
    }

    if(NeAACDecInit2(hDecoder, mp4config.asc.buf, mp4config.asc.size,
                    &samplerate, &channels) < 0)
    {
        /* If some error initializing occured, skip the file */
        faad_fprintf(stderr, "Error initializing decoder library.\n");
        NeAACDecClose(hDecoder);
        mp4read_close();
        return 1;
    }

    framesize = 1024;
    useAacLength = 0;
    decoded = 0;

    if (mp4config.asc.size)
    {
        if (NeAACDecAudioSpecificConfig(mp4config.asc.buf, mp4config.asc.size, &mp4ASC) >= 0)
        {
            if (mp4ASC.frameLengthFlag == 1) framesize = 960;
            if (mp4ASC.sbr_present_flag == 1 || mp4ASC.forceUpSampling) framesize *= 2;
        }
    }

    /* print some mp4 file info */
    faad_fprintf(stderr, "%s file info:\n\n", mp4file);
    {
        /*int k, j;*/
        char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
        float seconds;
        seconds = (float)mp4config.samples/(float)mp4ASC.samplingFrequency;

        *song_length = seconds;

        faad_fprintf(stderr, "%s\t%.3f secs, %d ch, %d Hz\n\n", ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
            seconds, mp4ASC.channelsConfiguration, mp4ASC.samplingFrequency);
    }

    if (infoOnly)
    {
        NeAACDecClose(hDecoder);
        mp4read_close();
        return 0;
    }

    startSampleId = 0;
    if (seek_to > 0.1) {
        int64_t sample = (int64_t)(seek_to * mp4config.samplerate / framesize);
        uint32_t limit = ~0u;
        startSampleId = sample < limit ? (uint32_t)sample : limit;
    }

    mp4read_seek(startSampleId);
    for (sampleId = startSampleId; sampleId < mp4config.frame.nsamples; sampleId++)
    {
        /*int rc;*/
        unsigned long dur;
        unsigned int sample_count;

        if (mp4read_frame())
            break;

        sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, mp4config.bitbuf.data, mp4config.bitbuf.size);

        if (!sample_buffer) {
            /* unable to decode file, abort */
            break;
        }

        if (adts_out == 1)
        {
            adtsData = MakeAdtsHeader(&adtsDataSize, &frameInfo, 0);

            /* write the adts header */
            fwrite(adtsData, 1, adtsDataSize, adtsFile);

            fwrite(mp4config.bitbuf.data, 1, frameInfo.bytesconsumed, adtsFile);
        }

        dur = frameInfo.samples / frameInfo.channels;
        decoded += dur;

        if (decoded > mp4config.samples)
            dur += mp4config.samples - decoded;

        if (dur > framesize)
        {
            faad_fprintf(stderr, "Warning: excess frame detected in MP4 file.\n");
            dur = framesize;
        }

        if (!noGapless)
        {
            if (useAacLength || (mp4config.samplerate != samplerate)) {
                sample_count = frameInfo.samples;
            } else {
                sample_count = (unsigned int)(dur * frameInfo.channels);
                if (sample_count > frameInfo.samples)
                    sample_count = frameInfo.samples;
            }
        } else {
            sample_count = frameInfo.samples;
        }

        /* open the sound file now that the number of channels are known */
        if (first_time && !frameInfo.error)
        {
            /* print some channel info */
            print_channel_info(&frameInfo);

            if (!adts_out)
            {
                /* open output file */
                if(!to_stdout)
                {
                    aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
                        (int)outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
                } else {
#ifdef _WIN32
                    _setmode(_fileno(stdout), O_BINARY);
#endif
                    aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
                        (int)outputFormat, fileType, aacChannelConfig2wavexChannelMask(&frameInfo));
                }
                if (aufile == NULL)
                {
                    NeAACDecClose(hDecoder);
                    mp4read_close();
                    return 0;
                }
            }
            first_time = 0;
        }

        percent = min((int)(sampleId*100)/mp4config.frame.nsamples, 100);
        if (percent > old_percent)
        {
            old_percent = percent;
            snprintf(percents, MAX_PERCENTS, "%d%% decoding %s.", percent, mp4file);
            faad_fprintf(stderr, "%s\r", percents);
#ifdef _WIN32
            SetConsoleTitle(percents);
#endif
        }

        if ((frameInfo.error == 0) && (sample_count > 0) && (!adts_out))
        {
            if (write_audio_file(aufile, sample_buffer, sample_count) == 0)
                break;
        }

        if (frameInfo.error > 0)
        {
            faad_fprintf(stderr, "Warning: %s\n",
                NeAACDecGetErrorMessage(frameInfo.error));
        }
    }

    NeAACDecClose(hDecoder);

    if (adts_out == 1)
    {
        fclose(adtsFile);
    }

    mp4read_close();

    if (!first_time && !adts_out)
        close_audio_file(aufile);

    return frameInfo.error;
}

static int faad_main(int argc, char *argv[])
{
    int result;
    int infoOnly = 0;
    int writeToStdio = 0;
    int readFromStdin = 0;
    unsigned char object_type = LC;
    int def_srate = 0;
    unsigned char downMatrix = 0;
    int format = 1;
    unsigned char outputFormat = FAAD_FMT_16BIT;
    int outfile_set = 0;
    int adts_out = 0;
    unsigned char old_format = 0;
    int showHelp = 0;
    int mp4file = 0;
    int noGapless = 0;
    char *fnp;
    char *aacFileName = NULL;
    char *audioFileName = NULL;
    char *adtsFileName = NULL;
    float seekTo = 0;
    unsigned char header[8];
    size_t bread;
    float length = 0;
    FILE *hMP4File;
    char *faad_id_string;
    char *faad_copyright_string;

/* System dependant types */
#ifdef _WIN32
    long begin;
#else
    clock_t begin;
#endif

    unsigned long cap = NeAACDecGetCapabilities();


    /* begin process command line */
    progName = argv[0];
    while (1) {
        int c = -1;
        int option_index = 0;
        static struct option long_options[] = {
            { "quiet",      0, 0, 'q' },
            { "outfile",    0, 0, 'o' },
            { "adtsout",    0, 0, 'a' },
            { "oldformat",  0, 0, 't' },
            { "format",     0, 0, 'f' },
            { "bits",       0, 0, 'b' },
            { "samplerate", 0, 0, 's' },
            { "objecttype", 0, 0, 'l' },
            { "downmix",    0, 0, 'd' },
            { "info",       0, 0, 'i' },
            { "stdio",      0, 0, 'w' },
            { "stdio",      0, 0, 'g' },
            { "seek",       1, 0, 'j' },
            { "help",       0, 0, 'h' },
            { 0, 0, 0, 0 }
        };

        c = getopt_long(argc, argv, "o:a:s:f:b:l:j:wgdhitq",
            long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {
        case 'o':
            if (optarg)
            {
                outfile_set = 1;
                audioFileName = (char *) malloc(sizeof(char) * (strlen(optarg) + 1));
                if (audioFileName == NULL)
                {
                    faad_fprintf(stderr, "Error allocating memory for audioFileName.\n");
                    return 1;
                }
                strcpy(audioFileName, optarg);
            }
            break;
        case 'a':
            if (optarg)
            {
                adts_out = 1;
                adtsFileName = (char *) malloc(sizeof(char) * (strlen(optarg) + 1));
                if (adtsFileName == NULL)
                {
                    faad_fprintf(stderr, "Error allocating memory for adtsFileName.\n");
                    return 1;
                }
                strcpy(adtsFileName, optarg);
            }
            break;
        case 's':
            if (optarg)
            {
                char dr[10];
                if (sscanf(optarg, "%s", dr) < 1) {
                    def_srate = 0;
                } else {
                    def_srate = atoi(dr);
                }
            }
            break;
        case 'f':
            if (optarg)
            {
                char dr[10];
                if (sscanf(optarg, "%s", dr) < 1)
                {
                    format = 1;
                } else {
                    format = atoi(dr);
                    if ((format < 1) || (format > 2))
                        showHelp = 1;
                }
            }
            break;
        case 'b':
            if (optarg)
            {
                char dr[10];
                if (sscanf(optarg, "%s", dr) < 1)
                {
                    outputFormat = FAAD_FMT_16BIT; /* just use default */
                } else {
                    int val = atoi(dr);
                    if ((val < 1) || (val > 5))
                        showHelp = 1;
                    if (val == 5)  // Not yet unsupported by "audio".
                        showHelp = 1;
                    outputFormat = (unsigned char)val;
                }
            }
            break;
        case 'l':
            if (optarg)
            {
                char dr[10];
                if (sscanf(optarg, "%s", dr) < 1)
                {
                    object_type = LC; /* default */
                } else {
                    int val = atoi(dr);
                    if ((val != LC) &&
                        (val != MAIN) &&
                        (val != LTP) &&
                        (val != LD))
                    {
                        showHelp = 1;
                    }
                    object_type = (unsigned char)val;
                }
            }
            break;
        case 'j':
            if (optarg)
            {
                seekTo = (float)atof(optarg);
            }
            break;
        case 't':
            old_format = 1;
            break;
        case 'd':
            downMatrix = 1;
            break;
        case 'w':
            writeToStdio = 1;
            break;
        case 'g':
            noGapless = 1;
            break;
        case 'i':
            infoOnly = 1;
            break;
        case 'h':
            showHelp = 1;
            break;
        case 'q':
            quiet = 1;
            break;
        default:
            break;
        }
    }

    NeAACDecGetVersion(&faad_id_string, &faad_copyright_string);

    faad_fprintf(stderr, " *********** Ahead Software MPEG-4 AAC Decoder V%s ******************\n\n", faad_id_string);
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
    faad_fprintf(stderr, " Build: %s\n", BUILD_DATE);
#undef BUILD_DATE
    faad_fprintf(stderr, "%s", faad_copyright_string);
    if (cap & FIXED_POINT_CAP)
        faad_fprintf(stderr, " Fixed point version\n");
    else
        faad_fprintf(stderr, " Floating point version\n");
    faad_fprintf(stderr, "\n");
    faad_fprintf(stderr, " This program is free software; you can redistribute it and/or modify\n");
    faad_fprintf(stderr, " it under the terms of the GNU General Public License.\n");
    faad_fprintf(stderr, "\n");
    faad_fprintf(stderr, " **************************************************************************\n\n");


    /* check that we have at least two non-option arguments */
    /* Print help if requested */
    if (((argc - optind) < 1) || showHelp)
    {
        usage();
        return 1;
    }

#if 0
    /* only allow raw data on stdio */
    if (writeToStdio == 1)
    {
        format = 2;
    }
#endif

    /* point to the specified file name */
    aacFileName = (char *) malloc(sizeof(char) * (strlen(argv[optind]) + 1));
    if (aacFileName == NULL)
    {
        faad_fprintf(stderr, "Error allocating memory for aacFileName.\n");
        return 1;
    }
    strcpy(aacFileName, argv[optind]);

#ifdef _WIN32
    begin = GetTickCount();
#else
    begin = clock();
#endif

    /* Only calculate the path and open the file for writing if
       we are not writing to stdout.
     */
    if(!writeToStdio && !outfile_set)
    {
        audioFileName = (char *) malloc(sizeof(char) * (strlen(aacFileName) + strlen(file_ext[format]) + 1));
        if (audioFileName == NULL)
        {
            faad_fprintf(stderr, "Error allocating memory for audioFileName.\n");
            return 1;
        }
        strcpy(audioFileName, aacFileName);

        fnp = (char *)strrchr(audioFileName,'.');

        if (fnp)
            fnp[0] = '\0';

        strcat(audioFileName, file_ext[format]);
    }

    /* check for mp4 file */
    if (0 == strcmp(aacFileName, "-")) {
        faad_fprintf(stderr, "Reading from stdin: %s\n", aacFileName);
        readFromStdin = 1;
        hMP4File  = stdin;
#ifdef _WIN32
        _setmode(_fileno(stdin), O_BINARY);
#endif

    } else {

        mp4file = 0;
        hMP4File = faad_fopen(aacFileName, "rb");
        if (!hMP4File)
        {
            faad_fprintf(stderr, "Error opening file: %s\n", aacFileName);
            return 1;
        }
    }

    bread = fread(header, 1, 8, hMP4File);

    if (! readFromStdin )
      fclose(hMP4File);

    if (bread != 8) {
        faad_fprintf(stderr, "Error reading file.\n");
        return 1;
    }

    if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
        mp4file = 1;

    if (!mp4file && seekTo != 0) {
        faad_fprintf(stderr, "Warning: can only seek in MP4 files\n");
    }

    if (mp4file)
    {
        result = decodeMP4file(aacFileName, audioFileName, adtsFileName, writeToStdio,
            outputFormat, format, downMatrix, noGapless, infoOnly, adts_out, &length, seekTo);
    } else {

    if (readFromStdin == 1) {
        ungetc(header[7],hMP4File);
        ungetc(header[6],hMP4File);
        ungetc(header[5],hMP4File);
        ungetc(header[4],hMP4File);
        ungetc(header[3],hMP4File);
        ungetc(header[2],hMP4File);
        ungetc(header[1],hMP4File);
        ungetc(header[0],hMP4File);
    }

        result = decodeAACfile(aacFileName, audioFileName, adtsFileName, writeToStdio,
            def_srate, object_type, outputFormat, format, downMatrix, infoOnly, adts_out,
            old_format, &length);
    }

    if (audioFileName != NULL)
      free (audioFileName);
    if (adtsFileName != NULL)
      free (adtsFileName);

    if (!result && !infoOnly)
    {
#ifdef _WIN32
        float dec_length = (float)(GetTickCount()-begin)/1000.0f;
        SetConsoleTitle("FAAD");
#else
        /* clock() grabs time since the start of the app but when we decode
           multiple files, each file has its own starttime (begin).
         */
        float dec_length = (float)(clock() - begin)/(float)CLOCKS_PER_SEC;
#endif
        faad_fprintf(stderr, "Decoding %s took: %5.2f sec. %5.2fx real-time.\n", aacFileName,
            dec_length, (dec_length > 0.01) ? (length/dec_length) : 0.);
    }

    free (aacFileName);
    return 0;
}

int main(int argc, char *argv[])
{
#if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
    int argc_utf8, exit_code;
    char **argv_utf8;
    (void)argc;
    (void)argv;
    init_console_utf8(stderr);
    init_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
    exit_code = faad_main(argc_utf8, argv_utf8);
    free_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
    uninit_console_utf8();
    return exit_code;
#else
    return faad_main(argc, argv);
#endif
	exits(n == 0 ? nil : "failed");
}

M frontend/audio.h => frontend/audio.h +3 -0
@@ 55,6 55,9 @@ typedef struct

audio_file *open_audio_file(char *infile, int samplerate, int channels,
                            int outputFormat, int fileType, long channelMask);
#ifdef __plan9__
typedef ulong size_t;
#endif
size_t write_audio_file(audio_file *aufile, void *sample_buffer, int samples);
void close_audio_file(audio_file *aufile);


M frontend/mkfile => frontend/mkfile +3 -3
@@ 7,9 7,9 @@ TARG=\
CFLAGS=$CFLAGS -I../include -p -D__plan9__
BIN=/$objtype/bin/audio

$O.m4adec: m4adec.rc
	cp m4adec.rc $O.m4adec

default:V: all

</sys/src/cmd/mkmany

m4adec.install:V: m4adec.rc
	cp m4adec.rc $BIN/m4adec

M libfaad/common.h => libfaad/common.h +1 -1
@@ 101,7 101,7 @@ extern "C" {
/* Allow decoding of MAIN profile AAC */
#define MAIN_DEC
/* Allow decoding of SSR profile AAC */
#define SSR_DEC
//#define SSR_DEC
/* Allow decoding of LTP profile AAC */
#define LTP_DEC
/* Allow decoding of LD profile AAC */

M libfaad/drc.c => libfaad/drc.c +2 -0
@@ 31,7 31,9 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#endif
#include "syntax.h"
#include "drc.h"


M libfaad/filtbank.c => libfaad/filtbank.c +2 -0
@@ 31,12 31,14 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#ifdef _WIN32_WCE
#define assert(x)
#else
#include <assert.h>
#endif
#endif

#include "filtbank.h"
#include "syntax.h"

M libfaad/hcr.c => libfaad/hcr.c +2 -0
@@ 31,7 31,9 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#endif

#include "specrec.h"
#include "huffman.h"

M libfaad/mdct.c => libfaad/mdct.c +2 -0
@@ 47,12 47,14 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#ifdef _WIN32_WCE
#define assert(x)
#else
#include <assert.h>
#endif
#endif

#include "cfft.h"
#include "mdct.h"

M libfaad/mkfile => libfaad/mkfile +1 -1
@@ 1,7 1,7 @@
</$objtype/mkfile

LIB=libfaad.$objtype.a
CFLAGS=$CFLAGS -I../include -DPACKAGE_VERSION="2.9.2" -p -D__plan9__
CFLAGS=$CFLAGS -I../include -DPACKAGE_VERSION="2.10.1" -p -D__plan9__

OFILES=\
	bits.$O\

M libfaad/sbr_dec.c => libfaad/sbr_dec.c +2 -0
@@ 34,7 34,9 @@

#ifdef SBR_DEC

#ifndef __plan9__
#include <stdlib.h>
#endif

#include "syntax.h"
#include "bits.h"

M libfaad/sbr_hfadj.c => libfaad/sbr_hfadj.c +2 -0
@@ 29,7 29,9 @@
**/

/* High Frequency adjustment */
#ifndef __plan9__
#include <float.h>
#endif

#include "common.h"
#include "structs.h"

M libfaad/sbr_qmf.c => libfaad/sbr_qmf.c +2 -0
@@ 34,7 34,9 @@
#ifdef SBR_DEC


#ifndef __plan9__
#include <stdlib.h>
#endif
#include "sbr_dct.h"
#include "sbr_qmf.h"
#include "sbr_qmf_c.h"

M libfaad/specrec.c => libfaad/specrec.c +2 -0
@@ 38,7 38,9 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#endif
#include "specrec.h"
#include "filtbank.h"
#include "syntax.h"

M libfaad/ssr_fb.c => libfaad/ssr_fb.c +2 -0
@@ 33,7 33,9 @@

#ifdef SSR_DEC

#ifndef __plan9__
#include <stdlib.h>
#endif
#include "syntax.h"
#include "filtbank.h"
#include "mdct.h"

M libfaad/syntax.c => libfaad/syntax.c +2 -0
@@ 35,8 35,10 @@
#include "common.h"
#include "structs.h"

#ifndef __plan9__
#include <stdlib.h>
#include <stdio.h>
#endif

#include "syntax.h"
#include "specrec.h"