diff options
author | Roman Artiukhin <bahusdrive@gmail.com> | 2024-01-24 11:40:51 +0200 |
---|---|---|
committer | Roman Artiukhin <bahusdrive@gmail.com> | 2024-01-24 12:35:07 +0200 |
commit | 1122cae02804bd97887d51be6e5eee6a1616a09b (patch) | |
tree | e47a623ed7cc6c1b5a6df245b61adc4ae261fad2 /lib/rbcodec | |
parent | 49910eca4b400c817d1a6b65a53348280374927a (diff) | |
download | rockbox-1122cae02804bd97887d51be6e5eee6a1616a09b.tar.gz rockbox-1122cae02804bd97887d51be6e5eee6a1616a09b.zip |
Codecs: mpa: Improve seek in large mp3 vbr files
Use current position as toc mark and use it if it gives better accuracy.
Continuation of 3883c978
Change-Id: Ic6e8192fc43061f3c07128486dbefba7382be5ce
Diffstat (limited to 'lib/rbcodec')
-rw-r--r-- | lib/rbcodec/codecs/mpa.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c index c5d47a6791..5fdcb38da8 100644 --- a/lib/rbcodec/codecs/mpa.c +++ b/lib/rbcodec/codecs/mpa.c | |||
@@ -176,6 +176,8 @@ static int get_file_pos(int newtime) | |||
176 | struct mp3entry *id3 = ci->id3; | 176 | struct mp3entry *id3 = ci->id3; |
177 | 177 | ||
178 | if (id3->vbr) { | 178 | if (id3->vbr) { |
179 | int curpos = ci->curpos - id3->first_frame_offset; | ||
180 | long skipms_from_curpos = curpos > 0 ? (long) (id3->elapsed - newtime) : - newtime; | ||
179 | if (id3->has_toc) { | 181 | if (id3->has_toc) { |
180 | /* Use the TOC to find the new position */ | 182 | /* Use the TOC to find the new position */ |
181 | unsigned int percent = ((uint64_t)newtime * 100) / id3->length; | 183 | unsigned int percent = ((uint64_t)newtime * 100) / id3->length; |
@@ -183,28 +185,29 @@ static int get_file_pos(int newtime) | |||
183 | percent = 99; | 185 | percent = 99; |
184 | 186 | ||
185 | unsigned int pct_timestep = id3->length / 100; | 187 | unsigned int pct_timestep = id3->length / 100; |
186 | unsigned int toc_sizestep = id3->filesize / 256; | ||
187 | unsigned int cur_toc = id3->toc[percent]; | ||
188 | unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256; | ||
189 | unsigned int plength = (next_toc - cur_toc) * toc_sizestep; | ||
190 | |||
191 | /* Seek to TOC mark */ | ||
192 | pos = cur_toc * toc_sizestep; | ||
193 | 188 | ||
194 | /* Interpolate between this TOC mark and the next TOC mark */ | 189 | /* Interpolate between this TOC mark and the next TOC mark */ |
195 | int newtime_toc = newtime - percent * pct_timestep; | 190 | int skipms_from_toc = newtime - percent * pct_timestep; |
196 | pos += (uint64_t)plength * newtime_toc / pct_timestep; | 191 | if (skipms_from_toc < abs(skipms_from_curpos)) |
197 | } else { | 192 | { |
193 | unsigned int toc_sizestep = id3->filesize / 256; | ||
194 | unsigned int cur_toc = id3->toc[percent]; | ||
195 | unsigned int next_toc = percent < 99 ? id3->toc[percent+1] : 256; | ||
196 | unsigned int plength = (next_toc - cur_toc) * toc_sizestep; | ||
197 | |||
198 | pos = cur_toc * toc_sizestep + (uint64_t) plength * skipms_from_toc / pct_timestep; | ||
199 | } | ||
200 | } else if (newtime < abs(skipms_from_curpos)) { | ||
198 | /* No TOC exists, estimate the new position */ | 201 | /* No TOC exists, estimate the new position */ |
199 | pos = (uint64_t)newtime * id3->filesize / id3->length; | 202 | pos = (uint64_t)newtime * id3->filesize / id3->length; |
200 | } | 203 | } |
201 | // VBR seek might be very inaccurate in long files | 204 | // VBR seek might be very inaccurate in long files |
202 | // So make sure that seeking actually happened in the intended direction | 205 | // So make sure that seeking actually happened in the intended direction |
203 | // Fix jumps in the wrong direction by seeking relative to the current position | 206 | // Fix jumps in the wrong direction by seeking relative to the current position |
204 | long delta = id3->elapsed - newtime; | 207 | if (pos == -1 || (skipms_from_curpos >= 0 && pos > curpos) || (skipms_from_curpos < 0 && pos < curpos)) |
205 | if ((delta >= 0 && pos > ci->curpos) || (delta < 0 && pos < ci->curpos)) | ||
206 | { | 208 | { |
207 | pos = ci->curpos - delta * id3->filesize / id3->length; | 209 | pos = curpos - skipms_from_curpos * (id3->filesize / id3->length); |
210 | //LOGF("сurpos relative seek: %d, curpos: %d, newtime: %d", pos, curpos, newtime); | ||
208 | } | 211 | } |
209 | } else if (id3->bitrate) { | 212 | } else if (id3->bitrate) { |
210 | pos = newtime * (id3->bitrate / 8); | 213 | pos = newtime * (id3->bitrate / 8); |