aspose file tools*
The moose likes I/O and Streams and the fly likes Popping in streaming audio Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » I/O and Streams
Bookmark "Popping in streaming audio" Watch "Popping in streaming audio" New topic
Author

Popping in streaming audio

Jeremy Tartaglia
Ranch Hand

Joined: Mar 11, 2004
Posts: 62
Not sure if this is the right place for this post, but it seems to be the best fit.

I created an audio core for a game, and it works fine, except on occasion there is a very faint pop. It's not present in the sound clips (which are in Ogg Vorbis format), and I'm using the VorbisSPI to decode them. The core works like this:

It creates an audio line for each sound to be played, and loads a buffer from the file. A thread is running in the background which then pipes as much data as the line can hold out of the buffer, and into the line, refilling the buffer from the file.

I'd post code, but I feel there's way too much to post, and it's spread out over a few classes. I thought the pops might have something to do with the VM being bogged down with creating and loading buffers, so I created a circular buffer for the decoded data, and it does pop less, but it still pops. I'm completely at a loss for ideas.

If you need or would like to see the code, I'll post a simplified version of it. I just don't have one right now.

Thanks in advance.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Yeah, I think it's hard to offer any useful suggestions here without seeing some code. Plus, refactoring your code for simplicity is usually a good thing anyway. Hopefully it will become easier for you to do further work on, as a result.


"I'm not back." - Bill Harding, Twister
Jeremy Tartaglia
Ranch Hand

Joined: Mar 11, 2004
Posts: 62
Well, I think my code is relatively well factored, other than perhaps to use the existing CircularBuffer class, but for my purposes, I think it would be overkill.

WARNING: This is unpolished, mostly uncommented code. Sorry.

Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I've only taken a cursory look at the code so far, and I'm not familiar with the sound APIs you're using. Yet. But - are the sounds your're playing all small enough to fit within the BUFFER_SIZE you're using? Or are we talking about ongoing streaming through these buffers? I'm guessing the latter (from the thread title) but want to confirm. Do the clicks occur regularly? Is it possible they're occurring specifically whenever you refill the buffer? Or as least, sometimes when you fill the buffer? I.e. do clicks occur more often than buffer refils, less often, or exactly the same? Adding a println("fililng buffer") could give you a good idea which is the case - just look at the output as you listen to the sound.

Looking at floodBuffer(), my spidey sense is going off when I see the code is filling the buffer entirely. I'm thinking it may well be smoother to just read as many bytes as the system has ready, and pass them on to the AudioSystem.getLine() as they arrive, rather than making sure you fill up the buffer first. If theres some reason the system can't fill the buffer in one shot, you might as well deliver the bytes you do have, and then come back for more. That's what I'd be inclined to try, anyway. Though again, I'm not familiar with AudioStream etc, so maybe there's some reason why this approach doesn't work.
[ February 05, 2006: Message edited by: Jim Yingst ]
Jeremy Tartaglia
Ranch Hand

Joined: Mar 11, 2004
Posts: 62
But - are the sounds your're playing all small enough to fit within the BUFFER_SIZE you're using? Or are we talking about ongoing streaming through these buffers?

Yeah, these files are very large, even compressed: 2-4 megabytes ~ 20-50 uncompressed.

Do the clicks occur regularly? Is it possible they're occurring specifically whenever you refill the buffer? Or as least, sometimes when you fill the buffer? I.e. do clicks occur more often than buffer refils, less often, or exactly the same? Adding a println("fililng buffer") could give you a good idea which is the case - just look at the output as you listen to the sound.

The pops occur at the same instances every time, but it's not after a regular interval, no. I tried the System.out.println, and floodBuffer has nothing to do with the pops. They occur much more frequently than the pops.

Looking at floodBuffer(), my spidey sense is going off when I see the code is filling the buffer entirely. I'm thinking it may well be smoother to just reas as many bytes as the system has ready, and pass them on to the AudioSystem.getLine() as they arrive, rather than making sure you fill up the buffer first.

This was how I had it the first time. But, it requires that you have to read bytes from the file before you output them to the line. This creates IO lag, while my system loads the data from the file AFTER data has already been output to the line. It pops less now, but still pops.
[ February 05, 2006: Message edited by: Jeremy Tartaglia ]
Jeremy Tartaglia
Ranch Hand

Joined: Mar 11, 2004
Posts: 62
You know, maybe I should just never post questions here again.

The code is fine. The converter I used to go from ACM WAV -> Ogg Vorbis screwed up. The pops are in the audio file.

Everyone point and laugh at the dumb rookie.

Thanks for trying to help though.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Interesting. I'm surprised that the problem diminished when you switched to filling the buffer, but OK. Is it possible there was just some bug in the original code, that went away when you rewrote it to fill the buffer?

In main(), it looks like you're trying to stream two different sounds in one loop. I wonder if sometimes one sound is taking up too much of the time, while the other needs more data? Perhaps you could create two different Threads, each one feeding bytes to a different Sound object. That way while one thread's busy trying to fill its buffer reading from the sound file (which may well involve a blocking read), the other thread has a chance to do something and maybe keep the second sound from running out of data to play.

You might also want to play around with the buffer size and even the length of the Thread.sleep(), if you haven't already.

We don't get a lot of questions about the sound API here. In theory Other Java APIs would be the best place to ask about that, though in practice I'm not sure there are a lot of posters familiar with Java sound in that forum either. Might be worth a try though.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
D'oh! I saw your last message just after posting the above. Well, on the plus side I learned a little bit about the sound APIs, about which I knew nothing, previously. Now I know... slightly more than nothing. So no complaints here. Cheers...
 
Consider Paul's rocket mass heater.
 
subject: Popping in streaming audio