diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-07-18 17:36:51 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-07-18 17:36:51 +1000 |
commit | 6e1d29fe861ef5a81c5458cd8ae68d09f36e28c3 (patch) | |
tree | 36fb8a412649f1e749e2b9fc0268e80bc05251fb /source/frontend/StarVoice.cpp | |
parent | 34bb0b54222c1c0f3450c56e76f89f192d77374b (diff) |
Provide speaker info to HUD indicators
Diffstat (limited to 'source/frontend/StarVoice.cpp')
-rw-r--r-- | source/frontend/StarVoice.cpp | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/source/frontend/StarVoice.cpp b/source/frontend/StarVoice.cpp index c6ec1d0..9d84033 100644 --- a/source/frontend/StarVoice.cpp +++ b/source/frontend/StarVoice.cpp @@ -28,13 +28,13 @@ EnumMap<VoiceChannelMode> const VoiceChannelModeNames{ {VoiceChannelMode::Stereo, "Stereo"} }; -float getAudioChunkLoudness(int16_t* data, size_t samples) { +inline float getAudioChunkLoudness(int16_t* data, size_t samples, float volume) { if (!samples) return 0.f; double rms = 0.; for (size_t i = 0; i != samples; ++i) { - float sample = (float)data[i] / 32767.f; + float sample = ((float)data[i] / 32767.f) * volume; rms += (double)(sample * sample); } @@ -46,12 +46,12 @@ float getAudioChunkLoudness(int16_t* data, size_t samples) { return -127.f; } -float getAudioLoudness(int16_t* data, size_t samples) { +float getAudioLoudness(int16_t* data, size_t samples, float volume = 1.0f) { constexpr size_t CHUNK_SIZE = 50; float highest = -127.f; for (size_t i = 0; i < samples; i += CHUNK_SIZE) { - float level = getAudioChunkLoudness(data + i, std::min<size_t>(i + CHUNK_SIZE, samples) - i); + float level = getAudioChunkLoudness(data + i, std::min<size_t>(i + CHUNK_SIZE, samples) - i, volume); if (level > highest) highest = level; } @@ -192,6 +192,10 @@ Voice::SpeakerPtr Voice::setLocalSpeaker(SpeakerId speakerId) { return m_speakers.insert(m_speakerId, m_clientSpeaker).first->second; } +Voice::SpeakerPtr Voice::localSpeaker() { + return m_clientSpeaker; +} + Voice::SpeakerPtr Voice::speaker(SpeakerId speakerId) { if (m_speakerId == speakerId) return m_clientSpeaker; @@ -203,28 +207,47 @@ Voice::SpeakerPtr Voice::speaker(SpeakerId speakerId) { } } +List<Voice::SpeakerPtr> Voice::speakers(bool onlyPlaying) { + List<SpeakerPtr> result; + + auto sorter = [](SpeakerPtr const& a, SpeakerPtr const& b) -> bool { + if (a->lastPlayTime != b->lastPlayTime) + return a->lastPlayTime < b->lastPlayTime; + else + return a->speakerId < b->speakerId; + }; + + for (auto& p : m_speakers) { + if (!onlyPlaying || p.second->playing) + result.insertSorted(p.second, sorter); + } + + return result; +} + void Voice::readAudioData(uint8_t* stream, int len) { auto now = Time::monotonicMilliseconds(); - if (!m_encoder || m_inputMode == VoiceInputMode::PushToTalk && now > m_lastInputTime) - return; - - // Stop encoding if 2048 bytes have been encoded and not taken by the game thread yet - if (m_encodedChunksLength > 2048) - return; + bool active = m_encoder && m_encodedChunksLength < 2048 + && (m_inputMode == VoiceInputMode::VoiceActivity || now < m_lastInputTime); size_t sampleCount = len / 2; - float decibels = getAudioLoudness((int16_t*)stream, sampleCount); - m_clientSpeaker->decibelLevel = decibels; - bool active = true; + if (active) { + float volume = m_inputVolume; + float decibels = getAudioLoudness((int16_t*)stream, sampleCount); - if (m_inputMode == VoiceInputMode::VoiceActivity) { - if (decibels > m_threshold) - m_lastThresholdTime = now; - active = now - m_lastThresholdTime < 50; + if (m_inputMode == VoiceInputMode::VoiceActivity) { + if (decibels > m_threshold) + m_lastThresholdTime = now; + active = now - m_lastThresholdTime < 50; + } } - bool added = false; + if (active && !m_clientSpeaker->playing) + m_clientSpeaker->lastPlayTime = now; + + if (!(m_clientSpeaker->playing = active)) + return; MutexLocker captureLock(m_captureMutex); if (active) { @@ -232,7 +255,7 @@ void Voice::readAudioData(uint8_t* stream, int len) { auto data = (opus_int16*)malloc(len); memcpy(data, stream, len); m_capturedChunks.emplace(data, sampleCount); // takes ownership - added = true; + m_threadCond.signal(); } else { // Clear out any residual data so they don't manifest at the start of the next encode, whenever that is while (!m_capturedChunks.empty()) @@ -240,9 +263,6 @@ void Voice::readAudioData(uint8_t* stream, int len) { m_capturedChunksFrames = 0; } - - if (added) - m_threadCond.signal(); } void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) { @@ -493,9 +513,12 @@ bool Voice::playSpeaker(SpeakerPtr const& speaker, int channels) { if (speaker->playing || speaker->audioStream->samples.size() < minSamples) return false; - speaker->playing = true; - MutexLocker lock(m_activeSpeakersMutex); - m_activeSpeakers.insert(speaker); + if (!speaker->playing) { + speaker->lastPlayTime = Time::monotonicMilliseconds(); + speaker->playing = true; + MutexLocker lock(m_activeSpeakersMutex); + m_activeSpeakers.insert(speaker); + } return true; } @@ -529,6 +552,8 @@ void Voice::thread() { samples[i] *= m_inputVolume; } + m_clientSpeaker->decibelLevel = getAudioLoudness(samples.data(), samples.size()); + if (int encodedSize = opus_encode(m_encoder.get(), samples.data(), VOICE_FRAME_SIZE, (unsigned char*)encoded.ptr(), encoded.size())) { if (encodedSize == 1) continue; |