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

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

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