/* libmpg123: MPEG Audio Decoder library copyright 1995-2010 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 "icy2utf8.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; #include "aligncheck.h" #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) { /* When we have no accurate position, gapless code does not make sense. */ if(!fr->accurate) return; /* Important: We first cut samples from the end, then cut from beginning (including left-shift of the buffer). This order works also for the case where firstframe == lastframe. */ /* The last interesting (planned) frame: Only use some leading samples. Note a difference from the below: The last frame and offset are unchanges by seeks. The lastoff keeps being valid. */ if(fr->lastframe > -1 && fr->num >= fr->lastframe) { /* There can be more than one frame of padding at the end, so we ignore the whole frame if we are beyond lastframe. */ off_t byteoff = (fr->num == fr->lastframe) ? samples_to_bytes(fr, fr->lastoff) : 0; if((off_t)fr->buffer.fill > byteoff) { fr->buffer.fill = byteoff; } debug1("Cut frame buffer on end of stream, fill now %"SIZE_P" bytes.", (size_p)fr->buffer.fill); } /* 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((off_t)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; /* We can only reach this frame again by seeking. And on seeking, firstoff will be recomputed. So it is safe to null it here (and it makes the if() decision abort earlier). */ fr->firstoff = 0; } } #endif int attribute_align_arg mpg123_init(void) { ALIGNCHECKK if((sizeof(short) != 2) || (sizeof(long) < 4)) return MPG123_BAD_TYPES; if(initialized) return MPG123_OK; /* no need to initialize twice */ #ifndef NO_LAYER12 init_layer12(); /* inits also shared tables with layer1 */ #endif #ifndef NO_LAYER3 init_layer3(); #endif prepare_decode_tables(); check_decoders(); initialized = 1; return MPG123_OK; } void attribute_align_arg mpg123_exit(void) { /* nothing yet, but something later perhaps */ } /* create a new handle with specified decoder, decoder can be "", "auto" or NULL for auto-detection */ mpg123_handle attribute_align_arg *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 attribute_align_arg *mpg123_parnew(mpg123_pars *mp, const char* decoder, int *error) { mpg123_handle *fr = NULL; int err = MPG123_OK; #if (defined CCALIGN) && (defined NEED_ALIGNCHECK) && ((defined DEBUG) || (defined CHECK_ALIGN)) #ifdef CCALIGN double ALIGNED(16) altest[4]; if(((size_t)altest) % 16 != 0) { error("Stack variable is not aligned! Your combination of compiler/library is dangerous!"); *error = MPG123_BAD_ALIGN; return NULL; } #endif #endif 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) { /* Cleanup that mess! ... use mpg123_decoder / decode_update! */ if(frame_outbuffer(fr) != 0) { err = MPG123_NO_BUFFERS; frame_exit(fr); free(fr); fr = NULL; } else { /* I smell cleanup here... with get_next_frame() */ /* if(decode_update(fr) != 0) { err = fr->err != MPG123_OK ? fr->err : MPG123_BAD_DECODER; frame_exit(fr); free(fr); fr = NULL; } else */ fr->decoder_change = 1; } } else if(err == MPG123_OK) err = MPG123_OUT_OF_MEM; if(error != NULL) *error = err; return fr; } int attribute_align_arg mpg123_decoder(mpg123_handle *mh, const char* decoder) { enum optdec dt = dectype(decoder); ALIGNCHECK(mh); 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)) { mh->err = MPG123_NO_BUFFERS; frame_exit(mh); return MPG123_ERR; } /* I smell cleanup here... with get_next_frame() */ decode_update(mh); mh->decoder_change = 1; return MPG123_OK; } int attribute_align_arg mpg123_param(mpg123_handle *mh, enum mpg123_parms key, long val, double fval) { int r; ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; r = mpg123_par(&mh->p, key, val, fval); if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; } else { /* Special treatment for some settings. */ #ifdef FRAME_INDEX if(key == MPG123_INDEX_SIZE) { /* Apply frame index size and grow property on the fly. */ r = frame_index_setup(mh); if(r != MPG123_OK) mh->err = MPG123_INDEX_FAIL; } #endif } return r; } int attribute_align_arg mpg123_par(mpg123_pars *mp, enum mpg123_parms key, long val, double fval) { int ret = MPG123_OK; ALIGNCHECKK 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; #endif if(ret == MPG123_OK) 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? */ #ifdef NO_NTOM if(val > 0) ret = MPG123_BAD_RATE; #else if(val > 96000) ret = MPG123_BAD_RATE; else mp->force_rate = val < 0 ? 0 : val; /* >0 means enable, 0 disable */ #endif break; case MPG123_DOWN_SAMPLE: #ifdef NO_DOWNSAMPLE if(val != 0) ret = MPG123_BAD_RATE; #else if(val < 0 || val > 2) ret = MPG123_BAD_RATE; else mp->down_sample = (int)val; #endif 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: #ifndef NO_ICY mp->icy_interval = val > 0 ? val : 0; #else if(val > 0) ret = MPG123_BAD_PARAM; #endif break; case MPG123_OUTSCALE: /* Choose the value that is non-zero, if any. Downscaling integers to 1.0 . */ mp->outscale = val == 0 ? fval : (double)val/SHORT_SCALE; break; case MPG123_TIMEOUT: #ifdef TIMEOUT_READ mp->timeout = val >= 0 ? val : 0; #else if(val > 0) ret = MPG123_NO_TIMEOUT; #endif break; case MPG123_RESYNC_LIMIT: mp->resync_limit = val; break; case MPG123_INDEX_SIZE: #ifdef FRAME_INDEX mp->index_size = val; #else ret = MPG123_NO_INDEX; #endif break; case MPG123_PREFRAMES: if(val >= 0) mp->preframes = val; else ret = MPG123_BAD_VALUE; break; default: ret = MPG123_BAD_PARAM; } return ret; } int attribute_align_arg mpg123_getparam(mpg123_handle *mh, enum mpg123_parms key, long *val, double *fval) { int r; ALIGNCHECK(mh); 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 attribute_align_arg mpg123_getpar(mpg123_pars *mp, enum mpg123_parms key, long *val, double *fval) { int ret = 0; ALIGNCHECKK 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) #ifdef NO_NTOM *val = 0; #else *val = mp->force_rate; #endif 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: #ifndef NO_ICY if(val) *val = (long)mp->icy_interval; #else if(val) *val = 0; #endif break; case MPG123_OUTSCALE: if(fval) *fval = mp->outscale; if(val) *val = (long)(mp->outscale*SHORT_SCALE); break; case MPG123_RESYNC_LIMIT: if(val) *val = mp->resync_limit; break; case MPG123_INDEX_SIZE: if(val) #ifdef FRAME_INDEX *val = mp->index_size; #else *val = 0; /* graceful fallback: no index is index of zero size */ #endif break; case MPG123_PREFRAMES: *val = mp->preframes; break; default: ret = MPG123_BAD_PARAM; } return ret; } int attribute_align_arg mpg123_getstate(mpg123_handle *mh, enum mpg123_state key, long *val, double *fval) { int ret = MPG123_OK; long theval = 0; double thefval = 0.; ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; switch(key) { case MPG123_ACCURATE: theval = mh->accurate; break; default: mh->err = MPG123_BAD_KEY; ret = MPG123_ERR; } if(val != NULL) *val = theval; if(fval != NULL) *fval = thefval; return ret; } int attribute_align_arg mpg123_eq(mpg123_handle *mh, enum mpg123_channels channel, int band, double val) { ALIGNCHECK(mh); 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; } double attribute_align_arg mpg123_geteq(mpg123_handle *mh, enum mpg123_channels channel, int band) { double ret = 0.; ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; /* Handle this gracefully. When there is no band, it has no volume. */ if(band > -1 && band < 32) switch(channel) { case MPG123_LEFT|MPG123_RIGHT: ret = 0.5*(REAL_TO_DOUBLE(mh->equalizer[0][band])+REAL_TO_DOUBLE(mh->equalizer[1][band])); break; case MPG123_LEFT: ret = REAL_TO_DOUBLE(mh->equalizer[0][band]); break; case MPG123_RIGHT: ret = REAL_TO_DOUBLE(mh->equalizer[1][band]); break; /* Default case is already handled: ret = 0 */ } return ret; } /* plain file access, no http! */ int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); return open_stream(mh, path, -1); } int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); return open_stream(mh, NULL, fd); } int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *iohandle) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); if(mh->rdat.r_read_handle == NULL) { mh->err = MPG123_BAD_CUSTOM_IO; return MPG123_ERR; } return open_stream_handle(mh, iohandle); } int attribute_align_arg mpg123_open_feed(mpg123_handle *mh) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); return open_feed(mh); } int attribute_align_arg mpg123_replace_reader( mpg123_handle *mh, long (*r_read) (int, void *, size_t), off_t (*r_lseek)(int, off_t, int) ) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); mh->rdat.r_read = r_read; mh->rdat.r_lseek = r_lseek; return MPG123_OK; } int attribute_align_arg mpg123_replace_reader_handle( mpg123_handle *mh, long (*r_read) (void*, void *, size_t), off_t (*r_lseek)(void*, off_t, int), void (*cleanup)(void*) ) { ALIGNCHECK(mh); if(mh == NULL) return MPG123_ERR; mpg123_close(mh); mh->rdat.r_read_handle = r_read; mh->rdat.r_lseek_handle = r_lseek; mh->rdat.cleanup_handle = cleanup; return MPG123_OK; } int decode_update(mpg123_handle *mh) { long native_rate; int b; ALIGNCHECK(mh); native_rate = frame_freq(mh); b = frame_output_format(mh); /* Select the new output format based on given constraints. */ if(b < 0) return MPG123_ERR; if(b == 1) mh->new_format = 1; /* Store for later... */ debug3("updating decoder structure with native rate %li and af.rate %li (new format: %i)", native_rate, mh->af.rate, mh->new_format); 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 = samples_to_bytes(mh, (spf(mh)>>mh->down_sample)); break; #ifndef NO_NTOM 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 = mh->af.encsize * mh->af.channels * ( ( NTOM_MUL-1+spf(mh) * (((size_t)NTOM_MUL*mh->af.rate)/frame_freq(mh)) )/NTOM_MUL ); } break; #endif } 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;; 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 attribute_align_arg mpg123_safe_buffer(void) { /* real is the largest possible output (it's 32bit float, 32bit int or 64bit double). */ return sizeof(real)*2*1152*NTOM_MAX; } size_t attribute_align_arg 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; #ifndef NO_NTOM /* The ignored decoding may have failed. Make sure ntom stays consistent. */ if(mh->down_sample == 3) ntom_set_ntom(mh, mh->num+1); #endif 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. */ debug4("read of frame %li returned %i (to_decode=%i) at sample %li", (long)mh->num, b, mh->to_decode, (long)mpg123_tell(mh)); 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; debug("What about updating/checking gapless sample count here?"); 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; } /* Now some accounting: Look at the numbers and decide if we want this frame. */ ++mh->playnum; /* Plain skipping without decoding, only when frame is not ignored on next cycle. */ if(mh->num < mh->firstframe || (mh->p.doublespeed && (mh->playnum % mh->p.doublespeed))) { if(!(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe)) { frame_skip(mh); /* Should one fix NtoM here or not? It is not work the trouble for doublespeed, but what with leading frames? */ } } /* Or, we are finally done and have a new frame. */ else break; } while(1); if(change) { if(decode_update(mh) < 0) /* dito... */ return MPG123_ERR; debug1("new format: %i", mh->new_format); mh->decoder_change = 0; if(mh->fresh) { #ifdef GAPLESS int 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); #endif mh->fresh = 0; #ifdef GAPLESS /* 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; } /* Assumption: A buffer full of zero samples can be constructed by repetition of this byte. Only to be used by decode_the_frame() ... */ static int zero_byte(mpg123_handle *fr) { #ifndef NO_8BIT return fr->af.encoding & MPG123_ENC_8 ? fr->conv16to8[0] : 0; #else return 0; /* All normal signed formats have the zero here (even in byte form -- that may be an assumption for your funny machine...). */ #endif } /* Not part of the api. This just decodes the frame and fills missing bits with zeroes. There can be frames that are broken and thus make do_layer() fail. */ void decode_the_frame(mpg123_handle *fr) { size_t needed_bytes = samples_to_bytes(fr, frame_expect_outsamples(fr)); fr->clip += (fr->do_layer)(fr); /*fprintf(stderr, "frame %"OFF_P": got %"SIZE_P" / %"SIZE_P"\n", fr->num,(size_p)fr->buffer.fill, (size_p)needed_bytes);*/ /* There could be less data than promised. Also, then debugging, we look out for coding errors that could result in _more_ data than expected. */ #ifdef DEBUG if(fr->buffer.fill != needed_bytes) { #endif if(fr->buffer.fill < needed_bytes) { if(VERBOSE2) fprintf(stderr, "Note: broken frame %li, filling up with %"SIZE_P" zeroes, from %"SIZE_P"\n", (long)fr->num, (size_p)(needed_bytes-fr->buffer.fill), (size_p)fr->buffer.fill); /* One could do a loop with individual samples instead... but zero is zero Actually, that is wrong: zero is mostly a series of null bytes, but we have funny 8bit formats that have a different opinion on zero... Unsigned 16 or 32 bit formats are handled later. */ memset( fr->buffer.data + fr->buffer.fill, zero_byte(fr), needed_bytes - fr->buffer.fill ); fr->buffer.fill = needed_bytes; #ifndef NO_NTOM /* ntom_val will be wrong when the decoding wasn't carried out completely */ ntom_set_ntom(fr, fr->num+1); #endif } #ifdef DEBUG else { if(NOQUIET) error2("I got _more_ bytes than expected (%"SIZE_P" / %"SIZE_P"), that should not be possible!", (size_p)fr->buffer.fill, (size_p)needed_bytes); } } #endif /* Handle unsigned output formats via reshifting after decode here. */ #ifndef NO_32BIT if(fr->af.encoding == MPG123_ENC_UNSIGNED_32) { /* 32bit signed -> unsigned */ size_t i; int32_t *ssamples; uint32_t *usamples; ssamples = (int32_t*)fr->buffer.data; usamples = (uint32_t*)fr->buffer.data; debug("converting output to unsigned 32 bit integer"); for(i=0; ibuffer.fill/sizeof(int32_t); ++i) { /* Different strategy since we don't have a larger type at hand. Also watch out for silly +-1 fun because integer constants are signed in C90! */ if(ssamples[i] >= 0) usamples[i] = (uint32_t)ssamples[i] + 2147483647+1; /* The smalles value goes zero. */ else if(ssamples[i] == ((int32_t)-2147483647-1)) usamples[i] = 0; /* Now -value is in the positive range of signed int ... so it's a possible value at all. */ else usamples[i] = (uint32_t)2147483647+1 - (uint32_t)(-ssamples[i]); } } #endif #ifndef NO_16BIT if(fr->af.encoding == MPG123_ENC_UNSIGNED_16) { size_t i; short *ssamples; unsigned short *usamples; ssamples = (short*)fr->buffer.data; usamples = (unsigned short*)fr->buffer.data; debug("converting output to unsigned 16 bit integer"); for(i=0; ibuffer.fill/sizeof(short); ++i) { long tmp = (long)ssamples[i]+32768; usamples[i] = (unsigned short)tmp; } } #endif } /* Decode the current frame into the frame structure's buffer, accessible at the location stored in