diff options
author | waker <wakeroid@gmail.com> | 2009-09-03 00:02:06 +0200 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2009-09-03 00:02:06 +0200 |
commit | 99644f1ebe00db9ea6117ccac25a909b291bdb07 (patch) | |
tree | 8360d046ade7d2c7e08f8d6b321f139bc7212e0c /plugins | |
parent | 5006b8847e0ad37cfa7dd2fab3e57478ec863557 (diff) |
demac seeking and proper cuesheet support
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/demac/demac.c | 109 |
1 files changed, 85 insertions, 24 deletions
diff --git a/plugins/demac/demac.c b/plugins/demac/demac.c index 51876531..024e7194 100644 --- a/plugins/demac/demac.c +++ b/plugins/demac/demac.c @@ -31,7 +31,7 @@ static DB_decoder_t plugin; static DB_functions_t *deadbeef; -#define CALC_CRC 1 +#define CALC_CRC 0 #define BLOCKS_PER_LOOP 4608 #define MAX_CHANNELS 2 @@ -59,6 +59,8 @@ static int bytesconsumed; static int timestart; static int timeend; static int nblocks; +static int samplestoskip; +static int samplesdecoded; static float ape_duration; @@ -251,6 +253,7 @@ demac_ape_parseheader(FILE *fp, struct ape_ctx_t* ape_ctx) return -1; } } + ape_ctx->numseekpoints = ape_ctx->seektablelength/sizeof (int32_t); } ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength + @@ -261,6 +264,9 @@ demac_ape_parseheader(FILE *fp, struct ape_ctx_t* ape_ctx) } static int +demac_seek (float seconds); + +static int demac_init (DB_playItem_t *it) { crc_errors = 0; fp = fopen (it->fname, "rb"); @@ -290,12 +296,15 @@ demac_init (DB_playItem_t *it) { fprintf(stderr, "demac: decoding file - v%.2f, compression level %d\n", ape_ctx.fileversion/1000.0, ape_ctx.compressiontype); currentframe = 0; + fprintf (stderr, "seek first frame: %d\n", ape_ctx.firstframe); fseek (fp, ape_ctx.firstframe, SEEK_SET); bytesinbuffer = fread (inbuffer, 1, INPUT_CHUNKSIZE, fp); firstbyte = 3; bufferfill = 0; bytesconsumed = 0; nblocks = 0; + samplestoskip = 0; + samplesdecoded = 0; plugin.info.bps = ape_ctx.bps; plugin.info.samplerate = ape_ctx.samplerate; @@ -305,6 +314,7 @@ demac_init (DB_playItem_t *it) { if (it->timeend > 0) { timestart = it->timestart; timeend = it->timeend; + demac_seek (0); } else { timestart = 0; @@ -347,7 +357,6 @@ demac_read (char *buffer, int size) { init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed); /* Update buffer */ - printf ("bytesinbuffer=%d, bytesconsumed=%d\n", bytesinbuffer, bytesconsumed); memmove(inbuffer,inbuffer + bytesconsumed, bytesinbuffer - bytesconsumed); bytesinbuffer -= bytesconsumed; @@ -381,7 +390,15 @@ demac_read (char *buffer, int size) { uint8_t *pp = wavbuffer + bufferfill; #endif uint8_t *p = wavbuffer + bufferfill; - for (i = 0 ; i < blockstodecode ; i++) + int i = 0; + while (samplestoskip > 0 && i < blockstodecode) { + i++; + samplestoskip--; + p += ape_ctx.channels * 2; + samplesdecoded++; + } + + for (; i < blockstodecode ; i++) { sample16 = decoded0[i]; *(p++) = sample16 & 0xff; @@ -394,6 +411,7 @@ demac_read (char *buffer, int size) { *(p++) = (sample16 >> 8) & 0xff; bufferfill += 2; } + samplesdecoded++; } assert (bufferfill <= WAVBUFFER_SIZE); @@ -437,37 +455,80 @@ demac_read (char *buffer, int size) { bufferfill -= sz; } } - + plugin.info.readpos = samplesdecoded / (float)plugin.info.samplerate - timestart; + if (plugin.info.readpos >= (timeend - timestart)) { + return 0; + } return sz; } +/* Given an ape_ctx and a sample to seek to, return the file position + to the frame containing that sample, and the number of samples to + skip in that frame. + */ + +static int ape_calc_seekpos(struct ape_ctx_t* ape_ctx, + uint32_t new_sample, + uint32_t* newframe, + uint32_t* filepos, + uint32_t* samplestoskip) +{ + uint32_t n; + + n = new_sample / ape_ctx->blocksperframe; + if (n >= ape_ctx->numseekpoints) + { + /* We don't have a seekpoint for that frame */ + return 0; + } + + *newframe = n; + *filepos = ape_ctx->seektable[n]; + *samplestoskip = new_sample - (n * ape_ctx->blocksperframe); + + return 1; +} + + static int demac_seek (float seconds) { seconds += timestart; - int npt = ape_ctx.seektablelength / sizeof (uint32_t); - if (npt == ape_ctx.totalframes) { - // convert to seekpoint number - int nseekpt = seconds / ape_duration * npt; - if (nseekpt >= npt) { - nseekpt = npt-1; - } - // reset all cached stuff + uint32_t newsample = seconds * plugin.info.samplerate; + if (newsample > ape_ctx.totalsamples) { + return -1; + } + uint32_t nf, fpos; + if (ape_calc_seekpos (&ape_ctx, newsample, &nf, &fpos, &samplestoskip)) { + firstbyte = 3 - (fpos & 3); + fpos &= ~3; + fseek (fp, fpos, SEEK_SET); + bytesinbuffer = fread (inbuffer, 1, INPUT_CHUNKSIZE, fp); bufferfill = 0; - currentframe = nseekpt; - bytesinbuffer = 0; - nblocks = 0; bytesconsumed = 0; - fseek (fp, ape_ctx.firstframe + ape_ctx.seektable[nseekpt], SEEK_SET); - bytesinbuffer = fread (inbuffer, 1, INPUT_CHUNKSIZE, fp); - firstbyte = 3; - plugin.info.readpos = npt * ape_duration / ape_ctx.totalframes; - return 0; + nblocks = 0; + samplesdecoded = newsample-samplestoskip; + plugin.info.readpos = seconds; } else { - fprintf (stderr, "demac: ape without seektable - not implemented yet\n"); - return -1; + // no seektable + if (newsample > samplesdecoded) { + samplestoskip = newsample - samplesdecoded; + } + else { + fpos = ape_ctx.firstframe; + samplestoskip = newsample; + firstbyte = 3 - (fpos & 3); + fpos &= ~3; + fseek (fp, fpos, SEEK_SET); + bytesinbuffer = fread (inbuffer, 1, INPUT_CHUNKSIZE, fp); + bufferfill = 0; + bytesconsumed = 0; + nblocks = 0; + samplesdecoded = 0; + } } - return -1; + plugin.info.readpos = seconds - timestart; + return 0; } static DB_playItem_t * @@ -482,7 +543,7 @@ demac_insert (DB_playItem_t *after, const char *fname) { fclose (fp); return NULL; } - ape_dumpinfo (&ape_ctx); +// ape_dumpinfo (&ape_ctx); if ((ape_ctx.fileversion < APE_MIN_VERSION) || (ape_ctx.fileversion > APE_MAX_VERSION)) { fprintf(stderr, "demac: unsupported file version - %.2f\n", ape_ctx.fileversion/1000.0); fclose (fp); |