Stashing some changes
This commit is contained in:
parent
28225b5f48
commit
105eb52eef
@ -110,7 +110,7 @@ if (MSVC)
|
|||||||
foreach(CompilerFlag ${CompilerFlags})
|
foreach(CompilerFlag ${CompilerFlags})
|
||||||
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
||||||
endforeach()
|
endforeach()
|
||||||
add_compile_options("/MTd")
|
#add_compile_options("/MTd")
|
||||||
add_compile_options("/EHsc") #We require exception handling
|
add_compile_options("/EHsc") #We require exception handling
|
||||||
else()
|
else()
|
||||||
#This is a bad thing here!
|
#This is a bad thing here!
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "AudioOutput.h"
|
#include "./AudioOutput.h"
|
||||||
#include "AudioMerger.h"
|
#include "./AudioMerger.h"
|
||||||
|
#include "./AudioResampler.h"
|
||||||
#include "../logger.h"
|
#include "../logger.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -170,6 +171,7 @@ void AudioOutput::cleanup_buffers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioOutput::fill_buffer(void *output, size_t frameCount, size_t channels) {
|
void AudioOutput::fill_buffer(void *output, size_t frameCount, size_t channels) {
|
||||||
|
const auto local_frame_count = this->_resampler ? this->_resampler->
|
||||||
lock_guard buffer_lock(this->buffer_lock);
|
lock_guard buffer_lock(this->buffer_lock);
|
||||||
if(this->_volume <= 0) {
|
if(this->_volume <= 0) {
|
||||||
for(auto& source : this->_sources)
|
for(auto& source : this->_sources)
|
||||||
|
@ -101,6 +101,7 @@ namespace tc::audio {
|
|||||||
std::recursive_mutex device_lock;
|
std::recursive_mutex device_lock;
|
||||||
std::shared_ptr<AudioDevice> device{nullptr};
|
std::shared_ptr<AudioDevice> device{nullptr};
|
||||||
std::shared_ptr<AudioDevicePlayback> _playback{nullptr};
|
std::shared_ptr<AudioDevicePlayback> _playback{nullptr};
|
||||||
|
std::unique_ptr<AudioResampler> _resampler{nullptr};
|
||||||
|
|
||||||
std::mutex buffer_lock; /* not required, but why not. Usually only used within audio_callback! */
|
std::mutex buffer_lock; /* not required, but why not. Usually only used within audio_callback! */
|
||||||
void* source_buffer = nullptr;
|
void* source_buffer = nullptr;
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
using namespace tc::audio;
|
using namespace tc::audio;
|
||||||
|
|
||||||
namespace tc::audio {
|
namespace tc::audio {
|
||||||
|
inline bool ends_with(std::string const & value, std::string const & ending) {
|
||||||
|
if (ending.size() > value.size()) return false;
|
||||||
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||||
|
}
|
||||||
|
|
||||||
std::deque<std::shared_ptr<AudioDevice>> devices() {
|
std::deque<std::shared_ptr<AudioDevice>> devices() {
|
||||||
std::deque<std::shared_ptr<AudioDevice>> result{};
|
std::deque<std::shared_ptr<AudioDevice>> result{};
|
||||||
for(auto& backend : SoundIOBackendHandler::all_backends()) {
|
for(auto& backend : SoundIOBackendHandler::all_backends()) {
|
||||||
@ -22,6 +27,13 @@ namespace tc::audio {
|
|||||||
result.insert(result.end(), input_devices.begin(), input_devices.end());
|
result.insert(result.end(), input_devices.begin(), input_devices.end());
|
||||||
result.insert(result.end(), output_devices.begin(), output_devices.end());
|
result.insert(result.end(), output_devices.begin(), output_devices.end());
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
//Remove all not raw devices. We do not support shared mode yet
|
||||||
|
result.erase(std::remove_if(result.begin(), result.end(), [](const std::shared_ptr<AudioDevice>& device) {
|
||||||
|
if(device->driver() != "WASAPI") return false;
|
||||||
|
return !ends_with(device->id(), "_raw");
|
||||||
|
}), result.end());
|
||||||
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ namespace tc::audio {
|
|||||||
virtual void consume(const void* /* buffer */, size_t /* samples */, size_t /* channel count */) = 0;
|
virtual void consume(const void* /* buffer */, size_t /* samples */, size_t /* channel count */) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] virtual size_t sample_rate() const = 0;
|
||||||
|
|
||||||
[[nodiscard]] bool start(std::string& /* error */);
|
[[nodiscard]] bool start(std::string& /* error */);
|
||||||
void stop_if_possible();
|
void stop_if_possible();
|
||||||
void stop();
|
void stop();
|
||||||
@ -43,6 +45,8 @@ namespace tc::audio {
|
|||||||
virtual void fill_buffer(void* /* target */, size_t /* samples */, size_t /* channel count */) = 0;
|
virtual void fill_buffer(void* /* target */, size_t /* samples */, size_t /* channel count */) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] virtual size_t sample_rate() const = 0;
|
||||||
|
|
||||||
[[nodiscard]] bool start(std::string& /* error */);
|
[[nodiscard]] bool start(std::string& /* error */);
|
||||||
void stop_if_possible();
|
void stop_if_possible();
|
||||||
void stop();
|
void stop();
|
||||||
@ -52,6 +56,8 @@ namespace tc::audio {
|
|||||||
return this->_sources;
|
return this->_sources;
|
||||||
}
|
}
|
||||||
void register_source(Source* /* source */);
|
void register_source(Source* /* source */);
|
||||||
|
|
||||||
|
/* will and must be blocking until audio callback is done */
|
||||||
void remove_source(Source* /* source */);
|
void remove_source(Source* /* source */);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -134,6 +134,13 @@ void SoundIOBackendHandler::disconnect() {
|
|||||||
soundio_disconnect(this->soundio_handle);
|
soundio_disconnect(this->soundio_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string sample_rates(struct ::SoundIoDevice *dev) {
|
||||||
|
std::string result{};
|
||||||
|
for(size_t index = 0; index < dev->sample_rate_count; index++)
|
||||||
|
result += (index > 0 ? ", [" : "[") + std::to_string(dev->sample_rates[index].min) + ";" + std::to_string(dev->sample_rates[index].max) + "]";
|
||||||
|
return dev->sample_rate_count ? result : "none";
|
||||||
|
}
|
||||||
|
|
||||||
void SoundIOBackendHandler::handle_device_change() {
|
void SoundIOBackendHandler::handle_device_change() {
|
||||||
log_debug(category::audio, tr("Device list changed for backend {}. Reindexing devices."), this->name());
|
log_debug(category::audio, tr("Device list changed for backend {}. Reindexing devices."), this->name());
|
||||||
|
|
||||||
@ -160,7 +167,7 @@ void SoundIOBackendHandler::handle_device_change() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto device = std::make_shared<SoundIODevice>(dev, this->name(), i == default_input_device, true);
|
auto device = std::make_shared<SoundIODevice>(dev, this->name(), i == default_input_device, true);
|
||||||
log_trace(category::audio, tr("Found input device {} ({})."), dev->id, dev->name);
|
log_trace(category::audio, tr("Found input device {} ({}). Raw: {}. Rates: {}"), dev->id, dev->name, dev->is_raw, sample_rates(dev));
|
||||||
this->cached_input_devices.push_back(device);
|
this->cached_input_devices.push_back(device);
|
||||||
if(i == default_input_device)
|
if(i == default_input_device)
|
||||||
this->_default_input_device = device;
|
this->_default_input_device = device;
|
||||||
@ -181,7 +188,7 @@ void SoundIOBackendHandler::handle_device_change() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto device = std::make_shared<SoundIODevice>(dev, this->name(), i == default_output_device, true);
|
auto device = std::make_shared<SoundIODevice>(dev, this->name(), i == default_output_device, true);
|
||||||
log_trace(category::audio, tr("Found output device {} ({})."), dev->id, dev->name);
|
log_trace(category::audio, tr("Found output device {} ({}). Raw: {}. Rates: {}."), dev->id, dev->name, dev->is_raw, sample_rates(dev));
|
||||||
this->cached_output_devices.push_back(device);
|
this->cached_output_devices.push_back(device);
|
||||||
if(i == default_output_device)
|
if(i == default_output_device)
|
||||||
this->_default_output_device = device;
|
this->_default_output_device = device;
|
||||||
@ -201,6 +208,12 @@ void SoundIOBackendHandler::handle_backend_disconnect(int error) {
|
|||||||
|
|
||||||
SoundIODevice::SoundIODevice(struct ::SoundIoDevice *dev, std::string driver, bool default_, bool owned) : device_handle{dev}, driver_name{std::move(driver)}, _default{default_} {
|
SoundIODevice::SoundIODevice(struct ::SoundIoDevice *dev, std::string driver, bool default_, bool owned) : device_handle{dev}, driver_name{std::move(driver)}, _default{default_} {
|
||||||
if(!owned) soundio_device_ref(dev);
|
if(!owned) soundio_device_ref(dev);
|
||||||
|
|
||||||
|
if(this->device_handle->is_raw) {
|
||||||
|
this->_device_id = std::string{dev->id} + "_raw";
|
||||||
|
} else {
|
||||||
|
this->_device_id = dev->id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundIODevice::~SoundIODevice() {
|
SoundIODevice::~SoundIODevice() {
|
||||||
@ -208,7 +221,7 @@ SoundIODevice::~SoundIODevice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string SoundIODevice::id() const {
|
std::string SoundIODevice::id() const {
|
||||||
return this->device_handle->id;
|
return this->_device_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SoundIODevice::name() const {
|
std::string SoundIODevice::name() const {
|
||||||
|
@ -26,19 +26,25 @@ namespace tc::audio {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr std::array kSampleRateOrder{48000, 44100};
|
||||||
|
constexpr auto kDefaultSampleRate{kSampleRateOrder[0]};
|
||||||
|
|
||||||
class SoundIOPlayback : public AudioDevicePlayback {
|
class SoundIOPlayback : public AudioDevicePlayback {
|
||||||
public:
|
public:
|
||||||
constexpr static auto kChunkSize{960};
|
constexpr static auto kChunkTime{0.02};
|
||||||
|
|
||||||
explicit SoundIOPlayback(struct ::SoundIoDevice* /* handle */);
|
explicit SoundIOPlayback(struct ::SoundIoDevice* /* handle */);
|
||||||
virtual ~SoundIOPlayback();
|
virtual ~SoundIOPlayback();
|
||||||
|
|
||||||
|
size_t sample_rate() const override;
|
||||||
protected:
|
protected:
|
||||||
bool impl_start(std::string& /* error */) override;
|
bool impl_start(std::string& /* error */) override;
|
||||||
void impl_stop() override;
|
void impl_stop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
size_t _sample_rate;
|
||||||
bool stream_invalid{false};
|
bool stream_invalid{false};
|
||||||
|
bool have_underflow{false};
|
||||||
struct ::SoundIoDevice* device_handle{nullptr};
|
struct ::SoundIoDevice* device_handle{nullptr};
|
||||||
struct ::SoundIoOutStream* stream{nullptr};
|
struct ::SoundIoOutStream* stream{nullptr};
|
||||||
|
|
||||||
@ -54,11 +60,13 @@ namespace tc::audio {
|
|||||||
explicit SoundIORecord(struct ::SoundIoDevice* /* handle */);
|
explicit SoundIORecord(struct ::SoundIoDevice* /* handle */);
|
||||||
virtual ~SoundIORecord();
|
virtual ~SoundIORecord();
|
||||||
|
|
||||||
|
size_t sample_rate() const override;
|
||||||
protected:
|
protected:
|
||||||
bool impl_start(std::string& /* error */) override;
|
bool impl_start(std::string& /* error */) override;
|
||||||
void impl_stop() override;
|
void impl_stop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
size_t _sample_rate;
|
||||||
bool stream_invalid{false};
|
bool stream_invalid{false};
|
||||||
struct ::SoundIoDevice* device_handle{nullptr};
|
struct ::SoundIoDevice* device_handle{nullptr};
|
||||||
struct ::SoundIoInStream* stream{nullptr};
|
struct ::SoundIoInStream* stream{nullptr};
|
||||||
@ -86,6 +94,8 @@ namespace tc::audio {
|
|||||||
[[nodiscard]] std::shared_ptr<AudioDevicePlayback> playback() override;
|
[[nodiscard]] std::shared_ptr<AudioDevicePlayback> playback() override;
|
||||||
[[nodiscard]] std::shared_ptr<AudioDeviceRecord> record() override;
|
[[nodiscard]] std::shared_ptr<AudioDeviceRecord> record() override;
|
||||||
private:
|
private:
|
||||||
|
std::string _device_id{};
|
||||||
|
|
||||||
std::string driver_name{};
|
std::string driver_name{};
|
||||||
struct ::SoundIoDevice* device_handle{nullptr};
|
struct ::SoundIoDevice* device_handle{nullptr};
|
||||||
bool _default{false};
|
bool _default{false};
|
||||||
|
@ -2,29 +2,51 @@
|
|||||||
// Created by wolverindev on 07.02.20.
|
// Created by wolverindev on 07.02.20.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "SoundIO.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include "SoundIO.h"
|
||||||
#include "../../logger.h"
|
#include "../../logger.h"
|
||||||
|
|
||||||
using namespace tc::audio;
|
using namespace tc::audio;
|
||||||
|
|
||||||
SoundIOPlayback::SoundIOPlayback(struct ::SoundIoDevice *device) : device_handle{device} {
|
SoundIOPlayback::SoundIOPlayback(struct ::SoundIoDevice *device) : device_handle{device} {
|
||||||
soundio_device_ref(device);
|
soundio_device_ref(device);
|
||||||
|
|
||||||
|
if(device->probe_error || !device->sample_rate_count)
|
||||||
|
this->_sample_rate = kDefaultSampleRate;
|
||||||
|
else {
|
||||||
|
for(const auto& sample_rate : kSampleRateOrder) {
|
||||||
|
for(size_t index{0}; index < device->sample_rate_count; index++) {
|
||||||
|
auto supported_rate = device->sample_rates[index];
|
||||||
|
if(supported_rate.min <= sample_rate && supported_rate.max >= sample_rate) {
|
||||||
|
this->_sample_rate = sample_rate;
|
||||||
|
goto _found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_sample_rate = kDefaultSampleRate;
|
||||||
|
_found:;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundIOPlayback::~SoundIOPlayback() {
|
SoundIOPlayback::~SoundIOPlayback() {
|
||||||
soundio_device_unref(this->device_handle);
|
soundio_device_unref(this->device_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t SoundIOPlayback::sample_rate() const {
|
||||||
|
return this->_sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
bool SoundIOPlayback::impl_start(std::string &error) {
|
bool SoundIOPlayback::impl_start(std::string &error) {
|
||||||
assert(this->device_handle);
|
assert(this->device_handle);
|
||||||
|
|
||||||
this->buffer = soundio_ring_buffer_create(nullptr, kChunkSize * sizeof(float) * 2); /* 2 channels */
|
//TODO: Figure out how many channels!
|
||||||
|
this->buffer = soundio_ring_buffer_create(nullptr, (int) (kChunkTime * this->_sample_rate * sizeof(float) * 2)); /* 2 channels */
|
||||||
if(!buffer) {
|
if(!buffer) {
|
||||||
error = "failed to allocate the buffer";
|
error = "failed to allocate the buffer";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
soundio_ring_buffer_clear(this->buffer);
|
|
||||||
|
|
||||||
this->stream = soundio_outstream_create(this->device_handle);
|
this->stream = soundio_outstream_create(this->device_handle);
|
||||||
if(!this->stream) {
|
if(!this->stream) {
|
||||||
@ -33,6 +55,7 @@ bool SoundIOPlayback::impl_start(std::string &error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->stream->userdata = this;
|
this->stream->userdata = this;
|
||||||
|
this->stream->sample_rate = this->_sample_rate;
|
||||||
this->stream->format = SoundIoFormatFloat32LE;
|
this->stream->format = SoundIoFormatFloat32LE;
|
||||||
this->stream->software_latency = 0.02;
|
this->stream->software_latency = 0.02;
|
||||||
|
|
||||||
@ -54,28 +77,37 @@ bool SoundIOPlayback::impl_start(std::string &error) {
|
|||||||
|
|
||||||
if(auto err = soundio_outstream_open(this->stream); err) {
|
if(auto err = soundio_outstream_open(this->stream); err) {
|
||||||
error = soundio_strerror(err) + std::string{" (open)"};
|
error = soundio_strerror(err) + std::string{" (open)"};
|
||||||
soundio_outstream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
}
|
||||||
return false;
|
|
||||||
|
if(this->_sample_rate != this->stream->sample_rate) {
|
||||||
|
error = "sample rate mismatch (" + std::to_string(this->_sample_rate) + " <> " + std::to_string(this->stream->sample_rate) + ")";
|
||||||
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(false && this->stream->layout_error) {
|
if(false && this->stream->layout_error) {
|
||||||
error = std::string{"failed to set audio layout: "} + soundio_strerror(this->stream->layout_error);
|
error = std::string{"failed to set audio layout: "} + soundio_strerror(this->stream->layout_error);
|
||||||
soundio_outstream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto err = soundio_outstream_start(this->stream); err) {
|
if(auto err = soundio_outstream_start(this->stream); err) {
|
||||||
error = soundio_strerror(err) + std::string{" (start)"};
|
error = soundio_strerror(err) + std::string{" (start)"};
|
||||||
soundio_outstream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soundio_outstream_wasapi_set_sleep_divider(this->stream,100); // Play one quarter and then request fill again so we've 3 quarters to fill up again
|
||||||
//TODO: Test for interleaved channel layout!
|
//TODO: Test for interleaved channel layout!
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error_cleanup:
|
||||||
|
|
||||||
|
if(this->stream) soundio_outstream_destroy(this->stream);
|
||||||
|
this->stream = nullptr;
|
||||||
|
|
||||||
|
if(this->buffer) soundio_ring_buffer_destroy(this->buffer);
|
||||||
|
this->buffer = nullptr;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundIOPlayback::impl_stop() {
|
void SoundIOPlayback::impl_stop() {
|
||||||
@ -94,10 +126,28 @@ void SoundIOPlayback::write_callback(int frame_count_min, int frame_count_max) {
|
|||||||
struct SoundIoChannelArea *areas;
|
struct SoundIoChannelArea *areas;
|
||||||
int frames_left{frame_count_min}, err;
|
int frames_left{frame_count_min}, err;
|
||||||
|
|
||||||
if(frames_left < 120)
|
const auto min_interval = this->have_underflow ? 0.02 : 0.01;
|
||||||
frames_left = 120;
|
const auto max_latency = 0.02;
|
||||||
if(frames_left > frame_count_max)
|
|
||||||
frames_left = frame_count_max;
|
|
||||||
|
{
|
||||||
|
const auto _min_interval_frames = (int) (min_interval * this->stream->sample_rate + .5);
|
||||||
|
|
||||||
|
if(frames_left < _min_interval_frames)
|
||||||
|
frames_left = _min_interval_frames;
|
||||||
|
if(frames_left > frame_count_max)
|
||||||
|
frames_left = frame_count_max;
|
||||||
|
if(frame_count_max == 0) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
double latency{};
|
||||||
|
if(auto err = soundio_outstream_get_latency(this->stream, &latency); err) {
|
||||||
|
log_warn(category::audio, tr("Failed to get auto stream latency: {}"), err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(latency > max_latency) return;
|
||||||
|
}
|
||||||
|
|
||||||
while(frames_left > 0) {
|
while(frames_left > 0) {
|
||||||
int frame_count{frames_left};
|
int frame_count{frames_left};
|
||||||
|
@ -10,12 +10,33 @@ using namespace tc::audio;
|
|||||||
|
|
||||||
SoundIORecord::SoundIORecord(struct ::SoundIoDevice *device) : device_handle{device} {
|
SoundIORecord::SoundIORecord(struct ::SoundIoDevice *device) : device_handle{device} {
|
||||||
soundio_device_ref(device);
|
soundio_device_ref(device);
|
||||||
|
|
||||||
|
if(device->probe_error || !device->sample_rate_count)
|
||||||
|
this->_sample_rate = kDefaultSampleRate;
|
||||||
|
else {
|
||||||
|
for(const auto& sample_rate : kSampleRateOrder) {
|
||||||
|
for(size_t index{0}; index < device->sample_rate_count; index++) {
|
||||||
|
auto supported_rate = device->sample_rates[index];
|
||||||
|
if(supported_rate.min <= sample_rate && supported_rate.max >= sample_rate) {
|
||||||
|
this->_sample_rate = sample_rate;
|
||||||
|
goto _found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_sample_rate = kDefaultSampleRate;
|
||||||
|
_found:;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundIORecord::~SoundIORecord() {
|
SoundIORecord::~SoundIORecord() {
|
||||||
soundio_device_unref(this->device_handle);
|
soundio_device_unref(this->device_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t SoundIORecord::sample_rate() const {
|
||||||
|
return this->_sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
bool SoundIORecord::impl_start(std::string &error) {
|
bool SoundIORecord::impl_start(std::string &error) {
|
||||||
assert(this->device_handle);
|
assert(this->device_handle);
|
||||||
|
|
||||||
@ -34,6 +55,7 @@ bool SoundIORecord::impl_start(std::string &error) {
|
|||||||
|
|
||||||
this->stream->userdata = this;
|
this->stream->userdata = this;
|
||||||
this->stream->format = SoundIoFormatFloat32LE;
|
this->stream->format = SoundIoFormatFloat32LE;
|
||||||
|
this->stream->sample_rate = this->_sample_rate;
|
||||||
this->stream->software_latency = 0.02;
|
this->stream->software_latency = 0.02;
|
||||||
|
|
||||||
this->stream->overflow_callback = [](auto str) {
|
this->stream->overflow_callback = [](auto str) {
|
||||||
@ -54,28 +76,36 @@ bool SoundIORecord::impl_start(std::string &error) {
|
|||||||
|
|
||||||
if(auto err = soundio_instream_open(this->stream); err) {
|
if(auto err = soundio_instream_open(this->stream); err) {
|
||||||
error = soundio_strerror(err) + std::string{" (open)"};
|
error = soundio_strerror(err) + std::string{" (open)"};
|
||||||
soundio_instream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
}
|
||||||
return false;
|
|
||||||
|
if(this->_sample_rate != this->stream->sample_rate) {
|
||||||
|
error = "sample rate mismatch (" + std::to_string(this->_sample_rate) + " <> " + std::to_string(this->stream->sample_rate) + ")";
|
||||||
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(false && this->stream->layout_error) {
|
if(false && this->stream->layout_error) {
|
||||||
error = std::string{"failed to set audio layout: "} + soundio_strerror(this->stream->layout_error);
|
error = std::string{"failed to set audio layout: "} + soundio_strerror(this->stream->layout_error);
|
||||||
soundio_instream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto err = soundio_instream_start(this->stream); err) {
|
if(auto err = soundio_instream_start(this->stream); err) {
|
||||||
error = soundio_strerror(err) + std::string{" (start)"};
|
error = soundio_strerror(err) + std::string{" (start)"};
|
||||||
soundio_instream_destroy(this->stream);
|
goto error_cleanup;
|
||||||
this->stream = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Test for interleaved channel layout!
|
//TODO: Test for interleaved channel layout!
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error_cleanup:
|
||||||
|
|
||||||
|
if(this->stream) soundio_instream_destroy(this->stream);
|
||||||
|
this->stream = nullptr;
|
||||||
|
|
||||||
|
if(this->buffer) soundio_ring_buffer_destroy(this->buffer);
|
||||||
|
this->buffer = nullptr;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundIORecord::impl_stop() {
|
void SoundIORecord::impl_stop() {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "ProtocolHandler.h"
|
#include "ProtocolHandler.h"
|
||||||
#include "ServerConnection.h"
|
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include "../logger.h"
|
#include "../logger.h"
|
||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
@ -7,7 +6,6 @@
|
|||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
#include <protocol/buffers.h>
|
#include <protocol/buffers.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <iostream>
|
|
||||||
#include <tomcrypt.h>
|
#include <tomcrypt.h>
|
||||||
#include <tommath.h>
|
#include <tommath.h>
|
||||||
|
|
||||||
|
@ -147,10 +147,21 @@ void UDPSocket::callback_read(evutil_socket_t fd) {
|
|||||||
source_address_length = sizeof(sockaddr);
|
source_address_length = sizeof(sockaddr);
|
||||||
read_length = recvfrom(fd, (char*) buffer, (int) buffer_length, MSG_DONTWAIT, &source_address, &source_address_length);
|
read_length = recvfrom(fd, (char*) buffer, (int) buffer_length, MSG_DONTWAIT, &source_address, &source_address_length);
|
||||||
if(read_length <= 0) {
|
if(read_length <= 0) {
|
||||||
if(errno == EAGAIN || (read_length == 0 && read_count > 0))
|
if(read_length == 0 && read_count > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
logger::warn(category::socket, tr("Failed to receive data: {}/{}"), errno, strerror(errno));
|
int error;
|
||||||
|
#ifdef WIN32
|
||||||
|
error = WSAGetLastError();
|
||||||
|
if(error == WSAEWOULDBLOCK)
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
error = errno;
|
||||||
|
if(errno == EAGAIN)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
logger::warn(category::socket, tr("Failed to receive data: {}"), error);
|
||||||
break; /* this should never happen! */
|
break; /* this should never happen! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ void force_log_node(logger::category::value, spdlog::level::level_enum, const st
|
|||||||
#ifdef NODEJS_API
|
#ifdef NODEJS_API
|
||||||
#include <NanGet.h>
|
#include <NanGet.h>
|
||||||
#include <include/NanEventCallback.h>
|
#include <include/NanEventCallback.h>
|
||||||
#include <include/NanStrings.h>
|
|
||||||
|
|
||||||
/* NODE JS */
|
/* NODE JS */
|
||||||
struct LogMessage {
|
struct LogMessage {
|
||||||
|
Loading…
Reference in New Issue
Block a user