portaudio

 
 

Thư viện C mã nguồn mở cho I/O âm thanh

Nhập và xuất âm thanh thời gian thực trên Windows, macOS, Linux và các hệ thống khác thông qua API C mã nguồn mở.

PortAudio là gì?

PortAudio là một thư viện C miễn phí, mã nguồn mở, đa nền tảng cho phép các nhà phát triển viết các ứng dụng âm thanh di động với khả năng nhập và xuất thời gian thực. Nó trừu tượng hoá các hệ thống âm thanh đặc thù của nền tảng như ASIO, CoreAudio, ALSA, WASAPI và JACK, cho phép I/O âm thanh nhất quán trên Windows, macOS, Linux và các hệ điều hành khác. Thư viện hỗ trợ nhiều định dạng âm thanh — bao gồm cả số thực 32-bit — và thực hiện chuyển đổi định dạng nội bộ. Với API đơn giản nhưng mạnh mẽ, PortAudio được sử dụng rộng rãi trong phần mềm âm thanh, plugin, công cụ giáo dục và các dự án nghiên cứu yêu cầu xử lý âm thanh độ trễ thấp và hiệu suất cao.

PortAudio cung cấp hai chế độ hoạt động chính: dựa trên callback (cho việc truyền phát độ trễ thấp) và đọc/ghi chặn (cho I/O đồng bộ đơn giản hơn). Nó bao gồm tài liệu phong phú, các chương trình mẫu và công cụ kiểm thử để giúp các nhà phát triển bắt đầu nhanh chóng. Thư viện được duy trì bởi cộng đồng toàn cầu và được cấp phép theo giấy phép MIT, khiến nó phù hợp cho cả ứng dụng mã nguồn mở và thương mại. Dù bạn đang xây dựng một trạm làm việc âm thanh kỹ thuật số, một công cụ nhận dạng giọng nói, hay một ứng dụng âm nhạc tương tác, PortAudio cung cấp nền tảng đáng tin cậy, nhẹ nhàng cho việc phát triển âm thanh đa nền tảng.

Previous Next

Bắt đầu với PortAudio

Để bắt đầu sử dụng PortAudio, bạn có thể xây dựng từ mã nguồn hoặc cài đặt qua các trình quản lý gói. Đối với hầu hết các nhà phát triển, cách dễ nhất là sao chép kho portaudio GitHub chính thức và biên dịch bằng CMake hoặc autotools. Trên Linux, cài đặt bằng `apt install portaudio19-dev`; trên macOS, dùng `brew install portaudio`; trên Windows, tải xuống các binary đã biên dịch sẵn hoặc sử dụng vcpkg (`vcpkg install portaudio`). Sau khi cài đặt, bao gồm `portaudio.h` và liên kết với thư viện (`-lportaudio`). Thư viện này nhẹ và có ít phụ thuộc, giúp việc tích hợp cho các ứng dụng âm thanh thời gian thực trở nên đơn giản.

Cài đặt PortAudio qua Trình quản lý gói

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

# macOS (Homebrew)
brew install portaudio

# Windows (vcpkg)
vcpkg install portaudio

Phát luồng âm thanh thời gian thực với Callback

Chế độ streaming dựa trên callback của PortAudio là lý tưởng cho xử lý âm thanh thời gian thực, độ trễ thấp. Khi một luồng được khởi động, PortAudio định kỳ gọi hàm callback của bạn để yêu cầu hoặc cung cấp dữ liệu âm thanh. Chế độ này cho phép bạn kiểm soát chính xác thời gian và giảm thiểu tình trạng thiếu bộ đệm. Callback nhận các bộ đệm đầu vào và đầu ra, số khung, thông tin thời gian và cờ trạng thái — cho phép tạo âm thanh động, xử lý hiệu ứng hoặc phân tích. Vì callback chạy trong một luồng có ưu tiên cao, nó phải thực thi nhanh chóng (thông thường dưới 10ms) để tránh lỗi. Điều này làm cho nó hoàn hảo cho các ứng dụng âm thanh trực tiếp như bộ tổng hợp, pedal hiệu ứng guitar, hoặc hệ thống truyền thông giọng nói, nơi hiệu năng quyết định là rất quan trọng.

Trình tạo sóng sin thời gian thực qua Callback

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;
}

Liệt kê và truy vấn thiết bị

PortAudio cung cấp các API mạnh mẽ để liệt kê và kiểm tra các thiết bị âm thanh có sẵn—bao gồm cả thiết bị đầu vào và đầu ra—cùng với khả năng của chúng. Các nhà phát triển có thể truy vấn tên thiết bị, số kênh, tần số mẫu mặc định và giá trị độ trễ bằng các hàm như `Pa_GetDeviceCount()`, `Pa_GetDeviceInfo()`, và `Pa_GetDefaultInputDeviceID()`. Điều này cho phép các ứng dụng hiển thị cho người dùng danh sách các thiết bị hợp lệ và cấu hình luồng một cách tối ưu. Bạn cũng có thể phát hiện thiết bị mặc định, kiểm tra các tần số mẫu được hỗ trợ và xác định độ trễ tối thiểu/tối đa. Tính linh hoạt này là cần thiết để xây dựng các công cụ âm thanh có thể cấu hình, DAW hoặc máy ghi âm thoại, thích nghi với các cấu hình phần cứng đa dạng mà không cần cấu hình thủ công.

Liệt kê tất cả các thiết bị âm thanh khả dụng

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();

Hỗ trợ API máy chủ đa nền tảng

PortAudio trừu tượng hoá các API âm thanh đặc thù nền tảng thông qua các triển khai API host mô-đun, đảm bảo hành vi nhất quán trên các hệ điều hành. Trên Windows, nó hỗ trợ ASIO (cho âm thanh chuyên nghiệp), WASAPI (Vista+), DirectSound và MME cổ điển. macOS tận dụng Core Audio để đạt độ trễ cực thấp, trong khi Linux hỗ trợ ALSA, JACK và PulseAudio. Các hệ thống BSD sử dụng OSS hoặc sndio. Các nhà phát triển viết một lần và triển khai ở mọi nơi—không cần biên dịch có điều kiện cho logic cốt lõi. Thư viện tự động chọn API host tốt nhất có sẵn hoặc cho phép bạn chỉ định một cách rõ ràng. Tính đa năng này khiến PortAudio trở thành lựa chọn lý tưởng cho các công cụ âm thanh di động, phần mềm giáo dục và các khung nghiên cứu phải chạy ổn định trên phần cứng và cấu hình OS đa dạng.

Buộc sử dụng API máy chủ JACK trên 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);

Chuyển đổi định dạng âm thanh và dithering

PortAudio xử lý việc chuyển đổi định dạng mẫu nội bộ một cách trong suốt, cho phép các client sử dụng các định dạng tiện lợi như 32-bit floating point trong khi hệ thống nền tảng sử dụng các định dạng nguyên bản địa (ví dụ: 16-bit PCM). Nó hỗ trợ chuyển đổi giữa các định dạng nguyên 8-, 16-, 24- và 32-bit, cũng như 32-bit float. Ngoài ra, nó cung cấp tùy chọn dithering trong quá trình giảm độ sâu bit để giảm thiểu tiếng ồn lượng tử—một tính năng tinh tế nhưng quan trọng đối với các ứng dụng âm thanh chất lượng cao. Dithering giữ nguyên chất lượng âm thanh cảm nhận được khi chuyển đổi từ độ sâu bit cao hơn sang thấp hơn. Những khả năng này đảm bảo độ trung thực âm thanh nhất quán trên các nền tảng mà không yêu cầu các nhà phát triển phải tự triển khai logic xử lý định dạng phức tạp.

Cấu hình đầu vào 32-bit Float với dithering

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
 Tiếng Việt