📄 main.c
字号:
/*** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**** Any non-GPL usage of this software or parts of this software is strictly** forbidden.**** Commercial non-GPL licensing of this software is possible.** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.**** $Id: main.c,v 1.76 2004/03/27 11:14:49 menno Exp $**/#ifdef _WIN32#define WIN32_LEAN_AND_MEAN#include <windows.h>#define off_t __int64#else#include <time.h>#endif#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <neaacdec.h>#include <mp4ff.h>#include "audio.h"#ifndef min#define min(a,b) ( (a) < (b) ? (a) : (b) )#endif#define MAX_CHANNELS 6 /* make this higher to support files with more channels *//* FAAD file buffering routines */typedef struct { long bytes_into_buffer; long bytes_consumed; long file_offset; unsigned char *buffer; int at_eof; FILE *infile;} aac_buffer;int fill_buffer(aac_buffer *b){ int 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 = 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;}void advance_buffer(aac_buffer *b, int bytes){ b->file_offset += bytes; b->bytes_consumed = bytes; b->bytes_into_buffer -= bytes;}static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0};int adts_parse(aac_buffer *b, int *bitrate, float *length){ int frames, frame_length; int t_framelength = 0; int samplerate; 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); 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;}uint32_t read_callback(void *user_data, void *buffer, uint32_t length){ return fread(buffer, 1, length, (FILE*)user_data);}uint32_t seek_callback(void *user_data, uint64_t position){ return fseek((FILE*)user_data, position, SEEK_SET);}/* 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 0x80000000long 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; }}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 "";}void print_channel_info(NeAACDecFrameInfo *frameInfo){ /* print some channel info */ int i; long channelMask = aacChannelConfig2wavexChannelMask(frameInfo); fprintf(stderr, " ---------------------\n"); if (frameInfo->num_lfe_channels > 0) { fprintf(stderr, " | Config: %2d.%d Ch |", frameInfo->channels-frameInfo->num_lfe_channels, frameInfo->num_lfe_channels); } else { fprintf(stderr, " | Config: %2d Ch |", frameInfo->channels); } if (channelMask) fprintf(stderr, " WARNING: channels are reordered according to\n"); else fprintf(stderr, "\n"); fprintf(stderr, " ---------------------"); if (channelMask) fprintf(stderr, " MS defaults defined in WAVE_FORMAT_EXTENSIBLE\n"); else fprintf(stderr, "\n"); fprintf(stderr, " | Ch | Position |\n"); fprintf(stderr, " ---------------------\n"); for (i = 0; i < frameInfo->channels; i++) { fprintf(stderr, " | %.2d | %-14s |\n", i, position2string((int)frameInfo->channel_position[i])); } fprintf(stderr, " ---------------------\n"); fprintf(stderr, "\n");}int FindAdtsSRIndex(int sr){ int i; for (i = 0; i < 16; i++) { if (sr == adts_sample_rates[i]) return i; } return 16 - 1;}unsigned char *MakeAdtsHeader(int *dataSize, NeAACDecFrameInfo *hInfo, int 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;}/* globals */char *progName;char *file_ext[] ={ NULL, ".wav", ".aif", ".au", ".au", ".pcm", NULL};void usage(void){ fprintf(stdout, "\nUsage:\n"); fprintf(stdout, "%s [options] infile.aac\n", progName); fprintf(stdout, "Options:\n"); fprintf(stdout, " -h Shows this help screen.\n"); fprintf(stdout, " -i Shows info about the input file.\n"); fprintf(stdout, " -a X Write MPEG-4 AAC ADTS output file.\n"); fprintf(stdout, " -t Assume old ADTS format.\n"); fprintf(stdout, " -o X Set output filename.\n"); fprintf(stdout, " -f X Set output format. Valid values for X are:\n"); fprintf(stdout, " 1: Microsoft WAV format (default).\n"); fprintf(stdout, " 2: RAW PCM data.\n"); fprintf(stdout, " -b X Set output sample format. Valid values for X are:\n"); fprintf(stdout, " 1: 16 bit PCM data (default).\n"); fprintf(stdout, " 2: 24 bit PCM data.\n"); fprintf(stdout, " 3: 32 bit PCM data.\n"); fprintf(stdout, " 4: 32 bit floating point data.\n"); fprintf(stdout, " 5: 64 bit floating point data.\n"); fprintf(stdout, " -s X Force the samplerate to X (for RAW files).\n"); fprintf(stdout, " -l X Set object type. Supported object types:\n"); fprintf(stdout, " 1: Main object type.\n"); fprintf(stdout, " 2: LC (Low Complexity) object type.\n"); fprintf(stdout, " 4: LTP (Long Term Prediction) object type.\n"); fprintf(stdout, " 23: LD (Low Delay) object type.\n"); fprintf(stdout, " -d Down matrix 5.1 to 2 channels\n"); fprintf(stdout, " -w Write output to stdio instead of a file.\n"); fprintf(stdout, " -g Disable gapless decoding.\n"); fprintf(stdout, "Example:\n"); fprintf(stdout, " %s infile.aac\n", progName); fprintf(stdout, " %s infile.mp4\n", progName); fprintf(stdout, " %s -o outfile.wav infile.aac\n", progName); fprintf(stdout, " %s -w infile.aac > outfile.wav\n", progName); fprintf(stdout, " %s -a outfile.aac infile.aac\n", progName); return;}int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout, int def_srate, int object_type, int outputFormat, int fileType, int downMatrix, int infoOnly, int adts_out, int old_format, float *song_length){ int tagsize; unsigned long samplerate; unsigned char channels; void *sample_buffer; audio_file *aufile; FILE *adtsFile; unsigned char *adtsData; int adtsDataSize; NeAACDecHandle hDecoder; NeAACDecFrameInfo frameInfo; NeAACDecConfigurationPtr config; char percents[200]; int percent, old_percent = -1; int bread, fileread; int header_type = 0; int bitrate = 0; float length = 0; int first_time = 1; aac_buffer b; memset(&b, 0, sizeof(aac_buffer)); if (adts_out) { adtsFile = fopen(adts_fn, "wb"); if (adtsFile == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -