diff options
Diffstat (limited to 'source/frontend/StarVoice.hpp')
-rw-r--r-- | source/frontend/StarVoice.hpp | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/source/frontend/StarVoice.hpp b/source/frontend/StarVoice.hpp index 269adb4..e7ecd80 100644 --- a/source/frontend/StarVoice.hpp +++ b/source/frontend/StarVoice.hpp @@ -6,8 +6,11 @@ #include "StarGameTypes.hpp" #include "StarMaybe.hpp" #include "StarThread.hpp" +#include "StarDataStreamDevices.hpp" #include "StarApplicationController.hpp" +#include <queue> + struct OpusDecoder; typedef std::unique_ptr<OpusDecoder, void(*)(OpusDecoder*)> OpusDecoderPtr; struct OpusEncoder; @@ -27,6 +30,36 @@ STAR_CLASS(Voice); STAR_CLASS(VoiceAudioStream); STAR_CLASS(ApplicationController); +struct VoiceAudioChunk { + std::unique_ptr<int16_t[]> data; + size_t remaining; + size_t offset = 0; + + VoiceAudioChunk(int16_t* ptr, size_t size) { + data.reset(ptr); + remaining = size; + offset = 0; + } + + inline size_t takeSamples(std::vector<int16_t>& out, size_t count) { + size_t toRead = std::min<size_t>(count, remaining); + int16_t* start = data.get() + offset; + out.insert(out.end(), start, start + toRead); + offset += toRead; + remaining -= toRead; + return toRead; + } + + //this one's unsafe + inline int16_t takeSample() { + --remaining; + return *(data.get() + offset++); + } + + inline bool exhausted() { return remaining == 0; } +}; + + class Voice { public: // Individual speakers are represented by their connection ID. @@ -45,6 +78,13 @@ public: VoiceAudioStreamPtr audioStream; Mutex mutex; + atomic<bool> muted = false; + atomic<bool> playing = false; + atomic<float> decibelLevel = 0.0f; + atomic<Array<float, 2>> channelVolumes = Array<float, 2>::filled(1.0f); + + unsigned int minimumPlaySamples = 4096; + Speaker(SpeakerId speakerId); }; @@ -77,7 +117,7 @@ public: SpeakerPtr speaker(SpeakerId speakerId); // Called when receiving input audio data from SDL, on its own thread. - void getAudioData(uint8_t* stream, int len); + void readAudioData(uint8_t* stream, int len); // Called to mix voice audio with the game. void mix(int16_t* buffer, size_t frames, unsigned channels); @@ -87,6 +127,12 @@ public: void setDeviceName(Maybe<String> device); + int send(DataStreamBuffer& out, size_t budget); + bool receive(SpeakerPtr speaker, std::string_view view); + + // Must be called every frame with input state, expires after 1s. + void setInput(bool input = true); + inline int encoderChannels() const { return m_channelMode == VoiceChannelMode::Mono ? 1 : 2; } @@ -99,10 +145,13 @@ private: void openDevice(); void closeDevice(); + bool playSpeaker(SpeakerPtr const& speaker, int channels); + SpeakerId m_speakerId = 0; SpeakerPtr m_clientSpeaker; HashMap<SpeakerId, SpeakerPtr> m_speakers; + Mutex m_activeSpeakersMutex; HashSet<SpeakerPtr> m_activeSpeakers; OpusEncoderPtr m_encoder; @@ -110,10 +159,15 @@ private: float m_outputVolume = 1.0f; float m_inputVolume = 1.0f; float m_threshold = -50.0f; - + + int64_t m_lastSentTime = 0; + int64_t m_lastInputTime = 0; + int64_t m_lastThresholdTime = 0; + int64_t m_nextSaveTime = 0; bool m_enabled = true; bool m_inputEnabled = true; + int m_deviceChannels = 1; bool m_deviceOpen = false; Maybe<String> m_deviceName; VoiceInputMode m_inputMode; @@ -121,7 +175,23 @@ private: ApplicationControllerPtr m_applicationController; - double nextSaveTime = 0.0f; + struct EncodedChunk { + std::unique_ptr<unsigned char[]> data; + size_t size; + + EncodedChunk(unsigned char* _data, size_t len) { + data.reset(_data); + size = len; + } + }; + + std::vector<ByteArray> m_encodedChunks; + size_t m_encodedChunksLength = 0; + + std::queue<VoiceAudioChunk> m_capturedChunks; + size_t m_capturedChunksFrames = 0; + + Mutex m_captureMutex; }; } |