Line |
Branch |
Exec |
Source |
1 |
|
|
/* GATE PROJECT LICENSE: |
2 |
|
|
+----------------------------------------------------------------------------+ |
3 |
|
|
| Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | |
4 |
|
|
| All rights reserved. | |
5 |
|
|
| | |
6 |
|
|
| Redistribution and use in source and binary forms, with or without | |
7 |
|
|
| modification, are permitted provided that the following conditions are met:| |
8 |
|
|
| | |
9 |
|
|
| 1. Redistributions of source code must retain the above copyright notice, | |
10 |
|
|
| this list of conditions and the following disclaimer. | |
11 |
|
|
| 2. Redistributions in binary form must reproduce the above copyright | |
12 |
|
|
| notice, this list of conditions and the following disclaimer in the | |
13 |
|
|
| documentation and/or other materials provided with the distribution. | |
14 |
|
|
| | |
15 |
|
|
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| |
16 |
|
|
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 |
|
|
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 |
|
|
| ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
19 |
|
|
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 |
|
|
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 |
|
|
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 |
|
|
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 |
|
|
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 |
|
|
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
25 |
|
|
| THE POSSIBILITY OF SUCH DAMAGE. | |
26 |
|
|
+----------------------------------------------------------------------------+ |
27 |
|
|
*/ |
28 |
|
|
|
29 |
|
|
#include "gate/io/audiosources.hpp" |
30 |
|
|
|
31 |
|
|
namespace gate |
32 |
|
|
{ |
33 |
|
|
namespace io |
34 |
|
|
{ |
35 |
|
|
|
36 |
|
✗ |
AudioFormat::AudioFormat(uint32_t encodingId, uint32_t samplesPerSecond, uint16_t channels, uint16_t bitsPerSample) |
37 |
|
|
{ |
38 |
|
✗ |
this->encoding_id = encodingId; |
39 |
|
✗ |
this->samples_per_second = samplesPerSecond; |
40 |
|
✗ |
this->channels = channels; |
41 |
|
✗ |
this->bits_per_sample = bitsPerSample; |
42 |
|
✗ |
} |
43 |
|
✗ |
AudioFormat::AudioFormat(gate_audio_format_t const& src) |
44 |
|
✗ |
: gate_audio_format_t(src) |
45 |
|
|
{ |
46 |
|
✗ |
} |
47 |
|
|
|
48 |
|
✗ |
AudioFormat const& AudioFormat::choose(AudioFormat const* formats, size_t formatsCount, |
49 |
|
|
uint32_t const* desiredSamplesPerSecond, |
50 |
|
|
uint16_t const* desiredChannels, |
51 |
|
|
uint16_t const* desiredBitsPerSample) |
52 |
|
|
{ |
53 |
|
✗ |
gate_audio_format_t const* ptrFormat = gate_audio_format_choose( |
54 |
|
|
formats, formatsCount, desiredSamplesPerSecond, desiredChannels, desiredBitsPerSample); |
55 |
|
✗ |
if (!ptrFormat) |
56 |
|
|
{ |
57 |
|
✗ |
raiseException(results::NoMatch, "No matching format found", "AudioFormat::choose"); |
58 |
|
|
} |
59 |
|
✗ |
return *static_cast<AudioFormat const*>(ptrFormat); |
60 |
|
|
} |
61 |
|
|
|
62 |
|
✗ |
AudioSample::AudioSample() |
63 |
|
|
{ |
64 |
|
✗ |
Mem::clear(this->impl); |
65 |
|
✗ |
} |
66 |
|
|
|
67 |
|
✗ |
void AudioSample::initFrom(gate_audio_sample_t const& src) |
68 |
|
|
{ |
69 |
|
✗ |
this->impl.format = src.format; |
70 |
|
✗ |
this->impl.sample_count = src.sample_count; |
71 |
|
✗ |
this->impl.record_time = src.record_time; |
72 |
|
|
|
73 |
|
✗ |
this->impl.data = src.data; |
74 |
|
✗ |
if (this->impl.data != NULL) |
75 |
|
|
{ |
76 |
|
✗ |
gate_object_retain(this->impl.data); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
✗ |
this->impl.meta_data = src.meta_data; |
80 |
|
✗ |
if (this->impl.meta_data != NULL) |
81 |
|
|
{ |
82 |
|
✗ |
gate_object_retain(this->impl.meta_data); |
83 |
|
|
} |
84 |
|
✗ |
} |
85 |
|
|
|
86 |
|
✗ |
AudioSample::AudioSample(AudioSample const& src) |
87 |
|
✗ |
: impl(gate_audio_sample_t()) |
88 |
|
|
{ |
89 |
|
✗ |
this->initFrom(src.impl); |
90 |
|
✗ |
} |
91 |
|
|
|
92 |
|
✗ |
AudioSample::AudioSample(gate_audio_sample_t const& src) |
93 |
|
✗ |
: impl(gate_audio_sample_t()) |
94 |
|
|
{ |
95 |
|
✗ |
this->initFrom(src); |
96 |
|
✗ |
} |
97 |
|
|
|
98 |
|
✗ |
AudioSample::~AudioSample() noexcept |
99 |
|
|
{ |
100 |
|
✗ |
gate_audio_sample_release(&this->impl); |
101 |
|
✗ |
} |
102 |
|
|
|
103 |
|
✗ |
AudioSample& AudioSample::operator=(AudioSample const& src) |
104 |
|
|
{ |
105 |
|
|
//TODO |
106 |
|
✗ |
return *this; |
107 |
|
|
} |
108 |
|
|
|
109 |
|
✗ |
AudioSample& AudioSample::operator=(gate_audio_sample_t& src) |
110 |
|
|
{ |
111 |
|
|
//TODO |
112 |
|
✗ |
return *this; |
113 |
|
|
} |
114 |
|
|
|
115 |
|
✗ |
AudioFormat AudioSample::getFormat() const |
116 |
|
|
{ |
117 |
|
✗ |
return AudioFormat(this->impl.format); |
118 |
|
|
} |
119 |
|
|
|
120 |
|
✗ |
MemoryBlock AudioSample::getData() const |
121 |
|
|
{ |
122 |
|
✗ |
MemoryBlock block(this->impl.data); |
123 |
|
✗ |
gate_object_retain(this->impl.data); |
124 |
|
✗ |
return block; |
125 |
|
|
} |
126 |
|
✗ |
MemoryBlock AudioSample::getMetaData() const |
127 |
|
|
{ |
128 |
|
✗ |
MemoryBlock block(this->impl.meta_data); |
129 |
|
✗ |
gate_object_retain(this->impl.meta_data); |
130 |
|
✗ |
return block; |
131 |
|
|
} |
132 |
|
✗ |
uint32_t AudioSample::getSampleCount() const |
133 |
|
|
{ |
134 |
|
✗ |
return this->impl.sample_count; |
135 |
|
|
} |
136 |
|
✗ |
int64_t AudioSample::getRecordTime() const |
137 |
|
|
{ |
138 |
|
✗ |
return this->impl.record_time; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
✗ |
gate_audio_sample_t* AudioSample::c_impl() |
142 |
|
|
{ |
143 |
|
✗ |
return &this->impl; |
144 |
|
|
} |
145 |
|
✗ |
gate_audio_sample_t const* AudioSample::c_impl() const |
146 |
|
|
{ |
147 |
|
✗ |
return &this->impl; |
148 |
|
|
} |
149 |
|
|
|
150 |
|
✗ |
static gate_result_t enumDevicesCallback(gate_audio_device_t* device, void* param) |
151 |
|
|
{ |
152 |
|
✗ |
ArrayList<AudioDevice>* ptrList = reinterpret_cast<ArrayList<AudioDevice>*>(param); |
153 |
|
✗ |
AudioDevice dev(device); |
154 |
|
✗ |
gate_object_retain(device); // object belongs to device enumeration, add refcount to share it |
155 |
|
✗ |
ptrList->add(dev); |
156 |
|
✗ |
return GATE_RESULT_OK; |
157 |
|
|
} |
158 |
|
|
|
159 |
|
✗ |
Array<AudioDevice> AudioDevices::enumDevices(AudioDevice::DeviceTypeEnum deviceType) |
160 |
|
|
{ |
161 |
|
✗ |
ArrayList<AudioDevice> ret; |
162 |
|
|
gate_delegate_t audio_enum_delegate; |
163 |
|
✗ |
GATE_DELEGATE_BIND_FUNC(gate_audio_devices_enum, &audio_enum_delegate, enumDevicesCallback); |
164 |
|
✗ |
result_t result = gate_audio_devices_enum(deviceType, &audio_enum_delegate, &ret); |
165 |
|
✗ |
return ret.toArray(); |
166 |
|
|
} |
167 |
|
|
|
168 |
|
✗ |
AudioDevice AudioDevices::fromId(AudioDevice::DeviceTypeEnum deviceType, String const& id) |
169 |
|
|
{ |
170 |
|
✗ |
CstrBuffer buffer(id); |
171 |
|
✗ |
gate_audio_device_t* ptrDevice = NULL; |
172 |
|
✗ |
result_t result = gate_audio_device_by_id(deviceType, buffer.get(), &ptrDevice); |
173 |
|
✗ |
GATEXX_CHECK_EXCEPTION(result); |
174 |
|
✗ |
return AudioDevice(ptrDevice); |
175 |
|
|
} |
176 |
|
|
|
177 |
|
✗ |
AudioDevice AudioDevices::createWaveReader(Stream& inputStream) |
178 |
|
|
{ |
179 |
|
✗ |
gate_audio_device_t* ptrDevice = NULL; |
180 |
|
✗ |
result_t result = gate_audio_create_wave_reader(inputStream.c_impl(), &ptrDevice); |
181 |
|
✗ |
GATEXX_CHECK_EXCEPTION(result); |
182 |
|
✗ |
return AudioDevice(ptrDevice); |
183 |
|
|
} |
184 |
|
|
|
185 |
|
✗ |
AudioDevice AudioDevices::createWaveWriter(ControlStream& outputStream) |
186 |
|
|
{ |
187 |
|
✗ |
gate_audio_device_t* ptrDevice = NULL; |
188 |
|
✗ |
result_t result = gate_audio_create_wave_writer(outputStream.c_impl(), &ptrDevice); |
189 |
|
✗ |
GATEXX_CHECK_EXCEPTION(result); |
190 |
|
✗ |
return AudioDevice(ptrDevice); |
191 |
|
|
} |
192 |
|
|
|
193 |
|
|
|
194 |
|
✗ |
AudioDevice::AudioDevice() noexcept |
195 |
|
✗ |
: object_impl_t(NULL) |
196 |
|
|
{ |
197 |
|
|
|
198 |
|
✗ |
} |
199 |
|
|
|
200 |
|
|
|
201 |
|
✗ |
AudioDevice::AudioDevice(gate_audio_device_t* ptr_device) |
202 |
|
✗ |
: object_impl_t(ptr_device) |
203 |
|
|
{ |
204 |
|
✗ |
if (!ptr_device) |
205 |
|
|
{ |
206 |
|
✗ |
GATEXX_RAISE_ERROR(results::NullPointer); |
207 |
|
|
} |
208 |
|
✗ |
} |
209 |
|
|
|
210 |
|
✗ |
AudioDevice::AudioDevice(AudioDevice const& src) noexcept |
211 |
|
✗ |
: object_impl_t(src) |
212 |
|
|
{ |
213 |
|
|
|
214 |
|
✗ |
} |
215 |
|
|
|
216 |
|
✗ |
AudioDevice& AudioDevice::operator=(AudioDevice const& src) noexcept |
217 |
|
|
{ |
218 |
|
✗ |
object_impl_t::operator=(src); |
219 |
|
✗ |
return *this; |
220 |
|
|
} |
221 |
|
|
|
222 |
|
✗ |
AudioDevice::~AudioDevice() noexcept |
223 |
|
|
{ |
224 |
|
✗ |
} |
225 |
|
|
|
226 |
|
✗ |
String AudioDevice::getId() const noexcept |
227 |
|
|
{ |
228 |
|
✗ |
return String::createStatic(gate_audio_device_get_id(this->c_impl())); |
229 |
|
|
} |
230 |
|
|
|
231 |
|
✗ |
String AudioDevice::getName() const noexcept |
232 |
|
|
{ |
233 |
|
✗ |
return String::createStatic(gate_audio_device_get_name(this->c_impl())); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
✗ |
intptr_t AudioDevice::getHandle() const noexcept |
237 |
|
|
{ |
238 |
|
✗ |
return gate_audio_device_get_handle(this->c_impl()); |
239 |
|
|
} |
240 |
|
|
|
241 |
|
✗ |
AudioDevice::DeviceTypeEnum AudioDevice::getDeviceType() const noexcept |
242 |
|
|
{ |
243 |
|
✗ |
return AudioDevice::DeviceTypeEnum(gate_audio_device_get_device_type(this->c_impl())); |
244 |
|
|
} |
245 |
|
|
|
246 |
|
✗ |
Array<AudioFormat> AudioDevice::getSupportedFormats() |
247 |
|
|
{ |
248 |
|
|
gate_audio_format_t formats[256]; |
249 |
|
✗ |
size_t len_returned = gate_audio_device_get_supported_formats(this->c_impl(), formats, sizeof(formats) / sizeof(formats[0])); |
250 |
|
✗ |
ArrayList<AudioFormat> al(len_returned); |
251 |
|
✗ |
for (size_t n = 0; n != len_returned; ++n) |
252 |
|
|
{ |
253 |
|
✗ |
al.add(AudioFormat(formats[n])); |
254 |
|
|
} |
255 |
|
✗ |
return al.toArray(); |
256 |
|
|
} |
257 |
|
|
|
258 |
|
✗ |
VoidResult AudioDevice::tryOpen(AudioFormat const& format, size_t sampleCount) noexcept |
259 |
|
|
{ |
260 |
|
✗ |
result_t res = gate_audio_device_open(this->c_impl(), &format, sampleCount); |
261 |
|
✗ |
return makeResult(res); |
262 |
|
|
} |
263 |
|
✗ |
void AudioDevice::open(AudioFormat const& format, size_t sampleCount) |
264 |
|
|
{ |
265 |
|
✗ |
this->tryOpen(format, sampleCount).checkException("AudioDevice::open"); |
266 |
|
✗ |
} |
267 |
|
✗ |
VoidResult AudioDevice::close() noexcept |
268 |
|
|
{ |
269 |
|
✗ |
result_t res = gate_audio_device_close(this->c_impl()); |
270 |
|
✗ |
return makeResult(res); |
271 |
|
|
} |
272 |
|
|
|
273 |
|
✗ |
VoidResult AudioDevice::tryRead(AudioSample& sample) noexcept |
274 |
|
|
{ |
275 |
|
✗ |
result_t res = gate_audio_device_read(this->c_impl(), sample.c_impl()); |
276 |
|
✗ |
return makeResult(res); |
277 |
|
|
} |
278 |
|
✗ |
bool_t AudioDevice::read(AudioSample& sample) |
279 |
|
|
{ |
280 |
|
✗ |
VoidResult result = this->tryRead(sample); |
281 |
|
✗ |
if (result.hasError()) |
282 |
|
|
{ |
283 |
|
✗ |
if (result.error() == GATE_RESULT_ENDOFSTREAM) |
284 |
|
|
{ |
285 |
|
✗ |
return false; |
286 |
|
|
} |
287 |
|
|
} |
288 |
|
✗ |
result.checkException("AudioDevice::read"); |
289 |
|
✗ |
return true; |
290 |
|
|
} |
291 |
|
|
|
292 |
|
✗ |
VoidResult AudioDevice::tryWrite(AudioSample const& sample) noexcept |
293 |
|
|
{ |
294 |
|
✗ |
result_t res = gate_audio_device_write(this->c_impl(), sample.c_impl()); |
295 |
|
✗ |
return makeResult(res); |
296 |
|
|
} |
297 |
|
|
|
298 |
|
✗ |
void AudioDevice::write(AudioSample& sample) |
299 |
|
|
{ |
300 |
|
✗ |
this->tryWrite(sample).checkException("AudioDevice::write"); |
301 |
|
✗ |
} |
302 |
|
|
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
} // end of namespace io |
306 |
|
|
} // end of namespace gate |
307 |
|
|
|