stsaz / ffaudio

fast cross-platform interface for Audio Input/Output for C and C++

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ffaudio

ffaudio is a fast cross-platform interface for Audio Input/Output for C and C++.

It provides advanced features for complex apps like phiola audio player/recorder, or it can be used by tiny programs like wav player example.

Contents:

Features

  • List available playback/capture devices
  • Play audio
  • Capture audio
  • Blocking or non-blocking behaviour for write/drain/read functions
  • The most simple API as it can be

Supports:

  • AAudio (Android>=26)
    • formats: int16/float
    • mode: shared/exclusive
    • perf mode: power-save/low-latency
    • use "High Priority Callback"
  • ALSA (Linux):
    • "hw" and "plughw" modes
  • CoreAudio (macOS)
  • DirectSound (Windows)
  • JACK (Linux)
  • OSS (FreeBSD)
  • PulseAudio (Linux)
  • WASAPI (Windows):
    • shared and exclusive modes
    • loopback mode (record what you hear)

Note: JACK playback is not implemented.

How to use

Write your cross-platform code using ffaudio_interface interface.

List all available playback devices

	#include <ffaudio/audio.h>

	// get API
	const ffaudio_interface *audio = ffaudio_default_interface();

	// initialize audio subsystem
	ffaudio_init_conf initconf = {};
	int r = audio->init(&initconf);
	if (r < 0)
		exit(1);

	// enumerate devices one by one
	ffaudio_dev *d = audio->dev_alloc(FFAUDIO_DEV_PLAYBACK);
	for (;;) {
		int r = audio->dev_next(d);
		if (r > 0) {
			break;
		} else if (r < 0) {
			printf("error: %s\n", audio->dev_error(d));
			break;
		}

		printf("device: name: '%s'\n", audio->dev_info(d, FFAUDIO_DEV_NAME));
	}
	audio->dev_free(d);

	audio->uninit();

Record data from audio device

	#include <ffaudio/audio.h>

	// get API
	const ffaudio_interface *audio = ffaudio_default_interface();

	// initialize audio subsystem
	ffaudio_init_conf initconf = {};
	int r = audio->init(&initconf);
	if (r < 0)
		exit(1);

	// create audio buffer
	ffaudio_buf *buf = audio->alloc();

	// open audio buffer for recording
	ffaudio_conf bufconf = {};
	bufconf.format = FFAUDIO_F_INT16;
	bufconf.sample_rate = 44100;
	bufconf.channels = 2;
	r = audio->open(buf, &bufconf, FFAUDIO_CAPTURE);
	if (r == FFAUDIO_EFORMAT)
		r = audio->open(buf, &bufconf, FFAUDIO_CAPTURE); // open with the supported format
	if (r < 0)
		exit(1);

	// read data from audio buffer and write it to stderr
	for (;;) {
		const void *data;
		r = audio->read(buf, &data);
		if (r < 0)
			exit(1);

		write(2, data.ptr, data.len);
	}

	audio->free(buf);
	audio->uninit();

In order for ffaudio_default_interface() function to work you should define FFAUDIO_INTERFACE_DEFAULT_PTR with the API you want to use, either in code:

#define FFAUDIO_INTERFACE_DEFAULT_PTR  &ffalsa
#include <ffaudio/audio.h>

or in Makefile:

CFLAGS += -DFFAUDIO_INTERFACE_DEFAULT_PTR="&ffalsa"

But instead of calling ffaudio_default_interface() you can just use an API directly, e.g. ffalsa.

How to build

Include the necessary ffaudio C files into your project's build script, e.g.:

	./ffaudio-alsa.o: $(FFAUDIO_DIR)/ffaudio/alsa.c $(FFAUDIO_DIR)/ffaudio/audio.h
		gcc -c $(CFLAGS) $< -o $@

Use the neceessary linker flags for the audio API, described below.

Build information for each audio API

Configure your building script to compile particular C file and use appropriate link flags.

API Package Dependency Compile Linker Flags
AAudio - ffaudio/aaudio.c -laaudio
ALSA libalsa-devel ffaudio/alsa.c -lasound
PulseAudio libpulse-devel ffaudio/pulse.c -lpulse
JACK jack-audio-connection-kit-devel ffaudio/jack.c -ljack
WASAPI - ffaudio/wasapi.c -lole32
DirectSound - ffaudio/dsound.c -ldsound -ldxguid
CoreAudio - ffaudio/coreaudio.c -framework CoreFoundation -framework CoreAudio
OSS - ffaudio/oss.c -lm

How to test

git clone https://github.com/stsaz/ffbase
git clone https://github.com/stsaz/ffaudio
cd ffaudio/test
  • Linux:
make -B FFAUDIO_API=alsa
./ffaudio-alsa list
./ffaudio-alsa record 2>file.raw
./ffaudio-alsa play <file.raw

make -B FFAUDIO_API=pulse
./ffaudio-pulse list
./ffaudio-pulse record 2>file.raw
./ffaudio-pulse play <file.raw

make -B FFAUDIO_API=jack
./ffaudio-jack list
./ffaudio-jack record 2>file.raw
# [not implemented] ./ffaudio-jack play <file.raw
  • Android:

Install Android SDK & NDK; then cross-build for Android:

make FFAUDIO_API=aaudio \
	SYS=android \
	ROOT_DIR=../.. \
	SDK_DIR=/home/USER/Android/Sdk \
	NDK_VER=YOUR_NDK_VERSION

Run the executable on Android:

./ffaudio-aaudio record 2>file.raw
./ffaudio-aaudio play <file.raw
  • Windows:
make -B FFAUDIO_API=wasapi
.\ffaudio-wasapi.exe list
.\ffaudio-wasapi.exe record 2>file.raw
.\ffaudio-wasapi.exe play <file.raw

make -B FFAUDIO_API=dsound
.\ffaudio-dsound.exe list
.\ffaudio-dsound.exe record 2>file.raw
.\ffaudio-dsound.exe play <file.raw
  • macOS:
make FFAUDIO_API=coreaudio
./ffaudio-coreaudio list
./ffaudio-coreaudio record 2>file.raw
./ffaudio-coreaudio play <file.raw
  • FreeBSD:
make FFAUDIO_API=oss
./ffaudio-oss list
./ffaudio-oss record 2>file.raw
./ffaudio-oss play <file.raw

There are more additional arguments that you can pass to these executable files.

License

ffaudio is in the public-domain.

About

fast cross-platform interface for Audio Input/Output for C and C++

License:The Unlicense


Languages

Language:C 96.2%Language:Makefile 3.1%Language:Shell 0.7%