📄 libmpg123.c
字号:
/* libmpg123: MPEG Audio Decoder library copyright 1995-2008 by the mpg123 project - free software under the terms of the LGPL 2.1 see COPYING and AUTHORS files in distribution or http://mpg123.org*/#include "mpg123lib_intern.h"#include "getbits.h"#include "debug.h"#ifdef GAPLESS#define SAMPLE_ADJUST(x) ((x) - ((mh->p.flags & MPG123_GAPLESS) ? mh->begin_os : 0))#define SAMPLE_UNADJUST(x) ((x) + ((mh->p.flags & MPG123_GAPLESS) ? mh->begin_os : 0))#else#define SAMPLE_ADJUST(x) (x)#define SAMPLE_UNADJUST(x) (x)#endif#define SEEKFRAME(mh) ((mh)->ignoreframe < 0 ? 0 : (mh)->ignoreframe)static int initialized = 0;#ifdef GAPLESS/* Take the buffer after a frame decode (strictly: it is the data from frame fr->num!) and cut samples out. fr->buffer.fill may then be smaller than before...*/static void frame_buffercheck(mpg123_handle *fr){ /* The first interesting frame: Skip some leading samples. */ if(fr->firstoff && fr->num == fr->firstframe) { off_t byteoff = samples_to_bytes(fr, fr->firstoff); if(fr->buffer.fill > byteoff) { fr->buffer.fill -= byteoff; /* buffer.p != buffer.data only for own buffer */ debug6("cutting %li samples/%li bytes on begin, own_buffer=%i at %p=%p, buf[1]=%i", (long)fr->firstoff, (long)byteoff, fr->own_buffer, (void*)fr->buffer.p, (void*)fr->buffer.data, ((short*)fr->buffer.p)[2]); if(fr->own_buffer) fr->buffer.p = fr->buffer.data + byteoff; else memmove(fr->buffer.data, fr->buffer.data + byteoff, fr->buffer.fill); debug3("done cutting, buffer at %p =? %p, buf[1]=%i", (void*)fr->buffer.p, (void*)fr->buffer.data, ((short*)fr->buffer.p)[2]); } else fr->buffer.fill = 0; fr->firstoff = 0; /* Only enter here once... when you seek, firstoff should be reset. */ } /* The last interesting (planned) frame: Only use some leading samples. */ if(fr->lastoff && fr->num == fr->lastframe) { off_t byteoff = samples_to_bytes(fr, fr->lastoff); if(fr->buffer.fill > byteoff) { fr->buffer.fill = byteoff; } fr->lastoff = 0; /* Only enter here once... when you seek, lastoff should be reset. */ }}#endifint mpg123_init(void){ if((sizeof(short) != 2) || (sizeof(long) < 4)) return MPG123_BAD_TYPES; init_layer2(); /* inits also shared tables with layer1 */ init_layer3();#ifndef OPT_MMX_ONLY prepare_decode_tables();#endif check_decoders(); initialized = 1; return MPG123_OK;}void mpg123_exit(void){ /* nothing yet, but something later perhaps */ if(initialized) return;}/* create a new handle with specified decoder, decoder can be "", "auto" or NULL for auto-detection */mpg123_handle *mpg123_new(const char* decoder, int *error){ return mpg123_parnew(NULL, decoder, error);}/* ...the full routine with optional initial parameters to override defaults. */mpg123_handle *mpg123_parnew(mpg123_pars *mp, const char* decoder, int *error){ mpg123_handle *fr = NULL; int err = MPG123_OK; if(initialized) fr = (mpg123_handle*) malloc(sizeof(mpg123_handle)); else err = MPG123_NOT_INITIALIZED; if(fr != NULL) { frame_init_par(fr, mp); debug("cpu opt setting"); if(frame_cpu_opt(fr, decoder) != 1) { err = MPG123_BAD_DECODER; frame_exit(fr); free(fr); fr = NULL; } } if(fr != NULL) { if((frame_outbuffer(fr) != 0) || (frame_buffers(fr) != 0)) { err = MPG123_NO_BUFFERS; frame_exit(fr); free(fr); fr = NULL; } else { opt_make_decode_tables(fr); fr->decoder_change = 1; /* happening on frame change instead: init_layer3_stuff(fr); init_layer2_stuff(fr); */ } } else if(err == MPG123_OK) err = MPG123_OUT_OF_MEM; if(error != NULL) *error = err; return fr;}int mpg123_decoder(mpg123_handle *mh, const char* decoder){ enum optdec dt = dectype(decoder); if(mh == NULL) return MPG123_ERR; if(dt == nodec) { mh->err = MPG123_BAD_DECODER; return MPG123_ERR; } if(dt == mh->cpu_opts.type) return MPG123_OK; /* Now really change. */ /* frame_exit(mh); frame_init(mh); */ debug("cpu opt setting"); if(frame_cpu_opt(mh, decoder) != 1) { mh->err = MPG123_BAD_DECODER; frame_exit(mh); return MPG123_ERR; } /* New buffers for decoder are created in frame_buffers() */ if((frame_outbuffer(mh) != 0) || (frame_buffers(mh) != 0)) { mh->err = MPG123_NO_BUFFERS; frame_exit(mh); return MPG123_ERR; } opt_make_decode_tables(mh); mh->decoder_change = 1; return MPG123_OK;}int mpg123_param(mpg123_handle *mh, enum mpg123_parms key, long val, double fval){ int r; if(mh == NULL) return MPG123_ERR; r = mpg123_par(&mh->p, key, val, fval); if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; } return r;}int mpg123_par(mpg123_pars *mp, enum mpg123_parms key, long val, double fval){ int ret = MPG123_OK; if(mp == NULL) return MPG123_BAD_PARS; switch(key) { case MPG123_VERBOSE: mp->verbose = val; break; case MPG123_FLAGS:#ifndef GAPLESS if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS; else#endif mp->flags = val; debug1("set flags to 0x%lx", (unsigned long) mp->flags); break; case MPG123_ADD_FLAGS:#ifndef GAPLESS /* Enabling of gapless mode doesn't work when it's not there, but disabling (below) is no problem. */ if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS; else#endif mp->flags |= val; debug1("set flags to 0x%lx", (unsigned long) mp->flags); break; case MPG123_REMOVE_FLAGS: mp->flags &= ~val; debug1("set flags to 0x%lx", (unsigned long) mp->flags); break; case MPG123_FORCE_RATE: /* should this trigger something? */ if(val > 96000) ret = MPG123_BAD_RATE; else mp->force_rate = val < 0 ? 0 : val; /* >0 means enable, 0 disable */ break; case MPG123_DOWN_SAMPLE: if(val < 0 || val > 2) ret = MPG123_BAD_RATE; else mp->down_sample = (int)val; break; case MPG123_RVA: if(val < 0 || val > MPG123_RVA_MAX) ret = MPG123_BAD_RVA; else mp->rva = (int)val; break; case MPG123_DOWNSPEED: mp->halfspeed = val < 0 ? 0 : val; break; case MPG123_UPSPEED: mp->doublespeed = val < 0 ? 0 : val; break; case MPG123_ICY_INTERVAL: mp->icy_interval = val > 0 ? val : 0; break; case MPG123_OUTSCALE:#ifdef FLOATOUT mp->outscale = fval;#else mp->outscale = val;#endif break; case MPG123_TIMEOUT:#ifndef WIN32 mp->timeout = val >= 0 ? val : 0;#else ret = MPG123_NO_TIMEOUT;#endif break; case MPG123_RESYNC_LIMIT: mp->resync_limit = val; break; default: ret = MPG123_BAD_PARAM; } return ret;}int mpg123_getparam(mpg123_handle *mh, enum mpg123_parms key, long *val, double *fval){ int r; if(mh == NULL) return MPG123_ERR; r = mpg123_getpar(&mh->p, key, val, fval); if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; } return r;}int mpg123_getpar(mpg123_pars *mp, enum mpg123_parms key, long *val, double *fval){ int ret = 0; if(mp == NULL) return MPG123_BAD_PARS; switch(key) { case MPG123_VERBOSE: if(val) *val = mp->verbose; break; case MPG123_FLAGS: case MPG123_ADD_FLAGS: if(val) *val = mp->flags; break; case MPG123_FORCE_RATE: if(val) *val = mp->force_rate; break; case MPG123_DOWN_SAMPLE: if(val) *val = mp->down_sample; break; case MPG123_RVA: if(val) *val = mp->rva; break; case MPG123_DOWNSPEED: if(val) *val = mp->halfspeed; break; case MPG123_UPSPEED: if(val) *val = mp->doublespeed; break; case MPG123_ICY_INTERVAL: if(val) *val = (long)mp->icy_interval; break; case MPG123_OUTSCALE:#ifdef FLOATOUT if(fval) *fval = mp->outscale;#else if(val) *val = mp->outscale;#endif break; case MPG123_RESYNC_LIMIT: if(val) *val = mp->resync_limit; break; default: ret = MPG123_BAD_PARAM; } return ret;}int mpg123_eq(mpg123_handle *mh, enum mpg123_channels channel, int band, double val){ if(mh == NULL) return MPG123_ERR; if(band < 0 || band > 31){ mh->err = MPG123_BAD_BAND; return MPG123_ERR; } switch(channel) { case MPG123_LEFT|MPG123_RIGHT: mh->equalizer[0][band] = mh->equalizer[1][band] = DOUBLE_TO_REAL(val); break; case MPG123_LEFT: mh->equalizer[0][band] = DOUBLE_TO_REAL(val); break; case MPG123_RIGHT: mh->equalizer[1][band] = DOUBLE_TO_REAL(val); break; default: mh->err=MPG123_BAD_CHANNEL; return MPG123_ERR; } mh->have_eq_settings = TRUE; return MPG123_OK;}/* plain file access, no http! */int mpg123_open(mpg123_handle *mh, char *path){ if(mh == NULL) return MPG123_ERR; mpg123_close(mh); frame_reset(mh); return open_stream(mh, path, -1);}int mpg123_open_fd(mpg123_handle *mh, int fd){ if(mh == NULL) return MPG123_ERR; mpg123_close(mh); frame_reset(mh); return open_stream(mh, NULL, fd);}int mpg123_open_feed(mpg123_handle *mh){ if(mh == NULL) return MPG123_ERR; mpg123_close(mh); frame_reset(mh); return open_feed(mh);}int mpg123_replace_reader( mpg123_handle *mh, ssize_t (*r_read) (int, void *, size_t), off_t (*r_lseek)(int, off_t, int) ){ if(mh == NULL) return MPG123_ERR; mh->rdat.r_read = r_read; mh->rdat.r_lseek = r_lseek; return MPG123_OK;}int decode_update(mpg123_handle *mh){ long native_rate = frame_freq(mh); debug2("updating decoder structure with native rate %li and af.rate %li", native_rate, mh->af.rate); if(mh->af.rate == native_rate) mh->down_sample = 0; else if(mh->af.rate == native_rate>>1) mh->down_sample = 1; else if(mh->af.rate == native_rate>>2) mh->down_sample = 2; else mh->down_sample = 3; /* flexible (fixed) rate */ switch(mh->down_sample) { case 0: case 1: case 2: mh->down_sample_sblimit = SBLIMIT>>(mh->down_sample); /* With downsampling I get less samples per frame */ mh->outblock = sizeof(sample_t)*mh->af.channels*(spf(mh)>>mh->down_sample); break; case 3: { if(synth_ntom_set_step(mh) != 0) return -1; if(frame_freq(mh) > mh->af.rate) { mh->down_sample_sblimit = SBLIMIT * mh->af.rate; mh->down_sample_sblimit /= frame_freq(mh); } else mh->down_sample_sblimit = SBLIMIT; mh->outblock = sizeof(sample_t) * mh->af.channels * ( ( NTOM_MUL-1+spf(mh) * (((size_t)NTOM_MUL*mh->af.rate)/frame_freq(mh)) )/NTOM_MUL ); } break; } if(!(mh->p.flags & MPG123_FORCE_MONO)) { if(mh->af.channels == 1) mh->single = SINGLE_MIX; else mh->single = SINGLE_STEREO; } else mh->single = (mh->p.flags & MPG123_FORCE_MONO)-1; if(set_synth_functions(mh) != 0) return -1;; init_layer3_stuff(mh); init_layer2_stuff(mh); do_rva(mh); debug3("done updating decoder structure with native rate %li and af.rate %li and down_sample %i", frame_freq(mh), mh->af.rate, mh->down_sample); return 0;}size_t mpg123_safe_buffer(){ return sizeof(sample_t)*2*1152*NTOM_MAX;}size_t mpg123_outblock(mpg123_handle *mh){ if(mh != NULL) return mh->outblock; else return mpg123_safe_buffer();}static int get_next_frame(mpg123_handle *mh){ int change = mh->decoder_change; do { int b; /* Decode & discard some frame(s) before beginning. */ if(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe) { debug1("ignoring frame %li", (long)mh->num); /* Decoder structure must be current! decode_update has been called before... */ (mh->do_layer)(mh); mh->buffer.fill = 0; mh->to_ignore = mh->to_decode = FALSE; } /* Read new frame data; possibly breaking out here for MPG123_NEED_MORE. */ debug("read frame"); mh->to_decode = FALSE; b = read_frame(mh); /* That sets to_decode only if a full frame was read. */ debug3("read of frame %li returned %i (to_decode=%i)", (long)mh->num, b, mh->to_decode); if(b == MPG123_NEED_MORE) return MPG123_NEED_MORE; /* need another call with data */ else if(b <= 0) { /* More sophisticated error control? */ if(b==0 || mh->rdat.filepos == mh->rdat.filelen) { /* We simply reached the end. */ mh->track_frames = mh->num + 1; return MPG123_DONE; } else return MPG123_ERR; /* Some real error. */ } /* Now, there should be new data to decode ... and also possibly new stream properties */ if(mh->header_change > 1) { debug("big header change"); change = 1; } } while(mh->num < mh->firstframe); /* When we start actually using the CRC, this could move into the loop... */ /* A question of semantics ... should I fold start_frame and frame_number into firstframe/lastframe? */ if(mh->lastframe >= 0 && mh->num > mh->lastframe) { mh->to_decode = mh->to_ignore = FALSE; return MPG123_DONE; } if(change) { int b = frame_output_format(mh); /* Select the new output format based on given constraints. */ if(b < 0) return MPG123_ERR; /* not nice to fail here... perhaps once should add possibility to repeat this step */ if(decode_update(mh) < 0) return MPG123_ERR; /* dito... */ mh->decoder_change = 0; if(b == 1) mh->new_format = 1; /* Store for later... */#ifdef GAPLESS if(mh->fresh) { b=0; /* Prepare offsets for gapless decoding. */ debug1("preparing gapless stuff with native rate %li", frame_freq(mh)); frame_gapless_realinit(mh); frame_set_frameseek(mh, mh->num); mh->fresh = 0; /* Could this possibly happen? With a real big gapless offset... */ if(mh->num < mh->firstframe) b = get_next_frame(mh); if(b < 0) return b; /* Could be error, need for more, new format... */ }#endif } return MPG123_OK;}/* Put _one_ decoded frame into the frame structure's buffer, accessible at the location stored in <audio>, with <bytes> bytes available. The buffer contents will be lost on next call to mpg123_decode_frame. MPG123_OK -- successfully decoded the frame, you get your output data MPg123_DONE -- This is it. End. MPG123_ERR -- some error occured... MPG123_NEW_FORMAT -- new frame was read, it results in changed output format -> will be decoded on next call MPG123_NEED_MORE -- that should not happen as this function is intended for in-library stream reader but if you force it... MPG123_NO_SPACE -- not enough space in buffer for safe decoding, also should not happen num will be updated to the last decoded frame number (may possibly _not_ increase, p.ex. when format changed).*/int mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes){ if(bytes != NULL) *bytes = 0; if(mh == NULL) return MPG123_ERR; if(mh->buffer.size < mh->outblock) return MPG123_NO_SPACE; mh->buffer.fill = 0; /* always start fresh */ *bytes = 0; while(TRUE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -