FastLED 3.9.15
Loading...
Searching...
No Matches

◆ seek_to_sample_coarse()

static int32_t fl::third_party::vorbis::seek_to_sample_coarse ( stb_vorbis * f,
uint32 sample_number )
static

Definition at line 4458 of file stb_vorbis.cpp.hpp.

4459{
4460 ProbedPage left, right, mid;
4461 int32_t i, start_seg_with_known_loc, end_pos, page_start;
4462 uint32 delta, stream_length, padding, last_sample_limit;
4463 double offset = 0.0, bytes_per_sample = 0.0;
4464 int32_t probe = 0;
4465
4466 // find the last page and validate the target sample
4467 stream_length = stb_vorbis_stream_length_in_samples(f);
4468 if (stream_length == 0) return error(f, VORBIS_seek_without_length);
4469 if (sample_number > stream_length) return error(f, VORBIS_seek_invalid);
4470
4471 // this is the maximum difference between the window-center (which is the
4472 // actual granule position value), and the right-start (which the spec
4473 // indicates should be the granule position (give or take one)).
4474 padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
4475 if (sample_number < padding)
4476 last_sample_limit = 0;
4477 else
4478 last_sample_limit = sample_number - padding;
4479
4480 left = f->p_first;
4481 while (left.last_decoded_sample == ~0U) {
4482 // (untested) the first page does not have a 'last_decoded_sample'
4483 set_file_offset(f, left.page_end);
4484 if (!get_seek_page_info(f, &left)) goto error;
4485 }
4486
4487 right = f->p_last;
4488 FL_ASSERT(right.last_decoded_sample != ~0U, "right sample must be decoded");
4489
4490 // starting from the start is handled differently
4491 if (last_sample_limit <= left.last_decoded_sample) {
4492 if (stb_vorbis_seek_start(f)) {
4493 if (f->current_loc > sample_number)
4494 return error(f, VORBIS_seek_failed);
4495 return 1;
4496 }
4497 return 0;
4498 }
4499
4500 while (left.page_end != right.page_start) {
4501 FL_ASSERT(left.page_end < right.page_start, "left page_end must be < right page_start");
4502 // search range in bytes
4503 delta = right.page_start - left.page_end;
4504 if (delta <= 65536) {
4505 // there's only 64K left to search - handle it linearly
4506 set_file_offset(f, left.page_end);
4507 } else {
4508 if (probe < 2) {
4509 if (probe == 0) {
4510 // first probe (interpolate)
4511 double data_bytes = right.page_end - left.page_start;
4512 bytes_per_sample = data_bytes / right.last_decoded_sample;
4513 offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample);
4514 } else {
4515 // second probe (try to bound the other side)
4516 double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample;
4517 if (error >= 0 && error < 8000) error = 8000;
4518 if (error < 0 && error > -8000) error = -8000;
4519 offset += error * 2;
4520 }
4521
4522 // ensure the offset is valid
4523 if (offset < left.page_end)
4524 offset = left.page_end;
4525 if (offset > right.page_start - 65536)
4526 offset = right.page_start - 65536;
4527
4529 } else {
4530 // binary search for large ranges (offset by 32K to ensure
4531 // we don't hit the right page)
4532 set_file_offset(f, left.page_end + (delta / 2) - 32768);
4533 }
4534
4535 if (!vorbis_find_page(f, nullptr, nullptr)) goto error;
4536 }
4537
4538 for (;;) {
4539 if (!get_seek_page_info(f, &mid)) goto error;
4540 if (mid.last_decoded_sample != ~0U) break;
4541 // (untested) no frames end on this page
4542 set_file_offset(f, mid.page_end);
4543 FL_ASSERT(mid.page_start < right.page_start, "mid page_start must be < right page_start");
4544 }
4545
4546 // if we've just found the last page again then we're in a tricky file,
4547 // and we're close enough (if it wasn't an interpolation probe).
4548 if (mid.page_start == right.page_start) {
4549 if (probe >= 2 || delta <= 65536)
4550 break;
4551 } else {
4552 if (last_sample_limit < mid.last_decoded_sample)
4553 right = mid;
4554 else
4555 left = mid;
4556 }
4557
4558 ++probe;
4559 }
4560
4561 // seek back to start of the last packet
4562 page_start = left.page_start;
4563 set_file_offset(f, page_start);
4564 if (!start_page(f)) return error(f, VORBIS_seek_failed);
4565 end_pos = f->end_seg_with_known_loc;
4566 FL_ASSERT(end_pos >= 0, "end_pos must be >= 0");
4567
4568 for (;;) {
4569 for (i = end_pos; i > 0; --i)
4570 if (f->segments[i-1] != 255)
4571 break;
4572
4573 start_seg_with_known_loc = i;
4574
4575 if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet))
4576 break;
4577
4578 // (untested) the final packet begins on an earlier page
4579 if (!go_to_page_before(f, page_start))
4580 goto error;
4581
4582 page_start = stb_vorbis_get_file_offset(f);
4583 if (!start_page(f)) goto error;
4584 end_pos = f->segment_count - 1;
4585 }
4586
4587 // prepare to start decoding
4588 f->current_loc_valid = false;
4589 f->last_seg = false;
4590 f->valid_bits = 0;
4591 f->packet_bytes = 0;
4592 f->bytes_in_seg = 0;
4593 f->previous_length = 0;
4594 f->next_seg = start_seg_with_known_loc;
4595
4596 for (i = 0; i < start_seg_with_known_loc; i++)
4597 skip(f, f->segments[i]);
4598
4599 // start decoding (optimizable - this frame is generally discarded)
4601 return 0;
4602 if (f->current_loc > sample_number)
4603 return error(f, VORBIS_seek_failed);
4604 return 1;
4605
4606error:
4607 // try to restore the file to a valid state
4609 return error(f, VORBIS_seek_failed);
4610}
#define FL_ASSERT(x, MSG)
Definition assert.h:6
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
static int32_t start_page(vorb *f) FL_NOEXCEPT
static int32_t error(vorb *f, enum STBVorbisError e) FL_NOEXCEPT
static int32_t get_seek_page_info(stb_vorbis *f, ProbedPage *z) FL_NOEXCEPT
static int32_t vorbis_pump_first_frame(stb_vorbis *f) FL_NOEXCEPT
static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) FL_NOEXCEPT
static void skip(vorb *z, int32_t n) FL_NOEXCEPT
int32_t stb_vorbis_seek_start(stb_vorbis *f) FL_NOEXCEPT
uint32_t stb_vorbis_stream_length_in_samples(stb_vorbis *f) FL_NOEXCEPT
static constexpr uint8_t PAGEFLAG_continued_packet
uint32_t stb_vorbis_get_file_offset(stb_vorbis *f) FL_NOEXCEPT
static int32_t set_file_offset(stb_vorbis *f, uint32_t loc) FL_NOEXCEPT
static int32_t go_to_page_before(stb_vorbis *f, uint32_t limit_offset) FL_NOEXCEPT
fl::u32 uint32_t
Definition coder.h:219
fl::i32 int32_t
Definition coder.h:220

References error(), FL_ASSERT, FL_NOEXCEPT, get_seek_page_info(), go_to_page_before(), fl::third_party::vorbis::ProbedPage::last_decoded_sample, offset(), fl::third_party::vorbis::ProbedPage::page_end, fl::third_party::vorbis::ProbedPage::page_start, PAGEFLAG_continued_packet, set_file_offset(), skip(), start_page(), stb_vorbis_get_file_offset(), stb_vorbis_seek_start(), stb_vorbis_stream_length_in_samples(), vorbis_find_page(), vorbis_pump_first_frame(), VORBIS_seek_failed, VORBIS_seek_invalid, and VORBIS_seek_without_length.

Referenced by stb_vorbis_seek_frame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: