From d444fa7db996a3ee20c1364559e9518c07548ba8 Mon Sep 17 00:00:00 2001 From: Wohlstand Date: Fri, 18 Feb 2022 22:55:50 +0300 Subject: [PATCH] stb_vorbis: report the sample-accurate offset Added the `stb_vorbis_get_playback_sample_offset()` call that reports the sample-accurate position which is required for several operations such as loop range processing. --- stb_vorbis.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 3e5c2504c0..3b332b4f5c 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -21,6 +21,7 @@ // // Feature contributors: // Dougall Johnson (sample-exact seeking) +// Vitaly Novichkov (sample-accurate tell) // // Bugfix/warning contributors: // Terje Mathisen Niklas Frykholm Andy Hill @@ -165,6 +166,12 @@ extern void stb_vorbis_close(stb_vorbis *f); // NOT WORKING YET after a seek with PULLDATA API extern int stb_vorbis_get_sample_offset(stb_vorbis *f); +// this function returns the count of returned samples from the beginning of the +// file. Functions "stb_vorbis_get_samples_*", "stb_vorbis_seek_*()" will +// affect the returned value. Use this call to get the accurate sample position +// during playback. +extern int stb_vorbis_get_playback_sample_offset(stb_vorbis *f); + // returns the current seek point within the file, or offset from the beginning // of the memory buffer. In pushdata mode it returns 0. extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); @@ -863,6 +870,9 @@ struct stb_vorbis uint32 current_loc; // sample location of next frame to decode int current_loc_valid; + int32 current_playback_loc; // sample location of played samples + int current_playback_loc_valid; + // per-blocksize precomputed data // twiddle factors @@ -3512,6 +3522,8 @@ static int vorbis_pump_first_frame(stb_vorbis *f) res = vorbis_decode_packet(f, &len, &left, &right); if (res) vorbis_finish_frame(f, len, left, right); + f->current_playback_loc = 0; + f->current_playback_loc_valid = TRUE; return res; } @@ -4302,6 +4314,14 @@ int stb_vorbis_get_sample_offset(stb_vorbis *f) return -1; } +int stb_vorbis_get_playback_sample_offset(stb_vorbis *f) +{ + if (f->current_playback_loc_valid) + return f->current_playback_loc; + else + return -1; +} + stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) { stb_vorbis_info d; @@ -4913,13 +4933,16 @@ int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) } // the next frame should start with the sample if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed); + f->current_playback_loc = sample_number; return 1; } int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) { - if (!stb_vorbis_seek_frame(f, sample_number)) + if (!stb_vorbis_seek_frame(f, sample_number)) { + f->current_playback_loc_valid = FALSE; return 0; + } if (sample_number != f->current_loc) { int n; @@ -4930,6 +4953,9 @@ int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) f->channel_buffer_start += (sample_number - frame_start); } + f->current_playback_loc_valid = TRUE; + f->current_playback_loc = sample_number; + return 1; } @@ -5322,6 +5348,7 @@ int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short if (n == len) break; if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; } + f->current_playback_loc += n; return n; } @@ -5339,6 +5366,7 @@ int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, in if (n == len) break; if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; } + f->current_playback_loc += n; return n; } @@ -5447,6 +5475,7 @@ int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; } + f->current_playback_loc += n; return n; } @@ -5473,6 +5502,7 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; } + f->current_playback_loc += n; return n; } #endif // STB_VORBIS_NO_PULLDATA_API