2024-12-01 19:35:24 +00:00
|
|
|
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
|
|
|
|
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
|
2019-12-27 21:52:45 +00:00
|
|
|
//( { file_desc: "Cross platform audio device interface." kw:[audio rt] }
|
|
|
|
//
|
|
|
|
// This interface provides data declarations for platform dependent
|
|
|
|
// audio I/O functions. The implementation for the functions are
|
|
|
|
// in platform specific modules. See cwAudioDeviceAlsa.cpp.
|
|
|
|
//
|
|
|
|
// ALSA Notes:
|
|
|
|
// Assign capture device to line or mic input:
|
|
|
|
// amixer -c 0 cset iface=MIXER,name='Input Source',index=0 Mic
|
|
|
|
// amixer -c 0 cset iface=MIXER,name='Input Source',index=0 Line
|
|
|
|
//
|
|
|
|
// -c 0 select the first card
|
|
|
|
// -iface=MIXER the cset is targetting the MIXER component
|
|
|
|
// -name='Input Source',index=0 the control to set is the first 'Input Source'
|
|
|
|
// Note that the 'Capture' control sets the input gain.
|
|
|
|
//
|
|
|
|
// See alsamixer for a GUI to accomplish the same thing.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//)
|
|
|
|
|
2019-12-26 02:44:14 +00:00
|
|
|
#ifndef cwAudioDevice_H
|
|
|
|
#define cwAudioDevice_H
|
|
|
|
|
2020-03-23 14:41:28 +00:00
|
|
|
#include "cwAudioDeviceDecls.h"
|
|
|
|
|
2019-12-26 02:44:14 +00:00
|
|
|
namespace cw
|
|
|
|
{
|
|
|
|
namespace audio
|
|
|
|
{
|
|
|
|
namespace device
|
|
|
|
{
|
|
|
|
|
|
|
|
// Audio port callback signature.
|
|
|
|
// inPktArray[inPktCnt] are full packets of audio coming from the ADC to the application.
|
|
|
|
// outPktArray[outPktCnt] are empty packets of audio which will be filled by the application
|
|
|
|
// and then sent to the DAC.
|
|
|
|
//
|
|
|
|
// The value of audioFrameCnt gives the number of samples per channel which are available
|
|
|
|
// in the packet data buffer 'audioBytesPtr'. The callback function may decrease this number in
|
|
|
|
// output packets if the number of samples available is less than the size of the buffer.
|
|
|
|
// It is the responsibility of the calling audio port to notice this change and pass the new,
|
|
|
|
// decreased number of samples to the hardware.
|
|
|
|
//
|
|
|
|
// In general it should be assmed that this call is made from a system thread which is not
|
|
|
|
// the same as the application thread.
|
|
|
|
// The usual thread safety precautions should therefore be taken if this function implementation
|
2019-12-27 21:52:45 +00:00
|
|
|
// interacts with data structures also handled by the application. The audio buffer class (\see cwAudioBuf.h)
|
2019-12-26 02:44:14 +00:00
|
|
|
// is designed to provide a safe and efficient way to communicate between
|
|
|
|
// the audio thread and the application.
|
2019-12-28 02:51:28 +00:00
|
|
|
typedef void (*cbFunc_t)( void* cbArg, audioPacket_t* inPktArray, unsigned inPktCnt, audioPacket_t* outPktArray, unsigned outPktCnt );
|
2019-12-26 02:44:14 +00:00
|
|
|
|
|
|
|
typedef struct driver_str
|
|
|
|
{
|
|
|
|
void* drvArg;
|
|
|
|
rc_t (*deviceCount)( struct driver_str* drvArg);
|
|
|
|
const char* (*deviceLabel)( struct driver_str* drvArg, unsigned devIdx );
|
|
|
|
unsigned (*deviceChannelCount)( struct driver_str* drvArg, unsigned devIdx, bool inputFl );
|
|
|
|
double (*deviceSampleRate)( struct driver_str* drvArg, unsigned devIdx );
|
|
|
|
unsigned (*deviceFramesPerCycle)( struct driver_str* drvArg, unsigned devIdx, bool inputFl );
|
2023-02-15 01:46:41 +00:00
|
|
|
rc_t (*deviceSetup)( struct driver_str* drvArg, unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cb, void* cbData, unsigned cbDevIdx );
|
2019-12-26 02:44:14 +00:00
|
|
|
rc_t (*deviceStart)( struct driver_str* drvArg, unsigned devIdx );
|
|
|
|
rc_t (*deviceStop)( struct driver_str* drvArg, unsigned devIdx );
|
2023-02-15 01:46:41 +00:00
|
|
|
bool (*deviceIsStarted)( struct driver_str* drvArg, unsigned devIdx );
|
2023-02-19 19:16:37 +00:00
|
|
|
|
|
|
|
// deviceExecute() is called to indicate that a device should execute a callback as soon as possible.
|
|
|
|
// This function is called by one device to synchronize another device.
|
2023-02-15 01:46:41 +00:00
|
|
|
rc_t (*deviceExecute)( struct driver_str* drvArg, unsigned devIdx );
|
2023-02-19 19:16:37 +00:00
|
|
|
|
|
|
|
// An input device that is started but not enabled will source zeros.
|
|
|
|
// An output device that is started but not enabled will ignore incoming samples (and sink zeros),
|
|
|
|
// audio device files will not write.
|
|
|
|
rc_t (*deviceEnable)( struct driver_str* drvArg, unsigned devIdx, bool inputFl, bool enableFl );
|
|
|
|
|
|
|
|
// This function is only enabled on audio device files.
|
|
|
|
rc_t (*deviceSeek)( struct driver_str* drvArg, unsigned devIdx, bool inputFl, unsigned frameOffset );
|
|
|
|
|
2019-12-26 02:44:14 +00:00
|
|
|
void (*deviceRealTimeReport)( struct driver_str* drvArg, unsigned devIdx );
|
|
|
|
} driver_t;
|
|
|
|
|
|
|
|
typedef handle<struct device_str> handle_t;
|
|
|
|
|
|
|
|
rc_t create( handle_t& hRef );
|
|
|
|
rc_t destroy( handle_t& hRef );
|
|
|
|
|
|
|
|
rc_t registerDriver( handle_t h, driver_t* drv );
|
|
|
|
|
2020-03-23 14:41:28 +00:00
|
|
|
unsigned count( handle_t h );
|
|
|
|
unsigned labelToIndex( handle_t h, const char* label );
|
|
|
|
const char* label( handle_t h, unsigned devIdx );
|
|
|
|
unsigned channelCount( handle_t h, unsigned devIdx, bool inputFl );
|
|
|
|
double sampleRate( handle_t h, unsigned devIdx );
|
|
|
|
unsigned framesPerCycle( handle_t h, unsigned devIdx, bool inputFl );
|
2023-02-15 01:46:41 +00:00
|
|
|
bool isAsync( handle_t h, unsigned devIdx );
|
|
|
|
|
2019-12-27 21:52:45 +00:00
|
|
|
|
|
|
|
// Configure a device.
|
|
|
|
// All devices must be setup before they are started.
|
|
|
|
// framesPerCycle is the requested number of samples per audio callback. The
|
|
|
|
// actual number of samples made from a callback may be smaller. See the note
|
|
|
|
// regarding this in audioPacket_t.
|
|
|
|
// If the device cannot support the requested configuration then the function
|
|
|
|
// will return an error code.
|
|
|
|
// If the device is started when this function is called then it will be
|
|
|
|
// automatically stopped and then restarted following the reconfiguration.
|
|
|
|
// If the reconfiguration fails then the device may not be restared.
|
2020-03-23 14:41:28 +00:00
|
|
|
rc_t setup(
|
2019-12-27 21:52:45 +00:00
|
|
|
handle_t h,
|
|
|
|
unsigned devIdx,
|
|
|
|
double sr,
|
|
|
|
unsigned frmPerCycle,
|
|
|
|
cbFunc_t cb,
|
|
|
|
void* cbData );
|
|
|
|
|
2020-03-23 14:41:28 +00:00
|
|
|
rc_t start( handle_t h, unsigned devIdx );
|
|
|
|
rc_t stop( handle_t h, unsigned devIdx );
|
|
|
|
bool isStarted( handle_t h, unsigned devIdx );
|
2023-02-15 01:46:41 +00:00
|
|
|
rc_t execute( handle_t h, unsigned devIdx );
|
2023-02-19 19:16:37 +00:00
|
|
|
rc_t enable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl );
|
|
|
|
rc_t seek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset );
|
|
|
|
void realTimeReport( handle_t h, unsigned devIdx );
|
|
|
|
|
2023-02-15 01:46:41 +00:00
|
|
|
void report( handle_t h );
|
|
|
|
void realTimeReport( handle_t h );
|
2019-12-26 02:44:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|