[linux-audio-dev] realtime audio i/o with disk input

2002-03-20 Thread Maarten de Boer

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

2002-03-20 Thread Tommi Ilmonen

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

2002-03-20 Thread Paul Davis

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

2002-03-20 Thread Maarten de Boer

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

2002-03-20 Thread Maarten de Boer

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

2002-03-20 Thread Paul Davis

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?

2002-03-20 Thread Nathaniel Virgo


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)

2002-03-20 Thread Richard Snow

unsubscribe instructions please?




Re: [linux-audio-dev] midi re-direction?

2002-03-20 Thread Paul Davis


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?

2002-03-20 Thread Kay Pruefer


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.