diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-03-22 10:02:05 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-03-22 10:02:05 +0000 |
commit | 7a3822c8b03a5438a1bcfd6e38c0e6860dda3348 (patch) | |
tree | e50740c7f0ccd6aff1aac0e292a000ac7ef6be14 | |
parent | 20fccd84897352478c3306e41ca0fab0a5f4c65e (diff) | |
download | rockbox-7a3822c8b03a5438a1bcfd6e38c0e6860dda3348.tar.gz rockbox-7a3822c8b03a5438a1bcfd6e38c0e6860dda3348.zip |
fix bug: WAV file playback does not resume (FS#11077)
Not only WAV but also Sun audio, SMAF, vox and WAV64 can resume.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25289 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/aiff.c | 28 | ||||
-rw-r--r-- | apps/codecs/au.c | 27 | ||||
-rw-r--r-- | apps/codecs/libpcm/dialogic_oki_adpcm.c | 20 | ||||
-rw-r--r-- | apps/codecs/libpcm/dvi_adpcm.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/ieee_float.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/itut_g711.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/linear_pcm.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/ms_adpcm.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/pcm_common.h | 13 | ||||
-rw-r--r-- | apps/codecs/libpcm/qt_ima_adpcm.c | 8 | ||||
-rw-r--r-- | apps/codecs/libpcm/swf_adpcm.c | 15 | ||||
-rw-r--r-- | apps/codecs/libpcm/yamaha_adpcm.c | 11 | ||||
-rw-r--r-- | apps/codecs/smaf.c | 25 | ||||
-rw-r--r-- | apps/codecs/vox.c | 37 | ||||
-rw-r--r-- | apps/codecs/wav.c | 16 | ||||
-rw-r--r-- | apps/codecs/wav64.c | 16 | ||||
-rw-r--r-- | apps/metadata/vox.c | 1 |
17 files changed, 188 insertions, 69 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index 62d79ac340..4e16788e06 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -100,6 +100,9 @@ next_track: | |||
100 | 100 | ||
101 | codec_set_replaygain(ci->id3); | 101 | codec_set_replaygain(ci->id3); |
102 | 102 | ||
103 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | ||
104 | bytesdone = ci->id3->offset; | ||
105 | |||
103 | /* assume the AIFF header is less than 1024 bytes */ | 106 | /* assume the AIFF header is less than 1024 bytes */ |
104 | buf = ci->request_buffer(&n, 1024); | 107 | buf = ci->request_buffer(&n, 1024); |
105 | if (n < 54) { | 108 | if (n < 54) { |
@@ -279,9 +282,26 @@ next_track: | |||
279 | firstblockposn = 1024 - n; | 282 | firstblockposn = 1024 - n; |
280 | ci->advance_buffer(firstblockposn); | 283 | ci->advance_buffer(firstblockposn); |
281 | 284 | ||
285 | /* make sure we're at the correct offset */ | ||
286 | if (bytesdone > (uint32_t) firstblockposn) { | ||
287 | /* Round down to previous block */ | ||
288 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | ||
289 | PCM_SEEK_POS, NULL); | ||
290 | |||
291 | if (newpos->pos > format.numbytes) | ||
292 | goto done; | ||
293 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
294 | { | ||
295 | bytesdone = newpos->pos; | ||
296 | decodedsamples = newpos->samples; | ||
297 | } | ||
298 | ci->seek_complete(); | ||
299 | } else { | ||
300 | /* already where we need to be */ | ||
301 | bytesdone = 0; | ||
302 | } | ||
303 | |||
282 | /* The main decoder loop */ | 304 | /* The main decoder loop */ |
283 | bytesdone = 0; | ||
284 | ci->set_elapsed(0); | ||
285 | endofstream = 0; | 305 | endofstream = 0; |
286 | 306 | ||
287 | while (!endofstream) { | 307 | while (!endofstream) { |
@@ -290,8 +310,8 @@ next_track: | |||
290 | break; | 310 | break; |
291 | 311 | ||
292 | if (ci->seek_time) { | 312 | if (ci->seek_time) { |
293 | /* 2nd args(read_buffer) is unnecessary in the format which AIFF supports. */ | 313 | /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ |
294 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, NULL); | 314 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); |
295 | 315 | ||
296 | if (newpos->pos > format.numbytes) | 316 | if (newpos->pos > format.numbytes) |
297 | break; | 317 | break; |
diff --git a/apps/codecs/au.c b/apps/codecs/au.c index 19348bc299..1e6af25924 100644 --- a/apps/codecs/au.c +++ b/apps/codecs/au.c | |||
@@ -135,6 +135,9 @@ next_track: | |||
135 | 135 | ||
136 | codec_set_replaygain(ci->id3); | 136 | codec_set_replaygain(ci->id3); |
137 | 137 | ||
138 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | ||
139 | bytesdone = ci->id3->offset; | ||
140 | |||
138 | ci->memset(&format, 0, sizeof(struct pcm_format)); | 141 | ci->memset(&format, 0, sizeof(struct pcm_format)); |
139 | format.is_signed = true; | 142 | format.is_signed = true; |
140 | format.is_little_endian = false; | 143 | format.is_little_endian = false; |
@@ -191,7 +194,6 @@ next_track: | |||
191 | 194 | ||
192 | decodedsamples = 0; | 195 | decodedsamples = 0; |
193 | codec = 0; | 196 | codec = 0; |
194 | bytesdone = 0; | ||
195 | 197 | ||
196 | /* get codec */ | 198 | /* get codec */ |
197 | codec = get_au_codec(format.formattag); | 199 | codec = get_au_codec(format.formattag); |
@@ -236,6 +238,25 @@ next_track: | |||
236 | goto done; | 238 | goto done; |
237 | } | 239 | } |
238 | 240 | ||
241 | /* make sure we're at the correct offset */ | ||
242 | if (bytesdone > (uint32_t) firstblockposn) { | ||
243 | /* Round down to previous block */ | ||
244 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | ||
245 | PCM_SEEK_POS, NULL); | ||
246 | |||
247 | if (newpos->pos > format.numbytes) | ||
248 | goto done; | ||
249 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
250 | { | ||
251 | bytesdone = newpos->pos; | ||
252 | decodedsamples = newpos->samples; | ||
253 | } | ||
254 | ci->seek_complete(); | ||
255 | } else { | ||
256 | /* already where we need to be */ | ||
257 | bytesdone = 0; | ||
258 | } | ||
259 | |||
239 | /* The main decoder loop */ | 260 | /* The main decoder loop */ |
240 | endofstream = 0; | 261 | endofstream = 0; |
241 | 262 | ||
@@ -246,8 +267,8 @@ next_track: | |||
246 | } | 267 | } |
247 | 268 | ||
248 | if (ci->seek_time) { | 269 | if (ci->seek_time) { |
249 | /* 2nd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ | 270 | /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ |
250 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, NULL); | 271 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); |
251 | 272 | ||
252 | if (newpos->pos > format.numbytes) | 273 | if (newpos->pos > format.numbytes) |
253 | break; | 274 | break; |
diff --git a/apps/codecs/libpcm/dialogic_oki_adpcm.c b/apps/codecs/libpcm/dialogic_oki_adpcm.c index 62d092e677..4a6465f196 100644 --- a/apps/codecs/libpcm/dialogic_oki_adpcm.c +++ b/apps/codecs/libpcm/dialogic_oki_adpcm.c | |||
@@ -44,6 +44,7 @@ static const int index_table[] ICONST_ATTR = { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct adpcm_data cur_data; | 46 | static struct adpcm_data cur_data; |
47 | static int blocksperchunk; | ||
47 | 48 | ||
48 | static struct pcm_format *fmt; | 49 | static struct pcm_format *fmt; |
49 | 50 | ||
@@ -71,7 +72,8 @@ static bool set_format(struct pcm_format *format) | |||
71 | fmt->samplesperblock = 2; | 72 | fmt->samplesperblock = 2; |
72 | 73 | ||
73 | /* chunksize = about 1/32[sec] data */ | 74 | /* chunksize = about 1/32[sec] data */ |
74 | fmt->chunksize = ci->id3->frequency >> 6; | 75 | blocksperchunk = ci->id3->frequency >> 6; |
76 | fmt->chunksize = blocksperchunk * fmt->blockalign; | ||
75 | 77 | ||
76 | max_chunk_count = (uint64_t)ci->id3->length * ci->id3->frequency | 78 | max_chunk_count = (uint64_t)ci->id3->length * ci->id3->frequency |
77 | / (2000LL * fmt->chunksize); | 79 | / (2000LL * fmt->chunksize); |
@@ -146,20 +148,18 @@ static int decode_for_seek(const uint8_t *inbuf, size_t inbufsize) | |||
146 | return CODEC_OK; | 148 | return CODEC_OK; |
147 | } | 149 | } |
148 | 150 | ||
149 | static struct pcm_pos *get_seek_pos(long seek_time, | 151 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
150 | uint8_t *(*read_buffer)(size_t *realsize)) | 152 | uint8_t *(*read_buffer)(size_t *realsize)) |
151 | { | 153 | { |
152 | static struct pcm_pos newpos; | 154 | static struct pcm_pos newpos; |
153 | uint32_t seek_count = 0; | 155 | uint32_t seek_count = (seek_mode == PCM_SEEK_TIME)? |
154 | uint32_t new_count; | 156 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
157 | / (blocksperchunk * fmt->samplesperblock) : | ||
158 | seek_val / fmt->chunksize; | ||
159 | uint32_t new_count = seek(seek_count, &cur_data, read_buffer, &decode_for_seek); | ||
155 | 160 | ||
156 | if (seek_time > 0) | ||
157 | seek_count = (uint64_t)seek_time * ci->id3->frequency | ||
158 | / (2000LL * fmt->chunksize); | ||
159 | |||
160 | new_count = seek(seek_count, &cur_data, read_buffer, &decode_for_seek); | ||
161 | newpos.pos = new_count * fmt->chunksize; | 161 | newpos.pos = new_count * fmt->chunksize; |
162 | newpos.samples = (newpos.pos / fmt->blockalign) * fmt->samplesperblock; | 162 | newpos.samples = new_count * blocksperchunk * fmt->samplesperblock; |
163 | return &newpos; | 163 | return &newpos; |
164 | } | 164 | } |
165 | 165 | ||
diff --git a/apps/codecs/libpcm/dvi_adpcm.c b/apps/codecs/libpcm/dvi_adpcm.c index 2784b21786..2e702ca394 100644 --- a/apps/codecs/libpcm/dvi_adpcm.c +++ b/apps/codecs/libpcm/dvi_adpcm.c | |||
@@ -54,12 +54,14 @@ static bool set_format(struct pcm_format *format) | |||
54 | return true; | 54 | return true; |
55 | } | 55 | } |
56 | 56 | ||
57 | static struct pcm_pos *get_seek_pos(long seek_time, | 57 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
58 | uint8_t *(*read_buffer)(size_t *realsize)) | 58 | uint8_t *(*read_buffer)(size_t *realsize)) |
59 | { | 59 | { |
60 | static struct pcm_pos newpos; | 60 | static struct pcm_pos newpos; |
61 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 61 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
62 | / (1000LL * fmt->samplesperblock); | 62 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
63 | / fmt->samplesperblock : | ||
64 | seek_val / fmt->blockalign; | ||
63 | 65 | ||
64 | (void)read_buffer; | 66 | (void)read_buffer; |
65 | newpos.pos = newblock * fmt->blockalign; | 67 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/ieee_float.c b/apps/codecs/libpcm/ieee_float.c index 7e3498edcb..639390bcd5 100644 --- a/apps/codecs/libpcm/ieee_float.c +++ b/apps/codecs/libpcm/ieee_float.c | |||
@@ -59,12 +59,14 @@ static bool set_format(struct pcm_format *format) | |||
59 | return true; | 59 | return true; |
60 | } | 60 | } |
61 | 61 | ||
62 | static struct pcm_pos *get_seek_pos(long seek_time, | 62 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
63 | uint8_t *(*read_buffer)(size_t *realsize)) | 63 | uint8_t *(*read_buffer)(size_t *realsize)) |
64 | { | 64 | { |
65 | static struct pcm_pos newpos; | 65 | static struct pcm_pos newpos; |
66 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 66 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
67 | / (1000LL * fmt->samplesperblock); | 67 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
68 | / fmt->samplesperblock : | ||
69 | seek_val / fmt->blockalign; | ||
68 | 70 | ||
69 | (void)read_buffer; | 71 | (void)read_buffer; |
70 | newpos.pos = newblock * fmt->blockalign; | 72 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/itut_g711.c b/apps/codecs/libpcm/itut_g711.c index 097dd5cc25..88ff5f59e6 100644 --- a/apps/codecs/libpcm/itut_g711.c +++ b/apps/codecs/libpcm/itut_g711.c | |||
@@ -139,12 +139,14 @@ static bool set_format(struct pcm_format *format) | |||
139 | return true; | 139 | return true; |
140 | } | 140 | } |
141 | 141 | ||
142 | static struct pcm_pos *get_seek_pos(long seek_time, | 142 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
143 | uint8_t *(*read_buffer)(size_t *realsize)) | 143 | uint8_t *(*read_buffer)(size_t *realsize)) |
144 | { | 144 | { |
145 | static struct pcm_pos newpos; | 145 | static struct pcm_pos newpos; |
146 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 146 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
147 | / (1000LL * fmt->samplesperblock); | 147 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
148 | / fmt->samplesperblock : | ||
149 | seek_val / fmt->blockalign; | ||
148 | 150 | ||
149 | (void)read_buffer; | 151 | (void)read_buffer; |
150 | newpos.pos = newblock * fmt->blockalign; | 152 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/linear_pcm.c b/apps/codecs/libpcm/linear_pcm.c index e58856efe8..5c3c140b8c 100644 --- a/apps/codecs/libpcm/linear_pcm.c +++ b/apps/codecs/libpcm/linear_pcm.c | |||
@@ -71,12 +71,14 @@ static bool set_format(struct pcm_format *format) | |||
71 | return true; | 71 | return true; |
72 | } | 72 | } |
73 | 73 | ||
74 | static struct pcm_pos *get_seek_pos(long seek_time, | 74 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
75 | uint8_t *(*read_buffer)(size_t *realsize)) | 75 | uint8_t *(*read_buffer)(size_t *realsize)) |
76 | { | 76 | { |
77 | static struct pcm_pos newpos; | 77 | static struct pcm_pos newpos; |
78 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 78 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
79 | / (1000LL * fmt->samplesperblock); | 79 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
80 | / fmt->samplesperblock : | ||
81 | seek_val / fmt->blockalign; | ||
80 | 82 | ||
81 | (void)read_buffer; | 83 | (void)read_buffer; |
82 | newpos.pos = newblock * fmt->blockalign; | 84 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/ms_adpcm.c b/apps/codecs/libpcm/ms_adpcm.c index 79365807ef..a385d6c99f 100644 --- a/apps/codecs/libpcm/ms_adpcm.c +++ b/apps/codecs/libpcm/ms_adpcm.c | |||
@@ -60,12 +60,14 @@ static bool set_format(struct pcm_format *format) | |||
60 | return true; | 60 | return true; |
61 | } | 61 | } |
62 | 62 | ||
63 | static struct pcm_pos *get_seek_pos(long seek_time, | 63 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
64 | uint8_t *(*read_buffer)(size_t *realsize)) | 64 | uint8_t *(*read_buffer)(size_t *realsize)) |
65 | { | 65 | { |
66 | static struct pcm_pos newpos; | 66 | static struct pcm_pos newpos; |
67 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 67 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
68 | / (1000LL * fmt->samplesperblock); | 68 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
69 | / fmt->samplesperblock : | ||
70 | seek_val / fmt->blockalign; | ||
69 | 71 | ||
70 | (void)read_buffer; | 72 | (void)read_buffer; |
71 | newpos.pos = newblock * fmt->blockalign; | 73 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/pcm_common.h b/apps/codecs/libpcm/pcm_common.h index 412ffbce0b..91c3ab7f1e 100644 --- a/apps/codecs/libpcm/pcm_common.h +++ b/apps/codecs/libpcm/pcm_common.h | |||
@@ -124,6 +124,9 @@ struct pcm_pos { | |||
124 | uint32_t samples; | 124 | uint32_t samples; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | #define PCM_SEEK_TIME 0 | ||
128 | #define PCM_SEEK_POS 1 | ||
129 | |||
127 | struct pcm_codec { | 130 | struct pcm_codec { |
128 | /* | 131 | /* |
129 | * sets the format speciffic RIFF/AIFF header information and checks the pcm_format. | 132 | * sets the format speciffic RIFF/AIFF header information and checks the pcm_format. |
@@ -140,8 +143,12 @@ struct pcm_codec { | |||
140 | /* | 143 | /* |
141 | * get seek position | 144 | * get seek position |
142 | * | 145 | * |
143 | * [In] seek_time | 146 | * [In] seek_val |
144 | * seek time [ms] | 147 | * seek time [ms] or seek position |
148 | * | ||
149 | * [In] seek_mode | ||
150 | * if seek_mode sets PCM_SEEK_TIME, then seek_val means the seek time. | ||
151 | * if seek_mode sets PCM_SEEK_POS, then seek_val means the seek position. | ||
145 | * | 152 | * |
146 | * [In] read_buffer | 153 | * [In] read_buffer |
147 | * the function which reads the data from the file (chunksize bytes read). | 154 | * the function which reads the data from the file (chunksize bytes read). |
@@ -149,7 +156,7 @@ struct pcm_codec { | |||
149 | * return | 156 | * return |
150 | * position after the seeking. | 157 | * position after the seeking. |
151 | */ | 158 | */ |
152 | struct pcm_pos *(*get_seek_pos)(long seek_time, | 159 | struct pcm_pos *(*get_seek_pos)(uint32_t seek_val, int seek_mode, |
153 | uint8_t *(*read_buffer)(size_t *realsize)); | 160 | uint8_t *(*read_buffer)(size_t *realsize)); |
154 | 161 | ||
155 | /* | 162 | /* |
diff --git a/apps/codecs/libpcm/qt_ima_adpcm.c b/apps/codecs/libpcm/qt_ima_adpcm.c index 003de22dd8..d7b3360eb3 100644 --- a/apps/codecs/libpcm/qt_ima_adpcm.c +++ b/apps/codecs/libpcm/qt_ima_adpcm.c | |||
@@ -57,12 +57,14 @@ static bool set_format(struct pcm_format *format) | |||
57 | return true; | 57 | return true; |
58 | } | 58 | } |
59 | 59 | ||
60 | static struct pcm_pos *get_seek_pos(long seek_time, | 60 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
61 | uint8_t *(*read_buffer)(size_t *realsize)) | 61 | uint8_t *(*read_buffer)(size_t *realsize)) |
62 | { | 62 | { |
63 | static struct pcm_pos newpos; | 63 | static struct pcm_pos newpos; |
64 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 64 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? |
65 | / (1000LL * fmt->samplesperblock); | 65 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) |
66 | / fmt->samplesperblock : | ||
67 | seek_val / fmt->blockalign; | ||
66 | 68 | ||
67 | (void)read_buffer; | 69 | (void)read_buffer; |
68 | newpos.pos = newblock * fmt->blockalign; | 70 | newpos.pos = newblock * fmt->blockalign; |
diff --git a/apps/codecs/libpcm/swf_adpcm.c b/apps/codecs/libpcm/swf_adpcm.c index ebc4328c59..c440fd1303 100644 --- a/apps/codecs/libpcm/swf_adpcm.c +++ b/apps/codecs/libpcm/swf_adpcm.c | |||
@@ -81,20 +81,21 @@ static bool set_format(struct pcm_format *format) | |||
81 | return true; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | static struct pcm_pos *get_seek_pos(long seek_time, | 84 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
85 | uint8_t *(*read_buffer)(size_t *realsize)) | 85 | uint8_t *(*read_buffer)(size_t *realsize)) |
86 | { | 86 | { |
87 | static struct pcm_pos newpos; | 87 | static struct pcm_pos newpos; |
88 | uint32_t chunkbits = blockbits; | 88 | uint32_t chunkbits = blockbits; |
89 | uint32_t seekbits = (((uint64_t)seek_time * ci->id3->frequency) | 89 | uint32_t seekblocks = (seek_mode == PCM_SEEK_TIME)? |
90 | / (1000LL * fmt->samplesperblock)) * blockbits + 2; | 90 | ((uint64_t)seek_val * ci->id3->frequency) |
91 | / (1000LL * fmt->samplesperblock) : | ||
92 | ((seek_val << 3) - 2) / blockbits; | ||
93 | uint32_t seekbits = seekblocks * blockbits + 2; | ||
91 | 94 | ||
92 | (void)read_buffer; | 95 | (void)read_buffer; |
93 | 96 | ||
94 | newpos.pos = seekbits >> 3; | 97 | newpos.pos = seekbits >> 3; |
95 | newpos.samples = (((uint64_t)seek_time * ci->id3->frequency) | 98 | newpos.samples = seekblocks * fmt->samplesperblock; |
96 | / (1000LL * fmt->samplesperblock)) | ||
97 | * fmt->samplesperblock; | ||
98 | 99 | ||
99 | if (newpos.pos == 0) | 100 | if (newpos.pos == 0) |
100 | { | 101 | { |
diff --git a/apps/codecs/libpcm/yamaha_adpcm.c b/apps/codecs/libpcm/yamaha_adpcm.c index 0b997ad776..f1fb9b68ae 100644 --- a/apps/codecs/libpcm/yamaha_adpcm.c +++ b/apps/codecs/libpcm/yamaha_adpcm.c | |||
@@ -214,15 +214,14 @@ static int decode_for_seek(const uint8_t *inbuf, size_t inbufsize) | |||
214 | return CODEC_OK; | 214 | return CODEC_OK; |
215 | } | 215 | } |
216 | 216 | ||
217 | static struct pcm_pos *get_seek_pos(long seek_time, | 217 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, |
218 | uint8_t *(*read_buffer)(size_t *realsize)) | 218 | uint8_t *(*read_buffer)(size_t *realsize)) |
219 | { | 219 | { |
220 | static struct pcm_pos newpos; | 220 | static struct pcm_pos newpos; |
221 | uint32_t new_count= 0; | 221 | uint32_t new_count = (seek_mode == PCM_SEEK_TIME)? |
222 | 222 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) | |
223 | if (seek_time > 0) | 223 | / (blocksperchunk * fmt->samplesperblock) : |
224 | new_count = ((uint64_t)seek_time * ci->id3->frequency | 224 | seek_val / fmt->chunksize; |
225 | / (1000LL * fmt->samplesperblock)) / blocksperchunk; | ||
226 | 225 | ||
227 | if (!has_block_header) | 226 | if (!has_block_header) |
228 | { | 227 | { |
diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c index 33a2a4b403..6763e95001 100644 --- a/apps/codecs/smaf.c +++ b/apps/codecs/smaf.c | |||
@@ -409,6 +409,28 @@ next_track: | |||
409 | ci->seek_buffer(firstblockposn); | 409 | ci->seek_buffer(firstblockposn); |
410 | ci->seek_complete(); | 410 | ci->seek_complete(); |
411 | 411 | ||
412 | /* make sure we're at the correct offset */ | ||
413 | if (bytesdone > (uint32_t) firstblockposn) | ||
414 | { | ||
415 | /* Round down to previous block */ | ||
416 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | ||
417 | PCM_SEEK_POS, &read_buffer); | ||
418 | |||
419 | if (newpos->pos > format.numbytes) | ||
420 | goto done; | ||
421 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
422 | { | ||
423 | bytesdone = newpos->pos; | ||
424 | decodedsamples = newpos->samples; | ||
425 | } | ||
426 | ci->seek_complete(); | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | /* already where we need to be */ | ||
431 | bytesdone = 0; | ||
432 | } | ||
433 | |||
412 | /* The main decoder loop */ | 434 | /* The main decoder loop */ |
413 | endofstream = 0; | 435 | endofstream = 0; |
414 | 436 | ||
@@ -418,7 +440,8 @@ next_track: | |||
418 | break; | 440 | break; |
419 | 441 | ||
420 | if (ci->seek_time) { | 442 | if (ci->seek_time) { |
421 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, &read_buffer); | 443 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, |
444 | &read_buffer); | ||
422 | 445 | ||
423 | if (newpos->pos > format.numbytes) | 446 | if (newpos->pos > format.numbytes) |
424 | break; | 447 | break; |
diff --git a/apps/codecs/vox.c b/apps/codecs/vox.c index 21742e16d9..ff5d571e8d 100644 --- a/apps/codecs/vox.c +++ b/apps/codecs/vox.c | |||
@@ -52,9 +52,8 @@ enum codec_status codec_main(void) | |||
52 | int bufcount; | 52 | int bufcount; |
53 | int endofstream; | 53 | int endofstream; |
54 | uint8_t *voxbuf; | 54 | uint8_t *voxbuf; |
55 | off_t firstblockposn; /* position of the first block in file */ | 55 | off_t firstblockposn = 0; /* position of the first block in file */ |
56 | const struct pcm_codec *codec; | 56 | const struct pcm_codec *codec; |
57 | int offset = 0; | ||
58 | 57 | ||
59 | /* Generic codec initialisation */ | 58 | /* Generic codec initialisation */ |
60 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | 59 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); |
@@ -70,7 +69,10 @@ next_track: | |||
70 | ci->sleep(1); | 69 | ci->sleep(1); |
71 | 70 | ||
72 | codec_set_replaygain(ci->id3); | 71 | codec_set_replaygain(ci->id3); |
73 | 72 | ||
73 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | ||
74 | bytesdone = ci->id3->offset; | ||
75 | |||
74 | ci->memset(&format, 0, sizeof(struct pcm_format)); | 76 | ci->memset(&format, 0, sizeof(struct pcm_format)); |
75 | 77 | ||
76 | /* set format */ | 78 | /* set format */ |
@@ -80,12 +82,9 @@ next_track: | |||
80 | format.blockalign = 1; | 82 | format.blockalign = 1; |
81 | 83 | ||
82 | /* advance to first WAVE chunk */ | 84 | /* advance to first WAVE chunk */ |
83 | ci->advance_buffer(offset); | 85 | firstblockposn = 0; |
84 | |||
85 | firstblockposn = offset; | ||
86 | |||
87 | decodedsamples = 0; | 86 | decodedsamples = 0; |
88 | bytesdone = 0; | 87 | ci->advance_buffer(firstblockposn); |
89 | 88 | ||
90 | /* | 89 | /* |
91 | * get codec | 90 | * get codec |
@@ -124,6 +123,25 @@ next_track: | |||
124 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 123 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
125 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 124 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
126 | 125 | ||
126 | /* make sure we're at the correct offset */ | ||
127 | if (bytesdone > (uint32_t) firstblockposn) { | ||
128 | /* Round down to previous block */ | ||
129 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | ||
130 | PCM_SEEK_POS, &read_buffer); | ||
131 | |||
132 | if (newpos->pos > format.numbytes) | ||
133 | goto done; | ||
134 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
135 | { | ||
136 | bytesdone = newpos->pos; | ||
137 | decodedsamples = newpos->samples; | ||
138 | } | ||
139 | ci->seek_complete(); | ||
140 | } else { | ||
141 | /* already where we need to be */ | ||
142 | bytesdone = 0; | ||
143 | } | ||
144 | |||
127 | /* The main decoder loop */ | 145 | /* The main decoder loop */ |
128 | endofstream = 0; | 146 | endofstream = 0; |
129 | 147 | ||
@@ -134,7 +152,8 @@ next_track: | |||
134 | } | 152 | } |
135 | 153 | ||
136 | if (ci->seek_time) { | 154 | if (ci->seek_time) { |
137 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, &read_buffer); | 155 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, |
156 | &read_buffer); | ||
138 | 157 | ||
139 | if (newpos->pos > format.numbytes) | 158 | if (newpos->pos > format.numbytes) |
140 | break; | 159 | break; |
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index 14d7136592..e286f4dc6a 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -374,10 +374,17 @@ next_track: | |||
374 | /* make sure we're at the correct offset */ | 374 | /* make sure we're at the correct offset */ |
375 | if (bytesdone > (uint32_t) firstblockposn) { | 375 | if (bytesdone > (uint32_t) firstblockposn) { |
376 | /* Round down to previous block */ | 376 | /* Round down to previous block */ |
377 | uint32_t offset = bytesdone - bytesdone % format.blockalign; | 377 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, |
378 | PCM_SEEK_POS, &read_buffer); | ||
378 | 379 | ||
379 | ci->advance_buffer(offset-firstblockposn); | 380 | if (newpos->pos > format.numbytes) |
380 | bytesdone = offset - firstblockposn; | 381 | goto done; |
382 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
383 | { | ||
384 | bytesdone = newpos->pos; | ||
385 | decodedsamples = newpos->samples; | ||
386 | } | ||
387 | ci->seek_complete(); | ||
381 | } else { | 388 | } else { |
382 | /* already where we need to be */ | 389 | /* already where we need to be */ |
383 | bytesdone = 0; | 390 | bytesdone = 0; |
@@ -393,7 +400,8 @@ next_track: | |||
393 | } | 400 | } |
394 | 401 | ||
395 | if (ci->seek_time) { | 402 | if (ci->seek_time) { |
396 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, &read_buffer); | 403 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, |
404 | &read_buffer); | ||
397 | 405 | ||
398 | if (newpos->pos > format.numbytes) | 406 | if (newpos->pos > format.numbytes) |
399 | break; | 407 | break; |
diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c index 1913dafe5c..c06f78c802 100644 --- a/apps/codecs/wav64.c +++ b/apps/codecs/wav64.c | |||
@@ -380,10 +380,17 @@ next_track: | |||
380 | /* make sure we're at the correct offset */ | 380 | /* make sure we're at the correct offset */ |
381 | if (bytesdone > (uint32_t) firstblockposn) { | 381 | if (bytesdone > (uint32_t) firstblockposn) { |
382 | /* Round down to previous block */ | 382 | /* Round down to previous block */ |
383 | uint32_t offset = bytesdone - bytesdone % format.blockalign; | 383 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, |
384 | PCM_SEEK_POS, &read_buffer); | ||
384 | 385 | ||
385 | ci->advance_buffer(offset-firstblockposn); | 386 | if (newpos->pos > format.numbytes) |
386 | bytesdone = offset - firstblockposn; | 387 | goto done; |
388 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | ||
389 | { | ||
390 | bytesdone = newpos->pos; | ||
391 | decodedsamples = newpos->samples; | ||
392 | } | ||
393 | ci->seek_complete(); | ||
387 | } else { | 394 | } else { |
388 | /* already where we need to be */ | 395 | /* already where we need to be */ |
389 | bytesdone = 0; | 396 | bytesdone = 0; |
@@ -399,7 +406,8 @@ next_track: | |||
399 | } | 406 | } |
400 | 407 | ||
401 | if (ci->seek_time) { | 408 | if (ci->seek_time) { |
402 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, &read_buffer); | 409 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, |
410 | &read_buffer); | ||
403 | 411 | ||
404 | if (newpos->pos > format.numbytes) | 412 | if (newpos->pos > format.numbytes) |
405 | break; | 413 | break; |
diff --git a/apps/metadata/vox.c b/apps/metadata/vox.c index 3f4e5d553c..f6bc849a88 100644 --- a/apps/metadata/vox.c +++ b/apps/metadata/vox.c | |||
@@ -40,6 +40,7 @@ bool get_vox_metadata(int fd, struct mp3entry* id3) | |||
40 | * bitspersample: 4 | 40 | * bitspersample: 4 |
41 | */ | 41 | */ |
42 | id3->frequency = 8000; | 42 | id3->frequency = 8000; |
43 | id3->bitrate = 8000 * 4 / 1000; | ||
43 | id3->vbr = false; /* All VOX files are CBR */ | 44 | id3->vbr = false; /* All VOX files are CBR */ |
44 | id3->filesize = filesize(fd); | 45 | id3->filesize = filesize(fd); |
45 | id3->length = id3->filesize >> 2; | 46 | id3->length = id3->filesize >> 2; |