At Thu, 17 Jun 2004 12:50:06 +0200, Mario Lang wrote: > > I am currently trying to figure out how to restructure the code > of my little yatm tool to be flexible and extensible in the future. > Basically, I'd like to be able to become a JACK client at > some point in the future. Since JACK uses a poll model, I have > to majorly restructure my code. I think what I need is the following: > Three threads, one for the UI, one for the MPEG/Vorbis/Speex decoder, > and one for audio output (to either libao or JACK).
You actually probably only need two threads, one for the UI and one for audio (more on this below). > Additionally, I'd like to have the ability to make the > buffer in between remember the last n seconds of audio data and make > it possible to jump back in time <=n seconds during playback. I think you could just change the value of the position indicator to have it point that many frames back in time. > I've looked at the lock-free ringbuffer of JACK, but I am not > sure if this is really what I need here. The lock-free ringbuffer is necessary to communicate to the audio thread in an RT-safe manner. RT doesn't really mean "goes fast" so much as it means "has a guaranteed minimum speed." If you communicate with the JACK thread just by mutex-protected global variables, that guarantee becomes difficult to make. This is because the JACK thread will have to lock each mutex to check the value, and there is a possibility that it might end up waiting an indeterminate amount of time to get that lock if your UI thread has it. If you use multiple variables protected this way, things get worse. So basically, if you need to tell your JACK thread something, you need to do it with a ringbuffer. What I'd recommend doing is creating a UI thread and having it communicate to the audio thread via the ringbuffer. The audio thread would have some setting indicating a chunk of memory or file (whatever) to read sound data from, in addition to settings on how to read it and where it currently is within the file. You would adjust these settings by checking for messages from the UI in the ringbuffer at the beginning of each callback invocation. After checking for messages, just mixdown the number of frames requested into the provided buffer, transforming it in accordance with thread's current settings. Hope that helps, -Pete