[BACK]Return to audio-port.html CVS log [TXT][DIR] Up to [local] / www

Annotation of www/audio-port.html, Revision 1.10

1.8       naddy       1: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                      2:        "http://www.w3.org/TR/html4/loose.dtd">
1.1       espie       3: <html>
                      4:  <head>
                      5:   <meta http-equiv="Content-Type"
                      6:        content="text/html; charset=iso-8859-1">
                      7:   <meta name="resource-type"
                      8:        content="document">
                      9:   <meta name="description"
                     10:        CONTENT="How to make an OpenBSD port; audio">
                     11:   <meta name="keywords"
                     12:        content="openbsd,ports,audio">
                     13:   <meta name="distribution"
                     14:        content="global">
                     15:   <meta name="copyright"
1.6       horacio    16:        content="This document copyright 1998-2002 by OpenBSD.">
1.1       espie      17:   <title>Porting audio applications to OpenBSD</title>
                     18:   <link rev="made" HREF="mailto:www@openbsd.org">
                     19:  </head>
                     20:  <body text="#000000" bgcolor="#FFFFFF" link="#23238E">
1.7       jsyn       21: <a href="index.html"><img alt="[OpenBSD]" height="30" width="141" src="images/smalltitle.gif" border="0"></a>
1.1       espie      22:
                     23:   <h1>Porting audio applications to OpenBSD</h1>
                     24:
                     25: <p>
                     26:   This document currently deals with sampled sounds issues only. Contributions
                     27:   dealing with synthesizers and waveform tables are welcome.
                     28:
                     29: </p>
1.8       naddy      30: <p>
1.1       espie      31:        Audio applications tend to be hard to port, as this is a domain where
                     32:        interfaces are not standardized at all, though approaches don't vary
                     33:        much between operating systems.
1.8       naddy      34: </p>
1.1       espie      35:
1.8       naddy      36:   <h2><font color="#e00000">Using <code>ossaudio</code></font></h2>
1.1       espie      37:
                     38:   The <code>ossaudio</code> emulation is possibly the simplest way, but
                     39:   it won't always work, and it is not such a great idea usually.
                     40:   <ul>
                     41:        <li>It redefines <code>ioctl</code>. If the code to port uses
                     42:        <code>ioctl</code> for more than audio, you will have to
                     43:        <code>#undef ioctl</code> and use the bare form with
                     44:        <code>_ossioctl</code>.
                     45:
                     46:        <li>Some features of linux sound are not emulated.
                     47:
                     48:        <li>Applications with correct linux sound support that is not
                     49:        Intel-specific tend to use these features.
                     50:
                     51:   </ul>
                     52:
1.8       naddy      53:   <h2><font color="#e00000">Using existing NetBSD or FreeBSD code</font></h2>
1.1       espie      54:   Since we share part of the audio interface with NetBSD and FreeBSD,
                     55:   starting from a NetBSD port is reasonable. Be aware that some files
                     56:   changed places, and that some entries in <code>sys/audioio.h</code>
                     57:   are obsolete.  Also, many ports tend to be incorrectly coded and to
                     58:   work on only one type of machine. Some changes are bound to be
                     59:   necessary, though.  Read through the next part.
                     60:
1.8       naddy      61:   <h2><font color="#e00000">Writing OpenBSD code</font></h2>
                     62:          <h3><font color="#0000e0">Hardware independence</font></h3>
1.1       espie      63:
                     64:    <p>
                     65:        <strong>YOU SHOULDN'T ASSUME ANYTHING ABOUT THE AUDIO HARDWARE USED.
                     66:        </strong><br>
                     67:        Wrong code is code that only checks the <code>a_info.play.precision</code>
                     68:        field against 8 or 16 bits, and assumes unsigned or signed samples based
                     69:        on soundblaster behavior. You should check the sample type explicitly,
                     70:        and code according to that. Simple example:
1.8       naddy      71:     </p>
1.1       espie      72:        <pre>
                     73:     AUDIO_INIT_INFO(&amp;a_info);
                     74:     a_info.play.encoding = AUDIO_ENCODING_SLINEAR;
                     75:     a_info.play.precision = 16;
                     76:     a_info.play.sample_rate = 22050;
                     77:     error = ioctl(audio, AUDIO_SETINFO, &amp;a_info);
                     78:     if (error)
                     79:        /* deal with it */
                     80:     error = ioctl(audio, AUDIO_GETINFO, &amp;a_info);
                     81:     switch(a_info.play.encoding)
                     82:        {
                     83:     case AUDIO_ENCODING_ULINEAR_LE:
                     84:     case AUDIO_ENCODING_ULINEAR_BE:
                     85:        if (a_info.play.precision == 8)
                     86:            /* ... */
                     87:        else
                     88:            /* ... */
                     89:        break;
                     90:     case ...
                     91:
                     92:     default:
                     93:        /* don't forget to deal with what you don't know !!! For instance, */
                     94:        fprintf(stderr,
                     95:                "Unsupported audio format (%d), ask ports@ about that\n",
                     96:                a_info.play.encoding);
                     97:
                     98:        }
                     99:     /* now don't forget to check what sampling frequency you actually got */
                    100:        </pre>
                    101:
1.8       naddy     102:   <p>
1.1       espie     103:   This is about the smallest code fragment that will deal with most issues.
                    104:
1.10    ! aanriot   105:        <h3><font color="#0000e0">16 bit formats and endianness</font></h3>
1.1       espie     106:        In normal usage, you just ask for an encoding type (e.g.,
1.9       saad      107:        <code>AUDIO_ENCODING_SLINEAR</code>), and you retrieve
1.10    ! aanriot   108:        an encoding with endianness (e.g., <code>AUDIO_ENCODING_SLINEAR_LE</code>).
        !           109:        Considering that a soundcard does not have to use the same endianness
1.1       espie     110:        as your platform, you should be prepared to deal with that.
                    111:        The easiest way is probably to prepare a full audio buffer, and to use
1.10    ! aanriot   112:        <code>swab(3)</code> if an endianness change is required.
1.1       espie     113:        Dealing with external samples usually amounts to:
                    114:        <ol>
                    115:                <li>Parsing the sample format,
                    116:                <li>Getting the sample in,
1.10    ! aanriot   117:                <li>Swapping endianness if it is not your native format,
1.1       espie     118:                <li>Computing what you want to output into a buffer,
1.10    ! aanriot   119:                <li>Swapping endianness if the sound card is not in your native format,
1.1       espie     120:                <li>Playing the buffer.
                    121:        </ol>
                    122:        Obviously, you may be able to remove steps 3 and 5 if you are simply
                    123:        playing a sound sample which happens to be in your sound card native
                    124:        format.
                    125:
1.8       naddy     126:        <h3><font color="#0000e0">Audio quality</font></h3>
1.1       espie     127:        <p>
                    128:        Hardware may have some weird limitations, such as being unable to get
                    129:        over 22050 Hz in stereo, but up to 44100 in mono.  In such cases, you
                    130:        should give the user a change to state his preferences, then try your
                    131:        best to give the best performance possible. For instance, it is stupid
                    132:        to limit the frequency to 22050 Hz because you are outputting stereo.
                    133:        What if the user does not have a stereo sound system connected to his
                    134:        audio card output ?
                    135:        </p>
                    136:
                    137:        <p>
                    138:        It is also stupid to hardcode soundblaster-like limitations into your
                    139:        program. You should be aware of these, but do try to get over the
                    140:        22050&nbsp;Hz/stereo barrier and check the results.
                    141:        </p>
                    142:
                    143:        <h4>Sampling frequency</h4>
                    144:        You should definitely check the sampling frequency your card gives you
                    145:        back. A 5% discrepancy already amounts to a half-tone, and some people
                    146:        have much more accurate hearing than that, though most of us won't
                    147:        notice a thing.  Your application should be able to perform
                    148:        resampling on the fly, possibly naively, or through devious
                    149:        applications of Shannon's resampling formula if you can.
                    150:
                    151:        <h4>Dynamic range</h4>
                    152:        <p>
                    153:        Samples don't always use the full range of values they could.  First,
                    154:         samples recorded with a low gain will not sound very loud on the
                    155:        machine, forcing the user to turn the volume up.
                    156:        Second, on machines with badly isolated audio, low sound output means
                    157:        you mostly hear your machine heart-beat, and not the sound you expected.
                    158:        Finally, dumb conversion from 16 bits to 8 bits may leave you with only
                    159:        4 bits of usable audio, which makes for an awfully bad quality.
                    160:        </p>
                    161:        <p>
                    162:        If possible, the best solution is probably to scan the whole stream
                    163:        you are going to play ahead of time, and to scale it so that it fits
                    164:        the full dynamic range.  If you can't afford that, but you can manage
                    165:        to get a bit of look-ahead on what you're going to play, you can
                    166:        adjust the volume boost on the fly, you just have to make sure
                    167:        that the boost factor stays at a low frequency compared to the
1.3       jufi      168:        sound you want to play, and that you get absolutely <em>no
                    169:        overflows</em> -- those will always sound much worse than the
1.1       espie     170:        improvement you're trying to achieve.<br>
                    171:        As sound volume perception is logarithmic, using arithmetic shifts is usually
                    172:        enough. If your data is signed, you should explicitly code the shift as
                    173:        a division, as C <code>&gt;&gt;</code> operator is not portable on
                    174:        signed data.
                    175:        </p>
                    176:        <p>
                    177:        If all else fails, you should at least try to provide the user with
                    178:        a volume scaling option.
                    179:        </p>
                    180:
1.8       naddy     181:        <h3><font color="#0000e0">Audio performance</font></h3>
1.1       espie     182:        <p>
                    183:        Low-end applications usually don't have much to worry about.  Keep in
                    184:        mind that some of us do use OpenBSD on low-end 68030, and that if a
                    185:        sound application can run on that, it should.
                    186:        </p>
                    187:
                    188:        <p>
                    189:        Don't forget to run benches.  Theoretical optimizations are just that:
                    190:        theoretical. Some hard figures should be collected to check what's a
                    191:        sizeable improvement, and what's not.
                    192:        </p>
                    193:
                    194:        <p>
                    195:        For high performance audio applications, such as mpegI-layer3, some
                    196:        points should be taken into account:
1.8       naddy     197:        </p>
1.1       espie     198:        <ul>
                    199:            <li>The audio interface does provide you with the natural hardware
                    200:            blocksize. Using multiples of that for your output buffer is
                    201:            essential.  Keep in mind that <code>write</code>, as a system call,
                    202:            incurs a high cost compared to internal audio processing.
                    203:
                    204:            <li>Bandwidth is a very important factor when dealing with audio.
                    205:            A useful way to optimize an audio player is to see it as a
                    206:            decompressor. The longer you can keep with the compressed data, the
                    207:            better usually. Very short loops that do very little processing are
                    208:            usually a bad idea. It is generally much better to combine all
                    209:            processing into one loop.
                    210:
                    211:            <li>Some formats do incur more overhead than others. The
                    212:            <code>AUDIO_GETENC</code> <code>ioctl</code> should be used
                    213:            to retrieve all formats that the audio device provides.
                    214:            Be especially aware of the
                    215:            <code>AUDIO_ENCODINGFLAG_EMULATED</code> flag. If your
                    216:            application is already able to output all kinds of weird formats,
                    217:            and reasonably optimized for that, try to use a native format at
                    218:            all costs. On the other hand, the emulation code present in the
                    219:            audio device can be assumed to be reasonably optimal, so don't
                    220:            replace it with quickly hacked up code.
                    221:        </ul>
                    222:
                    223:        <p>A model you may have to follow to get optimal results is to first
                    224:        compile a small test program that enquires about the specific audio
                    225:        hardware available, then proceed to configure your program so that it
                    226:        deals optimally with this hardware. You may reasonably expect people
                    227:        who want good audio performance to recompile your port when they change
                    228:        hardware, provided it makes a difference.
                    229:        </p>
                    230:
1.8       naddy     231:        <h3><font color="#0000e0">Real time or synchronized</font></h3>
1.1       espie     232:        <p>
                    233:        Considering that OpenBSD is not real time, you may still wish to write
                    234:        audio applications that are mostly real time, for instance games. In
                    235:        such a case, you will have to lower the blocksize so that the sound
                    236:        effects don't get out of synch with the current game.  The problem
                    237:        with this if that the audio device may get starved, which yields
                    238:        horrible results.
                    239:        </p>
                    240:        <p>
                    241:        In case you simply want audio to be synchronized with some graphics
                    242:        output, but the behavior of your program is predictable, synchronization
                    243:        is easier to achieve. You just play your audio samples, and ask the
                    244:        audio device what you are currently playing with
                    245:        <code>AUDIO_GETOOFFS</code>, then use  that information to
                    246:        post-synchronize graphics.  Provided you ask sufficiently often (say,
                    247:        every tenth of a second), and as long as you have enough horse-power to
                    248:        run your application, you can get very good synchronization that way.
                    249:        You might have to tweak the figures by a constant offset, as there is
                    250:        some lag between what the audio reports, what's currently playing, and
                    251:        the time it takes for XWindow to display something.
                    252:        </p>
1.8       naddy     253:   <h2><font color="#e00000">Contributing code back</font></h2>
1.1       espie     254:    <p>In the case of audio applications, working with the original program's
                    255:        author is very important. If his code does only work with soundblaster
                    256:        cards for instance, there is a good chance he will have to cope with
                    257:        other technology soon.
                    258:        </p>
                    259:
                    260:        <p>
                    261:        <strong>If you don't sent your comments to him by then, your work will
                    262:        have been useless</strong>.</p>
1.8       naddy     263:        <p>
1.1       espie     264:        It may also be that the author has already noticed whatever problems
                    265:        you are currently dealing with, and is addressing them in his current
                    266:        development tree.  If the patches you are writing amount to more than
                    267:        a handful of lines, cooperation is almost certainly a very good idea.
1.8       naddy     268:        </p>
1.1       espie     269:
                    270:   <hr>
                    271:   <a href="porting.html"><img height=24 width=24 src=back.gif
                    272:    border=0 alt=Porting></a>
1.8       naddy     273:   <a href="mailto:www@openbsd.org">www@openbsd.org</a>
1.10    ! aanriot   274: <br><small>$OpenBSD: audio-port.html,v 1.9 2004/11/05 21:57:05 saad Exp $</small>
1.1       espie     275:  </body>
                    276: </html>