Examples.
#define _GNU_SOURCE
#include <pthread.h>
#include <sys/prctl.h>
#include <sched.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/sysinfo.h>
#include <sys/syscall.h>
#ifndef SYS_gettid
#warning "SYS_gettid unavailable on this system"
#else
#define gettid() ((pid_t)syscall(SYS_gettid))
#endif
#include "AudioStream.h"
#include "ModuleList.h"
AudioStream *as;
UINT32 hwInputChannels = 1;
UINT32 hwOutputChannels = 2;
char* inputDeviceName;
char* outputDeviceName;
UINT32 portNo = 15002;
UINT32 fundamentalBlockSize = 32;
double sampleRate = 48000.0;
UINT32 enableAudioLogging = 0;
const char* awbPath;
UINT32 loadAWB = 0;
float coreSpeed = 1e9f;
float profileSpeed = 10e6f;
UINT32 setCPUs;
UINT32 firstCallback = 1;
void sig_handler(int signo)
{
printf("Exiting RTAudio-alsa\n");
exit(0);
}
static const void* moduleDescriptorTable[] =
{
LISTOFCLASSOBJECTS
};
UINT32 moduleDescriptorTableSize = sizeof(moduleDescriptorTable) / sizeof(moduleDescriptorTable[0]);
{
INT32 i, availableProcessors, cpuToSet, ret;
cpu_set_t pumpthread_set;
printf("Audio Start Callback: Starting audio stream \n");
if (setCPUs)
{
if (ret != 0)
{
printf("aweOS_getThreadPIDs failed with error %d. Not setting CPU affinity... \n ", ret);
}
else
{
availableProcessors = get_nprocs();
{
cpuToSet = (i + 1) % availableProcessors;
CPU_ZERO(&pumpthread_set);
CPU_SET(cpuToSet, &pumpthread_set);
ret = sched_setaffinity(threadPIDs.
pumpThreadPIDs[i],
sizeof(cpu_set_t), &pumpthread_set);
if (ret == 0)
{
printf(
"Set pumpThread %d (PID = %u) to CPU %d \n", i, threadPIDs.
pumpThreadPIDs[i], cpuToSet);
}
else
{
printf("Could not set CPU affinity of pumpThread %d to CPU %d , errno: %d \n", i, cpuToSet, errno);
}
}
}
}
AudioStream_start(as);
return 0;
}
{
printf("Audio Stop Callback: Stopping audio stream \n");
AudioStream_stop(as);
firstCallback = 1;
return 0;
}
{
{
printf(
"Got xrun on audio recording input stream: total xruns = %u, time of xrun = %f\n", recordingNotification->
xruns, recordingNotification->
xrunTime);
}
{
printf(
"Got xrun on audio recording output stream: total xruns = %u, time of xrun = %f\n", recordingNotification->
xruns, recordingNotification->
xrunTime);
}
else
{
printf(
"Got audio recording error notification: %d\n", recordingNotification->
error);
}
}
{
UINT32 position = 0;
if (0 == ret)
{
printf("The layout %s loaded succesfully\n", filePath);
}
else
{
printf("The layout %s downloaded unsuccessfully at position %u with error = %s \n", filePath, position, strerror(ret));
exit(1);
}
}
AudioStream_CallbackResult audio_callback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
AudioStream_CallbackFlag statusFlags,
void *userData)
{
(void)userData;
UINT32 i, j;
INT32 pumpRet;
if (statusFlags != 0)
{
printf("xrun ");
return AudioStream_CallbackResult_Continue;
}
if (firstCallback && setCPUs)
{
#if defined(SYS_gettid)
cpu_set_t pumpthread_set;
pid_t audioCallbackPID;
INT32 ret;
static const int cpuToSet = 0;
CPU_ZERO(&pumpthread_set);
CPU_SET(cpuToSet, &pumpthread_set);
audioCallbackPID = gettid();
ret = sched_setaffinity(audioCallbackPID, sizeof(cpu_set_t), &pumpthread_set);
if (ret == 0)
{
printf("Set audio callback thread (PID = %d) to CPU %d \n", audioCallbackPID, cpuToSet);
}
else
{
printf("Could not set CPU affinity of audo callback thread (PID = %d) to CPU %d , errno: %d \n", audioCallbackPID, cpuToSet, errno);
}
#endif
firstCallback = 0;
}
{
{
INT32 ret;
for (i = 0; i < hwInputChannels; i++)
{
if (ret != 0)
{
}
}
if (pumpRet < 0)
{
{
}
}
for (j = 0; j < hwOutputChannels; j++)
{
if (ret != 0)
{
}
}
}
}
return AudioStream_CallbackResult_Continue;
}
int initializeAudioStream()
{
as = AudioStream_create();
if (as == NULL)
{
printf("Error initializing AudioStream\n");
}
else
{
printf("AudioStream init success\n");
}
AudioStream_open(as, inputDeviceName, hwInputChannels,
outputDeviceName, hwOutputChannels,
AudioStream_SampleFormat_S32_LE,
sampleRate, fundamentalBlockSize,
audio_callback, NULL);
return 0;
}
static void usage(const char *program)
{
printf(
"Usage: %s [args]\n"
" -load:<file> AWB file to load. If no AWB is specified, then app waits for a layout from tuning interface\n"
" -inputdevice:<str> The alsa device id for the input device. Default hw:0,0 \n"
" -outputdevice:<str> The alsa device id for the output device. Default hw:0,0\n"
" -hwinchannels:<int> The number of hw input channels for the alsa audio device \n"
" -hwoutchannels:<int> The number of hw output channels for the alsa audio device\n"
" -blocksize:<int> The fundamental hw blocksize of the alsa device (DMA)\n"
" -samplerate:<int> The samplerate of the audio hw\n"
" -enabledAudioLog Enable audio logging. Logs will be saved to <appdirectory>/audio-logs/\n"
" -portno:<int> Port number to open the TCP tuning socket on. Default 15002\n"
" -coreSpeed:<float> Processor clock speed in Hz. Default 1 GHz\n"
" -profileSpeed:<float> Application profiling speed in Hz. Default 10 MHz \n"
" -enableCPUAffinity Enable the logic in audioStart callback which will query thread PIDs and attempt to set CPU affinity per layout \n"
" -help Show usage\n"
"This program shows realtime audio integration with the alsa API.\n",
program);
exit(0);
}
int main(int argc, char **argv)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
printf("Can't catch SIGINT (%d)\n", SIGINT);
}
inputDeviceName = "hw:0,0";
outputDeviceName = "hw:0,0";
setCPUs = 0;
UINT32 i;
if (1 == argc)
{
printf("No command line options specified. Using defaults\n");
}
else
{
for (i = 1; i < argc; i++)
{
const char *arg = argv[i];
if ((0 == strncmp(arg, "-inputdevice:", 13)))
{
inputDeviceName = (char*)(arg + 13);
printf(" cmd line arg set inputdevice to %s \n", inputDeviceName);
}
else if ((0 == strncmp(arg, "-outputdevice:", 14)))
{
outputDeviceName = (char*)(arg + 14);
printf(" cmd line arg set outputdevice to %s \n", outputDeviceName);
}
else if ((0 == strncmp(arg, "-hwinchannels:", 14)))
{
hwInputChannels = atoi(arg + 14);
printf(" hardware input channels set to %u \n", hwInputChannels);
}
else if ((0 == strncmp(arg, "-hwoutchannels:", 15)))
{
hwOutputChannels = atoi(arg + 15);
printf(" hardware output channels set to %u \n", hwOutputChannels);
}
else if ((0 == strncmp(arg, "-blocksize:", 11)))
{
fundamentalBlockSize = atoi(arg + 11);
printf(" fundamental block size set to %u \n", fundamentalBlockSize);
}
else if ((0 == strncmp(arg, "-samplerate:", 12)))
{
sampleRate = atof(arg + 12);
printf(" sample rate set to %f \n", sampleRate);
}
else if ((0 == strncmp(arg, "-portno:", 8)))
{
portNo = atoi(arg + 8);
printf(" portno for socket is %u \n", portNo);
}
else if (0 == strncmp(arg, "-load:", 6))
{
awbPath = arg + 6;
loadAWB = 1;
printf(" load: %s\n",awbPath);
}
else if ((0 == strncmp(arg, "-enableAudioLog", 15)))
{
enableAudioLogging = 1;
printf(" audio logging enabled \n");
}
else if ((0 == strncmp(arg, "-coreSpeed:", 11)))
{
coreSpeed = atof(arg + 11);
printf(" coreSpeed set to %f\n", coreSpeed);
}
else if ((0 == strncmp(arg, "-profileSpeed:", 14)))
{
profileSpeed = atof(arg + 14);
printf(" profileSpeed set to %f \n", profileSpeed);
}
else if ((0 == strncmp(arg, "-enableCPUAffinity", 13)))
{
setCPUs = 1;
printf(" enableCPUAffinity activated. query for PIDs in audiostart callback and attempt to set CPU affinity \n");
}
else if ((0 == strncmp(arg, "-help", 5)))
{
usage(argv[0]);
}
else
{
printf("main: unknown option '%s'\n", arg);
}
}
}
INT32 ret;
ret =
aweOS_init(&g_AWEOSInstance, &configParams, moduleDescriptorTable, moduleDescriptorTableSize);
if (ret != 0)
{
printf("FATAL: aweOS_init failed. exiting application \n");
exit(1);
}
else
{
initializeAudioStream();
if (enableAudioLogging)
{
if (ret != 0)
{
printf("failed to enable audio logging: ret = %d\n", ret);
}
if (ret != 0)
{
printf("Failed to register audio logging callback function: ret = %d\n", ret);
}
}
if (tuningRet < 0)
{
}
else
{
printf("Opened TCP tuning interface on port %u: Waiting for AWE Server Connection from PC... \n", portNo);
}
if (loadAWB)
{
loadAWBFile(g_AWEOSInstance, awbPath);
}
while (1)
{
usleep(100000);
}
}
}
The AWE Core OS API header file.
#define E_CALLBACK_NOT_REALTIME
Audio Callback is not at realtime priority.
Definition: Errors.h:339
@ Sample32bit
Data is 32 bit PCM .
Definition: StandardDefs.h:231
#define AUDIO_RECORDING_NOTIFICATION_ALL
Audio recording: Notify on errors and overruns.
Definition: AWECoreOS.h:80
void AWEOSInstance
The AWE Core OS Instance instance type.
Definition: AWECoreOS.h:106
INT32 aweOS_audioExportSamples(AWEOSInstance *pAWEOS, void *outSamples, INT32 outStride, INT32 channel, SampleType outType)
Export samples to a user buffer from a specific channel of the AWEOSInstance's output pin.
INT32 aweOS_audioPumpAll(AWEOSInstance *pAWEOS)
Pump one fundamental block size of audio through the loaded layout and all of its sublayouts.
INT32 aweOS_audioIsStarted(const AWEOSInstance *pAWEOS)
Check if this instance has received an Audio Start command.
INT32 aweOS_init(AWEOSInstance **pAWEOS, const AWEOSConfigParameters *aweParams, const void *pModuleDescriptorTable, UINT32 moduleDescriptorTableSize)
Initialize the AWEOSInstance with the specified configuration parameters.
INT32 aweOS_audioRecordingRegisterNotificationCallback(AWEOSInstance *pAWEOS, recordNotificationCallbackFunction recordNotificationCallback, UINT32 recordNotificationMask)
Register a callback function for audio recording event notificiations.
INT32 aweOS_layoutIsValid(const AWEOSInstance *pAWEOS)
Determines if a layout is loaded and valid.
INT32 aweOS_audioRecordingEnable(AWEOSInstance *pAWEOS, char *path, char *baseName, UINT32 bufferLength, SampleType sampleType)
Enables recording of all input and output audio of AWEOSInstance.
INT32 aweOS_tuningSocketOpen(AWEOSInstance **pAWEOS, INT32 portNo, UINT32 numInstances)
Initialize and open an integrated TCP/IP tuning interface socket.
UINT32 aweOS_getThreadPIDs(AWEOSInstance *pAWEOS, AWEOSThreadPIDs_t *threadPIDs)
Return the PIDs of all internally spawned AWE Core OS threads.
const char * aweOS_errorToString(INT32 errorCode)
Convert an error code (INT32) to its corresponding error string.
INT32 aweOS_audioImportSamples(AWEOSInstance *pAWEOS, void *inSamples, INT32 inStride, INT32 channel, SampleType inType)
Import samples from an audio buffer to a specific channel of the AWEOSInstance's input pin.
INT32 aweOS_getParamDefaults(AWEOSConfigParameters *aweParams)
Populates an AWEOSConfigParameters structure with defaults.
INT32 aweOS_loadAWBFile(AWEOSInstance *pAWEOS, const char *binaryFile, UINT32 *pErrorOffset)
Executes packet commands from an AWB file on the filesystem.
Audio recording notification callback argument structure.
Definition: AWECoreOS.h:65
STATUS notificationStatus
type of notification being reported
Definition: AWECoreOS.h:66
FLOAT32 xrunTime
time in seconds of xrun in recording - 0 if error
Definition: AWECoreOS.h:69
UINT32 xruns
total xruns on recording stream - 0 if error
Definition: AWECoreOS.h:68
INT32 error
error value - 0 if xrun
Definition: AWECoreOS.h:67
Internal threading PID structure, meant to be used with aweOS_getThreadPIDs.
Definition: AWECoreOS.h:84
UINT32 numPumpThreads
The number of running pump threads.
Definition: AWECoreOS.h:87
UINT32 * pumpThreadPIDs
Pointer to an array of the running pump thread PIDs of size pumpThreadPIDs[numPumpThreads].
Definition: AWECoreOS.h:88
AWEOSConfigParameters.
Definition: AWECoreOS.h:117
float profileSpeed
Application profiling speed in Hz.
Definition: AWECoreOS.h:132
INT32 instanceId
ID number of instance.
Definition: AWECoreOS.h:139
float coreSpeed
Processor clock speed in Hz.
Definition: AWECoreOS.h:131
UINT32 numThreads
Maximum number of supported sublayouts.
Definition: AWECoreOS.h:134
UINT32 fundamentalBlockSize
Fundamental block size of audio driver.
Definition: AWECoreOS.h:136
UINT32 outChannels
Number of output channels of audio device.
Definition: AWECoreOS.h:138
UINT32 packetBufferSize
Size of packet buffers.
Definition: AWECoreOS.h:129
INT32(* cbAudioStop)(AWEOSInstance *pAWEOS)
Pointer to user created callback function for audio stop commands.
Definition: AWECoreOS.h:126
float sampleRate
Sample rate of audio device.
Definition: AWECoreOS.h:135
UINT32 inChannels
Number of input channels of audio device.
Definition: AWECoreOS.h:137
INT32(* cbAudioStart)(AWEOSInstance *pAWEOS)
Pointer to user created callback function for audio start commands.
Definition: AWECoreOS.h:125