📄 mp3onlydec.c
字号:
/****************************************************************************//* * mpegdec.c -- MPEG 3 only Audio decoder ... * * Author : St閜hane TAVENARD * * (C) Copyright 1997-1998 St閜hane TAVENARD * All Rights Reserved * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *//****************************************************************************/#include "defs.h"#include "mpegaud.h"#include "mpeg3dec.h"#include "mpegdec.h"#include "mpegtab.h"#ifdef USE_RC4#include "rc4.h"#endif/****************************************************************************//* * Now default buffer size */#define MPEGDEC_BITSTREAM_BUFFER_SIZE 16384/****************************************************************************//* * Decode the current Header * Return 0 if Ok */static int MPEGDEC_decode_header(MPA_STREAM *mps){ MPA_HEADER *mph = &mps->header; INT16 bitrate_per_channel; INT16 table; mps->bitrate = MPT_bitrate[mph->ID][mph->layer-1][mph->bitrate_index]; if (mph->mode == MPA_MODE_MONO) { mps->stereo = FALSE; mps->channels = 1; bitrate_per_channel = mps->bitrate; } else { mps->stereo = TRUE; mps->channels = 2; bitrate_per_channel = mps->bitrate>>1; } mps->sfreq = MPT_freq[mph->ID][mph->sampling_frequency]; if (!mps->sfreq) return(MPEGDEC_ERR_BADFRAME); if (mph->half_freq) mps->sfreq >>= 1; // #2 if (mph->layer == 2) { if (mph->ID == MPA_ID_1) { if (((mph->sampling_frequency == MPA_SAMP_48000) && (bitrate_per_channel >= 56)) || ((bitrate_per_channel >= 56) && (bitrate_per_channel <= 80))) table = 0; else if ((mph->sampling_frequency != MPA_SAMP_48000) && (bitrate_per_channel >= 96)) table = 1; else if ((mph->sampling_frequency != MPA_SAMP_32000) && (bitrate_per_channel <= 48)) table = 2; else table = 3; } else { table = 4; } mps->sblimit = MPT_sblimit[ table ]; if (table != mps->current_table) { switch( table ) { case 0: mps->alloc = MPT_alloc_0; break; case 1: mps->alloc = MPT_alloc_1; break; case 2: mps->alloc = MPT_alloc_2; break; case 3: mps->alloc = MPT_alloc_3; break; default: mps->alloc = MPT_alloc_4; break; } mps->current_table = table; /* * *** WARNING *** * Reset when sblimit changed (because some MPEG * layer I inside layer II) reset fraction's */ memset(mps->fraction, 0, MPA_MAX_CHANNELS * MPA_GROUPS * MPA_SBLIMIT * sizeof(MPEGAUD_FRACT_TYPE)); } } else { mps->sblimit = MPA_SBLIMIT; } if (mph->mode == MPA_MODE_JOINT_STEREO) mps->jsbound = MPT_jsbound[mph->layer-1][mph->mode_extension]; else mps->jsbound = mps->sblimit; return(MPEGDEC_ERR_NONE);}/****************************************************************************//* * Read the next MPEG AUDIO Header * check: check if it's an mpeg audio stream, ie begin with a sync word * Return MPEGDEC_ERR_EOF if end of stream reached. */static int MPEGDEC_read_header(MPA_STREAM *mps, BOOL check){ UINT32 value; UINT32 header; BITSTREAM *bs; MPA_HEADER *mph; UINT8 old_first;/* * We check: Sync is either 0xFFF or 0xFFE (MPEG 2.5) * Layer is not 4 (coded value is 0x0) * Bitrate index is not 0xF (forbidden) * Bitrate index is not 0x0 (free not supported) * Frequency index is not 0x3 (reserved) */#define SYNC_VALID( v ) (((v & 0xFFE00000) == 0xFFE00000) && \ ((v & 0x00060000) != 0x00000000) && \ ((v & 0xF000) != 0xF000) && \ ((v & 0xF000) != 0x0000) && \ ((v & 0x0C00) != 0xC000)) bs = mps->bitstream; if (BSTR_end(bs)) return(MPEGDEC_ERR_EOF); mph = &mps->header; /* * Header is: <Sync:12><ID:1><Lay:2><Prot:1> * <Rate:4><Freq:2><Pad:1><Priv:1> * <Mode:2><Ext:2><Copy:1><Orig:1><Emph:2> * Total: 32 bits * with <Sync> = 0xFFF for MPEG 1,2 <Sync> = 0xFFE for MPEG 2.5 * <Rate> can't be 0xF, so use it to skip leading 0xFF */ // Seek to sync word old_first = bs->bits; // This could be the last byte read (not always !) // Read first 24 bits value = BSTR_read_byte(bs); value <<= 8; value |= BSTR_read_byte(bs); value <<= 8; value |= BSTR_read_byte(bs); // Check if first sync is valid value <<= 8; if (SYNC_VALID(value)) { // Ok, first sync is valid value |= BSTR_read_byte(bs); } else { // first sync not valid -> try to use previous byte (tolerance!) int loops = 16384; if (check) return(MPEGDEC_ERR_BADFRAME); // Not an MPEG Stream ! value >>= 8; value |= old_first << 24; // use previous byte while (!SYNC_VALID(value)) { value <<= 8; value |= BSTR_read_byte(bs); if (BSTR_end(bs)) return(MPEGDEC_ERR_EOF); if (loops-- <=0) return(MPEGDEC_ERR_BADFRAME); } } mph->header_pos = BSTR_pos(bs) - 4; // (header is 4 bytes long) mph->half_freq = (value & 0x00100000) ? FALSE : TRUE; header = value; mph->emphasis = header & 0x0003; header >>= 2; mph->original = header & 0x0001; header >>= 1; mph->copyright = header & 0x0001; header >>= 1; mph->mode_extension = header & 0x0003; header >>= 2; mph->mode = header & 0x0003; header >>= 2; mph->private_bit = header & 0x0001; header >>= 1; mph->padding_bit = header & 0x0001; header >>= 1; mph->sampling_frequency = header & 0x0003; header >>= 2; mph->bitrate_index = header & 0x000F; header >>= 4; mph->protection_bit = (header & 0x0001) ? FALSE : TRUE; header >>= 1; mph->layer = 4 - (header & 0x0003); header >>= 2; mph->ID = header & 0x0001; // Check for correct values if (mph->bitrate_index == 0xF) return(MPEGDEC_ERR_BADFRAME); // Already checked in sync search if (mph->sampling_frequency == 0x3) return(MPEGDEC_ERR_BADFRAME); if (mph->layer == 4) return(MPEGDEC_ERR_BADFRAME); if (mph->protection_bit) mph->crc_check = BSTR_read_bits(bs, 16); return(MPEGDEC_decode_header(mps));}/****************************************************************************//* * Find an mpeg synchronization pattern in a buffer * This function can be use to check if a file contains MPEG audio stream * Inputs: buffer = stream buffer to analyze * buffer_size = need to know top of buffer (must be >= 4) * Return the the sync position (>=0) or MPEGDEC_ERR_NO_SYNC if not found*/INT32 MPEGDEC_find_sync(INT8 *buffer, INT32 buffer_size){ INT32 index = 0; UINT32 value = 0; UINT8 *b; b = (UINT8 *)buffer; while (index < buffer_size) { value <<= 8; value |= (UINT32)(*b++); if ((index >= 3) && SYNC_VALID(value)) return(index - 3); index++; } return(MPEGDEC_ERR_NO_SYNC);}/****************************************************************************//* * Synchronize the bitstream * Return 0 if ok*/static int synchronize(MPA_STREAM *mps){#define MAX_TRIES 9 INT16 try = MAX_TRIES; int status; INT32 slots; while (try--) { status = MPEGDEC_read_header(mps, FALSE); if (status == MPEGDEC_ERR_EOF) return(status); if (status == MPEGDEC_ERR_NONE) { // Header found int bitrate, sfreq, layer, id; MPA_HEADER *mph = &mps->header; id = mph->ID; layer = mph->layer; sfreq = mps->sfreq; bitrate = mps->bitrate; // Calculate the number of slots between 2 headers if (layer == 1) slots = 48000; else slots = 144000; if ((layer == 3) && (id == MPA_ID_2)) slots >>= 1; slots *= bitrate; slots /= sfreq; if (mph->padding_bit) slots++; // Now skip slots-4 bytes if (mph->protection_bit) slots -= 6; // #12 else slots -= 4; while (slots--) BSTR_read_byte(mps->bitstream); // Now check if header ok and same id, norm, (bitrate) and freq status = MPEGDEC_read_header( mps, TRUE ); if (status == MPEGDEC_ERR_NONE) { if ((mph->ID == id) && (mph->layer == layer) && (mps->sfreq == sfreq) ) { int err; err = BSTR_seek(mps->bitstream, mph->header_pos); if (err) return(MPEGDEC_ERR_BADFRAME); err = MPEGDEC_read_header(mps, TRUE); return(err); } } else if (status == MPEGDEC_ERR_EOF) { return(status); } } } return(MPEGDEC_ERR_BADFRAME);}/****************************************************************************//* * Fill the current MPEG Audio stream information */static void fill_info(MPEGDEC_STREAM *mpds){ MPA_STREAM *mps; mps = (MPA_STREAM *) mpds->handle; mpds->norm = (mps->header.ID == MPA_ID_1) ? 1 : 2; mpds->layer = mps->header.layer; mpds->mode = mps->header.mode; mpds->bitrate = mps->bitrate; mpds->frequency = mps->sfreq; mpds->channels = mps->channels; if (mps->bitrate) mpds->ms_duration = mps->stream_size / (mps->bitrate>>3); else mpds->ms_duration = 0; mpds->private_bit = (INT16) mps->header.private_bit; mpds->copyright = (INT16) mps->header.copyright; mpds->original = (INT16) mps->header.original; mpds->dec_frequency = mps->sfreq / mps->freq_div; mpds->dec_channels = (mps->force_mono) ? 1 : mpds->channels; mpds->dec_quality = mps->quality;}/****************************************************************************//* * Set the output scale for the current stream * Inputs: mpds = mpeg audio stream ptr returned by MPEGDEC_open * scale_percent = scale factor in % to apply to decoded output * 100 is the nominal value * Return 0 if Ok, MPEGDEC_ERR_BADVALUE if invalid scale */int MPEGDEC_scale(MPEGDEC_STREAM *mpds, INT32 scale_percent){ MPA_STREAM *mps; mps = (MPA_STREAM *) mpds->handle; if (MPEGSUB_scale(mps->mpegsub, scale_percent)) return(MPEGDEC_ERR_BADVALUE); return(MPEGDEC_ERR_NONE);}/****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -