Library / SDK
PortAudio/portaudio avatar
PortAudio/portaudio

PortAudio: thirteen audio backends, two I/O models, three version numbers

PortAudio is a cross-platform, open-source C language library for real-time audio input and output.

2,156 stars411 forksCNOASSERTION

At a glance

What is it?
PortAudio puts thirteen host backends behind one C audio I/O API, offers a callback or a blocking buffer model, and converts client formats to the native format internally. Its version numbering disagrees with itself, and its test programs are the only acceptance suite the project ships.
Who is it for?
PortAudio earns its place in any C codebase that must run the same audio path on Windows, macOS and Linux, because one client API covers five Windows backends and eight others without naming any of them. It is the wrong layer for a project that needs sample rate conversion, a documented thread priority or a device mixer, since the README covers none of those three.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Thirteen host API backends sit behind one API surface

Every audio path in PortAudio ends in a directory under `src/hostapi`, and the README enumerates thirteen of them.

bash
src/hostapi/alsa        = Advanced Linux Sound Architecture (ALSA)
src/hostapi/asihpi      = AudioScience HPI
src/hostapi/asio        = ASIO for Windows and Macintosh
src/hostapi/audioio     = /dev/audio (Solaris/NetBSD Audio)
src/hostapi/coreaudio   = Macintosh Core Audio for OS X
src/hostapi/dsound      = Windows Direct Sound
src/hostapi/jack        = JACK Audio Connection Kit
src/hostapi/oss         = Unix Open Sound System (OSS)
src/hostapi/pulseaudio  = Sound system for POSIX OSes
src/hostapi/sndio       = Small audio and MIDI framework (sndio)
src/hostapi/wasapi      = Windows Vista WASAPI
src/hostapi/wdmks       = Windows WDM Kernel Streaming
src/hostapi/wmme        = Windows MultiMedia Extensions (MME)

Five of those entries target Windows, with `asio` serving Windows and Macintosh from a single implementation. The rest spread over Linux, the BSDs, Solaris and the Mac, which is where the portability claim earns its keep: a caller linking the client API never names a backend.

The layer above them is split three ways. `src/common` holds platform independent and host independent code for all implementations, `src/os` holds code that is OS specific but host API neutral, and each backend sits in its own directory below that. A new host API is meant to be added without touching the two layers above it, though the README does not spell out the interface a new backend has to satisfy.

Callback delivery and blocking buffers hand the buffer to different code

PortAudio moves samples two ways, and the choice decides who carries the real-time obligation.

In callback mode the library calls into client code when it needs audio processed. In the other mode the client makes blocking read and write calls that buffer data between the native audio subsystem and the client. A callback application never learns when the device will want the next block, so it has to finish inside the callback or lose audio. A blocking application can sleep between calls, and instead of dropping audio it misses a deadline.

Format handling sits below both paths. Clients may hand over 32 bit floating point and other formats, and conversion to the native format happens internally, so the client never has to know whether the hardware wants integer samples or floating point. What the README does not mention anywhere is sample rate conversion. That leaves a program opening a capture device at one rate and a playback device at another responsible for the mismatch itself, which is the most common reason a cross platform audio port turns into per platform work.

The API spec has two addresses in the same tree

The README points at two different files for the same job.

bash
include/portaudio.h     = header file for PortAudio API. Specifies API.
src/common/             = platform independent code, host independent
                              code for all implementations.
src/os                  = os specific (but host api neutral) code
src/hostapi             = implementations for different host apis

Its documentation section tells you to see `src/common/portaudio.h` for the API spec, while the important files section above names `include/portaudio.h` as the header that specifies the API. Nothing in the repository listing reconciles the two spellings, so a build that adds `src/common` for convenience and a packaging recipe that adds `include` can install different headers.

Generated documentation is a third location, since the docs live at `/doc/html/index.html` only after Doxygen runs and that path is absent from a fresh checkout. The root ships both `Doxyfile` and `Doxyfile.developer`, and the README does not say which one produces the published pages. When a call's exact contract matters, read the header that your own include path resolves, rather than trusting either name.

Three version schemes share one checkout

Pick a version out of this tree three ways and the answers will not agree.

The only tag listed for the project is v19.7.0, carrying the date 2021-04-06. Both documentation URLs sit under a v19 path, so the compilation tutorial lives at:

bash
http://portaudio.com/docs/v19-doxydocs/tutorial_start.html

The pkg-config template at the root is named `portaudio-2.0.pc.in`, which advertises a 2.0 series that the tag list does not show. Meanwhile the last push was on 2026-09-25, so the tree keeps moving while the newest published tag stays where it was. A downstream packager pinning v19.7.0 by that tag gets a 2021 snapshot, and a packager reading the pkg-config filename gets a different number again. Nothing in the README explains the split, so treat the tag as a label rather than as a description of the code being compiled.

CMake, autotools and msvc build the same tree

The root directory carries three build systems at once, and the README gives no command for any of them.

bash
CMakeLists.txt
cmake/
configure
configure.ac
Makefile.in
aclocal.m4
msvc/
vcpkg.json
portaudio-2.0.pc.in
README.configure.txt

`CMakeLists.txt` and `cmake/` cover CMake, `configure` with `configure.ac`, `Makefile.in` and `aclocal.m4` cover autotools, and `msvc/` covers Visual Studio. A `vcpkg.json` manifest and the pkg-config template sit next to them for packaging. Where a user is pointed for compilation help is an external page on portaudio.com, the URL in the block above.

The tree also ships `README.configure.txt`, which the README never explains, so a first build means reading a file the project does not introduce. Licence handling is the other thing a packager cannot guess: GitHub classifies the licence as Other, a custom licence the LICENSE file defines, and the README restates none of its terms.

Examples target the backends that need special handling

The `examples/` directory is where backend quirks become visible.

The README sends new users to `examples/paex_saw.c`, but the rest of the directory is organised by awkward case. `paex_mono_asio_channel_select.c` handles picking channels on a multi-channel interface, `paex_wmme_ac3.c` and `paex_wmme_surround.c` push formats through the Windows path the host API table calls Windows MultiMedia Extensions, and `paex_sine_c++.cpp` shows the C API compiled as C++ rather than C. `paex_read_write_wire.c` is the blocking counterpart to the callback model, passing input to output. `paex_write_sine_nonint.c` covers non-interleaved output, and `paex_record_file.c` writes a take to disk.

Two programs, `pa_devs.c` and `pa_fuzz.c`, exist in both `examples/` and `test/`, and the README does not say which copy came first or which one to build first. The `bindings/` directory sits in the same position: present in the tree, and never named in the README.

The test directory is the acceptance suite you can run

PortAudio ships its own checks, and they are specific about what a port has to survive.

bash
test/pa_minlat.c         = determine minimum latency for your machine
test/paqa_devs.c         = self test that opens all devices
test/paqa_errs.c         = test error detection and reporting
test/patest_maxsines.c   = how many sine waves can we play? Tests Pa_GetCPULoad().
test/patest_sync.c       = test synchronization of audio and video
test/patest_dither.c     = hear effects of dithering (extremely subtle)

`pa_minlat.c` exists because latency belongs to the machine and the backend, not to the library, so the number you get is yours to measure. `patest_maxsines.c` exists to stress `Pa_GetCPULoad()`, the only CPU measurement the README names. `paqa_devs.c` opens every device it can find, and `paqa_errs.c` checks that errors are detected and reported rather than swallowed.

One entry sets an expectation you cannot meet by ear, since `patest_dither.c` is labelled extremely subtle. Checking this library's format conversion by listening is not a test. The root even carries `filtered1.wav`, a sample asset the README never mentions, and two Python helpers, `pa_compare_def_files.py` and `pa_whitelint.py`, whose purpose is not stated anywhere.

Where the wrapper costs more than it saves

Two things the README does not promise are worth checking before adopting it. There is no documented sample rate conversion, so a client opening capture and playback at different rates resamples itself. There is also no documented thread priority, CPU affinity or buffer policy, which are exactly the settings a real time audio path tends to need.

A project already committed to one native stack can also argue that the wrapper is the wrong layer. `src/hostapi/alsa` and `src/hostapi/coreaudio` are themselves implementations over native subsystems, so linking PortAudio puts one more translation step between your code and that subsystem, and the format conversion you would have written by hand happens instead of being debugged by hand. Staying inside PortAudio and choosing a backend is the other option: `jack` already sits in `src/hostapi/jack` for routing work, and `pulseaudio` covers desktop Linux, so switching routing models does not mean leaving the API.

What PortAudio does promise is narrow and checkable: 32 bit floating point input converted internally to the native format, one API across thirteen backends, and a test directory that measures the rest on your own hardware.

Editorial conclusion

PortAudio earns its place in any C codebase that must run the same audio path on Windows, macOS and Linux, because one client API covers five Windows backends and eight others without naming any of them. It is the wrong layer for a project that needs sample rate conversion, a documented thread priority or a device mixer, since the README covers none of those three. Before committing, run `test/pa_minlat.c` and `test/patest_maxsines.c` on the target hardware, then check which header your build actually installs.

Frequently asked questions

Does PortAudio convert sample rates automatically?

No. The README documents conversion of client formats, including 32 bit floating point, to the native format, and says nothing about sample rate conversion. A client whose capture and playback devices run at different rates has to handle the mismatch.

How do I measure audio latency with PortAudio?

The repository ships `test/pa_minlat.c`, described as determining minimum latency for your machine. Latency is measured on your hardware and backend rather than read off a table.

Which PortAudio backends cover Windows and macOS?

The host API list names `src/hostapi/asio` for Windows and Macintosh, plus `dsound`, `wasapi`, `wdmks` and `wmme` on Windows, and `src/hostapi/coreaudio` for Core Audio on OS X.

What licence does PortAudio use, and can I ship it inside a product?

GitHub classifies the licence as Other, a custom licence that the LICENSE file defines, and the README restates none of its terms. The file itself has to be read directly, since the repository offers no summary to rely on.

Does PortAudio build with CMake, autotools and Visual Studio?

All three are present in the root: `CMakeLists.txt` with a `cmake/` directory, `configure` with `configure.ac` and `Makefile.in`, and `msvc/`. The README itself gives no build command and sends compilation questions to its hosted tutorial.

How does PortAudio report CPU load in a real time callback?

Through `Pa_GetCPULoad()`, the only CPU measurement the README names. `test/patest_maxsines.c` exists to exercise it by playing as many sine waves as the machine manages.

Official sources

  1. Issues
  2. PortAudio/portaudio on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/portaudio-portaudio.svg)](https://hysenlabs.com/projects/portaudio-portaudio)

Was this useful?