From 848b11399f2e34d7f1e0523e214287bfdcc5816c Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Sun, 16 Jul 2023 23:04:09 +1000 Subject: [PATCH] Get SE-compatible voice transmission working --- source/application/StarMainApplication_sdl.cpp | 7 +++++-- source/client/StarClientApplication.cpp | 14 +++++++++----- source/frontend/StarVoice.cpp | 5 +++-- source/frontend/StarVoice.hpp | 2 +- source/game/StarWorldClient.cpp | 5 ++++- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/source/application/StarMainApplication_sdl.cpp b/source/application/StarMainApplication_sdl.cpp index 1685cc0..8b8c702 100644 --- a/source/application/StarMainApplication_sdl.cpp +++ b/source/application/StarMainApplication_sdl.cpp @@ -345,7 +345,10 @@ public: m_sdlAudioInputDevice = SDL_OpenAudioDevice(name, 1, &desired, &obtained, 0); if (m_sdlAudioInputDevice) { - Logger::info("Opened audio input device '{}'", SDL_GetAudioDeviceName(m_sdlAudioInputDevice, 1)); + if (name) + Logger::info("Opened audio input device '{}'", name); + else + Logger::info("Opened default audio input device"); SDL_PauseAudioDevice(m_sdlAudioInputDevice, 0); } else @@ -356,7 +359,7 @@ public: bool closeAudioInputDevice() { if (m_sdlAudioInputDevice) { - Logger::info("Closing audio input device '{}'", SDL_GetAudioDeviceName(m_sdlAudioInputDevice, 1)); + Logger::info("Closing audio input device"); SDL_CloseAudioDevice(m_sdlAudioInputDevice); m_sdlAudioInputDevice = 0; return true; diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp index 8dfd110..f7ab21b 100644 --- a/source/client/StarClientApplication.cpp +++ b/source/client/StarClientApplication.cpp @@ -16,7 +16,7 @@ #include "StarRootLoader.hpp" #include "StarInput.hpp" #include "StarVoice.hpp" - +#include "StarCurve25519.hpp" #include "StarInterfaceLuaBindings.hpp" #include "StarInputLuaBindings.hpp" @@ -855,9 +855,8 @@ void ClientApplication::updateRunning() { m_voice->setInput(m_input->bindHeld("opensb", "pushToTalk")); DataStreamBuffer voiceData; voiceData.setByteOrder(ByteOrder::LittleEndian); - voiceData.writeBytes(VoiceBroadcastPrefix.utf8Bytes()); + //voiceData.writeBytes(VoiceBroadcastPrefix.utf8Bytes()); transmitting with SE compat for now bool needstoSendVoice = m_voice->send(voiceData, 5000); - m_universeClient->update(); if (checkDisconnection()) @@ -881,8 +880,13 @@ void ClientApplication::updateRunning() { } if (worldClient->inWorld()) { - if (needstoSendVoice) - worldClient->sendSecretBroadcast(StringView(voiceData.ptr(), voiceData.size())); + if (needstoSendVoice) { + auto signature = Curve25519::sign(voiceData.ptr(), voiceData.size()); + std::string_view signatureView((char*)signature.data(), signature.size()); + std::string_view audioDataView(voiceData.ptr(), voiceData.size()); + auto broadcast = strf("data\0voice\0{}{}"s, signatureView, audioDataView); + worldClient->sendSecretBroadcast(broadcast, true); + } m_voice->setLocalSpeaker(worldClient->connection()); } worldClient->setInteractiveHighlightMode(isActionTaken(InterfaceAction::ShowLabels)); diff --git a/source/frontend/StarVoice.cpp b/source/frontend/StarVoice.cpp index 4c0f4be..c6ec1d0 100644 --- a/source/frontend/StarVoice.cpp +++ b/source/frontend/StarVoice.cpp @@ -269,7 +269,6 @@ void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) { speaker->decibelLevel = getAudioLoudness(speakerBuffer.data(), samples); auto channelVolumes = speaker->channelVolumes.load(); - for (size_t i = 0; i != samples; ++i) sharedBuffer[i] += (int32_t)(speakerBuffer[i]) * channelVolumes[i % 2]; } @@ -366,6 +365,8 @@ bool Voice::receive(SpeakerPtr speaker, std::string_view view) { uint32_t opusLength = 0; while (!reader.atEnd()) { reader >> opusLength; + if (reader.pos() + opusLength > reader.size()) + throw VoiceException("Opus packet length goes past end of buffer"s, false); auto opusData = (unsigned char*)reader.ptr() + reader.pos(); reader.seek(opusLength, IOSeek::Relative); @@ -536,7 +537,7 @@ void Voice::thread() { { MutexLocker lock(m_encodeMutex); - m_encodedChunks.emplace_back(move(encoded)); // reset takes ownership of data buffer + m_encodedChunks.emplace_back(move(encoded)); m_encodedChunksLength += encodedSize; encoded = ByteArray(VOICE_MAX_PACKET_SIZE, 0); diff --git a/source/frontend/StarVoice.hpp b/source/frontend/StarVoice.hpp index 3b95235..38964b0 100644 --- a/source/frontend/StarVoice.hpp +++ b/source/frontend/StarVoice.hpp @@ -171,7 +171,7 @@ private: int64_t m_lastThresholdTime = 0; int64_t m_nextSaveTime = 0; bool m_enabled = true; - bool m_inputEnabled = true; + bool m_inputEnabled = false; int m_deviceChannels = 1; bool m_deviceOpen = false; diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index 54d4651..091d66e 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -966,7 +966,10 @@ void WorldClient::update() { // Secret broadcasts are transmitted through DamageNotifications for vanilla server compatibility. // Because DamageNotification packets are spoofable, we have to sign the data so other clients can validate that it is legitimate. auto& publicKey = Curve25519::publicKey(); - m_mainPlayer->setSecretProperty(SECRET_BROADCAST_PUBLIC_KEY, String((const char*)publicKey.data(), publicKey.size())); + String publicKeyString((const char*)publicKey.data(), publicKey.size()); + m_mainPlayer->setSecretProperty(SECRET_BROADCAST_PUBLIC_KEY, publicKeyString); + // Temporary: Backwards compatibility with StarExtensions + m_mainPlayer->effectsAnimator()->setGlobalTag("\0SE_VOICE_SIGNING_KEY"s, publicKeyString); ++m_currentStep; //m_interpolationTracker.update(m_currentStep);