Re: Sound glitch when using libvorbisfile and libao
Marshall Mason <[email protected]> Fri, 26 Jun 2015 18:50:51 -0700
| Newsgroups | gmane.comp.multimedia.ogg.vorbis.devel |
|---|---|
| Message-ID | <CANMExBS2O4L=nT1OKZcX8SAsdQEXrG_9Qm-aRobGOrxrmYSoJA@mail.gmail.com> |
--===============0532822381==
Content-Type: multipart/alternative; boundary=047d7b86dcfc1d0cfe051976167f
--047d7b86dcfc1d0cfe051976167f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hi Gunter,
I've solved the sound glitch. Since it was hard to reproduce, it took me a
while, but I eventually figured it out.
What I needed to do was fill the buffer with more data before handing it
off to ao_play. It requires lots of bookkeeping, pointer arithmetic, and a
sufficiently large buffer.
First, the bigger buffer. I just pulled this code from ogg123:
#define PRIMAGIC (2*2*2*2*3*3*3*5*7)
#define AUDIO_CHUNK_SIZE ((16384 + PRIMAGIC - 1)/ PRIMAGIC * PRIMAGIC)
char convbuffer[AUDIO_CHUNK_SIZE];
const int convsize =3D AUDIO_CHUNK_SIZE;
The loop is now more convoluted. Here's the old one, for reference:
long bytes_read =3D 0;
do {
bytes_read =3D decode_vorbisfile(&vf);
ao_play(device, pcmout, bytes_read);
} while (bytes_read > 0);
Here's the new loop, which now works:
long bytes_filled =3D 0;
long bytes_remaining =3D convsize;
while (1) {
while (bytes_remaining >=3D 4096) {
int current_section;
long bytes_read =3D ov_read(&vf, convbuffer + bytes_filled,
bytes_remaining, 0, 2, 1, ¤t_section);
if (bytes_read =3D=3D 0) break;
bytes_remaining -=3D bytes_read;
bytes_filled +=3D bytes_read;
}
if (bytes_filled =3D=3D 0) break;
ao_play(device, convbuffer, bytes_filled);
bytes_remaining =3D convsize;
bytes_filled =3D 0;
}
I'm not sure why, when the system is busy, the buffer needs more data
before ao_play is called. All I can think of is that there might be some
sort of race condition and ov_read is filling the buffer too slowly to keep
up with ao_play.
Thanks,
Marshall
On Sun, Jun 14, 2015 at 10:02 AM, Marshall Mason <[email protected]>
wrote:
> Hi Gunter,
> I think this problem started happening when I upgraded from Debian Wheezy
> to Debian Jessie. If nothing looks amiss in my code, it probably is a sou=
nd
> driver problem. But since it works 100% of the time in ogg123, I feel I
> must have missed some corner case.
>
> My audio driver is almost always active. I usually have my music player
> going in the background when I do my testing. The problem surfaces more
> reliably after watching a bunch of YouTube videos, but not consistently
> enough to use it as a test case.
>
> I'll keep poking at it, and will give an update if I figure it out.
>
> Thanks for your responses.
>
> Marshall
>
> On Sun, Jun 14, 2015 at 12:51 AM, Gunter K=C3=B6nigsmann <gunter@peterpal=
l.de>
> wrote:
>
>> Dear Marshall,
>>
>> I spent most of yesterday finding out that wxWidget's wxStringArray
>> sometimes drops whitespace in a new entry depending on the character the
>> last entry ended with - so I know what you mean. But your code looks cle=
an
>> and after listening to the bell for what felt too long I started using y=
our
>> program as a regular audio player.
>> I too assume the problem lies in the audio driver your soundcard is usin=
g
>> and has to be triggered by using some exact timing. One potential way to
>> test for this would be keeping the audio driver active between running
>> instances of your program: You said the problem always turns up when
>> starting the playback. Is it possible for you to constantly play back
>> silent audio in the background while testing? Alsa can be configured to
>> automatically mix all streams that are being played back simultaneously =
and
>> the sound servers all support this feature, too.
>>
>> Kind regards,
>>
>> Gunter.
>>
>
>
--047d7b86dcfc1d0cfe051976167f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Gunter,</div><div>I've solved the sound glitch=
. Since it was hard to reproduce, it took me a while, but I eventually figu=
red it out.</div><div><br></div><div>What I needed to do was fill the buffe=
r with more data before handing it off to ao_play. It requires lots of book=
keeping, pointer arithmetic, and a sufficiently large buffer.</div><div><br=
></div><div>First, the bigger buffer. I just pulled this code from ogg123:<=
/div><div><br></div><div>#define PRIMAGIC (2*2*2*2*3*3*3*5*7)</div><div>#de=
fine AUDIO_CHUNK_SIZE ((16384 + PRIMAGIC - 1)/ PRIMAGIC * PRIMAGIC)</div><d=
iv>char convbuffer[AUDIO_CHUNK_SIZE];</div><div>const int convsize =3D AUDI=
O_CHUNK_SIZE;</div><div><br></div><div>The loop is now more convoluted. Her=
e's the old one, for reference:</div><div><br></div><div>long bytes_rea=
d =3D 0;</div><div>do {</div><div>=C2=A0 =C2=A0 bytes_read =3D decode_vorbi=
sfile(&vf);</div><div>=C2=A0 =C2=A0 ao_play(device, pcmout, bytes_read)=
;</div><div>} while (bytes_read > 0);</div><div><br></div><div>Here'=
s the new loop, which now works:</div><div><br></div><div>long bytes_filled=
=3D 0;</div><div>long bytes_remaining =3D convsize;</div><div>while (1) {<=
/div><div>=C2=A0 =C2=A0 while (bytes_remaining >=3D 4096) {</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int current_section;</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 long bytes_read =3D ov_read(&vf, convbuffer + bytes_fille=
d, bytes_remaining, 0, 2, 1, &current_section);</div><div>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 if (bytes_read =3D=3D 0) break;</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 bytes_remaining -=3D bytes_read;</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 bytes_filled +=3D bytes_read;</div><div>=C2=A0 =C2=A0 }</div><div>=
=C2=A0 =C2=A0 if (bytes_filled =3D=3D 0) break;</div><div>=C2=A0 =C2=A0 ao_=
play(device, convbuffer, bytes_filled);</div><div>=C2=A0 =C2=A0 bytes_remai=
ning =3D convsize;</div><div>=C2=A0 =C2=A0 bytes_filled =3D 0;</div><div>}<=
/div><div><br></div><div>I'm not sure why, when the system is busy, the=
buffer needs more data before ao_play is called. All I can think of is tha=
t there might be some sort of race condition and ov_read is filling the buf=
fer too slowly to keep up with ao_play.</div><div><br></div><div>Thanks,</d=
iv><div>Marshall</div></div><div class=3D"gmail_extra"><br><div class=3D"gm=
ail_quote">On Sun, Jun 14, 2015 at 10:02 AM, Marshall Mason <span dir=3D"lt=
r"><<a href=3D"mailto:[email protected]" target=3D"_blank">marsha=
[email protected]</a>></span> wrote:<br><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr">Hi Gunter,<div>I think this problem started happening when=
I upgraded from Debian Wheezy to Debian Jessie. If nothing looks amiss in =
my code, it probably is a sound driver problem. But since it works 100% of =
the time in ogg123, I feel I must have missed some corner case.</div><div><=
br></div><div>My audio driver is almost always active. I usually have my mu=
sic player going in the background when I do my testing. The problem surfac=
es more reliably after watching a bunch of YouTube videos, but not consiste=
ntly enough to use it as a test case.</div><div><br></div><div>I'll kee=
p poking at it, and will give an update if I figure it out.</div><div><br><=
/div><div>Thanks for your responses.</div><span class=3D"HOEnZb"><font colo=
r=3D"#888888"><div><br></div><div>Marshall</div></font></span></div><div cl=
ass=3D"HOEnZb"><div class=3D"h5"><div class=3D"gmail_extra"><br><div class=
=3D"gmail_quote">On Sun, Jun 14, 2015 at 12:51 AM, Gunter K=C3=B6nigsmann <=
span dir=3D"ltr"><<a href=3D"mailto:[email protected]" target=3D"_blan=
k">[email protected]</a>></span> wrote:<br><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex">Dear Marshall,<div><br></div><div>I spent most of yesterday finding out=
that wxWidget's wxStringArray sometimes drops whitespace in a new entr=
y depending on the character the last entry ended with - so I know what you=
mean. But your code looks clean and after listening to the bell for what f=
elt too long I started using your program as a regular audio player.</div><=
div>I too assume the problem lies in the audio driver your soundcard is usi=
ng and has to be triggered by using some exact timing. One potential way to=
test for this would be keeping the audio driver active between running ins=
tances of your program: You said the problem always turns up when starting =
the playback. Is it possible for you to constantly play back silent audio i=
n the background while testing? Alsa can be configured to automatically mix=
all streams that are being played back simultaneously and the sound server=
s all support this feature, too.</div><div><br></div><div>Kind regards,</di=
v><div><br></div><div>=C2=A0 =C2=A0 =C2=A0Gunter.</div></blockquote></div><=
br></div>
</div></div></blockquote></div><br></div>
--047d7b86dcfc1d0cfe051976167f--
--===============0532822381==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Vorbis-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/vorbis-dev
--===============0532822381==--