2013-12-19 17:10:14 +00:00
|
|
|
#pragma once
|
|
|
|
#include "types.h"
|
2021-03-01 09:13:40 +00:00
|
|
|
#include "cfg/option.h"
|
2021-04-30 17:57:11 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <atomic>
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-04-24 19:41:38 +00:00
|
|
|
typedef std::vector<std::string> (*audio_option_callback_t)();
|
|
|
|
enum audio_option_type
|
|
|
|
{
|
2019-05-02 18:24:49 +00:00
|
|
|
integer = 0
|
|
|
|
, checkbox = 1
|
2019-04-24 19:41:38 +00:00
|
|
|
, list = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
std::string cfg_name;
|
|
|
|
std::string caption;
|
|
|
|
audio_option_type type;
|
|
|
|
|
|
|
|
// type int_value (spin edit)
|
|
|
|
int min_value;
|
|
|
|
int max_value;
|
|
|
|
|
|
|
|
// type list edit (string/char*)
|
|
|
|
audio_option_callback_t list_callback;
|
|
|
|
} audio_option_t;
|
|
|
|
|
|
|
|
typedef audio_option_t* (*audio_options_func_t)(int* option_count);
|
|
|
|
|
2015-04-14 14:58:41 +00:00
|
|
|
typedef void (*audio_backend_init_func_t)();
|
2021-03-23 15:27:57 +00:00
|
|
|
typedef u32 (*audio_backend_push_func_t)(const void *data, u32 frames, bool wait);
|
2015-04-14 14:58:41 +00:00
|
|
|
typedef void (*audio_backend_term_func_t)();
|
|
|
|
typedef struct {
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string slug;
|
|
|
|
std::string name;
|
2015-04-14 14:58:41 +00:00
|
|
|
audio_backend_init_func_t init;
|
|
|
|
audio_backend_push_func_t push;
|
|
|
|
audio_backend_term_func_t term;
|
2019-04-24 19:41:38 +00:00
|
|
|
audio_options_func_t get_options;
|
2020-12-05 17:47:09 +00:00
|
|
|
bool (*init_record)(u32 sampling_freq);
|
|
|
|
u32 (*record)(void *, u32);
|
|
|
|
audio_backend_term_func_t term_record;
|
2015-04-14 14:58:41 +00:00
|
|
|
} audiobackend_t;
|
2020-12-05 17:47:09 +00:00
|
|
|
bool RegisterAudioBackend(audiobackend_t* backend);
|
|
|
|
void InitAudio();
|
|
|
|
void TermAudio();
|
|
|
|
void WriteSample(s16 right, s16 left);
|
|
|
|
|
|
|
|
void StartAudioRecording(bool eight_khz);
|
|
|
|
u32 RecordAudio(void *buffer, u32 samples);
|
|
|
|
void StopAudioRecording();
|
2019-04-05 20:22:46 +00:00
|
|
|
|
|
|
|
u32 GetAudioBackendCount();
|
|
|
|
audiobackend_t* GetAudioBackend(int num);
|
2019-09-07 12:37:39 +00:00
|
|
|
audiobackend_t* GetAudioBackend(const std::string& slug);
|
2021-03-23 15:27:57 +00:00
|
|
|
|
|
|
|
constexpr u32 SAMPLE_COUNT = 512; // push() is always called with that many frames
|
2021-04-30 17:57:11 +00:00
|
|
|
|
|
|
|
class RingBuffer
|
|
|
|
{
|
|
|
|
std::vector<u8> buffer;
|
|
|
|
std::atomic_int readCursor { 0 };
|
|
|
|
std::atomic_int writeCursor { 0 };
|
|
|
|
|
|
|
|
u32 readSize() {
|
2021-12-11 17:33:28 +00:00
|
|
|
return (u32)((writeCursor - readCursor + buffer.size()) % buffer.size());
|
2021-04-30 17:57:11 +00:00
|
|
|
}
|
|
|
|
u32 writeSize() {
|
2021-12-11 17:33:28 +00:00
|
|
|
return (u32)((readCursor - writeCursor + buffer.size() - 1) % buffer.size());
|
2021-04-30 17:57:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool write(const u8 *data, u32 size)
|
|
|
|
{
|
|
|
|
if (size > writeSize())
|
|
|
|
return false;
|
|
|
|
u32 wc = writeCursor;
|
2021-12-11 17:33:28 +00:00
|
|
|
u32 chunkSize = std::min<u32>(size, (u32)buffer.size() - wc);
|
2021-04-30 17:57:11 +00:00
|
|
|
memcpy(&buffer[wc], data, chunkSize);
|
|
|
|
wc = (wc + chunkSize) % buffer.size();
|
|
|
|
size -= chunkSize;
|
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
data += chunkSize;
|
|
|
|
memcpy(&buffer[wc], data, size);
|
|
|
|
wc = (wc + size) % buffer.size();
|
|
|
|
}
|
|
|
|
writeCursor = wc;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read(u8 *data, u32 size)
|
|
|
|
{
|
|
|
|
if (size > readSize())
|
|
|
|
return false;
|
|
|
|
u32 rc = readCursor;
|
2021-12-11 17:33:28 +00:00
|
|
|
u32 chunkSize = std::min<u32>(size, (u32)buffer.size() - rc);
|
2021-04-30 17:57:11 +00:00
|
|
|
memcpy(data, &buffer[rc], chunkSize);
|
|
|
|
rc = (rc + chunkSize) % buffer.size();
|
|
|
|
size -= chunkSize;
|
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
data += chunkSize;
|
|
|
|
memcpy(data, &buffer[rc], size);
|
|
|
|
rc = (rc + size) % buffer.size();
|
|
|
|
}
|
|
|
|
readCursor = rc;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setCapacity(size_t size)
|
|
|
|
{
|
|
|
|
std::fill(buffer.begin(), buffer.end(), 0);
|
|
|
|
buffer.resize(size);
|
|
|
|
readCursor = 0;
|
|
|
|
writeCursor = 0;
|
|
|
|
}
|
|
|
|
};
|