diff --git a/include/dpp/discordvoiceclient.h b/include/dpp/discordvoiceclient.h index dcd048f16b..ff32dc057e 100644 --- a/include/dpp/discordvoiceclient.h +++ b/include/dpp/discordvoiceclient.h @@ -561,9 +561,9 @@ class DPP_EXPORT discord_voice_client : public websocket_client std::chrono::high_resolution_clock::time_point last_timestamp; /** - * @brief Fraction of the sleep that was not executed after the last audio packet was sent + * @brief Last sent packet duration */ - std::chrono::nanoseconds last_sleep_remainder{}; + uint64_t last_duration; /** * @brief Maps receiving ssrc to user id @@ -799,12 +799,11 @@ class DPP_EXPORT discord_voice_client : public websocket_client * audio data because Discord does not expect to receive, say, 3 minutes' * worth of audio data in 1 second. * - * There are some inaccuracies in the throttling method used by the recorded + * There was some inaccuracies in the throttling method used by the recorded * audio mode on some systems (mainly Windows) which causes gaps and stutters * in the resulting audio stream. The overlap audio mode provides a different - * implementation that fixes the issue. This method is slightly more CPU - * intensive, and should only be used if you encounter issues with recorded audio - * on your system. + * implementation that fixes the issue in the past. This method is not used + * anymore and behave the same as the recorded audio mode. * * Use discord_voice_client::set_send_audio_type to change this value as * it ensures thread safety. diff --git a/src/dpp/voice/enabled/constructor.cpp b/src/dpp/voice/enabled/constructor.cpp index ab2b3a9f59..c6bd52df34 100644 --- a/src/dpp/voice/enabled/constructor.cpp +++ b/src/dpp/voice/enabled/constructor.cpp @@ -50,6 +50,7 @@ discord_voice_client::discord_voice_client(dpp::cluster* _cluster, full_reconnec timestamp(0), packet_nonce(1), last_timestamp(std::chrono::high_resolution_clock::now()), + last_duration(0), sending(false), tracks(0), dave_version(enable_dave ? dave_version_1 : dave_version_none), diff --git a/src/dpp/voice/enabled/write_ready.cpp b/src/dpp/voice/enabled/write_ready.cpp index 4966ee2155..53bf1cc6d3 100644 --- a/src/dpp/voice/enabled/write_ready.cpp +++ b/src/dpp/voice/enabled/write_ready.cpp @@ -31,23 +31,27 @@ namespace dpp { void discord_voice_client::write_ready() { - bool needs_write = false; - { - std::lock_guard lock(this->stream_mutex); - const bool needs_stop_frames = this->paused && !this->sent_stop_frames; - const bool needs_send_audio = !this->paused && !outbuf.empty(); - needs_write = needs_stop_frames || needs_send_audio; - } + std::chrono::nanoseconds latency{0}; + if (send_audio_type != satype_live_audio) { + const auto now = std::chrono::high_resolution_clock::now(); + + const auto minimum = std::chrono::nanoseconds(last_duration); + const auto elapsed = std::chrono::duration_cast(now - last_timestamp); - if (needs_write) { - udp_events.flags = WANT_READ | WANT_WRITE | WANT_ERROR; - owner->socketengine->update_socket(udp_events); + if (elapsed < minimum) { + std::this_thread::sleep_for(minimum - elapsed); + udp_events.flags = WANT_READ | WANT_WRITE | WANT_ERROR; + owner->socketengine->update_socket(udp_events); + return; + } + + latency = elapsed - minimum; + last_timestamp = now; } uint64_t duration = 0; bool track_marker_found = false; uint64_t bufsize = 0; - send_audio_type_t type = satype_recorded_audio; { std::lock_guard lock(this->stream_mutex); if (this->paused) { @@ -58,7 +62,6 @@ void discord_voice_client::write_ready() { /* Fallthrough if paused */ } else if (!outbuf.empty()) { - type = send_audio_type; if (outbuf[0].packet.size() == sizeof(uint16_t) && (*(reinterpret_cast(outbuf[0].packet.data()))) == AUDIO_TRACK_MARKER) { outbuf.erase(outbuf.begin()); track_marker_found = true; @@ -74,40 +77,15 @@ void discord_voice_client::write_ready() { outbuf.erase(outbuf.begin()); } } + if (!outbuf.empty()) { + udp_events.flags = WANT_READ | WANT_WRITE | WANT_ERROR; + owner->socketengine->update_socket(udp_events); + } } } if (duration) { - if (type == satype_recorded_audio) { - std::chrono::nanoseconds latency = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - last_timestamp); - std::chrono::nanoseconds sleep_time = std::chrono::nanoseconds(duration) - latency; - if (sleep_time.count() > 0) { - std::this_thread::sleep_for(sleep_time); - } - } - else if (type == satype_overlap_audio) { - std::chrono::nanoseconds latency = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - last_timestamp); - std::chrono::nanoseconds sleep_time = std::chrono::nanoseconds(duration) + last_sleep_remainder - latency; - std::chrono::nanoseconds sleep_increment = (std::chrono::nanoseconds(duration) - latency) / AUDIO_OVERLAP_SLEEP_SAMPLES; - if (sleep_time.count() > 0) { - uint16_t samples_count = 0; - std::chrono::nanoseconds overshoot_accumulator{}; - - do { - std::chrono::high_resolution_clock::time_point start_sleep = std::chrono::high_resolution_clock::now(); - std::this_thread::sleep_for(sleep_increment); - std::chrono::high_resolution_clock::time_point end_sleep = std::chrono::high_resolution_clock::now(); - - samples_count++; - overshoot_accumulator += std::chrono::duration_cast(end_sleep - start_sleep) - sleep_increment; - sleep_time -= std::chrono::duration_cast(end_sleep - start_sleep); - } while (std::chrono::nanoseconds(overshoot_accumulator.count() / samples_count) + sleep_increment < sleep_time); - last_sleep_remainder = sleep_time; - } else { - last_sleep_remainder = std::chrono::nanoseconds(0); - } - } - - last_timestamp = std::chrono::high_resolution_clock::now(); + const auto latcount = latency.count(); + last_duration = duration > latcount ? duration - latcount : duration; if (!creator->on_voice_buffer_send.empty()) { voice_buffer_send_t snd(owner, 0, ""); snd.buffer_size = bufsize;