1. Produkty
  2.   Audio
  3.   C++
  4.   portaudio

portaudio

 
 

Otwarta biblioteka C do audio I/O

Wejście i wyjście audio w czasie rzeczywistym na Windows, macOS, Linux i inne za pośrednictwem otwartoźródłowego API C.

Czym jest portaudio?

PortAudio jest darmową, otwarto‑źródłową, wieloplatformową biblioteką w języku C, która umożliwia programistom tworzenie przenośnych aplikacji audio z możliwościami wejścia i wyjścia w czasie rzeczywistym. Abstrahuje ona specyficzne dla platform podsystemy audio, takie jak ASIO, CoreAudio, ALSA, WASAPI i JACK, zapewniając spójny I/O audio na systemach Windows, macOS, Linux i innych systemach operacyjnych. Biblioteka obsługuje wiele formatów audio — w tym 32‑bitowe liczby zmiennoprzecinkowe — i wewnętrznie dokonuje konwersji formatów. Dzięki prostemu, a jednocześnie potężnemu API, PortAudio jest szeroko stosowany w oprogramowaniu audio, wtyczkach, narzędziach edukacyjnych oraz projektach badawczych wymagających niskiej latencji i wysokiej wydajności przetwarzania dźwięku.

PortAudio oferuje dwa podstawowe tryby działania: oparty na wywołaniach zwrotnych (do strumieniowania o niskiej latencji) oraz blokujący odczyt/zapis (do prostszego synchronicznego I/O). Zawiera obszerną dokumentację, przykładowe programy i narzędzia testowe, które pomagają programistom szybko rozpocząć pracę. Biblioteka jest utrzymywana przez globalną społeczność i jest licencjonowana na licencji MIT, co czyni ją odpowiednią zarówno dla aplikacji open‑source, jak i komercyjnych. Niezależnie od tego, czy tworzysz cyfrową stację roboczą audio, narzędzie rozpoznawania mowy, czy interaktywną aplikację muzyczną, PortAudio zapewnia niezawodną, lekką podstawę do rozwoju audio na wielu platformach.

Previous Next

Rozpoczęcie pracy z portaudio

Aby rozpocząć korzystanie z PortAudio, możesz albo zbudować go ze źródeł, albo zainstalować za pomocą menedżerów pakietów. Dla większości programistów najprostszą metodą jest sklonowanie oficjalnego portaudio GitHub i kompilacja przy użyciu CMake lub autotools. Na Linuxie zainstaluj poleceniem `apt install portaudio19-dev`; na macOS użyj `brew install portaudio`; na Windows pobierz gotowe binaria lub użyj vcpkg (`vcpkg install portaudio`). Po instalacji dołącz `portaudio.h` i linkuj z biblioteką (`-lportaudio`). Biblioteka jest lekka i ma minimalne zależności, co ułatwia integrację w aplikacjach audio w czasie rzeczywistym.

Instalacja PortAudio za pomocą menedżerów pakietów

# Linux (Debian/Ubuntu)
sudo apt install portaudio19-dev

# macOS (Homebrew)
brew install portaudio

# Windows (vcpkg)
vcpkg install portaudio

Strumieniowanie dźwięku w czasie rzeczywistym z użyciem wywołań zwrotnych

Tryb strumieniowania oparty na wywołaniach zwrotnych w PortAudio jest idealny do przetwarzania dźwięku w czasie rzeczywistym o niskim opóźnieniu. Gdy strumień zostaje uruchomiony, PortAudio okresowo wywołuje Twoją funkcję zwrotną, aby żądać lub dostarczać dane audio. Ten tryb daje precyzyjną kontrolę nad synchronizacją i minimalizuje niedobory bufora. Funkcja zwrotna otrzymuje bufory wejściowe i wyjściowe, liczbę klatek, informacje o czasie oraz flagi statusu — umożliwiając dynamiczne generowanie dźwięku, przetwarzanie efektów lub analizę. Ponieważ funkcja zwrotna działa w wątku o wysokim priorytecie, musi wykonywać się szybko (zwykle poniżej 10 ms), aby uniknąć zakłóceń. Dzięki temu jest doskonała dla aplikacji audio na żywo, takich jak syntezatory, pedały efektów gitarowych czy systemy komunikacji głosowej, gdzie krytyczna jest deterministyczna wydajność.

Generator fali sinusoidalnej w czasie rzeczywistym za pomocą wywołania zwrotnego

typedef struct {
    float phase;
    float phase_increment;
} paTestData;

int patestCallback(const void *input, void *output,
    unsigned long frameCount,
    const PaStreamCallbackTimeInfo* timeInfo,
    PaStreamCallbackFlags statusFlags,
    void *userData)
{
    paTestData *data = (paTestData*)userData;
    float *out = (float*)output;
    for (unsigned long i = 0; i < frameCount; i++) {
        *out++ = sinf(data->phase);
        data->phase += data->phase_increment;
        if (data->phase >= M_PI * 2) data->phase -= M_PI * 2;
    }
    return paContinue;
}

Wyliczanie i zapytania o urządzenia

PortAudio udostępnia solidne interfejsy API do wyliczania i przeglądania dostępnych urządzeń audio — w tym urządzeń wejściowych i wyjściowych — wraz z ich możliwościami. Programiści mogą zapytać o nazwy urządzeń, liczbę kanałów, domyślne częstotliwości próbkowania oraz wartości opóźnień, używając funkcji takich jak `Pa_GetDeviceCount()`, `Pa_GetDeviceInfo()` i `Pa_GetDefaultInputDeviceID()`. Umożliwia to aplikacjom przedstawienie użytkownikom listy prawidłowych urządzeń i optymalne skonfigurowanie strumieni. Można także wykrywać domyślne urządzenia, sprawdzać obsługiwane częstotliwości próbkowania oraz określać minimalne/maksymalne opóźnienia. Ta elastyczność jest niezbędna przy tworzeniu konfigurowalnych narzędzi audio, DAW‑ów lub rejestratorów głosu, które dostosowują się do różnorodnych konfiguracji sprzętowych bez ręcznej konfiguracji.

Wyświetl wszystkie dostępne urządzenia audio

PaError err;
err = Pa_Initialize();
if (err != paNoError) goto error;

int numDevices = Pa_GetDeviceCount();
for (int i = 0; i < numDevices; i++) {
    const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
    printf("%d: %s (in: %d, out: %d)\n", 
        i, info->name, 
        info->maxInputChannels, 
        info->maxOutputChannels);
}
Pa_Terminate();

Wsparcie host API wieloplatformowego

PortAudio abstrahuje specyficzne dla platformy interfejsy audio poprzez modularne implementacje host API, zapewniając spójne zachowanie na różnych systemach operacyjnych. W systemie Windows obsługuje ASIO (dla profesjonalnego audio), WASAPI (Vista+), DirectSound oraz starsze MME. macOS wykorzystuje Core Audio do uzyskania ultra-niskich opóźnień, podczas gdy Linux wspiera ALSA, JACK i PulseAudio. Systemy BSD używają OSS lub sndio. Programiści piszą raz i wdrażają wszędzie — nie jest potrzebna warunkowa kompilacja dla logiki podstawowej. Biblioteka automatycznie wybiera najlepszy dostępny host API lub pozwala określić go ręcznie. Ta uniwersalność czyni PortAudio idealnym dla przenośnych narzędzi audio, oprogramowania edukacyjnego i frameworków badawczych, które muszą działać niezawodnie na różnorodnym sprzęcie i konfiguracjach systemów operacyjnych.

Wymuś użycie API hosta JACK w systemie Linux

PaStreamParameters inputParam, outputParam;
PaError err;

inputParam.device = Pa_GetHostApiInfoByType(paJACK)->defaultInputDevice;
inputParam.channelCount = 2;
inputParam.sampleFormat = paFloat32;
// ... configure outputParam similarly ...

PaStream *stream;
err = Pa_OpenStream(&stream, &inputParam, &outputParam, 
    44100, 256, paNoFlag, callback, NULL);

Konwersja formatu audio i dithering

PortAudio obsługuje wewnętrzną konwersję formatu próbkowania w sposób przejrzysty, umożliwiając klientom korzystanie z wygodnych formatów, takich jak 32‑bitowy zmiennoprzecinkowy, podczas gdy podstawowy system używa natywnych formatów całkowitoliczbowych (np. 16‑bitowy PCM). Obsługuje konwersję pomiędzy formatami całkowitoliczbowymi 8‑, 16‑, 24‑ i 32‑bitowymi, a także 32‑bitowym float. Dodatkowo oferuje opcjonalne dithering podczas redukcji głębokości bitowej, aby zminimalizować szum kwantyzacji — subtelna, ale krytyczna funkcja dla aplikacji audio o wysokiej wierności. Dithering zachowuje postrzeganą jakość dźwięku przy konwersji z wyższych na niższe głębokości bitowe. Te możliwości zapewniają spójną wierność audio na różnych platformach, bez konieczności implementowania przez programistów złożonej logiki obsługi formatów.

Skonfiguruj 32‑bitowe wejście zmiennoprzecinkowe z ditheringiem

PaStreamParameters inputParam = {0};
inputParam.device = Pa_GetDefaultInputDevice();
inputParam.channelCount = 2;
inputParam.sampleFormat = paFloat32;
inputParam.suggestedLatency = Pa_GetDeviceInfo(inputParam.device)->defaultLowInputLatency;

// Enable dithering for output conversion
PaStream *stream;
Pa_OpenStream(&stream, &inputParam, NULL, 44100, 128, 
    paClipOff | paDitherOff, NULL, NULL);
// Note: paDitherOff disables dithering; omit for default dithering
 Polski