[linux-audio-dev] realtime audio i/o with disk input
Hello, I mainly write this mail to Paul Davis, but of course everybody is welcome to answer :-) I am trying to do realtime audio i/o in combination with disk input. I know that Paul has a lot of experience with this. Rather than looking through his code, I'd appreciate some description of the approach he uses. I will comment my approach here, to see if you consider it correct or not. . What I am doing: I have 3 threads: - standard priority GUI thread - audio I/O thread (SCHED_RR, max, using alsa polling) - disk input thread The disk-input thread writes to a circular buffer, reading blocks of data from the hard-disk. It actually pre-fills it before starting the thread. The audio i/o thread reads from the circular buffer (and mixes it with the soundcard input, and writes it to the soundcard output, but that is not really relevant) The disk-input thread looks if it has space to write the next block to the circular buffer (it checks if the write-index will not cross the read-index). If there is no space, it waits for the readindex to move. This is done with a pthread_cond_wait in the disk-input thread, and a pthread_cond_signal in the audio i/o thread. pseudo-code: disk-input thread: pthread_mutex_lock while writeindex+blocksize readindex pthread_cond_wait pthread_mutex_lock audio i/o thread: pthread_mutex_lock readindex += fragmentsize pthread_cond_signal pthread_mutex_unlock In a similar way, the audio i/o thread also checks if the readindex will not pass the writeindex, which happens when the disk input thread did not fill the circular buffer in time. Also this is done with a pthread_cond_signal / pthread_cond_wait. Problems: - It tends to run well, but sometimes it chews up a lot of CPU or even all. I don't understand when this happens exactly. (this is the second time I write this mail: the first time I had the application running and it froze my machine. Hint: never write long e-mails while beta testing realtime priority applications ;-) ) - I can cause internal underruns (not filling the circular buffer in time), by doing a cat /dev/hda /dev/null - Also using X-windows can cause problems. I suppose this is VM related? Questions: - Is this approach correct? - Is the pthread_cond_wait the correct mechanism for the thread synchronisation? - With what priority should the disk input thread run? - Is it better to use SCHED_RR or SCHED_FIFO for the audio i/o thread? - Should I call mlockall? What would be the best moment to do that? - What would be a reasonable size for the circular buffer? And what about the blocksize to read the data from disk? Does that even matter? My system is an AMD k7 700 MHz, hdparm tuned,. 2.4.17 Andrew Morton LL kernel. Greatly appreciating your time and effort, Maarten
Re: [linux-audio-dev] realtime audio i/o with disk input
Hi. I do not know if you aware of my threaded-audio file C++ class that does the things you are trying to do. It is fairly small and compact and has been working well for more than six months with hardly and changes. So if you want a proven solution, then give it a try. One year I'll do final fixes to make it 5% faster, but right now I could not be bothered with such optimization. It is part of the DIVAIO library and distributed with Mustajuuri under LPLG (don't worry, you do not need to compile or link all of Mustajuuri to use DIVAIO). URLS: Doxygen documentation: http://www.tml.hut.fi/~tilmonen/diva/doc/code/doxygen-di/class_di_audiofilethreaded.html Code example: http://www.tml.hut.fi/~tilmonen/diva/doc/code/doxygen-di/class_di_audiofilethreaded.html#_details Download: http://www.tml.hut.fi/~tilmonen/mustajuuri/ On Wed, 20 Mar 2002, Maarten de Boer wrote: Hello, I mainly write this mail to Paul Davis, but of course everybody is welcome to answer :-) I am trying to do realtime audio i/o in combination with disk input. I know that Paul has a lot of experience with this. Rather than looking through his code, I'd appreciate some description of the approach he uses. I will comment my approach here, to see if you consider it correct or not. . What I am doing: I have 3 threads: - standard priority GUI thread - audio I/O thread (SCHED_RR, max, using alsa polling) - disk input thread The disk-input thread writes to a circular buffer, reading blocks of data from the hard-disk. It actually pre-fills it before starting the thread. The audio i/o thread reads from the circular buffer (and mixes it with the soundcard input, and writes it to the soundcard output, but that is not really relevant) The disk-input thread looks if it has space to write the next block to the circular buffer (it checks if the write-index will not cross the read-index). If there is no space, it waits for the readindex to move. This is done with a pthread_cond_wait in the disk-input thread, and a pthread_cond_signal in the audio i/o thread. pseudo-code: disk-input thread: pthread_mutex_lock while writeindex+blocksize readindex pthread_cond_wait pthread_mutex_lock audio i/o thread: pthread_mutex_lock readindex += fragmentsize pthread_cond_signal pthread_mutex_unlock In a similar way, the audio i/o thread also checks if the readindex will not pass the writeindex, which happens when the disk input thread did not fill the circular buffer in time. Also this is done with a pthread_cond_signal / pthread_cond_wait. Problems: - It tends to run well, but sometimes it chews up a lot of CPU or even all. I don't understand when this happens exactly. (this is the second time I write this mail: the first time I had the application running and it froze my machine. Hint: never write long e-mails while beta testing realtime priority applications ;-) ) - I can cause internal underruns (not filling the circular buffer in time), by doing a cat /dev/hda /dev/null - Also using X-windows can cause problems. I suppose this is VM related? Questions: - Is this approach correct? - Is the pthread_cond_wait the correct mechanism for the thread synchronisation? - With what priority should the disk input thread run? - Is it better to use SCHED_RR or SCHED_FIFO for the audio i/o thread? - Should I call mlockall? What would be the best moment to do that? - What would be a reasonable size for the circular buffer? And what about the blocksize to read the data from disk? Does that even matter? My system is an AMD k7 700 MHz, hdparm tuned,. 2.4.17 Andrew Morton LL kernel. Greatly appreciating your time and effort, Maarten Tommi Ilmonen Researcher = http://www.hut.fi/u/tilmonen/ Linux/IRIX audio: Mustajuuri = http://www.tml.hut.fi/~tilmonen/mustajuuri/ 3D audio/animation: DIVA = http://www.tml.hut.fi/Research/DIVA/
Re: [linux-audio-dev] realtime audio i/o with disk input
What I am doing: I have 3 threads: - standard priority GUI thread - audio I/O thread (SCHED_RR, max, using alsa polling) don't ever run application threads at max priority. it makes it impossible to construct a watchdog for runaways. The disk-input thread looks if it has space to write the next block to the circular buffer (it checks if the write-index will not cross the read-index). If there is no space, it waits for the readindex to move. This is done with a pthread_cond_wait in the disk-input thread, and a pthread_cond_signal in the audio i/o thread. you don't need to use mutexes for the buffer itself. when there is one reader and one writer, you can use a lock free ringbuffer. this will avoid blocking the audio thread when it goes to see if there is enough data. however, you probably do need to use mutexes to drive the disk input thread's operations. in ardour, the disk input thread gets woken periodically by the audio thread when the latter believes that work might be necessary. the disk input thread wakes up, checks on the current state of things, and then (maybe) gets busy. running and it froze my machine. Hint: never write long e-mails while beta testing realtime priority applications ;-) ) never beta test applications with RT priority :) you don't need RT priority to get this to work. - I can cause internal underruns (not filling the circular buffer in time), by doing a cat /dev/hda /dev/null - Also using X-windows can cause problems. I suppose this is VM related? are your IDE drives properly tuned with hdparm? there was a thread on alsa-devel about in the last 24 hours in which using hdparm completely fixed precisely this issue. several people have reported X Window issues. this seems to be specific to particular video adapters and/or motherboards. are you using a low latency kernel, and is low latency turned on? which version of XFree86 are you using, and which video adapter? - With what priority should the disk input thread run? ardour's disk thread runs at default priority, SCHED_OTHER. it uses hardly any CPU cycles (it spends most of its time asleep or waiting for disk I/O to complete) and thus doesn't suffer from the interactive penalty that ordinary programs would tend to. it will basically run as needed. - Should I call mlockall? What would be the best moment to do that? at program startup, once you know the user asked the program to run with RT priority. mlockall() affects an entire address space, not a thread. - What would be a reasonable size for the circular buffer? And what about the blocksize to read the data from disk? Does that even matter? from the experiments that benno and i did last year or before, we figured that a buffer of 5 seconds worth of data makes you immune to just about any and all possible disk i/o and scheduling delays. that's what ardour is using (though its user configurable). NB: JACK contains a *tiny* program, capture_client.c that does all this stuff, and records from N JACK ports to a disk file with N channels in any format supported by libsndfile. you could study that - its approach is a bit different from the circular buffer approach. --p
Re: [linux-audio-dev] realtime audio i/o with disk input
Thanks. Looking through Mustajuuri code, I have the impression you use the same approach as I do (that's at least reassuring). I will do some tests to see if the same problems occur, which would mean that they are caused somewhere else. Maarten
Re: [linux-audio-dev] realtime audio i/o with disk input
Thanks Paul for your reply. don't ever run application threads at max priority. it makes it impossible to construct a watchdog for runaways. Okay, I'll make that max-1 you don't need to use mutexes for the buffer itself. when there is one reader and one writer, you can use a lock free ringbuffer. this will avoid blocking the audio thread when it goes to see if there is enough data. Okay. Anyway, things are Wrong when there is not enough data. however, you probably do need to use mutexes to drive the disk input thread's operations. in ardour, the disk input thread gets woken periodically by the audio thread when the latter believes that work might be necessary. the disk input thread wakes up, checks on the current state of things, and then (maybe) gets busy. Okay, so I understand that you use the audio thread check if the buffer needs to be filled, the opposite of my approach, where the disk in thread checks this. Any particular reason for this? Ah, okay, in my approach the disk-in thread enters a while to see if the readindex has moved enough. It checks all the time, even if the readindex did move but not enough. With your approach, you only signal when you _know_ it has moved enough. Is that it? What is the wake-up mechanism you use? pthread_cond_signal/wait? never beta test applications with RT priority :) you don't need RT priority to get this to work. But at some point I need to run in in RT priority to see if that works. are your IDE drives properly tuned with hdparm? there was a thread on alsa-devel about in the last 24 hours in which using hdparm completely fixed precisely this issue. I believe I did. I run tunedisk from Benno's latencytest. several people have reported X Window issues. this seems to be specific to particular video adapters and/or motherboards. are you using a low latency kernel, and is low latency turned on? which Yes (Andrew Morton), and yes (echo 1 /proc/sys/kernel/lowlatency) version of XFree86 are you using, and which video adapter? 4.1.0 (debian woody), Matrox MGA 400 Maarten
Re: [linux-audio-dev] realtime audio i/o with disk input
Okay, I'll make that max-1 you don't need to use mutexes for the buffer itself. when there is one reader and one writer, you can use a lock free ringbuffer. this will avoid blocking the audio thread when it goes to see if there is enough data. Okay. Anyway, things are Wrong when there is not enough data. yes, but if you have to sleep on the mutex because the butler thread has it right then, you've just lost tens of usecs at least. Okay, so I understand that you use the audio thread check if the buffer needs to be filled, the opposite of my approach, where the disk in thread checks this. Any particular reason for this? yes, there is - consistency. there are two times when we need to call the butler thread: 1) when we've used enough data from our side of the buffer, and thus the butler needs to handle its side 2) when we invalidate the buffer contents because of a transport event (like a locate), and need the butler to refill. so, i have a single call, summon_butler() that is used to handle either case. in (2) its preceeded by wait_for_butler(); // waits until the butler thread is inactive invalidate_buffers(); // set buffer pointers so that the butler will refill it entirely next time there are several times when i need to stop the butler thread from being active - if its ran periodically all by itself, i have to use a more extensive and more long-lived locks to prevent it from interfering with certain transport related activities. that wouldn't be a *bad* approach, but the one i use has evolved to the point where it seems to work really well. the other issue with the butler thread is to make sure that it *never* does disk I/O in small chunks, and that it will keep working on those buffers that need more data but *always* in a round-robin fashion. that is, if buffers A and C need 2 chunks of data, and B needs 3, you load each one with one chunk, then do that again, then do B alone for its third chunk. this allows the butler to handle varispeed tracks with ease, without starving out tracks running at normal speed while you do too much work on those running ahead. all disk i/o in ardour happens in chunks of a fixed size, never more, never less. the default size (based on empirical studies on the relative throughput improvement as read sizes increase) is 256kB. Ah, okay, in my approach the disk-in thread enters a while to see if the readindex has moved enough. It checks all the time, even if the readindex did move but not enough. With your approach, you only signal when you _know_ it has moved enough. Is that it? more or less. What is the wake-up mechanism you use? pthread_cond_signal/wait? yes. sorry that i don't have more suggestions on why your IDE drives or X is messing you up. --p
[linux-audio-dev] midi re-direction?
Hi everyone, does anyone know if an app exists that can open a midi port and then, for instance, send channel 1 to the external midiport and all the rest to a virmidi port? I've asked this before on LAU, but I'd really like to know the answer because I'm thinking of writing my own if there isn't. It'll be my first midi app -- is there a book that can teach me what I need to know to program with midi on linux? (I'm a decent C++ programmer but I haven't much in the way of interacting with the operating system before) thanks, Nathaniel
[linux-audio-dev] (no subject)
unsubscribe instructions please?
Re: [linux-audio-dev] midi re-direction?
Hi everyone, does anyone know if an app exists that can open a midi port and then, for instance, send channel 1 to the external midiport and all the rest to a virmidi port? not known to me. I've asked this before on LAU, but I'd really like to know the answer because I'm thinking of writing my own if there isn't. It'll be my first midi app -- is there a book that can teach me what I need to know to program with midi on linux? (I'm a decent C++ programmer but I haven't much in the way of interacting with the operating system before) no, not if you're going to use the ALSA sequencer (and more or less no even if you're not). and BTW, you won't be obviously interacting with the OS. think of the sequencer as just another library, and you'll probably feel a lot more comfortable. --p
Re: [linux-audio-dev] midi re-direction?
On Wed, Mar 20, 2002 at 08:55:31PM +, Nathaniel Virgo wrote: does anyone know if an app exists that can open a midi port and then, for instance, send channel 1 to the external midiport and all the rest to a virmidi port? Maybe plm is what you want: http://member.nifty.ne.jp/Breeze/softwares/unix/index.html HTH Kay.