Fixed input stuff
This commit is contained in:
parent
35b8082a97
commit
0cdd1ad2c8
@ -27,13 +27,7 @@ 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());
|
||||||
}
|
}
|
||||||
#if defined(WIN32) && false
|
|
||||||
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +187,12 @@ namespace tc::audio {
|
|||||||
|
|
||||||
bool AudioDeviceRecord::start(std::string &error) {
|
bool AudioDeviceRecord::start(std::string &error) {
|
||||||
std::lock_guard lock{this->state_lock};
|
std::lock_guard lock{this->state_lock};
|
||||||
if(this->running) return true;
|
if(this->running && !this->stream_invalid) return true;
|
||||||
|
if(this->stream_invalid) {
|
||||||
|
this->impl_stop();
|
||||||
|
this->running = false;
|
||||||
|
this->stream_invalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!this->impl_start(error)) {
|
if(!this->impl_start(error)) {
|
||||||
log_error(category::audio, tr("Failed to start record: {}"), error);
|
log_error(category::audio, tr("Failed to start record: {}"), error);
|
||||||
@ -212,14 +211,16 @@ namespace tc::audio {
|
|||||||
|
|
||||||
this->impl_stop();
|
this->impl_stop();
|
||||||
this->running = false;
|
this->running = false;
|
||||||
|
this->stream_invalid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceRecord::stop() {
|
void AudioDeviceRecord::stop() {
|
||||||
std::lock_guard lock{this->state_lock};
|
std::lock_guard lock{this->state_lock};
|
||||||
if(this->running) return;
|
if(!this->running) return;
|
||||||
|
|
||||||
this->impl_stop();
|
this->impl_stop();
|
||||||
this->running = false;
|
this->running = false;
|
||||||
|
this->stream_invalid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceRecord::register_consumer(Consumer* source) {
|
void AudioDeviceRecord::register_consumer(Consumer* source) {
|
||||||
|
@ -33,6 +33,7 @@ namespace tc::audio {
|
|||||||
|
|
||||||
std::mutex state_lock{};
|
std::mutex state_lock{};
|
||||||
bool running{false};
|
bool running{false};
|
||||||
|
bool stream_invalid{false};
|
||||||
|
|
||||||
std::mutex consumer_lock{};
|
std::mutex consumer_lock{};
|
||||||
std::vector<Consumer*> _consumers{};
|
std::vector<Consumer*> _consumers{};
|
||||||
|
@ -80,12 +80,17 @@ namespace tc::audio {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t _sample_rate;
|
size_t _sample_rate;
|
||||||
bool stream_invalid{false};
|
|
||||||
struct ::SoundIoDevice* device_handle{nullptr};
|
struct ::SoundIoDevice* device_handle{nullptr};
|
||||||
struct ::SoundIoInStream* stream{nullptr};
|
struct ::SoundIoInStream* stream{nullptr};
|
||||||
|
|
||||||
|
size_t failed_count{0};
|
||||||
|
std::thread fail_recover_thread{};
|
||||||
|
std::mutex fail_cv_mutex{};
|
||||||
|
std::condition_variable fail_cv{};
|
||||||
|
|
||||||
struct ::SoundIoRingBuffer* buffer{nullptr};
|
struct ::SoundIoRingBuffer* buffer{nullptr};
|
||||||
|
|
||||||
|
void execute_recovery();
|
||||||
void read_callback(int frame_count_min, int frame_count_max);
|
void read_callback(int frame_count_min, int frame_count_max);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ SoundIORecord::SoundIORecord(struct ::SoundIoDevice *device) : device_handle{dev
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoundIORecord::~SoundIORecord() {
|
SoundIORecord::~SoundIORecord() {
|
||||||
|
{
|
||||||
|
std::lock_guard slock{this->state_lock};
|
||||||
|
if(this->running) this->impl_stop();
|
||||||
|
}
|
||||||
soundio_device_unref(this->device_handle);
|
soundio_device_unref(this->device_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +41,34 @@ size_t SoundIORecord::sample_rate() const {
|
|||||||
return this->_sample_rate;
|
return this->_sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundIORecord::execute_recovery() {
|
||||||
|
if(this->fail_recover_thread.joinable()) return;
|
||||||
|
|
||||||
|
this->fail_recover_thread = std::thread([&]{
|
||||||
|
_fail_begin:
|
||||||
|
{
|
||||||
|
std::unique_lock cv_lock{this->fail_cv_mutex};
|
||||||
|
auto fc = this->failed_count;
|
||||||
|
if(fc == 0) fc = 1;
|
||||||
|
else if(fc > 10) return;
|
||||||
|
this->fail_cv.wait_for(cv_lock, std::chrono::seconds{(fc - 1) * 10});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard slock{this->state_lock};
|
||||||
|
if(!this->running) return;
|
||||||
|
|
||||||
|
std::string error{};
|
||||||
|
this->impl_stop();
|
||||||
|
if(!this->impl_start(error)) {
|
||||||
|
log_info(category::audio, tr("Failed to recover from device fail: {}. Trying again later."), error);
|
||||||
|
this->failed_count++;
|
||||||
|
goto _fail_begin;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool SoundIORecord::impl_start(std::string &error) {
|
bool SoundIORecord::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
|
this->buffer = soundio_ring_buffer_create(nullptr, kChunkSize * sizeof(float) * 2); //2 Channels
|
||||||
if(!buffer) {
|
if(!buffer) {
|
||||||
error = "failed to allocate the buffer";
|
error = "failed to allocate the buffer";
|
||||||
@ -61,12 +90,18 @@ bool SoundIORecord::impl_start(std::string &error) {
|
|||||||
this->stream->overflow_callback = [](auto str) {
|
this->stream->overflow_callback = [](auto str) {
|
||||||
auto handle = reinterpret_cast<SoundIORecord*>(str->userdata);
|
auto handle = reinterpret_cast<SoundIORecord*>(str->userdata);
|
||||||
log_info(category::audio, tr("Having an overflow on {}"), handle->device_handle->id);
|
log_info(category::audio, tr("Having an overflow on {}"), handle->device_handle->id);
|
||||||
|
|
||||||
|
handle->failed_count++;
|
||||||
};
|
};
|
||||||
|
|
||||||
this->stream->error_callback = [](auto str, int err) {
|
this->stream->error_callback = [](auto str, int err) {
|
||||||
auto handle = reinterpret_cast<SoundIORecord*>(str->userdata);
|
auto handle = reinterpret_cast<SoundIORecord*>(str->userdata);
|
||||||
log_info(category::audio, tr("Having an error on {}: {}. Aborting recording."), handle->device_handle->id, soundio_strerror(err));
|
log_info(category::audio, tr("Having an error on {}: {}. Aborting recording and trying again later."), handle->device_handle->id, soundio_strerror(err));
|
||||||
|
std::lock_guard slock{handle->state_lock};
|
||||||
|
if(!handle->running) return;
|
||||||
|
|
||||||
handle->stream_invalid = true;
|
handle->stream_invalid = true;
|
||||||
|
handle->execute_recovery();
|
||||||
};
|
};
|
||||||
|
|
||||||
this->stream->read_callback = [](struct SoundIoInStream *str, int frame_count_min, int frame_count_max) {
|
this->stream->read_callback = [](struct SoundIoInStream *str, int frame_count_min, int frame_count_max) {
|
||||||
@ -111,6 +146,11 @@ bool SoundIORecord::impl_start(std::string &error) {
|
|||||||
void SoundIORecord::impl_stop() {
|
void SoundIORecord::impl_stop() {
|
||||||
if(!this->stream) return;
|
if(!this->stream) return;
|
||||||
|
|
||||||
|
if(this->fail_recover_thread.joinable() && std::this_thread::get_id() != this->fail_recover_thread.get_id()) {
|
||||||
|
this->fail_cv.notify_all();
|
||||||
|
this->fail_recover_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
soundio_instream_destroy(this->stream);
|
soundio_instream_destroy(this->stream);
|
||||||
this->stream = nullptr;
|
this->stream = nullptr;
|
||||||
|
|
||||||
@ -124,7 +164,7 @@ void SoundIORecord::read_callback(int frame_count_min, int frame_count_max) {
|
|||||||
struct SoundIoChannelArea *areas;
|
struct SoundIoChannelArea *areas;
|
||||||
|
|
||||||
int frames_left{frame_count_max};
|
int frames_left{frame_count_max};
|
||||||
int buffer_samples = soundio_ring_buffer_free_count(this->buffer) / (sizeof(float) * layout->channel_count);
|
int buffer_samples = kChunkSize - soundio_ring_buffer_fill_count(this->buffer) / (sizeof(float) * layout->channel_count);
|
||||||
|
|
||||||
while(frames_left > 0) {
|
while(frames_left > 0) {
|
||||||
int frame_count{frames_left};
|
int frame_count{frames_left};
|
||||||
@ -165,11 +205,13 @@ void SoundIORecord::read_callback(int frame_count_min, int frame_count_max) {
|
|||||||
if(buffer_samples == 0) {
|
if(buffer_samples == 0) {
|
||||||
std::lock_guard consumer{this->consumer_lock};
|
std::lock_guard consumer{this->consumer_lock};
|
||||||
const auto byte_count = soundio_ring_buffer_fill_count(this->buffer);
|
const auto byte_count = soundio_ring_buffer_fill_count(this->buffer);
|
||||||
const auto frame_count = byte_count / (sizeof(float) * layout->channel_count);
|
const auto buffer_frame_count = byte_count / (sizeof(float) * layout->channel_count);
|
||||||
|
|
||||||
for(auto& consumer : this->_consumers)
|
for(auto& consumer : this->_consumers)
|
||||||
consumer->consume(soundio_ring_buffer_read_ptr(this->buffer), frame_count, layout->channel_count);
|
consumer->consume(soundio_ring_buffer_read_ptr(this->buffer), buffer_frame_count, layout->channel_count);
|
||||||
|
|
||||||
soundio_ring_buffer_advance_read_ptr(this->buffer, byte_count);
|
soundio_ring_buffer_advance_read_ptr(this->buffer, byte_count);
|
||||||
buffer_samples = frame_count;
|
buffer_samples = kChunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto err = soundio_instream_end_read(this->stream); err) {
|
if(auto err = soundio_instream_end_read(this->stream); err) {
|
||||||
|
@ -77,7 +77,6 @@ long double ThresholdFilter::analyze(const void *_buffer, size_t channel) {
|
|||||||
/* equation taken from the web client */
|
/* equation taken from the web client */
|
||||||
|
|
||||||
auto buffer = (float*) _buffer;
|
auto buffer = (float*) _buffer;
|
||||||
buffer += channel;
|
|
||||||
|
|
||||||
long double value = 0;
|
long double value = 0;
|
||||||
auto sample = this->_frame_size;
|
auto sample = this->_frame_size;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user