summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/rbcodec/codecs/a52.c28
-rw-r--r--lib/rbcodec/codecs/a52_rm.c11
-rw-r--r--lib/rbcodec/codecs/aac.c15
-rw-r--r--lib/rbcodec/codecs/aiff.c17
-rw-r--r--lib/rbcodec/codecs/alac.c29
-rw-r--r--lib/rbcodec/codecs/ape.c70
-rw-r--r--lib/rbcodec/codecs/asap.c10
-rw-r--r--lib/rbcodec/codecs/atrac3_oma.c21
-rw-r--r--lib/rbcodec/codecs/atrac3_rm.c18
-rw-r--r--lib/rbcodec/codecs/au.c17
-rw-r--r--lib/rbcodec/codecs/ay.c6
-rw-r--r--lib/rbcodec/codecs/cook.c13
-rw-r--r--lib/rbcodec/codecs/flac.c16
-rw-r--r--lib/rbcodec/codecs/gbs.c5
-rw-r--r--lib/rbcodec/codecs/hes.c5
-rw-r--r--lib/rbcodec/codecs/kss.c5
-rw-r--r--lib/rbcodec/codecs/mod.c11
-rw-r--r--lib/rbcodec/codecs/mpa.c5
-rw-r--r--lib/rbcodec/codecs/mpc.c18
-rw-r--r--lib/rbcodec/codecs/nsf.c6
-rw-r--r--lib/rbcodec/codecs/opus.c47
-rw-r--r--lib/rbcodec/codecs/raac.c21
-rw-r--r--lib/rbcodec/codecs/sgc.c5
-rw-r--r--lib/rbcodec/codecs/sid.c22
-rw-r--r--lib/rbcodec/codecs/smaf.c21
-rw-r--r--lib/rbcodec/codecs/speex.c60
-rw-r--r--lib/rbcodec/codecs/tta.c16
-rw-r--r--lib/rbcodec/codecs/vgm.c5
-rw-r--r--lib/rbcodec/codecs/vorbis.c14
-rw-r--r--lib/rbcodec/codecs/vox.c20
-rw-r--r--lib/rbcodec/codecs/wav.c20
-rw-r--r--lib/rbcodec/codecs/wav64.c19
-rw-r--r--lib/rbcodec/codecs/wavpack.c14
-rwxr-xr-xlib/rbcodec/codecs/wma.c28
-rw-r--r--lib/rbcodec/codecs/wmapro.c17
-rw-r--r--lib/rbcodec/codecs/wmavoice.c24
36 files changed, 487 insertions, 192 deletions
diff --git a/lib/rbcodec/codecs/a52.c b/lib/rbcodec/codecs/a52.c
index 77caaf87c1..da670308b8 100644
--- a/lib/rbcodec/codecs/a52.c
+++ b/lib/rbcodec/codecs/a52.c
@@ -150,19 +150,28 @@ enum codec_status codec_run(void)
samplesdone = 0;
- /* The main decoding loop */
if (ci->id3->offset) {
- if (ci->seek_buffer(ci->id3->offset)) {
- samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
- A52_SAMPLESPERFRAME;
- ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
- }
+ sample_loc = (ci->id3->offset / ci->id3->bytesperframe) *
+ A52_SAMPLESPERFRAME;
+ param = ci->id3->offset;
+ }
+ else if (ci->id3->elapsed) {
+ sample_loc = ci->id3->elapsed/1000 * ci->id3->frequency;
+ param = sample_loc/A52_SAMPLESPERFRAME*ci->id3->bytesperframe;
}
else {
- ci->seek_buffer(ci->id3->first_frame_offset);
- ci->set_elapsed(0);
+ sample_loc = 0;
+ param = ci->id3->first_frame_offset;
+ }
+
+ if (ci->seek_buffer(param)) {
+ samplesdone = sample_loc;
}
+ ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
+
+ /* The main decoding loop */
+
while (1) {
enum codec_command_action action = ci->get_command(&param);
@@ -172,7 +181,8 @@ enum codec_status codec_run(void)
if (action == CODEC_ACTION_SEEK_TIME) {
sample_loc = param/1000 * ci->id3->frequency;
- if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
+ if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*
+ ci->id3->bytesperframe)) {
samplesdone = sample_loc;
ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
}
diff --git a/lib/rbcodec/codecs/a52_rm.c b/lib/rbcodec/codecs/a52_rm.c
index 42868437d8..3f07a43ce9 100644
--- a/lib/rbcodec/codecs/a52_rm.c
+++ b/lib/rbcodec/codecs/a52_rm.c
@@ -148,13 +148,15 @@ enum codec_status codec_run(void)
int consumed, packet_offset;
int playback_on = -1;
size_t resume_offset;
+ enum codec_command_action action;
intptr_t param;
- enum codec_command_action action = CODEC_ACTION_NULL;
if (codec_init()) {
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
resume_offset = ci->id3->offset;
ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -171,11 +173,14 @@ enum codec_status codec_run(void)
samplesdone = 0;
/* check for a mid-track resume and force a seek time accordingly */
- if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
- resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ if (resume_offset) {
+ resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
/* put number of subpackets to skip in resume_offset */
resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
+ }
+
+ if (param > 0) {
action = CODEC_ACTION_SEEK_TIME;
}
else {
diff --git a/lib/rbcodec/codecs/aac.c b/lib/rbcodec/codecs/aac.c
index c9cf737b48..015e332be2 100644
--- a/lib/rbcodec/codecs/aac.c
+++ b/lib/rbcodec/codecs/aac.c
@@ -72,6 +72,7 @@ enum codec_status codec_run(void)
uint32_t sbr_fac = 1;
unsigned char c = 0;
void *ret;
+ enum codec_command_action action;
intptr_t param;
bool empty_first_frame = false;
@@ -82,6 +83,8 @@ enum codec_status codec_run(void)
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
file_offset = ci->id3->offset;
ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -138,11 +141,16 @@ enum codec_status codec_run(void)
sound_samples_done = 0;
}
NeAACDecPostSeekReset(decoder, i);
+ elapsed_time = (sound_samples_done * 10) /
+ (ci->id3->frequency / 100);
+ } else if (param) {
+ elapsed_time = param;
+ action = CODEC_ACTION_SEEK_TIME;
} else {
+ elapsed_time = 0;
sound_samples_done = 0;
}
- elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
ci->set_elapsed(elapsed_time);
if (i == 0)
@@ -152,7 +160,8 @@ enum codec_status codec_run(void)
/* The main decoding loop */
while (i < demux_res.num_sample_byte_sizes) {
- enum codec_command_action action = ci->get_command(&param);
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
if (action == CODEC_ACTION_HALT)
break;
@@ -180,6 +189,8 @@ enum codec_status codec_run(void)
ci->seek_complete();
}
+ action = CODEC_ACTION_NULL;
+
/* There can be gaps between chunks, so skip ahead if needed. It
* doesn't seem to happen much, but it probably means that a
* "proper" file can have chunks out of order. Why one would want
diff --git a/lib/rbcodec/codecs/aiff.c b/lib/rbcodec/codecs/aiff.c
index 3bedfa5760..9fee781c03 100644
--- a/lib/rbcodec/codecs/aiff.c
+++ b/lib/rbcodec/codecs/aiff.c
@@ -99,6 +99,7 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
/* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
/* assume the AIFF header is less than 1024 bytes */
@@ -270,10 +271,20 @@ enum codec_status codec_run(void)
ci->advance_buffer(firstblockposn);
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn) {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ if (bytesdone) {
+ seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, NULL);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL);
if (newpos->pos > format.numbytes)
return CODEC_OK;
diff --git a/lib/rbcodec/codecs/alac.c b/lib/rbcodec/codecs/alac.c
index 5eb6e001f7..a3a5ad43b8 100644
--- a/lib/rbcodec/codecs/alac.c
+++ b/lib/rbcodec/codecs/alac.c
@@ -50,7 +50,7 @@ enum codec_status codec_run(void)
demux_res_t demux_res;
stream_t input_stream;
uint32_t samplesdone;
- uint32_t elapsedtime = 0;
+ uint32_t elapsedtime;
int samplesdecoded;
unsigned int i;
unsigned char* buffer;
@@ -71,9 +71,9 @@ enum codec_status codec_run(void)
stream_create(&input_stream,ci);
- /* Read from ci->id3->offset before calling qtmovie_read. */
- samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) /
- (ci->id3->bitrate*128));
+ /* Read resume info before calling qtmovie_read. */
+ elapsedtime = ci->id3->elapsed;
+ samplesdone = ci->id3->offset;
/* if qtmovie_read returns successfully, the stream is up to
* the movie data, which can be used directly by the decoder */
@@ -87,16 +87,24 @@ enum codec_status codec_run(void)
/* Set i for first frame, seek to desired sample position for resuming. */
i=0;
- if (samplesdone > 0) {
- if (m4a_seek(&demux_res, &input_stream, samplesdone,
+
+ if (elapsedtime || samplesdone) {
+ if (samplesdone) {
+ samplesdone =
+ (uint32_t)((uint64_t)samplesdone*ci->id3->frequency /
+ (ci->id3->bitrate*128));
+ }
+ else {
+ samplesdone = (elapsedtime/10) * (ci->id3->frequency/100);
+ }
+
+ if (!m4a_seek(&demux_res, &input_stream, samplesdone,
&samplesdone, (int*) &i)) {
- elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
- ci->set_elapsed(elapsedtime);
- } else {
samplesdone = 0;
}
}
+ elapsedtime = (samplesdone*10)/(ci->id3->frequency/100);
ci->set_elapsed(elapsedtime);
/* The main decoding loop */
@@ -106,9 +114,6 @@ enum codec_status codec_run(void)
if (action == CODEC_ACTION_HALT)
break;
- /* Request the required number of bytes from the input buffer */
- buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
-
/* Deal with any pending seek requests */
if (action == CODEC_ACTION_SEEK_TIME) {
if (m4a_seek(&demux_res, &input_stream,
diff --git a/lib/rbcodec/codecs/ape.c b/lib/rbcodec/codecs/ape.c
index 577e7b65e2..a6c5254d45 100644
--- a/lib/rbcodec/codecs/ape.c
+++ b/lib/rbcodec/codecs/ape.c
@@ -155,6 +155,7 @@ enum codec_status codec_run(void)
int res;
int firstbyte;
size_t resume_offset;
+ enum codec_command_action action;
intptr_t param;
if (codec_init()) {
@@ -162,8 +163,12 @@ enum codec_status codec_run(void)
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = 0;
+
/* Remember the resume position - when the codec is opened, the
playback engine will reset it. */
+ elapsedtime = ci->id3->elapsed;
resume_offset = ci->id3->offset;
ci->seek_buffer(0);
@@ -213,14 +218,21 @@ enum codec_status codec_run(void)
ape_resume(&ape_ctx, resume_offset,
&currentframe, &samplesdone, &samplestoskip, &firstbyte);
- } else {
+ elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
+ }
+ else {
currentframe = 0;
samplesdone = 0;
samplestoskip = 0;
firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
+
+ if (elapsedtime) {
+ /* Resume by simulated seeking */
+ param = elapsedtime;
+ action = CODEC_ACTION_SEEK_TIME;
+ }
}
- elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
ci->set_elapsed(elapsedtime);
/* Initialise the buffer */
@@ -247,36 +259,44 @@ frame_start:
/* Decode the frame a chunk at a time */
while (nblocks > 0)
{
- enum codec_command_action action = ci->get_command(&param);
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
- if (action == CODEC_ACTION_HALT)
- goto done;
+ if (action != CODEC_ACTION_NULL) {
+ if (action == CODEC_ACTION_HALT)
+ goto done;
- /* Deal with any pending seek requests */
- if (action == CODEC_ACTION_SEEK_TIME)
- {
- if (ape_calc_seekpos(&ape_ctx,
- (param/10) * (ci->id3->frequency/100),
- &currentframe,
- &newfilepos,
- &samplestoskip))
+ /* Deal with any pending seek requests */
+ if (action == CODEC_ACTION_SEEK_TIME)
{
- samplesdone = currentframe * ape_ctx.blocksperframe;
-
- /* APE's bytestream is weird... */
- firstbyte = 3 - (newfilepos & 3);
- newfilepos &= ~3;
-
- ci->seek_buffer(newfilepos);
- inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
+ if (ape_calc_seekpos(&ape_ctx,
+ (param/10) * (ci->id3->frequency/100),
+ &currentframe,
+ &newfilepos,
+ &samplestoskip))
+ {
+ samplesdone = currentframe * ape_ctx.blocksperframe;
+
+ /* APE's bytestream is weird... */
+ firstbyte = 3 - (newfilepos & 3);
+ newfilepos &= ~3;
+
+ ci->seek_buffer(newfilepos);
+ inbuffer = ci->request_buffer(&bytesleft,
+ INPUT_CHUNKSIZE);
+
+ elapsedtime = (samplesdone*10)/
+ (ape_ctx.samplerate/100);
+ ci->set_elapsed(elapsedtime);
+ ci->seek_complete();
+ action = CODEC_ACTION_NULL;
+ goto frame_start; /* Sorry... */
+ }
- elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
- ci->set_elapsed(elapsedtime);
ci->seek_complete();
- goto frame_start; /* Sorry... */
}
- ci->seek_complete();
+ action = CODEC_ACTION_NULL;
}
blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
diff --git a/lib/rbcodec/codecs/asap.c b/lib/rbcodec/codecs/asap.c
index 19b39a44c4..2c350ba450 100644
--- a/lib/rbcodec/codecs/asap.c
+++ b/lib/rbcodec/codecs/asap.c
@@ -52,6 +52,8 @@ enum codec_status codec_run(void)
return CODEC_ERROR;
}
+ param = ci->id3->elapsed;
+
codec_set_replaygain(ci->id3);
int bytes_done =0;
@@ -86,8 +88,6 @@ enum codec_status codec_run(void)
ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
bytesPerSample = 4;
}
- /* reset eleapsed */
- ci->set_elapsed(0);
song = asap.module_info->default_song;
duration = asap.module_info->durations[song];
@@ -100,6 +100,11 @@ enum codec_status codec_run(void)
ASAP_PlaySong(&asap, song, duration);
ASAP_MutePokeyChannels(&asap, 0);
+ if (param)
+ goto resume_start;
+
+ ci->set_elapsed(0);
+
/* The main decoder loop */
while (1) {
enum codec_command_action action = ci->get_command(&param);
@@ -108,6 +113,7 @@ enum codec_status codec_run(void)
break;
if (action == CODEC_ACTION_SEEK_TIME) {
+ resume_start:
/* New time is ready in param */
/* seek to pos */
diff --git a/lib/rbcodec/codecs/atrac3_oma.c b/lib/rbcodec/codecs/atrac3_oma.c
index 50f7c8f163..65d9ed8b38 100644
--- a/lib/rbcodec/codecs/atrac3_oma.c
+++ b/lib/rbcodec/codecs/atrac3_oma.c
@@ -50,13 +50,15 @@ enum codec_status codec_run(void)
int elapsed = 0;
size_t resume_offset;
intptr_t param;
- enum codec_command_action action = CODEC_ACTION_NULL;
+ enum codec_command_action action;
if (codec_init()) {
DEBUGF("codec init failed\n");
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
resume_offset = ci->id3->offset;
codec_set_replaygain(ci->id3);
@@ -79,11 +81,13 @@ enum codec_status codec_run(void)
frame_counter = 0;
/* check for a mid-track resume and force a seek time accordingly */
- if(resume_offset > ci->id3->first_frame_offset) {
- resume_offset -= ci->id3->first_frame_offset;
+ if (resume_offset) {
+ resume_offset -= MIN(resume_offset, ci->id3->first_frame_offset);
/* calculate resume_offset in frames */
- resume_offset = (int)resume_offset / FRAMESIZE;
- param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE);
+ param = (resume_offset/FRAMESIZE) * ((FRAMESIZE * 8)/BITRATE);
+ }
+
+ if ((unsigned long)param) {
action = CODEC_ACTION_SEEK_TIME;
}
else {
@@ -100,11 +104,9 @@ enum codec_status codec_run(void)
if (action == CODEC_ACTION_HALT)
break;
- bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
-
if (action == CODEC_ACTION_SEEK_TIME) {
/* Do not allow seeking beyond the file's length */
- if ((unsigned) param > ci->id3->length) {
+ if ((unsigned long) param > ci->id3->length) {
ci->set_elapsed(ci->id3->length);
ci->seek_complete();
break;
@@ -123,7 +125,6 @@ enum codec_status codec_run(void)
seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE);
frame_counter = seek_frame_offset;
ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
- bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
elapsed = param;
ci->set_elapsed(elapsed);
ci->seek_complete();
@@ -131,6 +132,8 @@ enum codec_status codec_run(void)
action = CODEC_ACTION_NULL;
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
+
res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
if(res != (int)FRAMESIZE) {
diff --git a/lib/rbcodec/codecs/atrac3_rm.c b/lib/rbcodec/codecs/atrac3_rm.c
index 997507425e..4b528c0a8d 100644
--- a/lib/rbcodec/codecs/atrac3_rm.c
+++ b/lib/rbcodec/codecs/atrac3_rm.c
@@ -57,17 +57,19 @@ enum codec_status codec_run(void)
uint8_t *bit_buffer;
uint16_t fs,sps,h;
uint32_t packet_count;
- int scrambling_unit_size, num_units, elapsed = 0;
+ int scrambling_unit_size, num_units, elapsed;
int playback_on = -1;
size_t resume_offset;
intptr_t param;
- enum codec_command_action action = CODEC_ACTION_NULL;
+ enum codec_command_action action;
if (codec_init()) {
DEBUGF("codec init failed\n");
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ elapsed = ci->id3->elapsed;
resume_offset = ci->id3->offset;
codec_set_replaygain(ci->id3);
@@ -98,15 +100,20 @@ enum codec_status codec_run(void)
}
/* check for a mid-track resume and force a seek time accordingly */
- if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
- resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ if(resume_offset) {
+ resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
num_units = (int)resume_offset / scrambling_unit_size;
/* put number of subpackets to skip in resume_offset */
resume_offset /= (sps + PACKET_HEADER_SIZE);
- param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
+ elapsed = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
+ }
+
+ if (elapsed > 0) {
+ param = elapsed;
action = CODEC_ACTION_SEEK_TIME;
}
else {
+ elapsed = 0;
ci->set_elapsed(0);
}
@@ -151,6 +158,7 @@ seek_start :
/* Seek to the start of the track */
if (param == 0) {
+ elapsed = 0;
ci->set_elapsed(0);
ci->seek_complete();
action = CODEC_ACTION_NULL;
diff --git a/lib/rbcodec/codecs/au.c b/lib/rbcodec/codecs/au.c
index 7ae7fe3e94..18d4296125 100644
--- a/lib/rbcodec/codecs/au.c
+++ b/lib/rbcodec/codecs/au.c
@@ -139,6 +139,7 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
/* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
ci->memset(&format, 0, sizeof(struct pcm_format));
@@ -236,10 +237,20 @@ enum codec_status codec_run(void)
}
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn) {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ if (bytesdone) {
+ seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, NULL);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL);
if (newpos->pos > format.numbytes)
goto done;
diff --git a/lib/rbcodec/codecs/ay.c b/lib/rbcodec/codecs/ay.c
index b11ad84294..88936df131 100644
--- a/lib/rbcodec/codecs/ay.c
+++ b/lib/rbcodec/codecs/ay.c
@@ -56,6 +56,7 @@ enum codec_status codec_run(void)
/* reset values */
track = is_multitrack = 0;
elapsed_time = 0;
+ param = ci->id3->elapsed;
DEBUGF("AY: next_track\n");
if (codec_init()) {
@@ -87,6 +88,10 @@ enum codec_status codec_run(void)
is_multitrack = 1;
}
+ if (param) {
+ goto resume_start;
+ }
+
next_track:
set_codec_track(track, is_multitrack);
@@ -98,6 +103,7 @@ next_track:
break;
if (action == CODEC_ACTION_SEEK_TIME) {
+ resume_start:
if (is_multitrack) {
track = param/1000;
ci->seek_complete();
diff --git a/lib/rbcodec/codecs/cook.c b/lib/rbcodec/codecs/cook.c
index 55188aad36..402d1d3fa6 100644
--- a/lib/rbcodec/codecs/cook.c
+++ b/lib/rbcodec/codecs/cook.c
@@ -56,14 +56,16 @@ enum codec_status codec_run(void)
uint32_t packet_count;
int scrambling_unit_size, num_units;
size_t resume_offset;
- intptr_t param = 0;
- enum codec_command_action action = CODEC_ACTION_NULL;
+ intptr_t param;
+ enum codec_command_action action;
if (codec_init()) {
DEBUGF("codec init failed\n");
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
resume_offset = ci->id3->offset;
codec_set_replaygain(ci->id3);
@@ -97,12 +99,15 @@ enum codec_status codec_run(void)
}
/* check for a mid-track resume and force a seek time accordingly */
- if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
- resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ if(resume_offset) {
+ resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
num_units = (int)resume_offset / scrambling_unit_size;
/* put number of subpackets to skip in resume_offset */
resume_offset /= (sps + PACKET_HEADER_SIZE);
param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
+ }
+
+ if (param) {
action = CODEC_ACTION_SEEK_TIME;
}
else {
diff --git a/lib/rbcodec/codecs/flac.c b/lib/rbcodec/codecs/flac.c
index 3390c24a2c..eab6e7c2bc 100644
--- a/lib/rbcodec/codecs/flac.c
+++ b/lib/rbcodec/codecs/flac.c
@@ -468,7 +468,8 @@ enum codec_status codec_run(void)
return CODEC_ERROR;
}
- /* Need to save offset for later use (cleared indirectly by flac_init) */
+ /* Need to save resume for later use (cleared indirectly by flac_init) */
+ elapsedtime = ci->id3->elapsed;
samplesdone = ci->id3->offset;
if (!flac_init(&fc,ci->id3->first_frame_offset)) {
@@ -481,9 +482,16 @@ enum codec_status codec_run(void)
STEREO_MONO : STEREO_NONINTERLEAVED);
codec_set_replaygain(ci->id3);
- flac_seek_offset(&fc, samplesdone);
- samplesdone=fc.samplenumber+fc.blocksize;
- elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency);
+ if (samplesdone || !elapsedtime) {
+ flac_seek_offset(&fc, samplesdone);
+ samplesdone=fc.samplenumber+fc.blocksize;
+ elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency);
+ }
+ else if (!flac_seek(&fc,(uint32_t)((uint64_t)elapsedtime
+ *ci->id3->frequency/1000))) {
+ elapsedtime = 0;
+ }
+
ci->set_elapsed(elapsedtime);
/* The main decoding loop */
diff --git a/lib/rbcodec/codecs/gbs.c b/lib/rbcodec/codecs/gbs.c
index def05ed351..717f56c82f 100644
--- a/lib/rbcodec/codecs/gbs.c
+++ b/lib/rbcodec/codecs/gbs.c
@@ -76,6 +76,11 @@ enum codec_status codec_run(void)
if (gbs_emu.m3u.size > 0)
gbs_emu.track_count = gbs_emu.m3u.size;
+ if (ci->id3->elapsed) {
+ track = ci->id3->elapsed/1000;
+ if (track >= gbs_emu.track_count) return CODEC_OK;
+ }
+
next_track:
set_codec_track(track);
diff --git a/lib/rbcodec/codecs/hes.c b/lib/rbcodec/codecs/hes.c
index 849fd88f12..56f49621c6 100644
--- a/lib/rbcodec/codecs/hes.c
+++ b/lib/rbcodec/codecs/hes.c
@@ -76,6 +76,11 @@ enum codec_status codec_run(void)
if (hes_emu.m3u.size > 0)
hes_emu.track_count = hes_emu.m3u.size;
+ if (ci->id3->elapsed) {
+ track = ci->id3->elapsed/1000;
+ if (track >= hes_emu.track_count) return CODEC_OK;
+ }
+
next_track:
set_codec_track(track);
diff --git a/lib/rbcodec/codecs/kss.c b/lib/rbcodec/codecs/kss.c
index 92efcd4e5f..e6cf866cdd 100644
--- a/lib/rbcodec/codecs/kss.c
+++ b/lib/rbcodec/codecs/kss.c
@@ -79,6 +79,11 @@ enum codec_status codec_run(void)
if (kss_emu.m3u.size > 0)
kss_emu.track_count = kss_emu.m3u.size;
+ if (ci->id3->elapsed) {
+ track = ci->id3->elapsed/1000;
+ if (track >= kss_emu.track_count) return CODEC_OK;
+ }
+
next_track:
set_codec_track(track);
diff --git a/lib/rbcodec/codecs/mod.c b/lib/rbcodec/codecs/mod.c
index 8bb2dc5163..4dd0cde6e5 100644
--- a/lib/rbcodec/codecs/mod.c
+++ b/lib/rbcodec/codecs/mod.c
@@ -1319,7 +1319,16 @@ enum codec_status codec_run(void)
loadmod(modfile);
/* The main decoder loop */
- ci->set_elapsed(0);
+#if 0
+ /* Needs to be a bit more elaborate or critical stuff is missed */
+ if (ci->id3->elapsed) {
+ modplayer.patterntableposition = ci->id3->elapsed/1000;
+ modplayer.currentline = 0;
+ }
+#endif
+
+ ci->set_elapsed(modplayer.patterntableposition*1000);
+
bytesdone = 0;
old_patterntableposition = 0;
diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c
index 07db248099..ca12087e87 100644
--- a/lib/rbcodec/codecs/mpa.c
+++ b/lib/rbcodec/codecs/mpa.c
@@ -346,6 +346,11 @@ enum codec_status codec_run(void)
current_frequency = ci->id3->frequency;
codec_set_replaygain(ci->id3);
+ if (!ci->id3->offset && ci->id3->elapsed) {
+ /* Have elapsed time but not offset */
+ ci->id3->offset = get_file_pos(ci->id3->elapsed);
+ }
+
if (ci->id3->offset) {
ci->seek_buffer(ci->id3->offset);
set_elapsed(ci->id3);
diff --git a/lib/rbcodec/codecs/mpc.c b/lib/rbcodec/codecs/mpc.c
index 9db40242dc..79f2aa22db 100644
--- a/lib/rbcodec/codecs/mpc.c
+++ b/lib/rbcodec/codecs/mpc.c
@@ -108,6 +108,7 @@ enum codec_status codec_run(void)
* sample seek position from the file offset, the sampling frequency and
* the bitrate. As the saved position is exactly calculated the reverse way
* there is no loss of information except rounding. */
+ elapsed_time = ci->id3->elapsed;
samplesdone = 100 * (((mpc_uint64_t)ci->id3->offset * frequency) / byterate);
/* Set up digital signal processing for correct number of channels */
@@ -122,19 +123,24 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
- /* Resume to saved sample offset. */
- elapsed_time = 0;
-
- if (samplesdone > 0)
+ if (samplesdone > 0 || elapsed_time)
{
- if (mpc_demux_seek_sample(demux, samplesdone) == MPC_STATUS_OK)
+ mpc_int64_t new_offset = samplesdone;
+
+ if (new_offset <= 0)
+ new_offset = (elapsed_time/10)*frequency; /* by time */
+
+ /* Resume to sample offset. */
+ if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK)
{
- elapsed_time = (samplesdone*10)/frequency;
+ samplesdone = new_offset;
}
else
{
samplesdone = 0;
}
+
+ elapsed_time = (samplesdone*10)/frequency;
}
ci->set_elapsed(elapsed_time);
diff --git a/lib/rbcodec/codecs/nsf.c b/lib/rbcodec/codecs/nsf.c
index 4c5b37c3fa..cbdf8e3ec5 100644
--- a/lib/rbcodec/codecs/nsf.c
+++ b/lib/rbcodec/codecs/nsf.c
@@ -57,6 +57,7 @@ enum codec_status codec_run(void)
track = is_multitrack = 0;
elapsed_time = 0;
+ param = ci->id3->elapsed;
DEBUGF("NSF: next_track\n");
if (codec_init()) {
@@ -85,6 +86,10 @@ enum codec_status codec_run(void)
if (nsf_emu.track_count > 1) is_multitrack = 1;
+ if (param) {
+ goto resume_start;
+ }
+
next_track:
set_codec_track(track, is_multitrack);
@@ -96,6 +101,7 @@ next_track:
break;
if (action == CODEC_ACTION_SEEK_TIME) {
+ resume_start:
if (is_multitrack) {
track = param/1000;
ci->seek_complete();
diff --git a/lib/rbcodec/codecs/opus.c b/lib/rbcodec/codecs/opus.c
index 15d96ff6fe..2c495aa8d0 100644
--- a/lib/rbcodec/codecs/opus.c
+++ b/lib/rbcodec/codecs/opus.c
@@ -314,6 +314,7 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
enum codec_status codec_run(void)
{
int error = CODEC_ERROR;
+ enum codec_command_action action;
intptr_t param;
ogg_sync_state oy;
ogg_page og;
@@ -325,13 +326,17 @@ enum codec_status codec_run(void)
OpusDecoder *st = NULL;
OpusHeader header;
int ret;
- unsigned long strtoffset = ci->id3->offset;
+ unsigned long strtoffset;
int skip = 0;
int64_t seek_target;
uint64_t granule_pos;
ogg_malloc_init();
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
+ strtoffset = ci->id3->offset;
+
global_stack = 0;
#if defined(CPU_COLDFIRE)
@@ -351,28 +356,40 @@ enum codec_status codec_run(void)
ci->seek_buffer(0);
ci->set_elapsed(0);
+ if (!strtoffset && param) {
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+
+ goto next_page;
+
while (1) {
- enum codec_command_action action = ci->get_command(&param);
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
- if (action == CODEC_ACTION_HALT)
- break;
+ if (action != CODEC_ACTION_NULL) {
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ if (st != NULL) {
+ /* calculate granule to seek to (including seek rewind) */
+ seek_target = (48LL * param) + header.preskip;
+ skip = MIN(seek_target, SEEK_REWIND);
+ seek_target -= skip;
- if (action == CODEC_ACTION_SEEK_TIME) {
- if (st != NULL) {
- /* calculate granule to seek to (including seek rewind) */
- seek_target = (48LL * param) + header.preskip;
- skip = MIN(seek_target, SEEK_REWIND);
- seek_target -= skip;
+ LOGF("Opus seek page:%lld,%lld,%ld\n",
+ seek_target, page_granule, (long)param);
+ speex_seek_page_granule(seek_target, page_granule, &oy, &os);
+ }
- LOGF("Opus seek page:%lld,%lld,%ld\n",
- seek_target, page_granule, (long)param);
- speex_seek_page_granule(seek_target, page_granule, &oy, &os);
+ ci->set_elapsed(param);
+ ci->seek_complete();
}
- ci->set_elapsed(param);
- ci->seek_complete();
+ action = CODEC_ACTION_NULL;
}
+ next_page:
/*Get the ogg buffer for writing*/
if (get_more_data(&oy) < 1) {
goto done;
diff --git a/lib/rbcodec/codecs/raac.c b/lib/rbcodec/codecs/raac.c
index 523560b63e..d2d3531028 100644
--- a/lib/rbcodec/codecs/raac.c
+++ b/lib/rbcodec/codecs/raac.c
@@ -63,14 +63,16 @@ enum codec_status codec_run(void)
unsigned char c = 0; /* channels */
int playback_on = -1;
size_t resume_offset;
+ enum codec_command_action action;
intptr_t param;
- enum codec_command_action action = CODEC_ACTION_NULL;
if (codec_init()) {
DEBUGF("FAAD: Codec init error\n");
return CODEC_ERROR;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
resume_offset = ci->id3->offset;
ci->memset(&rmctx,0,sizeof(RMContext));
@@ -104,15 +106,21 @@ enum codec_status codec_run(void)
}
/* check for a mid-track resume and force a seek time accordingly */
- if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
- resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ if (resume_offset) {
+ resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
/* put number of subpackets to skip in resume_offset */
resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
+ }
+
+ if (param > 0) {
action = CODEC_ACTION_SEEK_TIME;
}
- ci->set_elapsed(0);
- ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+ else {
+ /* Seek to the first packet */
+ ci->set_elapsed(0);
+ ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+ }
/* The main decoding loop */
while (1) {
@@ -124,7 +132,7 @@ enum codec_status codec_run(void)
if (action == CODEC_ACTION_SEEK_TIME) {
/* Do not allow seeking beyond the file's length */
- if ((unsigned) param > ci->id3->length) {
+ if ((unsigned long)param > ci->id3->length) {
ci->set_elapsed(ci->id3->length);
ci->seek_complete();
break;
@@ -164,6 +172,7 @@ enum codec_status codec_run(void)
ci->advance_buffer(pkt.length);
}
+
ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE);
buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
NeAACDecPostSeekReset(decoder, decoder->frame);
diff --git a/lib/rbcodec/codecs/sgc.c b/lib/rbcodec/codecs/sgc.c
index 348a54a2d3..eb260975c5 100644
--- a/lib/rbcodec/codecs/sgc.c
+++ b/lib/rbcodec/codecs/sgc.c
@@ -91,6 +91,11 @@ enum codec_status codec_run(void)
if (sgc_emu.m3u.size > 0)
sgc_emu.track_count = sgc_emu.m3u.size;
+ if (ci->id3->elapsed) {
+ track = ci->id3->elapsed/1000;
+ if (track >= sgc_emu.track_count) return CODEC_OK;
+ }
+
next_track:
set_codec_track(track);
diff --git a/lib/rbcodec/codecs/sid.c b/lib/rbcodec/codecs/sid.c
index 1a6d04155d..6e39d3f759 100644
--- a/lib/rbcodec/codecs/sid.c
+++ b/lib/rbcodec/codecs/sid.c
@@ -1253,6 +1253,7 @@ enum codec_status codec_run(void)
unsigned char subSongsMax, subSong, song_speed;
unsigned char *sidfile = NULL;
intptr_t param;
+ bool resume;
if (codec_init()) {
return CODEC_ERROR;
@@ -1269,15 +1270,10 @@ enum codec_status codec_run(void)
return CODEC_ERROR;
}
- c64Init(SAMPLE_RATE);
- LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr,
- &subSongsMax, &subSong, &song_speed, (unsigned short)filesize);
- sidPoke(24, 15); /* Turn on full volume */
- cpuJSR(init_addr, subSong); /* Start the song initialize */
+ param = ci->id3->elapsed;
+ resume = param != 0;
-
- /* Set the elapsed time to the current subsong (in seconds) */
- ci->set_elapsed(subSong*1000);
+ goto sid_start;
/* The main decoder loop */
while (1) {
@@ -1287,20 +1283,26 @@ enum codec_status codec_run(void)
break;
if (action == CODEC_ACTION_SEEK_TIME) {
+ sid_start:
/* New time is ready in param */
/* Start playing from scratch */
c64Init(SAMPLE_RATE);
LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr,
- &subSongsMax, &subSong, &song_speed, (unsigned short)filesize);
+ &subSongsMax, &subSong, &song_speed,
+ (unsigned short)filesize);
sidPoke(24, 15); /* Turn on full volume */
- subSong = param / 1000; /* Now use the current seek time in seconds as subsong */
+ if (!resume || (resume && param))
+ subSong = param / 1000; /* Now use the current seek time in
+ seconds as subsong */
cpuJSR(init_addr, subSong); /* Start the song initialize */
nSamplesToRender = 0; /* Start the rendering from scratch */
/* Set the elapsed time to the current subsong (in seconds) */
ci->set_elapsed(subSong*1000);
ci->seek_complete();
+
+ resume = false;
}
nSamplesRendered = 0;
diff --git a/lib/rbcodec/codecs/smaf.c b/lib/rbcodec/codecs/smaf.c
index d56aa0a860..e4ec6342b2 100644
--- a/lib/rbcodec/codecs/smaf.c
+++ b/lib/rbcodec/codecs/smaf.c
@@ -360,7 +360,8 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
- /* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ /* Need to save resume for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
decodedsamples = 0;
@@ -408,11 +409,21 @@ enum codec_status codec_run(void)
ci->seek_buffer(firstblockposn);
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn)
- {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ if (bytesdone) {
+ seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, &read_buffer);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
+ &read_buffer);
if (newpos->pos > format.numbytes)
return CODEC_OK;
diff --git a/lib/rbcodec/codecs/speex.c b/lib/rbcodec/codecs/speex.c
index ac3bc963b1..a073151ee2 100644
--- a/lib/rbcodec/codecs/speex.c
+++ b/lib/rbcodec/codecs/speex.c
@@ -381,7 +381,6 @@ enum codec_status codec_run(void)
int error = CODEC_ERROR;
SpeexBits bits;
- int eof = 0;
spx_ogg_sync_state oy;
spx_ogg_page og;
spx_ogg_packet op;
@@ -403,9 +402,10 @@ enum codec_status codec_run(void)
int packet_count = 0;
int lookahead;
int headerssize = 0;
- unsigned long strtoffset = ci->id3->offset;
+ unsigned long strtoffset;
void *st = NULL;
int j = 0;
+ enum codec_command_action action;
intptr_t param;
memset(&bits, 0, sizeof(bits));
@@ -416,6 +416,10 @@ enum codec_status codec_run(void)
goto exit;
}
+ action = CODEC_ACTION_NULL;
+ param = ci->id3->elapsed;
+ strtoffset = ci->id3->offset;
+
ci->seek_buffer(0);
ci->set_elapsed(0);
@@ -425,29 +429,39 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
- eof = 0;
- while (!eof) {
- enum codec_command_action action = ci->get_command(&param);
-
- if (action == CODEC_ACTION_HALT)
- break;
-
- /*seek (seeks to the page before the position) */
- if (action == CODEC_ACTION_SEEK_TIME) {
- if(samplerate!=0&&packet_count>1){
- LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
- ((spx_int64_t)param/1000) *
- (spx_int64_t)samplerate,
- page_granule, (long)param,
- (page_granule/samplerate)*1000, samplerate);
-
- speex_seek_page_granule(((spx_int64_t)param/1000) *
- (spx_int64_t)samplerate,
- page_granule, &oy, headerssize);
+ if (!strtoffset && param) {
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+
+ goto next_page;
+
+ while (1) {
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
+
+ if (action != CODEC_ACTION_NULL) {
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ /*seek (seeks to the page before the position) */
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ if(samplerate!=0&&packet_count>1){
+ LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
+ ((spx_int64_t)param/1000) *
+ (spx_int64_t)samplerate,
+ page_granule, (long)param,
+ (page_granule/samplerate)*1000, samplerate);
+
+ speex_seek_page_granule(((spx_int64_t)param/1000) *
+ (spx_int64_t)samplerate,
+ page_granule, &oy, headerssize);
+ }
+
+ ci->set_elapsed(param);
+ ci->seek_complete();
}
- ci->set_elapsed(param);
- ci->seek_complete();
+ action = CODEC_ACTION_NULL;
}
next_page:
diff --git a/lib/rbcodec/codecs/tta.c b/lib/rbcodec/codecs/tta.c
index 564496a14e..b7660a920f 100644
--- a/lib/rbcodec/codecs/tta.c
+++ b/lib/rbcodec/codecs/tta.c
@@ -82,10 +82,20 @@ enum codec_status codec_run(void)
decodedsamples = 0;
endofstream = 0;
- if (ci->id3->offset > 0)
+ if (ci->id3->offset || ci->id3->elapsed)
{
- /* Need to save offset for later use (cleared indirectly by advance_buffer) */
- new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
+ /* Need to save offset for later use (cleared indirectly by
+ advance_buffer) */
+ unsigned int pos = ci->id3->offset;
+ enum tta_seek_type type = TTA_SEEK_POS;
+
+ if (!pos) {
+ pos = ci->id3->elapsed / SEEK_STEP;
+ type = TTA_SEEK_TIME;
+ }
+
+ new_pos = set_position(pos, type);
+
if (new_pos >= 0)
decodedsamples = new_pos;
}
diff --git a/lib/rbcodec/codecs/vgm.c b/lib/rbcodec/codecs/vgm.c
index 9f2f1b9c5e..126305944f 100644
--- a/lib/rbcodec/codecs/vgm.c
+++ b/lib/rbcodec/codecs/vgm.c
@@ -127,7 +127,10 @@ enum codec_status codec_run(void)
Vgm_start_track(&vgm_emu);
- ci->set_elapsed(0);
+ if (ci->id3->elapsed != 0)
+ Track_seek(&vgm_emu, ci->id3->elapsed);
+
+ codec_update_elapsed();
codec_update_fade();
/* The main decoder loop */
diff --git a/lib/rbcodec/codecs/vorbis.c b/lib/rbcodec/codecs/vorbis.c
index c09d2cea6d..ca9db9b802 100644
--- a/lib/rbcodec/codecs/vorbis.c
+++ b/lib/rbcodec/codecs/vorbis.c
@@ -126,7 +126,6 @@ enum codec_status codec_run(void)
long n;
int current_section;
int previous_section;
- int eof;
ogg_int64_t vf_offsets[2];
ogg_int64_t vf_dataoffsets;
ogg_uint32_t vf_serialnos;
@@ -193,16 +192,17 @@ enum codec_status codec_run(void)
if (ci->id3->offset) {
ci->seek_buffer(ci->id3->offset);
ov_raw_seek(&vf, ci->id3->offset);
- ci->set_elapsed(ov_time_tell(&vf));
ci->set_offset(ov_raw_tell(&vf));
}
- else {
- ci->set_elapsed(0);
+ else if (ci->id3->elapsed) {
+ ov_time_seek(&vf, ci->id3->elapsed);
}
+ ci->set_elapsed(ov_time_tell(&vf));
+
previous_section = -1;
- eof = 0;
- while (!eof) {
+
+ while (1) {
enum codec_command_action action = ci->get_command(&param);
if (action == CODEC_ACTION_HALT)
@@ -230,7 +230,7 @@ enum codec_status codec_run(void)
}
if (n == 0) {
- eof = 1;
+ break;
} else if (n < 0) {
DEBUGF("Vorbis: Error decoding frame\n");
} else {
diff --git a/lib/rbcodec/codecs/vox.c b/lib/rbcodec/codecs/vox.c
index 66979e2911..d84af24cfc 100644
--- a/lib/rbcodec/codecs/vox.c
+++ b/lib/rbcodec/codecs/vox.c
@@ -73,7 +73,8 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
- /* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ /* Need to save resume for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
ci->seek_buffer(0);
@@ -123,10 +124,21 @@ enum codec_status codec_run(void)
ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn) {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ if (bytesdone) {
+ seek_val = bytesdone - MIN((uint32_t )firstblockposn, bytesdone);
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, &read_buffer);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
+ &read_buffer);
if (newpos->pos > format.numbytes) {
return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wav.c b/lib/rbcodec/codecs/wav.c
index cc65ab83b2..3208e2b5b8 100644
--- a/lib/rbcodec/codecs/wav.c
+++ b/lib/rbcodec/codecs/wav.c
@@ -182,7 +182,8 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
- /* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ /* Need to save resume for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
/* get RIFF chunk header */
@@ -361,10 +362,21 @@ enum codec_status codec_run(void)
}
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn) {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ if (bytesdone) {
+ seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, &read_buffer);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
+ &read_buffer);
if (newpos->pos > format.numbytes)
return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wav64.c b/lib/rbcodec/codecs/wav64.c
index 9b3b2d38e4..96e605faad 100644
--- a/lib/rbcodec/codecs/wav64.c
+++ b/lib/rbcodec/codecs/wav64.c
@@ -191,6 +191,7 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3);
/* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ param = ci->id3->elapsed;
bytesdone = ci->id3->offset;
/* get RIFF chunk header */
@@ -363,10 +364,22 @@ enum codec_status codec_run(void)
}
/* make sure we're at the correct offset */
- if (bytesdone > (uint32_t) firstblockposn) {
+ if (bytesdone > (uint32_t) firstblockposn || param) {
+ uint32_t seek_val;
+ int seek_mode;
+
+ /* we prefer offset resume */
+ if (bytesdone > (uint32_t) firstblockposn) {
+ seek_val = bytesdone - firstblockposn;
+ seek_mode = PCM_SEEK_POS;
+ } else {
+ seek_val = param;
+ seek_mode = PCM_SEEK_TIME;
+ }
+
/* Round down to previous block */
- struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
- PCM_SEEK_POS, &read_buffer);
+ struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
+ &read_buffer);
if (newpos->pos > format.numbytes) {
return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wavpack.c b/lib/rbcodec/codecs/wavpack.c
index c0cdafabac..d9c294397c 100644
--- a/lib/rbcodec/codecs/wavpack.c
+++ b/lib/rbcodec/codecs/wavpack.c
@@ -55,12 +55,16 @@ enum codec_status codec_run(void)
int bps;
*/
int nchans, sr_100;
+ unsigned long offset;
intptr_t param;
if (codec_init())
return CODEC_ERROR;
- ci->seek_buffer (ci->id3->offset);
+ param = ci->id3->elapsed;
+ offset = ci->id3->offset;
+
+ ci->seek_buffer (offset);
/* Create a decoder instance */
wpc = WavpackOpenFileInput (read_callback, error);
@@ -75,7 +79,12 @@ enum codec_status codec_run(void)
ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO);
sr_100 = ci->id3->frequency / 100;
- ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
+ if (!offset && param) {
+ goto resume_start; /* resume by elapsed */
+ }
+ else {
+ ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
+ }
/* The main decoder loop */
@@ -87,6 +96,7 @@ enum codec_status codec_run(void)
break;
if (action == CODEC_ACTION_SEEK_TIME) {
+ resume_start:;
int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10;
int n, d, skip;
diff --git a/lib/rbcodec/codecs/wma.c b/lib/rbcodec/codecs/wma.c
index 9039f81429..9a5e0c71fa 100755
--- a/lib/rbcodec/codecs/wma.c
+++ b/lib/rbcodec/codecs/wma.c
@@ -52,13 +52,16 @@ enum codec_status codec_run(void)
int audiobufsize;
int packetlength = 0;
int errcount = 0;
+ enum codec_command_action action;
intptr_t param;
/* Remember the resume position - when the codec is opened, the
playback engine will reset it. */
+ elapsedtime = ci->id3->elapsed;
resume_offset = ci->id3->offset;
restart_track:
+ action = CODEC_ACTION_NULL;
/* Proper reset of the decoder context. */
memset(&wmadec, 0, sizeof(wmadec));
@@ -78,13 +81,20 @@ restart_track:
return CODEC_ERROR;
}
- if (resume_offset > ci->id3->first_frame_offset)
+ if (resume_offset > ci->id3->first_frame_offset || elapsedtime)
{
- /* Get start of current packet */
- int packet_offset = (resume_offset - ci->id3->first_frame_offset)
- % wfx.packet_size;
- ci->seek_buffer(resume_offset - packet_offset);
- elapsedtime = asf_get_timestamp(&i);
+ if (resume_offset) {
+ /* Get start of current packet */
+ int packet_offset = (resume_offset -
+ MIN(resume_offset, ci->id3->first_frame_offset))
+ % wfx.packet_size;
+ ci->seek_buffer(resume_offset - packet_offset);
+ elapsedtime = asf_get_timestamp(&i);
+ }
+ else {
+ param = elapsedtime;
+ action = CODEC_ACTION_SEEK_TIME;
+ }
}
else
{
@@ -104,7 +114,8 @@ restart_track:
/* The main decoding loop */
while (res >= 0)
{
- enum codec_command_action action = ci->get_command(&param);
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
if (action != CODEC_ACTION_NULL) {
@@ -126,6 +137,7 @@ restart_track:
if (param == 0) {
ci->set_elapsed(0);
ci->seek_complete();
+ elapsedtime = 0;
goto restart_track; /* Pretend you never saw this... */
}
@@ -140,6 +152,8 @@ restart_track:
ci->set_elapsed(elapsedtime);
ci->seek_complete();
}
+
+ action = CODEC_ACTION_NULL;
}
errcount = 0;
diff --git a/lib/rbcodec/codecs/wmapro.c b/lib/rbcodec/codecs/wmapro.c
index d99ca1aa9e..f15f36813d 100644
--- a/lib/rbcodec/codecs/wmapro.c
+++ b/lib/rbcodec/codecs/wmapro.c
@@ -55,6 +55,8 @@ enum codec_status codec_run(void)
int size; /* Size of the input frame to the decoder */
intptr_t param;
+ elapsedtime = ci->id3->elapsed;
+
restart_track:
if (codec_init()) {
LOGF("(WMA PRO) Error: Error initialising codec\n");
@@ -75,11 +77,17 @@ restart_track:
return CODEC_ERROR;
}
- /* Now advance the file position to the first frame */
- ci->seek_buffer(ci->id3->first_frame_offset);
+ if (elapsedtime) {
+ elapsedtime = asf_seek(elapsedtime, &wfx);
+ if (elapsedtime < 1)
+ return CODEC_OK;
+ }
+ else {
+ /* Now advance the file position to the first frame */
+ ci->seek_buffer(ci->id3->first_frame_offset);
+ }
- elapsedtime = 0;
- ci->set_elapsed(0);
+ ci->set_elapsed(elapsedtime);
/* The main decoding loop */
@@ -95,6 +103,7 @@ restart_track:
if (param == 0) {
ci->set_elapsed(0);
ci->seek_complete();
+ elapsedtime = 0;
goto restart_track; /* Pretend you never saw this... */
}
diff --git a/lib/rbcodec/codecs/wmavoice.c b/lib/rbcodec/codecs/wmavoice.c
index 214e0737e7..4c89c6dc96 100644
--- a/lib/rbcodec/codecs/wmavoice.c
+++ b/lib/rbcodec/codecs/wmavoice.c
@@ -67,7 +67,6 @@ enum codec_status codec_run(void)
{
uint32_t elapsedtime;
asf_waveformatex_t wfx; /* Holds the stream properties */
- size_t resume_offset;
int res; /* Return values from asf_read_packet() and decode_packet() */
uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */
int audiobufsize; /* Payload size */
@@ -76,8 +75,8 @@ enum codec_status codec_run(void)
int pktcnt = 0; /* Count of the packets played */
intptr_t param;
- /* Remember the resume position */
- resume_offset = ci->id3->offset;
+ elapsedtime = ci->id3->elapsed;
+
restart_track:
if (codec_init()) {
LOGF("(WMA Voice) Error: Error initialising codec\n");
@@ -105,13 +104,17 @@ restart_track:
return CODEC_ERROR;
}
- /* Now advance the file position to the first frame */
- ci->seek_buffer(ci->id3->first_frame_offset);
-
- elapsedtime = 0;
- ci->set_elapsed(0);
+ if (elapsedtime) {
+ elapsedtime = asf_seek(elapsedtime, &wfx);
+ if (elapsedtime < 1)
+ return CODEC_OK;
+ }
+ else {
+ /* Now advance the file position to the first frame */
+ ci->seek_buffer(ci->id3->first_frame_offset);
+ }
- resume_offset = 0;
+ ci->set_elapsed(elapsedtime);
/* The main decoding loop */
@@ -129,6 +132,7 @@ restart_track:
if (param == 0) {
ci->set_elapsed(0);
ci->seek_complete();
+ elapsedtime = 0;
goto restart_track; /* Pretend you never saw this... */
}
@@ -136,7 +140,7 @@ restart_track:
if (elapsedtime < 1){
ci->set_elapsed(0);
ci->seek_complete();
- goto next_track;
+ break;
}
ci->set_elapsed(elapsedtime);