diff --git a/openrtx/include/interfaces/audio_path.h b/openrtx/include/interfaces/audio_path.h new file mode 100644 index 00000000..19dade1a --- /dev/null +++ b/openrtx/include/interfaces/audio_path.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef AUDIO_PATH_H +#define AUDIO_PATH_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum AudioSource +{ + SOURCE_MIC, ///< Receive audio signal from the microphone + SOURCE_RTX, ///< Receive audio signal from the transceiver + SOURCE_MCU ///< Receive audio signal from a memory buffer +}; + +enum AudioSink +{ + SINK_SPK, ///< Send audio signal to the speaker + SINK_RTX, ///< Send audio signal to the transceiver + SINK_MCU ///< Send audio signal to a memory buffer +}; + +enum AudioPriority +{ + PRIO_BEEP = 1, ///< Priority level of system beeps + PRIO_RX, ///< Priority level of incoming audio from RX stage + PRIO_PROMPT, ///< Priority level of voice prompts + PRIO_TX ///< Priority level of outward audio directed to TX stage +}; + +typedef int8_t pathId; + +/** + * Try to connect an audio path, returns an error if the path is already used + * with an higher priority. + * + * @param source: identifier of the input audio peripheral. + * @param sink: identifier of the output audio peripheral. + * @param prio: priority of the requester. + * @return a unique identifier of the opened path or -1 if path is already in use. + */ +pathId audioPath_open(enum AudioSource source, + enum AudioSink sink, + enum AudioPriority prio); + +/** + * Release an audio path. + * + * @param id: identifier of the previously opened path. + * @return true on success, false on error. + */ +bool audioPath_close(pathId id); + +#ifdef __cplusplus +} +#endif + +#endif /* AUDIO_PATH_H */ diff --git a/openrtx/include/interfaces/audio_stream.h b/openrtx/include/interfaces/audio_stream.h new file mode 100644 index 00000000..aa097876 --- /dev/null +++ b/openrtx/include/interfaces/audio_stream.h @@ -0,0 +1,159 @@ +/*************************************************************************** + * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef AUDIO_STREAM_H +#define AUDIO_STREAM_H + +#include +#include +#include "audio_path.h" + +#ifdef __cplusplus +#include + +extern "C" { +#endif + +typedef int16_t stream_sample_t; +typedef int8_t streamId; + +enum BufMode +{ + BUF_LINEAR, ///< Linear buffer mode, conversion stops when full. + BUF_CIRC, ///< Circular buffer mode, conversion never stops, thread woken up when full. + BUF_CIRC_DOUBLE ///< Circular double buffer mode, conversion never stops, thread woken up whenever half of the buffer is full. +}; + +typedef struct +{ + stream_sample_t *data; + size_t len; +} +dataBlock_t; + +/** + * Start the acquisition of an incoming audio stream, also opening the + * corresponding audio path. If a stream is opened from the same source but + * with an higher priority than the one currently open, the new stream takes + * over the previous one. + * The function returns an error when the audio path is not available or the + * selected stream is already in use by another process with higher priority. + * + * @param source: input source specifier. + * @param prio: priority of the requester. + * @param buf: pointer to a buffer used for management of sampled data. + * @param bufLength: length of the buffer, in elements. + * @param mode: buffer management mode. + * @param sampleRate: sample rate, in Hz. + * @return a unique identifier for the stream or -1 if the stream could not be opened. + */ +streamId inputStream_start(const enum AudioSource source, + const enum AudioPriority prio, + stream_sample_t * const buf, + const size_t bufLength, + const enum BufMode mode, + const uint32_t sampleRate); + +/** + * Get a chunk of data from an already opened input stream, blocking function. + * If buffer management is configured to BUF_LINEAR this function also starts a + * new data acquisition. + * + * @param id: identifier of the stream from which data is get. + * @return dataBlock_t containing a pointer to the chunk head and its length. If + * another thread is pending on this function, it returns immediately a dataBlock_t + * cointaining < NULL, 0 >. + */ +dataBlock_t inputStream_getData(streamId id); + +/** + * Release the current input stream, allowing for a new call of startInputStream. + * If this function is called when sampler is running, acquisition is stopped and + * any thread waiting on getData() is woken up and given a partial result. + * + * @param id: identifier of the stream to be stopped + */ +void inputStream_stop(streamId id); + +/** + * Send an audio stream to a given output. This function returns immediately if + * there is not another stream already running, otherwise it will block the + * caller until the previous stream terminates. + * If a stream is opened from the same source but with an higher priority than + * the one currently open, the new stream takes over the previous one. + * + * WARNING: the caller must ensure that buffer content is not modified while the + * stream is being reproduced. + * + * @param destination: destination of the output stream. + * @param prio: priority of the requester. + * @param buf: buffer containing the audio samples. + * @param length: length of the buffer, in elements. + * @param sampleRate: sample rate in Hz. + * @return a unique identifier for the stream or -1 if the stream could not be opened. + */ +streamId outputStream_start(const enum AudioSink destination, + const enum AudioPriority prio, + stream_sample_t * const buf, + const size_t length, + const uint32_t sampleRate); + +/** + * Interrupt a currently ongoing output stream before its natural ending. + * + * @param id: identifier of the stream to be stopped. + */ +void outputStream_stop(streamId id); + +#ifdef __cplusplus +} + +/** + * Get a chunk of data from an already opened input stream, blocking function. + * If buffer management is configured to BUF_LINEAR this function also starts a + * new data acquisition. + * Application code MUST ensure that the template parameter specifying the size + * of the returned std::array matches the size of the expected buffer, i.e. + * if acquisition is configured as double circular buffer, the template parameter + * must be set to one half of the buffer passed to inputStream_start. + * If there is a mismatch between the size of the std::array and the size of the + * data block returned (which is deterministic), a nullptr is returned. + * + * @param id: identifier of the stream to get data from. + * @return std::array pointer containing the acquired samples, nullptr if another + * thread is pending on this function. + */ +template +std::array *inputStream_getData(streamId id) +{ + /* + * Call corresponding C API then use placement new to obtain a std::array + * from the pointer returned. This is possible only if sizes are equal, thus + * an equality check is preformed and a nullptr is returned in case of + * mismatch. + */ + dataBlock_t buffer = inputStream_getData(id); + if(buffer.len != N) return nullptr; + return new (buffer.data) std::array; +} + +#endif + +#endif /* AUDIO_STREAM_H */