Re: [linux-audio-dev] ardour now operating smoothly with 24 channel playback, etc.

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] ardour now operating smoothly with 24 channel playback, etc.
From: Paul Barton-Davis (pbd_AT_Op.Net)
Date: Sat Apr 08 2000 - 20:55:44 EEST


>Downloaded the code but could not find the relevant buffer code. Could
>you explain here how exactly the buffers are implemented?

Its all in track.cc, with some size calculations in tape.cc.

Its almost identical to a soundcard:

1) we get the total requested buffer size from a config file setup by
   the user
2) we get the disk i/o size ("fragment size") from the config file
3) we create N buffers of the fragment size, such that N*fragment_size
   is equal to the buffer size (or less if the user specified stupid
   values). the buffers are held in an array of buffer descriptors.

then, in the audio thread, we use two indexes into the array. the
playback_buffer index tells us which buffer we are using for playback,
and the capture_buffer_index ... well, you can guess.

some of the time, these two are equal, but because capture trails
playback by a certain amount (also set in the config file), around the
time that the playback_buffer index is shifted to the next buffer, the
capture buffer index will still point to the old one.

meanwhile, the butler thread also has 2 indexes, flush_buffer and
refill_buffer. these indicate the buffer that the butler will next
attempt to flush and/or refill respectively. each time it flushes or
refills a buffer to/from disk, it updates these indexes.

wrapped around each buffer is a buffer descriptor (ARDOUR::Track::Buffer),
which contains information on the buffer size, the byte in the file
that the start of the buffer corresponds to (filled in when its
refilled), and two flags for "need refill" and "need flush". we use
the file byte value when flushing the data back to disk.

a playback underrun occurs if the audio thread advances it playback
buffer index and finds that the corresponding buffer still has "need
refill" marked. the rules regarding the flags:

        audio thread can only mark them true
        butler thread can only mark them false

they are not considered to be atomic in any SMP sense, because the
audio thread only sets them true when its already finished with the
a particular buffer, and likewise for the butler thread.

thats about it. if you want more, you'll have to read the code.

there is an as yet unsolved problem with this design that is bugging
me. to ensure decent disk throughput, the butler does this:

    foreach track
        read ahead
    foreach track
        write behind

the problem is that a buffer may need to be flushed before it is refilled.

so, for now, I do this:

    butler:

    while (1) {
    
        sleep_ok = true;

        foreach track {

            if (needs_flush) {
                sleep_ok = false;
            }

            if (needs_refill) {
               refill
               advance refill buffer

               if the new refill buffer needs refill too {
                      sleep_ok = false
               }
            }
         }
   
         foreach track {
                 if (needs flush) {
                    flush
                 }
         }

         if (sleep_ok) {
            sleep (20ms) << should tune this value to the audio fragsize
         }
    }

So, if we have a flushable buffer, then the first attempt to refill it
will fail (needs_flush is true). However, once we're done refilling
all the other tracks and flushing all tracks, instead of going to
sleep, the butler will loop around again, and this time it will be
able to refill it.

Sounds sort of OK, but it doesn't scale. Its tantamount to intermixing
read-ahead and write-behind, and thats no good because it causes extra
(slow) seeks.

I'll have to try flushing buffers first, then read-ahead, but I'm
worried that this will also fail, since write performance for large
disk i/o chunks tends to be slower than read (the disk h/w's cache
stops being able to help you, I think). Thus, we'd tend to get
playback underruns because we don't service the refills in
time. Anyway, it works right now when recording a 1-4 channels at a
time, I just need to redesign this aspect to handle many more channels
recording.

An alternative is to double up all the buffers (one set for playback,
one for capture), and copy the playback data into the capture buffers
for cross-fade purposes. This adds memory overhead and a little bit of
CPU overhead, but it may be the only way.

>How much Hammerfall costs? Some good quality 5-8 channel card?

In the US, a Hammerfall is about $500, the Hammerfall light somewhat
less. But that assumes you have A-D and D-A converters. Other
multichannel cards with analog I/O like the RME Digi96/* series and
the MidiMan Delta series are probably a better buy if external A/D-D/A
hardware is not an option for you.

>Only a few channels would be ok for me if Ardour can do mixdown
>for selected channels.

it does not do mixdown right now. at the moment, you need to think of
it as exactly like an Alesis ADAT, the new Mackie HDR or the Tascam 2424.

there is no particular reason that it could not support mixdown and/or
plugins in the future, but thats not part of my design space at the
present time. the idea is to hook up snd or something very similar as
the "other side" of ardour, so that you go back and forth between a
tape recorder interface, optimized for recording, and a soundfile
editor, optimized for editing and mixing. I imagine them as two tabs
on a tabbed folder design.

--p


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Sat Apr 08 2000 - 21:26:54 EEST