ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

frame.c
Go to the documentation of this file.
00001 /*
00002     frame: Heap of routines dealing with the core mpg123 data structure.
00003 
00004     copyright 2008-2010 by the mpg123 project - free software under the terms of the LGPL 2.1
00005     see COPYING and AUTHORS files in distribution or http://mpg123.org
00006     initially written by Thomas Orgis
00007 */
00008 
00009 #include "mpg123lib_intern.h"
00010 #include "getcpuflags.h"
00011 #include "debug.h"
00012 
00013 static void frame_fixed_reset(mpg123_handle *fr);
00014 
00015 /* that's doubled in decode_ntom.c */
00016 #define NTOM_MUL (32768)
00017 
00018 #define aligned_pointer(p, type, alignment) align_the_pointer(p, alignment)
00019 static void *align_the_pointer(void *base, unsigned int alignment)
00020 {
00021     /*
00022         Work in unsigned integer realm, explicitly.
00023         Tricking the compiler into integer operations like % by invoking base-NULL is dangerous: It results into ptrdiff_t, which gets negative on big addresses. Big screw up, that.
00024         I try to do it "properly" here: Casting only to uintptr_t and no artihmethic with void*.
00025     */
00026     uintptr_t baseval = (uintptr_t)(char*)base;
00027     uintptr_t aoff = baseval % alignment;
00028 
00029     debug3("align_the_pointer: pointer %p is off by %u from %u",
00030            base, (unsigned int)aoff, alignment);
00031 
00032     if(aoff) return (char*)base+alignment-aoff;
00033     else     return base;
00034 }
00035 
00036 void frame_default_pars(mpg123_pars *mp)
00037 {
00038     mp->outscale = 1.0;
00039 #ifdef GAPLESS
00040     mp->flags = MPG123_GAPLESS;
00041 #else
00042     mp->flags = 0;
00043 #endif
00044 #ifndef NO_NTOM
00045     mp->force_rate = 0;
00046 #endif
00047     mp->down_sample = 0;
00048     mp->rva = 0;
00049     mp->halfspeed = 0;
00050     mp->doublespeed = 0;
00051     mp->verbose = 0;
00052 #ifndef NO_ICY
00053     mp->icy_interval = 0;
00054 #endif
00055     mp->timeout = 0;
00056     mp->resync_limit = 1024;
00057 #ifdef FRAME_INDEX
00058     mp->index_size = INDEX_SIZE;
00059 #endif
00060     mp->preframes = 4; /* That's good  for layer 3 ISO compliance bitstream. */
00061     mpg123_fmt_all(mp);
00062 }
00063 
00064 void frame_init(mpg123_handle *fr)
00065 {
00066     frame_init_par(fr, NULL);
00067 }
00068 
00069 void frame_init_par(mpg123_handle *fr, mpg123_pars *mp)
00070 {
00071     fr->own_buffer = FALSE;
00072     fr->buffer.data = NULL;
00073     fr->rawbuffs = NULL;
00074     fr->rawbuffss = 0;
00075     fr->rawdecwin = NULL;
00076     fr->rawdecwins = 0;
00077 #ifndef NO_8BIT
00078     fr->conv16to8_buf = NULL;
00079 #endif
00080 #ifdef OPT_DITHER
00081     fr->dithernoise = NULL;
00082 #endif
00083     fr->layerscratch = NULL;
00084     fr->xing_toc = NULL;
00085     fr->cpu_opts.type = defdec();
00086     fr->cpu_opts.class = decclass(fr->cpu_opts.type);
00087 #ifndef NO_NTOM
00088     /* these two look unnecessary, check guarantee for synth_ntom_set_step (in control_generic, even)! */
00089     fr->ntom_val[0] = NTOM_MUL>>1;
00090     fr->ntom_val[1] = NTOM_MUL>>1;
00091     fr->ntom_step = NTOM_MUL;
00092 #endif
00093     /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */
00094     mpg123_reset_eq(fr);
00095     init_icy(&fr->icy);
00096     init_id3(fr);
00097     /* frame_outbuffer is missing... */
00098     /* frame_buffers is missing... that one needs cpu opt setting! */
00099     /* after these... frame_reset is needed before starting full decode */
00100     invalidate_format(&fr->af);
00101     fr->rdat.r_read = NULL;
00102     fr->rdat.r_lseek = NULL;
00103     fr->rdat.iohandle = NULL;
00104     fr->rdat.r_read_handle = NULL;
00105     fr->rdat.r_lseek_handle = NULL;
00106     fr->rdat.cleanup_handle = NULL;
00107     fr->wrapperdata = NULL;
00108     fr->wrapperclean = NULL;
00109     fr->decoder_change = 1;
00110     fr->err = MPG123_OK;
00111     if(mp == NULL) frame_default_pars(&fr->p);
00112     else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct));
00113 
00114     fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */
00115     frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */
00116     fr->synth = NULL;
00117     fr->synth_mono = NULL;
00118     fr->make_decode_tables = NULL;
00119 #ifdef FRAME_INDEX
00120     fi_init(&fr->index);
00121     frame_index_setup(fr); /* Apply the size setting. */
00122 #endif
00123 }
00124 
00125 #ifdef OPT_DITHER
00126 /* Also, only allocate the memory for the table on demand.
00127    In future, one could create special noise for different sampling frequencies(?). */
00128 int frame_dither_init(mpg123_handle *fr)
00129 {
00130     /* run-time dither noise table generation */
00131     if(fr->dithernoise == NULL)
00132     {
00133         fr->dithernoise = malloc(sizeof(float)*DITHERSIZE);
00134         if(fr->dithernoise == NULL) return 0;
00135 
00136         dither_table_init(fr->dithernoise);
00137     }
00138     return 1;
00139 }
00140 #endif
00141 
00142 mpg123_pars attribute_align_arg *mpg123_new_pars(int *error)
00143 {
00144     mpg123_pars *mp = malloc(sizeof(struct mpg123_pars_struct));
00145     if(mp != NULL){ frame_default_pars(mp); if(error != NULL) *error = MPG123_OK; }
00146     else if(error != NULL) *error = MPG123_OUT_OF_MEM;
00147     return mp;
00148 }
00149 
00150 void attribute_align_arg mpg123_delete_pars(mpg123_pars* mp)
00151 {
00152     if(mp != NULL) free(mp);
00153 }
00154 
00155 int attribute_align_arg mpg123_reset_eq(mpg123_handle *mh)
00156 {
00157     int i;
00158     mh->have_eq_settings = 0;
00159     for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0);
00160 
00161     return MPG123_OK;
00162 }
00163 
00164 int frame_outbuffer(mpg123_handle *fr)
00165 {
00166     size_t size = mpg123_safe_buffer()*AUDIOBUFSIZE;
00167     if(!fr->own_buffer) fr->buffer.data = NULL;
00168     if(fr->buffer.data != NULL && fr->buffer.size != size)
00169     {
00170         free(fr->buffer.data);
00171         fr->buffer.data = NULL;
00172     }
00173     fr->buffer.size = size;
00174     if(fr->buffer.data == NULL) fr->buffer.data = (unsigned char*) malloc(fr->buffer.size);
00175     if(fr->buffer.data == NULL)
00176     {
00177         fr->err = MPG123_OUT_OF_MEM;
00178         return -1;
00179     }
00180     fr->own_buffer = TRUE;
00181     fr->buffer.fill = 0;
00182     return 0;
00183 }
00184 
00185 int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size)
00186 {
00187     if(data == NULL || size < mpg123_safe_buffer())
00188     {
00189         mh->err = MPG123_BAD_BUFFER;
00190         return MPG123_ERR;
00191     }
00192     if(mh->own_buffer && mh->buffer.data != NULL) free(mh->buffer.data);
00193     mh->own_buffer = FALSE;
00194     mh->buffer.data = data;
00195     mh->buffer.size = size;
00196     mh->buffer.fill = 0;
00197     return MPG123_OK;
00198 }
00199 
00200 #ifdef FRAME_INDEX
00201 int frame_index_setup(mpg123_handle *fr)
00202 {
00203     int ret = MPG123_ERR;
00204     if(fr->p.index_size >= 0)
00205     { /* Simple fixed index. */
00206         fr->index.grow_size = 0;
00207         debug1("resizing index to %li", fr->p.index_size);
00208         ret = fi_resize(&fr->index, (size_t)fr->p.index_size);
00209         debug2("index resized... %lu at %p", (unsigned long)fr->index.size, (void*)fr->index.data);
00210     }
00211     else
00212     { /* A growing index. We give it a start, though. */
00213         fr->index.grow_size = (size_t)(- fr->p.index_size);
00214         if(fr->index.size < fr->index.grow_size)
00215         ret = fi_resize(&fr->index, fr->index.grow_size);
00216         else
00217         ret = MPG123_OK; /* We have minimal size already... and since growing is OK... */
00218     }
00219     debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret);
00220 
00221     return ret;
00222 }
00223 #endif
00224 
00225 static void frame_decode_buffers_reset(mpg123_handle *fr)
00226 {
00227     memset(fr->rawbuffs, 0, fr->rawbuffss);
00228 }
00229 
00230 int frame_buffers(mpg123_handle *fr)
00231 {
00232     int buffssize = 0;
00233     debug1("frame %p buffer", (void*)fr);
00234 /*
00235     the used-to-be-static buffer of the synth functions, has some subtly different types/sizes
00236 
00237     2to1, 4to1, ntom, generic, i386: real[2][2][0x110]
00238     mmx, sse: short[2][2][0x110]
00239     i586(_dither): 4352 bytes; int/long[2][2][0x110]
00240     i486: int[2][2][17*FIR_BUFFER_SIZE]
00241     altivec: static real __attribute__ ((aligned (16))) buffs[4][4][0x110]
00242 
00243     Huh, altivec looks like fun. Well, let it be large... then, the 16 byte alignment seems to be implicit on MacOSX malloc anyway.
00244     Let's make a reasonable attempt to allocate enough memory...
00245     Keep in mind: biggest ones are i486 and altivec (mutually exclusive!), then follows i586 and normal real.
00246     mmx/sse use short but also real for resampling.
00247     Thus, minimum is 2*2*0x110*sizeof(real).
00248 */
00249     if(fr->cpu_opts.type == altivec) buffssize = 4*4*0x110*sizeof(real);
00250 #ifdef OPT_I486
00251     else if(fr->cpu_opts.type == ivier) buffssize = 2*2*17*FIR_BUFFER_SIZE*sizeof(int);
00252 #endif
00253     else if(fr->cpu_opts.type == ifuenf || fr->cpu_opts.type == ifuenf_dither || fr->cpu_opts.type == dreidnow)
00254     buffssize = 2*2*0x110*4; /* don't rely on type real, we need 4352 bytes */
00255 
00256     if(2*2*0x110*sizeof(real) > buffssize)
00257     buffssize = 2*2*0x110*sizeof(real);
00258     buffssize += 15; /* For 16-byte alignment (SSE likes that). */
00259 
00260     if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize)
00261     {
00262         free(fr->rawbuffs);
00263         fr->rawbuffs = NULL;
00264     }
00265 
00266     if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize);
00267     if(fr->rawbuffs == NULL) return -1;
00268     fr->rawbuffss = buffssize;
00269     fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16);
00270     fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110;
00271     fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110;
00272     fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110;
00273     fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16);
00274     fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110;
00275     fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110;
00276     fr->real_buffs[1][1] = fr->real_buffs[1][0] + 0x110;
00277 #ifdef OPT_I486
00278     if(fr->cpu_opts.type == ivier)
00279     {
00280         fr->int_buffs[0][0] = (int*) fr->rawbuffs;
00281         fr->int_buffs[0][1] = fr->int_buffs[0][0] + 17*FIR_BUFFER_SIZE;
00282         fr->int_buffs[1][0] = fr->int_buffs[0][1] + 17*FIR_BUFFER_SIZE;
00283         fr->int_buffs[1][1] = fr->int_buffs[1][0] + 17*FIR_BUFFER_SIZE;
00284     }
00285 #endif
00286 #ifdef OPT_ALTIVEC
00287     if(fr->cpu_opts.type == altivec)
00288     {
00289         int i,j;
00290         fr->areal_buffs[0][0] = (real*) fr->rawbuffs;
00291         for(i=0; i<4; ++i) for(j=0; j<4; ++j)
00292         fr->areal_buffs[i][j] = fr->areal_buffs[0][0] + (i*4+j)*0x110;
00293     }
00294 #endif
00295     /* now the different decwins... all of the same size, actually */
00296     /* The MMX ones want 32byte alignment, which I'll try to ensure manually */
00297     {
00298         int decwin_size = (512+32)*sizeof(real);
00299 #ifdef OPT_MMXORSSE
00300 #ifdef OPT_MULTI
00301         if(fr->cpu_opts.class == mmxsse)
00302         {
00303 #endif
00304             /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */
00305             if(decwin_size < (512+32)*4) decwin_size = (512+32)*4;
00306 
00307             /* the second window + alignment zone -- we align for 32 bytes for SSE as
00308                requirement, 64 byte for matching cache line size (that matters!) */
00309             decwin_size += (512+32)*4 + 63;
00310             /* (512+32)*4/32 == 2176/32 == 68, so one decwin block retains alignment for 32 or 64 bytes */
00311 #ifdef OPT_MULTI
00312         }
00313 #endif
00314 #endif
00315 #if defined(OPT_ALTIVEC) || defined(OPT_ARM) 
00316         if(decwin_size < (512+32)*4) decwin_size = (512+32)*4;
00317         decwin_size += 512*4;
00318 #endif
00319         /* Hm, that's basically realloc() ... */
00320         if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size)
00321         {
00322             free(fr->rawdecwin);
00323             fr->rawdecwin = NULL;
00324         }
00325 
00326         if(fr->rawdecwin == NULL)
00327         fr->rawdecwin = (unsigned char*) malloc(decwin_size);
00328 
00329         if(fr->rawdecwin == NULL) return -1;
00330 
00331         fr->rawdecwins = decwin_size;
00332         fr->decwin = (real*) fr->rawdecwin;
00333 #ifdef OPT_MMXORSSE
00334 #ifdef OPT_MULTI
00335         if(fr->cpu_opts.class == mmxsse)
00336         {
00337 #endif
00338             /* align decwin, assign that to decwin_mmx, append decwins */
00339             /* I need to add to decwin what is missing to the next full 64 byte -- also I want to make gcc -pedantic happy... */
00340             fr->decwin = aligned_pointer(fr->rawdecwin,real,64);
00341             debug1("aligned decwin: %p", (void*)fr->decwin);
00342             fr->decwin_mmx = (float*)fr->decwin;
00343             fr->decwins = fr->decwin_mmx+512+32;
00344 #ifdef OPT_MULTI
00345         }
00346         else debug("no decwins/decwin_mmx for that class");
00347 #endif
00348 #endif
00349     }
00350 
00351     /* Layer scratch buffers are of compile-time fixed size, so allocate only once. */
00352     if(fr->layerscratch == NULL)
00353     {
00354         /* Allocate specific layer1/2/3 buffers, so that we know they'll work for SSE. */
00355         size_t scratchsize = 0;
00356         real *scratcher;
00357 #ifndef NO_LAYER1
00358         scratchsize += sizeof(real) * 2 * SBLIMIT;
00359 #endif
00360 #ifndef NO_LAYER2
00361         scratchsize += sizeof(real) * 2 * 4 * SBLIMIT;
00362 #endif
00363 #ifndef NO_LAYER3
00364         scratchsize += sizeof(real) * 2 * SBLIMIT * SSLIMIT; /* hybrid_in */
00365         scratchsize += sizeof(real) * 2 * SSLIMIT * SBLIMIT; /* hybrid_out */
00366 #endif
00367         /*
00368             Now figure out correct alignment:
00369             We need 16 byte minimum, smallest unit of the blocks is 2*SBLIMIT*sizeof(real), which is 64*4=256. Let's do 64bytes as heuristic for cache line (as proven useful in buffs above).
00370         */
00371         fr->layerscratch = malloc(scratchsize+63);
00372         if(fr->layerscratch == NULL) return -1;
00373 
00374         /* Get aligned part of the memory, then divide it up. */
00375         scratcher = aligned_pointer(fr->layerscratch,real,64);
00376         /* Those funky pointer casts silence compilers...
00377            One might change the code at hand to really just use 1D arrays, but in practice, that would not make a (positive) difference. */
00378 #ifndef NO_LAYER1
00379         fr->layer1.fraction = (real(*)[SBLIMIT])scratcher;
00380         scratcher += 2 * SBLIMIT;
00381 #endif
00382 #ifndef NO_LAYER2
00383         fr->layer2.fraction = (real(*)[4][SBLIMIT])scratcher;
00384         scratcher += 2 * 4 * SBLIMIT;
00385 #endif
00386 #ifndef NO_LAYER3
00387         fr->layer3.hybrid_in = (real(*)[SBLIMIT][SSLIMIT])scratcher;
00388         scratcher += 2 * SBLIMIT * SSLIMIT;
00389         fr->layer3.hybrid_out = (real(*)[SSLIMIT][SBLIMIT])scratcher;
00390         scratcher += 2 * SSLIMIT * SBLIMIT;
00391 #endif
00392         /* Note: These buffers don't need resetting here. */
00393     }
00394 
00395     /* Only reset the buffers we created just now. */
00396     frame_decode_buffers_reset(fr);
00397 
00398     debug1("frame %p buffer done", (void*)fr);
00399     return 0;
00400 }
00401 
00402 int frame_buffers_reset(mpg123_handle *fr)
00403 {
00404     fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */
00405     fr->bsnum = 0;
00406     /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */
00407     fr->bsbuf = fr->bsspace[1];
00408     fr->bsbufold = fr->bsbuf;
00409     fr->bitreservoir = 0; /* Not entirely sure if this is the right place for that counter. */
00410     frame_decode_buffers_reset(fr);
00411     memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512));
00412     memset(fr->ssave, 0, 34);
00413     fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0;
00414     memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT);
00415     return 0;
00416 }
00417 
00418 void frame_icy_reset(mpg123_handle* fr)
00419 {
00420 #ifndef NO_ICY
00421     if(fr->icy.data != NULL) free(fr->icy.data);
00422     fr->icy.data = NULL;
00423     fr->icy.interval = 0;
00424     fr->icy.next = 0;
00425 #endif
00426 }
00427 
00428 void frame_free_toc(mpg123_handle *fr)
00429 {
00430     if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; }
00431 }
00432 
00433 /* Just copy the Xing TOC over... */
00434 int frame_fill_toc(mpg123_handle *fr, unsigned char* in)
00435 {
00436     if(fr->xing_toc == NULL) fr->xing_toc = malloc(100);
00437     if(fr->xing_toc != NULL)
00438     {
00439         memcpy(fr->xing_toc, in, 100);
00440 #ifdef DEBUG
00441         debug("Got a TOC! Showing the values...");
00442         {
00443             int i;
00444             for(i=0; i<100; ++i)
00445             debug2("entry %i = %i", i, fr->xing_toc[i]);
00446         }
00447 #endif
00448         return TRUE;
00449     }
00450     return FALSE;
00451 }
00452 
00453 /* Prepare the handle for a new track.
00454    Reset variables, buffers... */
00455 int frame_reset(mpg123_handle* fr)
00456 {
00457     frame_buffers_reset(fr);
00458     frame_fixed_reset(fr);
00459     frame_free_toc(fr);
00460 #ifdef FRAME_INDEX
00461     fi_reset(&fr->index);
00462 #endif
00463 
00464     return 0;
00465 }
00466 
00467 /* Reset everythign except dynamic memory. */
00468 static void frame_fixed_reset(mpg123_handle *fr)
00469 {
00470     frame_icy_reset(fr);
00471     open_bad(fr);
00472     fr->to_decode = FALSE;
00473     fr->to_ignore = FALSE;
00474     fr->metaflags = 0;
00475     fr->outblock = mpg123_safe_buffer();
00476     fr->num = -1;
00477     fr->playnum = -1;
00478     fr->accurate = TRUE;
00479     fr->silent_resync = 0;
00480     fr->audio_start = 0;
00481     fr->clip = 0;
00482     fr->oldhead = 0;
00483     fr->firsthead = 0;
00484     fr->vbr = MPG123_CBR;
00485     fr->abr_rate = 0;
00486     fr->track_frames = 0;
00487     fr->track_samples = -1;
00488     fr->framesize=0; 
00489     fr->mean_frames = 0;
00490     fr->mean_framesize = 0;
00491     fr->freesize = 0;
00492     fr->lastscale = -1;
00493     fr->rva.level[0] = -1;
00494     fr->rva.level[1] = -1;
00495     fr->rva.gain[0] = 0;
00496     fr->rva.gain[1] = 0;
00497     fr->rva.peak[0] = 0;
00498     fr->rva.peak[1] = 0;
00499     fr->fsizeold = 0;
00500     fr->firstframe = 0;
00501     fr->ignoreframe = fr->firstframe-fr->p.preframes;
00502     fr->lastframe = -1;
00503     fr->fresh = 1;
00504     fr->new_format = 0;
00505 #ifdef GAPLESS
00506     frame_gapless_init(fr,0,0);
00507     fr->lastoff = 0;
00508     fr->firstoff = 0;
00509 #endif
00510 #ifdef OPT_I486
00511     fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1;
00512 #endif
00513     fr->bo = 1; /* the usual bo */
00514 #ifdef OPT_DITHER
00515     fr->ditherindex = 0;
00516 #endif
00517     reset_id3(fr);
00518     reset_icy(&fr->icy);
00519     /* ICY stuff should go into icy.c, eh? */
00520 #ifndef NO_ICY
00521     fr->icy.interval = 0;
00522     fr->icy.next = 0;
00523 #endif
00524     fr->halfphase = 0; /* here or indeed only on first-time init? */
00525     fr->error_protection = 0;
00526     fr->freeformat_framesize = -1;
00527 }
00528 
00529 void frame_free_buffers(mpg123_handle *fr)
00530 {
00531     if(fr->rawbuffs != NULL) free(fr->rawbuffs);
00532     fr->rawbuffs = NULL;
00533     fr->rawbuffss = 0;
00534     if(fr->rawdecwin != NULL) free(fr->rawdecwin);
00535     fr->rawdecwin = NULL;
00536     fr->rawdecwins = 0;
00537 #ifndef NO_8BIT
00538     if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf);
00539     fr->conv16to8_buf = NULL;
00540 #endif
00541     if(fr->layerscratch != NULL) free(fr->layerscratch);
00542 }
00543 
00544 void frame_exit(mpg123_handle *fr)
00545 {
00546     if(fr->own_buffer && fr->buffer.data != NULL)
00547     {
00548         debug1("freeing buffer at %p", (void*)fr->buffer.data);
00549         free(fr->buffer.data);
00550     }
00551     fr->buffer.data = NULL;
00552     frame_free_buffers(fr);
00553     frame_free_toc(fr);
00554 #ifdef FRAME_INDEX
00555     fi_exit(&fr->index);
00556 #endif
00557 #ifdef OPT_DITHER
00558     if(fr->dithernoise != NULL)
00559     {
00560         free(fr->dithernoise);
00561         fr->dithernoise = NULL;
00562     }
00563 #endif
00564     exit_id3(fr);
00565     clear_icy(&fr->icy);
00566     /* Clean up possible mess from LFS wrapper. */
00567     if(fr->wrapperclean != NULL)
00568     {
00569         fr->wrapperclean(fr->wrapperdata);
00570         fr->wrapperdata = NULL;
00571     }
00572 }
00573 
00574 int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi)
00575 {
00576     if(mh == NULL) return MPG123_ERR;
00577     if(mi == NULL)
00578     {
00579         mh->err = MPG123_ERR_NULL;
00580         return MPG123_ERR;
00581     }
00582     mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0);
00583     mi->layer = mh->lay;
00584     mi->rate = frame_freq(mh);
00585     switch(mh->mode)
00586     {
00587         case 0: mi->mode = MPG123_M_STEREO; break;
00588         case 1: mi->mode = MPG123_M_JOINT;  break;
00589         case 2: mi->mode = MPG123_M_DUAL;   break;
00590         case 3: mi->mode = MPG123_M_MONO;   break;
00591         default: error("That mode cannot be!");
00592     }
00593     mi->mode_ext = mh->mode_ext;
00594     mi->framesize = mh->framesize+4; /* Include header. */
00595     mi->flags = 0;
00596     if(mh->error_protection) mi->flags |= MPG123_CRC;
00597     if(mh->copyright)        mi->flags |= MPG123_COPYRIGHT;
00598     if(mh->extension)        mi->flags |= MPG123_PRIVATE;
00599     if(mh->original)         mi->flags |= MPG123_ORIGINAL;
00600     mi->emphasis = mh->emphasis;
00601     mi->bitrate  = frame_bitrate(mh);
00602     mi->abr_rate = mh->abr_rate;
00603     mi->vbr = mh->vbr;
00604     return MPG123_OK;
00605 }
00606 
00607 
00608 /*
00609     Fuzzy frame offset searching (guessing).
00610     When we don't have an accurate position, we may use an inaccurate one.
00611     Possibilities:
00612         - use approximate positions from Xing TOC (not yet parsed)
00613         - guess wildly from mean framesize and offset of first frame / beginning of file.
00614 */
00615 
00616 off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame)
00617 {
00618     /* Default is to go to the beginning. */
00619     off_t ret = fr->audio_start;
00620     *get_frame = 0;
00621 
00622     /* But we try to find something better. */
00623     /* Xing VBR TOC works with relative positions, both in terms of audio frames and stream bytes.
00624        Thus, it only works when whe know the length of things.
00625        Oh... I assume the offsets are relative to the _total_ file length. */
00626     if(fr->xing_toc != NULL && fr->track_frames > 0 && fr->rdat.filelen > 0)
00627     {
00628         /* One could round... */
00629         int toc_entry = (int) ((double)want_frame*100./fr->track_frames);
00630         /* It is an index in the 100-entry table. */
00631         if(toc_entry < 0)  toc_entry = 0;
00632         if(toc_entry > 99) toc_entry = 99;
00633 
00634         /* Now estimate back what frame we get. */
00635         *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames);
00636         fr->accurate = FALSE;
00637         fr->silent_resync = 1;
00638         /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only?
00639            ID3v1 info could also matter. */
00640         ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen);
00641     }
00642     else if(fr->mean_framesize > 0)
00643     {   /* Just guess with mean framesize (may be exact with CBR files). */
00644         /* Query filelen here or not? */
00645         fr->accurate = FALSE; /* Fuzzy! */
00646         fr->silent_resync = 1;
00647         *get_frame = want_frame;
00648         ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame);
00649     }
00650     debug5("fuzzy: want %li of %li, get %li at %li B of %li B",
00651         (long)want_frame, (long)fr->track_frames, (long)*get_frame, (long)ret, (long)(fr->rdat.filelen-fr->audio_start));
00652     return ret;
00653 }
00654 
00655 /*
00656     find the best frame in index just before the wanted one, seek to there
00657     then step to just before wanted one with read_frame
00658     do not care tabout the stuff that was in buffer but not played back
00659     everything that left the decoder is counted as played
00660     
00661     Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer!
00662 */
00663 
00664 off_t frame_index_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame)
00665 {
00666     /* default is file start if no index position */
00667     off_t gopos = 0;
00668     *get_frame = 0;
00669 #ifdef FRAME_INDEX
00670     /* Possibly use VBRI index, too? I'd need an example for this... */
00671     if(fr->index.fill)
00672     {
00673         /* find in index */
00674         size_t fi;
00675         /* at index fi there is frame step*fi... */
00676         fi = want_frame/fr->index.step;
00677         if(fi >= fr->index.fill) /* If we are beyond the end of frame index...*/
00678         {
00679             /* When fuzzy seek is allowed, we have some limited tolerance for the frames we want to read rather then jump over. */
00680             if(fr->p.flags & MPG123_FUZZY && want_frame - (fr->index.fill-1)*fr->index.step > 10)
00681             {
00682                 gopos = frame_fuzzy_find(fr, want_frame, get_frame);
00683                 if(gopos > fr->audio_start) return gopos; /* Only in that case, we have a useful guess. */
00684                 /* Else... just continue, fuzzyness didn't help. */
00685             }
00686             /* Use the last available position, slowly advancing from that one. */
00687             fi = fr->index.fill - 1;
00688         }
00689         /* We have index position, that yields frame and byte offsets. */
00690         *get_frame = fi*fr->index.step;
00691         gopos = fr->index.data[fi];
00692         fr->accurate = TRUE; /* When using the frame index, we are accurate. */
00693     }
00694     else
00695     {
00696 #endif
00697         if(fr->p.flags & MPG123_FUZZY)
00698         return frame_fuzzy_find(fr, want_frame, get_frame);
00699         /* A bit hackish here... but we need to be fresh when looking for the first header again. */
00700         fr->firsthead = 0;
00701         fr->oldhead = 0;
00702 #ifdef FRAME_INDEX
00703     }
00704 #endif
00705     debug2("index: 0x%lx for frame %li", (unsigned long)gopos, (long) *get_frame);
00706     return gopos;
00707 }
00708 
00709 off_t frame_ins2outs(mpg123_handle *fr, off_t ins)
00710 {   
00711     off_t outs = 0;
00712     switch(fr->down_sample)
00713     {
00714         case 0:
00715 #       ifndef NO_DOWNSAMPLE
00716         case 1:
00717         case 2:
00718 #       endif
00719             outs = ins>>fr->down_sample;
00720         break;
00721 #       ifndef NO_NTOM
00722         case 3: outs = ntom_ins2outs(fr, ins); break;
00723 #       endif
00724         default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample);
00725     }
00726     return outs;
00727 }
00728 
00729 off_t frame_outs(mpg123_handle *fr, off_t num)
00730 {
00731     off_t outs = 0;
00732     switch(fr->down_sample)
00733     {
00734         case 0:
00735 #       ifndef NO_DOWNSAMPLE
00736         case 1:
00737         case 2:
00738 #       endif
00739             outs = (spf(fr)>>fr->down_sample)*num;
00740         break;
00741 #ifndef NO_NTOM
00742         case 3: outs = ntom_frmouts(fr, num); break;
00743 #endif
00744         default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample);
00745     }
00746     return outs;
00747 }
00748 
00749 /* Compute the number of output samples we expect from this frame.
00750    This is either simple spf() or a tad more elaborate for ntom. */
00751 off_t frame_expect_outsamples(mpg123_handle *fr)
00752 {
00753     off_t outs = 0;
00754     switch(fr->down_sample)
00755     {
00756         case 0:
00757 #       ifndef NO_DOWNSAMPLE
00758         case 1:
00759         case 2:
00760 #       endif
00761             outs = spf(fr)>>fr->down_sample;
00762         break;
00763 #ifndef NO_NTOM
00764         case 3: outs = ntom_frame_outsamples(fr); break;
00765 #endif
00766         default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample);
00767     }
00768     return outs;
00769 }
00770 
00771 off_t frame_offset(mpg123_handle *fr, off_t outs)
00772 {
00773     off_t num = 0;
00774     switch(fr->down_sample)
00775     {
00776         case 0:
00777 #       ifndef NO_DOWNSAMPLE
00778         case 1:
00779         case 2:
00780 #       endif
00781             num = outs/(spf(fr)>>fr->down_sample);
00782         break;
00783 #ifndef NO_NTOM
00784         case 3: num = ntom_frameoff(fr, outs); break;
00785 #endif
00786         default: error("Bad down_sample ... should not be possible!!");
00787     }
00788     return num;
00789 }
00790 
00791 #ifdef GAPLESS
00792 /* input in _input_ samples */
00793 void frame_gapless_init(mpg123_handle *fr, off_t b, off_t e)
00794 {
00795     fr->begin_s = b;
00796     fr->end_s = e;
00797     /* These will get proper values later, from above plus resampling info. */
00798     fr->begin_os = 0;
00799     fr->end_os = 0;
00800     debug2("frame_gapless_init: from %lu to %lu samples", (long unsigned)fr->begin_s, (long unsigned)fr->end_s);
00801 }
00802 
00803 void frame_gapless_realinit(mpg123_handle *fr)
00804 {
00805     fr->begin_os = frame_ins2outs(fr, fr->begin_s);
00806     fr->end_os   = frame_ins2outs(fr, fr->end_s);
00807     debug2("frame_gapless_realinit: from %lu to %lu samples", (long unsigned)fr->begin_os, (long unsigned)fr->end_os);
00808 }
00809 
00810 /* When we got a new sample count, update the gaplessness. */
00811 void frame_gapless_update(mpg123_handle *fr, off_t total_samples)
00812 {
00813     if(fr->end_s < 1)
00814     {
00815         fr->end_s = total_samples;
00816         frame_gapless_realinit(fr);
00817     }
00818     else if(fr->end_s > total_samples)
00819     {
00820         if(NOQUIET) error2("end sample count smaller than gapless end! (%"OFF_P" < %"OFF_P").", (off_p)total_samples, (off_p)fr->end_s);
00821         /* Humbly disabling gapless stuff on track end. */
00822         fr->end_s = 0;
00823         frame_gapless_realinit(fr);
00824         fr->lastframe = -1;
00825         fr->lastoff = 0;
00826     }
00827 }
00828 
00829 #endif
00830 
00831 /* Compute the needed frame to ignore from, for getting accurate/consistent output for intended firstframe. */
00832 static off_t ignoreframe(mpg123_handle *fr)
00833 {
00834     off_t preshift = fr->p.preframes;
00835     /* Layer 3 _really_ needs at least one frame before. */
00836     if(fr->lay==3 && preshift < 1) preshift = 1;
00837     /* Layer 1 & 2 reall do not need more than 2. */
00838     if(fr->lay!=3 && preshift > 2) preshift = 2;
00839 
00840     return fr->firstframe - preshift;
00841 }
00842 
00843 /* The frame seek... This is not simply the seek to fe*spf(fr) samples in output because we think of _input_ frames here.
00844    Seek to frame offset 1 may be just seek to 200 samples offset in output since the beginning of first frame is delay/padding.
00845    Hm, is that right? OK for the padding stuff, but actually, should the decoder delay be better totally hidden or not?
00846    With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */
00847 void frame_set_frameseek(mpg123_handle *fr, off_t fe)
00848 {
00849     fr->firstframe = fe;
00850 #ifdef GAPLESS
00851     if(fr->p.flags & MPG123_GAPLESS)
00852     {
00853         /* Take care of the beginning... */
00854         off_t beg_f = frame_offset(fr, fr->begin_os);
00855         if(fe <= beg_f)
00856         {
00857             fr->firstframe = beg_f;
00858             fr->firstoff   = fr->begin_os - frame_outs(fr, beg_f);
00859         }
00860         else fr->firstoff = 0;
00861         /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */
00862         if(fr->end_os > 0)
00863         {
00864             fr->lastframe  = frame_offset(fr,fr->end_os);
00865             fr->lastoff    = fr->end_os - frame_outs(fr, fr->lastframe);
00866         } else fr->lastoff = 0;
00867     } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; }
00868 #endif
00869     fr->ignoreframe = ignoreframe(fr);
00870 #ifdef GAPLESS
00871     debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li",
00872            (long) fr->firstframe, (long) fr->firstoff,
00873            (long) fr->lastframe,  (long) fr->lastoff, (long) fr->ignoreframe);
00874 #else
00875     debug3("frame_set_frameseek: begin at %li frames, end at %li; ignore from %li",
00876            (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe);
00877 #endif
00878 }
00879 
00880 void frame_skip(mpg123_handle *fr)
00881 {
00882 #ifndef NO_LAYER3
00883     if(fr->lay == 3) set_pointer(fr, 512);
00884 #endif
00885 }
00886 
00887 /* Sample accurate seek prepare for decoder. */
00888 /* This gets unadjusted output samples and takes resampling into account */
00889 void frame_set_seek(mpg123_handle *fr, off_t sp)
00890 {
00891     fr->firstframe = frame_offset(fr, sp);
00892 #ifndef NO_NTOM
00893     if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe);
00894 #endif
00895     fr->ignoreframe = ignoreframe(fr);
00896 #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */
00897     fr->firstoff = sp - frame_outs(fr, fr->firstframe);
00898     debug5("frame_set_seek: begin at %li frames and %li samples, end at %li and %li; ignore from %li",
00899            (long) fr->firstframe, (long) fr->firstoff,
00900            (long) fr->lastframe,  (long) fr->lastoff, (long) fr->ignoreframe);
00901 #else
00902     debug3("frame_set_seek: begin at %li frames, end at %li; ignore from %li",
00903            (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe);
00904 #endif
00905     /* Old bit reservoir should be invalid, eh? */
00906     fr->bitreservoir = 0;
00907 }
00908 
00909 int attribute_align_arg mpg123_volume_change(mpg123_handle *mh, double change)
00910 {
00911     if(mh == NULL) return MPG123_ERR;
00912     return mpg123_volume(mh, change + (double) mh->p.outscale);
00913 }
00914 
00915 int attribute_align_arg mpg123_volume(mpg123_handle *mh, double vol)
00916 {
00917     if(mh == NULL) return MPG123_ERR;
00918 
00919     if(vol >= 0) mh->p.outscale = vol;
00920     else mh->p.outscale = 0.;
00921 
00922     do_rva(mh);
00923     return MPG123_OK;
00924 }
00925 
00926 static int get_rva(mpg123_handle *fr, double *peak, double *gain)
00927 {
00928     double p = -1;
00929     double g = 0;
00930     int ret = 0;
00931     if(fr->p.rva)
00932     {
00933         int rt = 0;
00934         /* Should one assume a zero RVA as no RVA? */
00935         if(fr->p.rva == 2 && fr->rva.level[1] != -1) rt = 1;
00936         if(fr->rva.level[rt] != -1)
00937         {
00938             p = fr->rva.peak[rt];
00939             g = fr->rva.gain[rt];
00940             ret = 1; /* Success. */
00941         }
00942     }
00943     if(peak != NULL) *peak = p;
00944     if(gain != NULL) *gain = g;
00945     return ret;
00946 }
00947 
00948 /* adjust the volume, taking both fr->outscale and rva values into account */
00949 void do_rva(mpg123_handle *fr)
00950 {
00951     double peak = 0;
00952     double gain = 0;
00953     double newscale;
00954     double rvafact = 1;
00955     if(get_rva(fr, &peak, &gain))
00956     {
00957         if(NOQUIET && fr->p.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", gain);
00958         rvafact = pow(10,gain/20);
00959     }
00960 
00961     newscale = fr->p.outscale*rvafact;
00962 
00963     /* if peak is unknown (== 0) this check won't hurt */
00964     if((peak*newscale) > 1.0)
00965     {
00966         newscale = 1.0/peak;
00967         warning2("limiting scale value to %f to prevent clipping with indicated peak factor of %f", newscale, peak);
00968     }
00969     /* first rva setting is forced with fr->lastscale < 0 */
00970     if(newscale != fr->lastscale || fr->decoder_change)
00971     {
00972         debug3("changing scale value from %f to %f (peak estimated to %f)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (double) (newscale*peak));
00973         fr->lastscale = newscale;
00974         /* It may be too early, actually. */
00975         if(fr->make_decode_tables != NULL) fr->make_decode_tables(fr); /* the actual work */
00976     }
00977 }
00978 
00979 
00980 int attribute_align_arg mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db)
00981 {
00982     if(mh == NULL) return MPG123_ERR;
00983     if(base)   *base   = mh->p.outscale;
00984     if(really) *really = mh->lastscale;
00985     get_rva(mh, NULL, rva_db);
00986     return MPG123_OK;
00987 }
00988 

Generated on Sat May 26 2012 04:24:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.