-
-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stb_vorbis: fix interleaved appends silence at end #97
stb_vorbis: fix interleaved appends silence at end #97
Conversation
CC: @Wohlstand |
I'm fine with this; if no one has an objection (@Wohlstand?), let's merge it. |
We should also probably point Sean Barrett at this if it's useful in a general sense to stb_vorbis. |
|
To me, this looks fine -- still waiting @Wohlstand to make a comment. I guess the same change is needed in |
Hello! |
I don't have an audio file that causes an issue with those for me to test, would have to come up with something in Audacity for this, the one in the issue was from the user of ags that noticed the issue and reported. |
Yea, I took a small look, and ye, as you said, the change is needed not just in one interleaved function: this problem exists in all other functions too. Mainstream Mixer as well as my MixerX fork doesn't use interleaved function (except of my experimental "turn into multi-track" feature to interpret extra channels as stereo/mono/etc. concurrent tracks with ability to mute each of them), and I guess, somebody reported this problem at the Mixer too, or I confuse some 🤔 |
Also, pay attention that |
src/stb_vorbis.h
Outdated
@@ -5656,6 +5657,11 @@ int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float | |||
break; | |||
} | |||
f->current_playback_loc += n; | |||
if(f->current_playback_loc > lgs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check for the lgs >= 0
, otherwise, it may return 0 (on any error) or -1 when it has an invalid duration value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a && lgs >= 0
check as requested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait a minute, the return value should be positive as is an unsigned int, how could it be -1
?
Dropping the previously added commit until a better rationality exists...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read the code and "-1 when it has an invalid duration value" doesn't exist, it can only be 0. Using lgs > 0
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It CAN return -1, because of:
#define SAMPLE_unknown 0xffffffff
when it's a signed 32-bit integer, it's -1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On my end of the fork, I already replaced all the offsets from int into int64_t to match the mainstream Vorbis (otherwise it won't allow play large files, longer than 5 hours, and also depending on the sample rate), and the value of SAMPLE_unknown
I simply replaced with -1
: simple and easy.: https://github.com/WohlSoft/SDL-Mixer-X/blob/master/src/codecs/stb_vorbis/stb_vorbis.h
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SAMPLE_unknown
Why not to just use the SAMPLE_unknown
value directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your code there is a mix of int64_t and uint64_t, shouldn't it be all uint64_t ? I felt that it would be easier to match the eventual 64-bit upgrade by using an existent constant instead of the current manual 0xf...f.
I have a feeling there should be an existing type for this instead like size_t. If one doesn't exist, it should be typedef to ensure it all matches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, I won't change anything right now because GitHub PR is melting: https://www.githubstatus.com/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears GitHub is normalizing
91f1206
to
fef554e
Compare
src/stb_vorbis.h
Outdated
@@ -5656,6 +5657,11 @@ int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float | |||
break; | |||
} | |||
f->current_playback_loc += n; | |||
if(f->current_playback_loc > lgs && lgs > 0 && lgs != UINT_MAX) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not to just use the SAMPLE_unknown
directly? It's private code, and you are free to use that here.
if(f->current_playback_loc > lgs && lgs > 0 && lgs != SAMPLE_unknown) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted as request : https://github.com/icculus/SDL_sound/compare/fef554e25e79aef3dd24fa964e219f9a5b20a309..945fbbe3a09dd1ae043c2a6b02c9e622cd24f346
I stand-by what I said that stb_vorbis using ints directly is terrible and it should use size_t and SIZE_MAX instead or any other regular c type that is appropriate or typedef things to make sense instead of using naked int/uint mixed around...
I think in the end I would prefer if SDL_sound gave me an options to use external Xiph libraries instead.
fef554e
to
945fbbe
Compare
945fbbe
to
833218a
Compare
Any changes to @ericoporto: Is the following refactored version good? (I build-tested only) diff --git a/src/stb_vorbis.h b/src/stb_vorbis.h
index 8686bdf..7d2418d 100644
--- a/src/stb_vorbis.h
+++ b/src/stb_vorbis.h
@@ -5512,6 +5512,21 @@ int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buff
return len;
}
+static int fixup_current_playback_loc(stb_vorbis *f, int n)
+{
+ unsigned int lgs;
+
+ f->current_playback_loc += n;
+ lgs = stb_vorbis_stream_length_in_samples(f);
+ if (f->current_playback_loc > lgs && lgs > 0 && lgs != SAMPLE_unknown) {
+ int r = n - (f->current_playback_loc - (int)lgs);
+ f->current_playback_loc = lgs;
+ return r;
+ }
+
+ return n;
+}
+
int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts)
{
float **outputs;
@@ -5528,8 +5543,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;
+ return fixup_current_playback_loc(f, n);
}
int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len)
@@ -5546,8 +5560,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;
+ return fixup_current_playback_loc(f, n);
}
#ifndef STB_VORBIS_NO_STDIO
@@ -5655,8 +5668,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;
+ return fixup_current_playback_loc(f, n);
}
int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples)
@@ -5682,8 +5694,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;
+ return fixup_current_playback_loc(f, n);
}
#endif // STB_VORBIS_NO_PULLDATA_API
|
Co-Authored-By: Ozkan Sezer <[email protected]>
833218a
to
c2ad77b
Compare
@sezero I tested and for the test case of issues I had this does fix it the same. Applied your patch here in the PR and force-pushed. My test case example I did using my rawdecoder (ericoporto@12fc296, which requires this audacity import setting). I also tried to listen a few small ogg files I had here using playsound (only game sfx, nothing fancy), and it appears to still work fine for them too. |
Good. Waiting an additional green light from @icculus
IIRC it is in #92, yes? Can you attach it here too? |
Sure. Build the rawdecoder from below (or just get this commit ericoporto@12fc296) #ifdef _WIN32
#define SDL_MAIN_HANDLED /* this is a console-only app */
#endif
#include <stdio.h>
#include <SDL.h>
#include <SDL_sound.h>
const size_t SampleDefaultBufferSize = 64 * 1024;
int main(int argc, char *argv[])
{
Sound_Init();
Sound_Sample * sample = Sound_NewSampleFromFile("VacuumNoise.ogg", NULL, SampleDefaultBufferSize);
if (!sample)
return -1;
FILE *f = fopen("test.raw", "wb");
if (!f)
{
Sound_FreeSample(sample);
return -2;
}
do
{
size_t sz = Sound_Decode(sample);
if (sz > 0)
{
fwrite(sample->buffer, 1, sz, f);
}
} while ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0);
fclose(f);
Sound_FreeSample(sample);
return 0;
} and run it with VacuumNoise.ogg.zip (unzip before). It should generate a If you don't apply this PR there will be silence in the end of the decoded raw file, if you do apply the patch the file will be properly terminated. An easy way to compare is to add |
I think this has lived here long enough. If there are other problems, open a new bug report. :) |
I guess we should apply this to SDL_mixer, yes? |
.. and done. |
fix #92
alternative to #95.