-
Notifications
You must be signed in to change notification settings - Fork 0
/
OpenALDataFetcher.cpp
101 lines (82 loc) · 2.92 KB
/
OpenALDataFetcher.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "OpenALDataFetcher.h"
OpenALDataFetcher::OpenALDataFetcher(
const ALCuint sample_rate,
const ALCsizei buffer_size,
const std::function<size_t(const std::vector<std::string>&)> &device_matcher
) {
internal_buffer = std::make_unique<short[]>(buffer_size);
internal_buffer_size = buffer_size;
this->sample_rate = sample_rate;
this->device_matcher = device_matcher;
ReloadDevice();
}
OpenALDataFetcher::~OpenALDataFetcher() {
if (device)
alcCaptureCloseDevice(device);
}
void OpenALDataFetcher::ReloadDevice() {
if (device)
alcCaptureCloseDevice(device);
// refresh the device list
BuildDeviceList();
if (device_list.size() == 0)
throw std::runtime_error("Could not find any capture devices");
// call the matcher and check its output
size_t device_id = device_matcher(device_list);
if (device_id >= device_list.size()) {
device_id = 0;
}
// try to open the device chosen by the matcher
device = alcCaptureOpenDevice(
device_list[device_id].c_str(),
sample_rate,
AL_FORMAT_MONO16,
internal_buffer_size
);
if (device == NULL)
throw std::runtime_error("Could not open device");
// try to start capturing from the device
alcCaptureStart(device);
if(alcGetError(device) != ALC_NO_ERROR)
throw std::runtime_error("Could not start capture");
}
void OpenALDataFetcher::BuildDeviceList() {
device_list.clear();
const ALCchar* devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (*devices == '\0')
return;
do {
device_list.push_back(std::string(devices));
devices += device_list.back().size() + 1;
} while (*devices != '\0');
}
ALCint OpenALDataFetcher::UpdateData() {
static clock::time_point last_capture;
ALCint available_samples;
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &available_samples);
ALCsizei readable_samples = std::min(available_samples, internal_buffer_size);
// Check for timeout if no samples are available and we've captured before
if (available_samples <= 0 && last_capture.time_since_epoch().count() > 0) {
std::chrono::duration<double> duration = clock::now() - last_capture;
// Reload device if we timed out
if (duration.count() > device_timeout) {
ReloadDevice();
return 0;
}
}
for (ALCsizei i = readable_samples; i < internal_buffer_size; ++i) {
internal_buffer[i - readable_samples] = internal_buffer[i];
}
alcCaptureSamples(
device,
(ALCvoid*)(internal_buffer.get() + internal_buffer_size - readable_samples),
readable_samples
);
last_capture = clock::now();
return readable_samples;
}
void OpenALDataFetcher::GetData(float buffer[]) {
for (ALCsizei i = 0; i < internal_buffer_size; i++) {
buffer[i] = map(internal_buffer[i], -32768, 32767, -1, 1);
}
}