#ifndef MINIMP3_H
#define MINIMP3_H
#include <stdint.h>
#define MINIMP3_MAX_SAMPLES_PER_FRAME …
mp3dec_frame_info_t;
mp3dec_t;
#ifdef __cplusplus
extern "C" {
#endif
void mp3dec_init(mp3dec_t *dec);
#ifndef MINIMP3_FLOAT_OUTPUT
typedef int16_t mp3d_sample_t;
#else
mp3d_sample_t;
void mp3dec_f32_to_s16(const float *in, int16_t *out, int num_samples);
#endif
int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info);
#ifdef __cplusplus
}
#endif
#endif
#if defined(MINIMP3_IMPLEMENTATION) && !defined(_MINIMP3_IMPLEMENTATION_GUARD)
#define _MINIMP3_IMPLEMENTATION_GUARD
#include <stdlib.h>
#include <string.h>
#define MAX_FREE_FORMAT_FRAME_SIZE …
#ifndef MAX_FRAME_SYNC_MATCHES
#define MAX_FRAME_SYNC_MATCHES …
#endif
#define MAX_L3_FRAME_PAYLOAD_BYTES …
#define MAX_BITRESERVOIR_BYTES …
#define SHORT_BLOCK_TYPE …
#define STOP_BLOCK_TYPE …
#define MODE_MONO …
#define MODE_JOINT_STEREO …
#define HDR_SIZE …
#define HDR_IS_MONO(h) …
#define HDR_IS_MS_STEREO(h) …
#define HDR_IS_FREE_FORMAT(h) …
#define HDR_IS_CRC(h) …
#define HDR_TEST_PADDING(h) …
#define HDR_TEST_MPEG1(h) …
#define HDR_TEST_NOT_MPEG25(h) …
#define HDR_TEST_I_STEREO(h) …
#define HDR_TEST_MS_STEREO(h) …
#define HDR_GET_STEREO_MODE(h) …
#define HDR_GET_STEREO_MODE_EXT(h) …
#define HDR_GET_LAYER(h) …
#define HDR_GET_BITRATE(h) …
#define HDR_GET_SAMPLE_RATE(h) …
#define HDR_GET_MY_SAMPLE_RATE(h) …
#define HDR_IS_FRAME_576(h) …
#define HDR_IS_LAYER_1(h) …
#define BITS_DEQUANTIZER_OUT …
#define MAX_SCF …
#define MAX_SCFI …
#define MINIMP3_MIN(a, b) …
#define MINIMP3_MAX(a, b) …
#if !defined(MINIMP3_NO_SIMD)
#if !defined(MINIMP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64))
#define MINIMP3_ONLY_SIMD
#endif
#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__))
#if defined(_MSC_VER)
#include <intrin.h>
#endif
#include <immintrin.h>
#define HAVE_SSE …
#define HAVE_SIMD …
#define VSTORE …
#define VLD …
#define VSET …
#define VADD …
#define VSUB …
#define VMUL …
#define VMAC(a, x, y) …
#define VMSB(a, x, y) …
#define VMUL_S(x, s) …
#define VREV(x) …
f4;
#if defined(_MSC_VER) || defined(MINIMP3_ONLY_SIMD)
#define minimp3_cpuid …
#else
static __inline__ __attribute__((always_inline)) void minimp3_cpuid(int CPUInfo[], const int InfoType)
{
#if defined(__PIC__)
__asm__ __volatile__(
#if defined(__x86_64__)
"push %%rbx\n"
"cpuid\n"
"xchgl %%ebx, %1\n"
"pop %%rbx\n"
#else
"xchgl %%ebx, %1\n"
"cpuid\n"
"xchgl %%ebx, %1\n"
#endif
: "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
: "a" (InfoType));
#else
__asm__ __volatile__(
"cpuid"
: "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
: "a" (InfoType));
#endif
}
#endif
static int have_simd(void)
{ … }
#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)
#include <arm_neon.h>
#define HAVE_SSE …
#define HAVE_SIMD …
#define VSTORE …
#define VLD …
#define VSET …
#define VADD …
#define VSUB …
#define VMUL …
#define VMAC …
#define VMSB …
#define VMUL_S …
#define VREV …
typedef float32x4_t f4;
static int have_simd()
{
return 1;
}
#else
#define HAVE_SSE …
#define HAVE_SIMD …
#ifdef MINIMP3_ONLY_SIMD
#error MINIMP3_ONLY_SIMD used, but SSE/NEON not enabled
#endif
#endif
#else
#define HAVE_SIMD …
#endif
#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64)
#define HAVE_ARMV6 …
static __inline__ __attribute__((always_inline)) int32_t minimp3_clip_int16_arm(int32_t a)
{
int32_t x = 0;
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
return x;
}
#else
#define HAVE_ARMV6 …
#endif
bs_t;
L12_scale_info;
L12_subband_alloc_t;
L3_gr_info_t;
mp3dec_scratch_t;
static void bs_init(bs_t *bs, const uint8_t *data, int bytes)
{ … }
static uint32_t get_bits(bs_t *bs, int n)
{ … }
static int hdr_valid(const uint8_t *h)
{ … }
static int hdr_compare(const uint8_t *h1, const uint8_t *h2)
{ … }
static unsigned hdr_bitrate_kbps(const uint8_t *h)
{ … }
static unsigned hdr_sample_rate_hz(const uint8_t *h)
{ … }
static unsigned hdr_frame_samples(const uint8_t *h)
{ … }
static int hdr_frame_bytes(const uint8_t *h, int free_format_size)
{ … }
static int hdr_padding(const uint8_t *h)
{ … }
#ifndef MINIMP3_ONLY_MP3
static const L12_subband_alloc_t *L12_subband_alloc_table(const uint8_t *hdr, L12_scale_info *sci)
{
const L12_subband_alloc_t *alloc;
int mode = HDR_GET_STEREO_MODE(hdr);
int nbands, stereo_bands = (mode == MODE_MONO) ? 0 : (mode == MODE_JOINT_STEREO) ? (HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32;
if (HDR_IS_LAYER_1(hdr))
{
static const L12_subband_alloc_t g_alloc_L1[] = { { 76, 4, 32 } };
alloc = g_alloc_L1;
nbands = 32;
} else if (!HDR_TEST_MPEG1(hdr))
{
static const L12_subband_alloc_t g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } };
alloc = g_alloc_L2M2;
nbands = 30;
} else
{
static const L12_subband_alloc_t g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } };
int sample_rate_idx = HDR_GET_SAMPLE_RATE(hdr);
unsigned kbps = hdr_bitrate_kbps(hdr) >> (int)(mode != MODE_MONO);
if (!kbps)
{
kbps = 192;
}
alloc = g_alloc_L2M1;
nbands = 27;
if (kbps < 56)
{
static const L12_subband_alloc_t g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } };
alloc = g_alloc_L2M1_lowrate;
nbands = sample_rate_idx == 2 ? 12 : 8;
} else if (kbps >= 96 && sample_rate_idx != 1)
{
nbands = 30;
}
}
sci->total_bands = (uint8_t)nbands;
sci->stereo_bands = (uint8_t)MINIMP3_MIN(stereo_bands, nbands);
return alloc;
}
static void L12_read_scalefactors(bs_t *bs, uint8_t *pba, uint8_t *scfcod, int bands, float *scf)
{
static const float g_deq_L12[18*3] = {
#define DQ …
DQ(3),DQ(7),DQ(15),DQ(31),DQ(63),DQ(127),DQ(255),DQ(511),DQ(1023),DQ(2047),DQ(4095),DQ(8191),DQ(16383),DQ(32767),DQ(65535),DQ(3),DQ(5),DQ(9)
};
int i, m;
for (i = 0; i < bands; i++)
{
float s = 0;
int ba = *pba++;
int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0;
for (m = 4; m; m >>= 1)
{
if (mask & m)
{
int b = get_bits(bs, 6);
s = g_deq_L12[ba*3 - 6 + b % 3]*(1 << 21 >> b/3);
}
*scf++ = s;
}
}
}
static void L12_read_scale_info(const uint8_t *hdr, bs_t *bs, L12_scale_info *sci)
{
static const uint8_t g_bitalloc_code_tab[] = {
0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16,
0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16,
0,17,18, 3,19,4,5,16,
0,17,18,16,
0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15,
0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14,
0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16
};
const L12_subband_alloc_t *subband_alloc = L12_subband_alloc_table(hdr, sci);
int i, k = 0, ba_bits = 0;
const uint8_t *ba_code_tab = g_bitalloc_code_tab;
for (i = 0; i < sci->total_bands; i++)
{
uint8_t ba;
if (i == k)
{
k += subband_alloc->band_count;
ba_bits = subband_alloc->code_tab_width;
ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset;
subband_alloc++;
}
ba = ba_code_tab[get_bits(bs, ba_bits)];
sci->bitalloc[2*i] = ba;
if (i < sci->stereo_bands)
{
ba = ba_code_tab[get_bits(bs, ba_bits)];
}
sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0;
}
for (i = 0; i < 2*sci->total_bands; i++)
{
sci->scfcod[i] = sci->bitalloc[i] ? HDR_IS_LAYER_1(hdr) ? 2 : get_bits(bs, 2) : 6;
}
L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf);
for (i = sci->stereo_bands; i < sci->total_bands; i++)
{
sci->bitalloc[2*i + 1] = 0;
}
}
static int L12_dequantize_granule(float *grbuf, bs_t *bs, L12_scale_info *sci, int group_size)
{
int i, j, k, choff = 576;
for (j = 0; j < 4; j++)
{
float *dst = grbuf + group_size*j;
for (i = 0; i < 2*sci->total_bands; i++)
{
int ba = sci->bitalloc[i];
if (ba != 0)
{
if (ba < 17)
{
int half = (1 << (ba - 1)) - 1;
for (k = 0; k < group_size; k++)
{
dst[k] = (float)((int)get_bits(bs, ba) - half);
}
} else
{
unsigned mod = (2 << (ba - 17)) + 1;
unsigned code = get_bits(bs, mod + 2 - (mod >> 3));
for (k = 0; k < group_size; k++, code /= mod)
{
dst[k] = (float)((int)(code % mod - mod/2));
}
}
}
dst += choff;
choff = 18 - choff;
}
}
return group_size*4;
}
static void L12_apply_scf_384(L12_scale_info *sci, const float *scf, float *dst)
{
int i, k;
memcpy(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float));
for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6)
{
for (k = 0; k < 12; k++)
{
dst[k + 0] *= scf[0];
dst[k + 576] *= scf[3];
}
}
}
#endif
static int L3_read_side_info(bs_t *bs, L3_gr_info_t *gr, const uint8_t *hdr)
{ … }
static void L3_read_scalefactors(uint8_t *scf, uint8_t *ist_pos, const uint8_t *scf_size, const uint8_t *scf_count, bs_t *bitbuf, int scfsi)
{ … }
static float L3_ldexp_q2(float y, int exp_q2)
{ … }
static void L3_decode_scalefactors(const uint8_t *hdr, uint8_t *ist_pos, bs_t *bs, const L3_gr_info_t *gr, float *scf, int ch)
{ … }
static const float g_pow43[129 + 16] = …;
static float L3_pow_43(int x)
{ … }
static void L3_huffman(float *dst, bs_t *bs, const L3_gr_info_t *gr_info, const float *scf, int layer3gr_limit)
{ … }
static void L3_midside_stereo(float *left, int n)
{ … }
static void L3_intensity_stereo_band(float *left, int n, float kl, float kr)
{ … }
static void L3_stereo_top_band(const float *right, const uint8_t *sfb, int nbands, int max_band[3])
{ … }
static void L3_stereo_process(float *left, const uint8_t *ist_pos, const uint8_t *sfb, const uint8_t *hdr, int max_band[3], int mpeg2_sh)
{ … }
static void L3_intensity_stereo(float *left, uint8_t *ist_pos, const L3_gr_info_t *gr, const uint8_t *hdr)
{ … }
static void L3_reorder(float *grbuf, float *scratch, const uint8_t *sfb)
{ … }
static void L3_antialias(float *grbuf, int nbands)
{ … }
static void L3_dct3_9(float *y)
{ … }
static void L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
{ … }
static void L3_idct3(float x0, float x1, float x2, float *dst)
{ … }
static void L3_imdct12(float *x, float *dst, float *overlap)
{ … }
static void L3_imdct_short(float *grbuf, float *overlap, int nbands)
{ … }
static void L3_change_sign(float *grbuf)
{ … }
static void L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
{ … }
static void L3_save_reservoir(mp3dec_t *h, mp3dec_scratch_t *s)
{ … }
static int L3_restore_reservoir(mp3dec_t *h, bs_t *bs, mp3dec_scratch_t *s, int main_data_begin)
{ … }
static void L3_decode(mp3dec_t *h, mp3dec_scratch_t *s, L3_gr_info_t *gr_info, int nch)
{ … }
static void mp3d_DCT_II(float *grbuf, int n)
{ … }
#ifndef MINIMP3_FLOAT_OUTPUT
static int16_t mp3d_scale_pcm(float sample)
{
#if HAVE_ARMV6
int32_t s32 = (int32_t)(sample + .5f);
s32 -= (s32 < 0);
int16_t s = (int16_t)minimp3_clip_int16_arm(s32);
#else
if (sample >= 32766.5) return (int16_t) 32767;
if (sample <= -32767.5) return (int16_t)-32768;
int16_t s = (int16_t)(sample + .5f);
s -= (s < 0);
#endif
return s;
}
#else
static float mp3d_scale_pcm(float sample)
{ … }
#endif
static void mp3d_synth_pair(mp3d_sample_t *pcm, int nch, const float *z)
{ … }
static void mp3d_synth(float *xl, mp3d_sample_t *dstl, int nch, float *lins)
{ … }
static void mp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, mp3d_sample_t *pcm, float *lins)
{ … }
static int mp3d_match_frame(const uint8_t *hdr, int mp3_bytes, int frame_bytes)
{ … }
static int mp3d_find_frame(const uint8_t *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
{ … }
void mp3dec_init(mp3dec_t *dec)
{ … }
int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info)
{ … }
#ifdef MINIMP3_FLOAT_OUTPUT
void mp3dec_f32_to_s16(const float *in, int16_t *out, int num_samples)
{ … }
#endif
#endif