Browse Source

add rtaudio c api wrappers (#98)

add rtaudio c api wrappers
tags/5.1.0
Serge Zaitsev Stephen Sinclair 8 years ago
parent
commit
5c69780f4b
4 changed files with 410 additions and 3 deletions
  1. +1
    -1
      CMakeLists.txt
  2. +4
    -2
      Makefile.am
  3. +261
    -0
      rtaudio_c.cpp
  4. +144
    -0
      rtaudio_c.h

+ 1
- 1
CMakeLists.txt View File

@@ -28,7 +28,7 @@ if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif (CMAKE_COMPILER_IS_GNUCXX)

set(rtaudio_SOURCES RtAudio.cpp)
set(rtaudio_SOURCES RtAudio.cpp rtaudio_c.cpp)

set(LINKLIBS)
if (CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*")


+ 4
- 2
Makefile.am View File

@@ -6,11 +6,13 @@ endif
lib_LTLIBRARIES = %D%/librtaudio.la
%C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@
%C%_librtaudio_la_SOURCES = \
%D%/RtAudio.cpp
%D%/RtAudio.cpp \
%D%/rtaudio_c.cpp

rtaudio_incdir = $(includedir)/rtaudio
rtaudio_inc_HEADERS = \
%D%/RtAudio.h
%D%/RtAudio.h \
%D%/rtaudio_c.h

pkgconfigdatadir = $(libdir)/pkgconfig
pkgconfigdata_DATA = rtaudio.pc


+ 261
- 0
rtaudio_c.cpp View File

@@ -0,0 +1,261 @@
#include "rtaudio_c.h"
#include "RtAudio.h"

#include <cstring>

#define MAX_ERROR_MESSAGE_LENGTH 512

struct rtaudio {
RtAudio *audio;

rtaudio_cb_t cb;
void *userdata;

int has_error;
char errmsg[MAX_ERROR_MESSAGE_LENGTH];
};

static const rtaudio_api_t compiled_api[] = {
#if defined(__UNIX_JACK__)
RTAUDIO_API_UNIX_JACK,
#endif
#if defined(__LINUX_ALSA__)
RTAUDIO_API_LINUX_ALSA,
#endif
#if defined(__LINUX_PULSE__)
RTAUDIO_API_LINUX_PULSE,
#endif
#if defined(__LINUX_OSS__)
RTAUDIO_API_LINUX_OSS,
#endif
#if defined(__WINDOWS_ASIO__)
RTAUDIO_API_WINDOWS_ASIO,
#endif
#if defined(__WINDOWS_WASAPI__)
RTAUDIO_API_WINDOWS_WASAPI,
#endif
#if defined(__WINDOWS_DS__)
RTAUDIO_API_WINDOWS_DS,
#endif
#if defined(__MACOSX_CORE__)
RTAUDIO_API_MACOSX_CORE,
#endif
#if defined(__RTAUDIO_DUMMY__)
RTAUDIO_API_DUMMY,
#endif
RTAUDIO_API_UNSPECIFIED,
};

const char *rtaudio_version() { return RTAUDIO_VERSION; }

const rtaudio_api_t *rtaudio_compiled_api() { return compiled_api; }

const char *rtaudio_error(rtaudio_t audio) {
if (audio->has_error) {
return audio->errmsg;
}
return NULL;
}

rtaudio_t rtaudio_create(rtaudio_api_t api) {
rtaudio_t audio = new struct rtaudio();
try {
audio->audio = new RtAudio((RtAudio::Api)api);
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return audio;
}

void rtaudio_destroy(rtaudio_t audio) { delete audio->audio; }

rtaudio_api_t rtaudio_current_api(rtaudio_t audio) {
return (rtaudio_api_t)audio->audio->getCurrentApi();
}

int rtaudio_device_count(rtaudio_t audio) {
return audio->audio->getDeviceCount();
}

rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio, int i) {
rtaudio_device_info_t result = {};
try {
audio->has_error = 0;
RtAudio::DeviceInfo info = audio->audio->getDeviceInfo(i);
result.probed = info.probed;
result.output_channels = info.outputChannels;
result.input_channels = info.inputChannels;
result.duplex_channels = info.duplexChannels;
result.is_default_output = info.isDefaultOutput;
result.is_default_input = info.isDefaultInput;
result.native_formats = info.nativeFormats;
result.preferred_sample_rate = info.preferredSampleRate;
strncpy(result.name, info.name.c_str(), sizeof(result.name) - 1);
for (unsigned int j = 0; j < info.sampleRates.size(); j++) {
if (j < sizeof(result.sample_rates) / sizeof(result.sample_rates[0])) {
result.sample_rates[j] = info.sampleRates[j];
}
}
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return result;
}

unsigned int rtaudio_get_default_output_device(rtaudio_t audio) {
return audio->audio->getDefaultOutputDevice();
}

unsigned int rtaudio_get_default_input_device(rtaudio_t audio) {
return audio->audio->getDefaultInputDevice();
}

static int proxy_cb_func(void *out, void *in, unsigned int nframes, double time,
RtAudioStreamStatus status, void *userdata) {
rtaudio_t audio = (rtaudio_t)userdata;
return audio->cb(out, in, nframes, time, (rtaudio_stream_status_t)status,
audio->userdata);
}

int rtaudio_open_stream(rtaudio_t audio,
rtaudio_stream_parameters_t *output_params,
rtaudio_stream_parameters_t *input_params,
rtaudio_format_t format, unsigned int sample_rate,
unsigned int *buffer_frames, rtaudio_cb_t cb,
void *userdata, rtaudio_stream_options_t *options,
rtaudio_error_cb_t /*errcb*/) {
try {
audio->has_error = 0;
RtAudio::StreamParameters *in = NULL;
RtAudio::StreamParameters *out = NULL;
RtAudio::StreamOptions *opts = NULL;

RtAudio::StreamParameters inparams;
RtAudio::StreamParameters outparams;
RtAudio::StreamOptions stream_opts;

if (input_params != NULL) {
inparams.deviceId = input_params->device_id;
inparams.nChannels = input_params->num_channels;
inparams.firstChannel = input_params->first_channel;
in = &inparams;
}
if (output_params != NULL) {
outparams.deviceId = output_params->device_id;
outparams.nChannels = output_params->num_channels;
outparams.firstChannel = output_params->first_channel;
out = &outparams;
}

if (options != NULL) {
stream_opts.flags = (RtAudioStreamFlags)options->flags;
stream_opts.numberOfBuffers = options->num_buffers;
stream_opts.priority = options->priority;
if (strlen(options->name) > 0) {
stream_opts.streamName = std::string(options->name);
}
opts = &stream_opts;
}
audio->cb = cb;
audio->userdata = userdata;
audio->audio->openStream(out, in, (RtAudioFormat)format, sample_rate,
buffer_frames, proxy_cb_func, (void *)audio, opts,
NULL);
return 0;
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}

void rtaudio_close_stream(rtaudio_t audio) { audio->audio->closeStream(); }

int rtaudio_start_stream(rtaudio_t audio) {
try {
audio->has_error = 0;
audio->audio->startStream();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}

int rtaudio_stop_stream(rtaudio_t audio) {
try {
audio->has_error = 0;
audio->audio->stopStream();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}

int rtaudio_abort_stream(rtaudio_t audio) {
try {
audio->has_error = 0;
audio->audio->abortStream();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}

int rtaudio_is_stream_open(rtaudio_t audio) {
return !!audio->audio->isStreamOpen();
}

int rtaudio_is_stream_running(rtaudio_t audio) {
return !!audio->audio->isStreamRunning();
}

double rtaudio_get_stream_time(rtaudio_t audio) {
try {
audio->has_error = 0;
return audio->audio->getStreamTime();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return 0;
}
}

void rtaudio_set_stream_time(rtaudio_t audio, double time) {
try {
audio->has_error = 0;
audio->audio->setStreamTime(time);
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
}

int rtaudio_get_stream_latency(rtaudio_t audio) {
try {
audio->has_error = 0;
return audio->audio->getStreamLatency();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}

unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio) {
try {
return audio->audio->getStreamSampleRate();
} catch (RtAudioError &err) {
audio->has_error = 1;
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}

void rtaudio_show_warnings(rtaudio_t audio, int show) {
audio->audio->showWarnings(!!show);
}

+ 144
- 0
rtaudio_c.h View File

@@ -0,0 +1,144 @@
#ifndef RTAUDIO_C_H
#define RTAUDIO_C_H

#if defined(RTAUDIO_EXPORT)
#define RTAUDIOAPI __declspec(dllexport)
#else
#define RTAUDIOAPI //__declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef unsigned long rtaudio_format_t;

#define RTAUDIO_FORMAT_SINT8 0x01
#define RTAUDIO_FORMAT_SINT16 0x02
#define RTAUDIO_FORMAT_SINT24 0x04
#define RTAUDIO_FORMAT_SINT32 0x08
#define RTAUDIO_FORMAT_FLOAT32 0x10
#define RTAUDIO_FORMAT_FLOAT64 0x20

typedef unsigned int rtaudio_stream_flags_t;

#define RTAUDIO_FLAGS_NONINTERLEAVED 0x1
#define RTAUDIO_FLAGS_MINIMIZE_LATENCY 0x2
#define RTAUDIO_FLAGS_HOG_DEVICE 0x4
#define RTAUDIO_FLAGS_SCHEDULE_REALTIME 0x8
#define RTAUDIO_FLAGS_ALSA_USE_DEFAULT 0x10

typedef unsigned int rtaudio_stream_status_t;

#define RTAUDIO_STATUS_INPUT_OVERFLOW 0x1
#define RTAUDIO_STATUS_OUTPUT_UNDERFLOW 0x2

typedef int (*rtaudio_cb_t)(void *out, void *in, unsigned int nFrames,
double stream_time, rtaudio_stream_status_t status,
void *userdata);

typedef enum rtaudio_error {
RTAUDIO_ERROR_WARNING,
RTAUDIO_ERROR_DEBUG_WARNING,
RTAUDIO_ERROR_UNSPECIFIED,
RTAUDIO_ERROR_NO_DEVICES_FOUND,
RTAUDIO_ERROR_INVALID_DEVICE,
RTAUDIO_ERROR_MEMORY_ERROR,
RTAUDIO_ERROR_INVALID_PARAMETER,
RTAUDIO_ERROR_INVALID_USE,
RTAUDIO_ERROR_DRIVER_ERROR,
RTAUDIO_ERROR_SYSTEM_ERROR,
RTAUDIO_ERROR_THREAD_ERROR,
} rtaudio_error_t;

typedef void (*rtaudio_error_cb_t)(rtaudio_error_t err, const char *msg);

typedef enum rtaudio_api {
RTAUDIO_API_UNSPECIFIED,
RTAUDIO_API_LINUX_ALSA,
RTAUDIO_API_LINUX_PULSE,
RTAUDIO_API_LINUX_OSS,
RTAUDIO_API_UNIX_JACK,
RTAUDIO_API_MACOSX_CORE,
RTAUDIO_API_WINDOWS_WASAPI,
RTAUDIO_API_WINDOWS_ASIO,
RTAUDIO_API_WINDOWS_DS,
RTAUDIO_API_DUMMY,
} rtaudio_api_t;

#define NUM_SAMPLE_RATES 16
#define MAX_NAME_LENGTH 512
typedef struct rtaudio_device_info {
int probed;
unsigned int output_channels;
unsigned int input_channels;
unsigned int duplex_channels;

int is_default_output;
int is_default_input;

rtaudio_format_t native_formats;

unsigned int preferred_sample_rate;
int sample_rates[NUM_SAMPLE_RATES];

char name[MAX_NAME_LENGTH];
} rtaudio_device_info_t;

typedef struct rtaudio_stream_parameters {
unsigned int device_id;
unsigned int num_channels;
unsigned int first_channel;
} rtaudio_stream_parameters_t;

typedef struct rtaudio_stream_options {
rtaudio_stream_flags_t flags;
unsigned int num_buffers;
int priority;
char name[MAX_NAME_LENGTH];
} rtaudio_stream_options_t;

typedef struct rtaudio *rtaudio_t;

RTAUDIOAPI const char *rtaudio_version();
RTAUDIOAPI const rtaudio_api_t *rtaudio_compiled_api();

RTAUDIOAPI const char *rtaudio_error(rtaudio_t audio);

RTAUDIOAPI rtaudio_t rtaudio_create(rtaudio_api_t api);
RTAUDIOAPI void rtaudio_destroy(rtaudio_t audio);

RTAUDIOAPI rtaudio_api_t rtaudio_current_api(rtaudio_t audio);

RTAUDIOAPI int rtaudio_device_count(rtaudio_t audio);
RTAUDIOAPI rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio,
int i);
RTAUDIOAPI unsigned int rtaudio_get_default_output_device(rtaudio_t audio);
RTAUDIOAPI unsigned int rtaudio_get_default_input_device(rtaudio_t audio);

RTAUDIOAPI int
rtaudio_open_stream(rtaudio_t audio, rtaudio_stream_parameters_t *output_params,
rtaudio_stream_parameters_t *input_params,
rtaudio_format_t format, unsigned int sample_rate,
unsigned int *buffer_frames, rtaudio_cb_t cb,
void *userdata, rtaudio_stream_options_t *options,
rtaudio_error_cb_t errcb);
RTAUDIOAPI void rtaudio_close_stream(rtaudio_t audio);
RTAUDIOAPI int rtaudio_start_stream(rtaudio_t audio);
RTAUDIOAPI int rtaudio_stop_stream(rtaudio_t audio);
RTAUDIOAPI int rtaudio_abort_stream(rtaudio_t audio);

RTAUDIOAPI int rtaudio_is_stream_open(rtaudio_t audio);
RTAUDIOAPI int rtaudio_is_stream_running(rtaudio_t audio);

RTAUDIOAPI double rtaudio_get_stream_time(rtaudio_t audio);
RTAUDIOAPI void rtaudio_set_stream_time(rtaudio_t audio, double time);
RTAUDIOAPI int rtaudio_get_stream_latency(rtaudio_t audio);
RTAUDIOAPI unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio);

RTAUDIOAPI void rtaudio_show_warnings(rtaudio_t audio, int show);

#ifdef __cplusplus
}
#endif
#endif /* RTAUDIO_C_H */

Loading…
Cancel
Save