more Lua voice callbacks
This commit is contained in:
parent
0c1c3611b1
commit
d682b164aa
@ -464,6 +464,8 @@ void ClientApplication::changeState(MainAppState newState) {
|
|||||||
}
|
}
|
||||||
m_cinematicOverlay->stop();
|
m_cinematicOverlay->stop();
|
||||||
|
|
||||||
|
m_voice->clearSpeakers();
|
||||||
|
|
||||||
if (auto p2pNetworkingService = appController()->p2pNetworkingService()) {
|
if (auto p2pNetworkingService = appController()->p2pNetworkingService()) {
|
||||||
p2pNetworkingService->setJoinUnavailable();
|
p2pNetworkingService->setJoinUnavailable();
|
||||||
p2pNetworkingService->setAcceptingP2PConnections(false);
|
p2pNetworkingService->setAcceptingP2PConnections(false);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "StarVoice.hpp"
|
#include "StarVoice.hpp"
|
||||||
#include "StarFormat.hpp"
|
#include "StarFormat.hpp"
|
||||||
|
#include "StarJsonExtra.hpp"
|
||||||
#include "StarApplicationController.hpp"
|
#include "StarApplicationController.hpp"
|
||||||
#include "StarTime.hpp"
|
#include "StarTime.hpp"
|
||||||
#include "StarRoot.hpp"
|
#include "StarRoot.hpp"
|
||||||
@ -103,6 +104,19 @@ Voice::Speaker::Speaker(SpeakerId id)
|
|||||||
audioStream = make_shared<VoiceAudioStream>();
|
audioStream = make_shared<VoiceAudioStream>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json Voice::Speaker::toJson() const {
|
||||||
|
return JsonObject{
|
||||||
|
{"speakerId", speakerId},
|
||||||
|
{"entityId", entityId },
|
||||||
|
{"name", name },
|
||||||
|
{"playing", (bool)playing},
|
||||||
|
{"muted", (bool)muted },
|
||||||
|
{"decibels", (float)decibelLevel},
|
||||||
|
{"smoothDecibels", (float)smoothDb },
|
||||||
|
{"position", jsonFromVec2F(position)}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Voice* Voice::s_singleton;
|
Voice* Voice::s_singleton;
|
||||||
|
|
||||||
Voice* Voice::singletonPtr() {
|
Voice* Voice::singletonPtr() {
|
||||||
@ -258,7 +272,11 @@ Voice::SpeakerPtr Voice::speaker(SpeakerId speakerId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Voice::SpeakerPtr> Voice::speakers(bool onlyPlaying) {
|
HashMap<Voice::SpeakerId, Voice::SpeakerPtr>& Voice::speakers() {
|
||||||
|
return m_speakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Voice::SpeakerPtr> Voice::sortedSpeakers(bool onlyPlaying) {
|
||||||
List<SpeakerPtr> result;
|
List<SpeakerPtr> result;
|
||||||
|
|
||||||
auto sorter = [](SpeakerPtr const& a, SpeakerPtr const& b) -> bool {
|
auto sorter = [](SpeakerPtr const& a, SpeakerPtr const& b) -> bool {
|
||||||
@ -276,6 +294,16 @@ List<Voice::SpeakerPtr> Voice::speakers(bool onlyPlaying) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Voice::clearSpeakers() {
|
||||||
|
auto it = m_speakers.begin();
|
||||||
|
while (it != m_speakers.end()) {
|
||||||
|
if (it->second == m_clientSpeaker)
|
||||||
|
it = ++it;
|
||||||
|
else
|
||||||
|
it = m_speakers.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Voice::readAudioData(uint8_t* stream, int len) {
|
void Voice::readAudioData(uint8_t* stream, int len) {
|
||||||
auto now = Time::monotonicMilliseconds();
|
auto now = Time::monotonicMilliseconds();
|
||||||
bool active = m_encoder && m_encodedChunksLength < 2048
|
bool active = m_encoder && m_encodedChunksLength < 2048
|
||||||
@ -335,7 +363,7 @@ void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) {
|
|||||||
SpeakerPtr const& speaker = *it;
|
SpeakerPtr const& speaker = *it;
|
||||||
VoiceAudioStream* audio = speaker->audioStream.get();
|
VoiceAudioStream* audio = speaker->audioStream.get();
|
||||||
MutexLocker audioLock(audio->mutex);
|
MutexLocker audioLock(audio->mutex);
|
||||||
if (!audio->samples.empty()) {
|
if (speaker->playing && !audio->samples.empty()) {
|
||||||
if (!speaker->muted) {
|
if (!speaker->muted) {
|
||||||
mix = true;
|
mix = true;
|
||||||
for (size_t i = 0; i != samples; ++i)
|
for (size_t i = 0; i != samples; ++i)
|
||||||
@ -343,9 +371,10 @@ void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) {
|
|||||||
|
|
||||||
speaker->decibelLevel = getAudioLoudness(speakerBuffer.data(), samples);
|
speaker->decibelLevel = getAudioLoudness(speakerBuffer.data(), samples);
|
||||||
|
|
||||||
auto levels = speaker->channelVolumes.load();
|
float volume = speaker->volume;
|
||||||
|
Array2F levels = speaker->channelVolumes;
|
||||||
for (size_t i = 0; i != samples; ++i)
|
for (size_t i = 0; i != samples; ++i)
|
||||||
sharedBuffer[i] += (int32_t)(speakerBuffer[i]) * levels[i % 2];
|
sharedBuffer[i] += (int32_t)(speakerBuffer[i]) * levels[i % 2] * volume;
|
||||||
//Blends the weaker channel into the stronger one,
|
//Blends the weaker channel into the stronger one,
|
||||||
/* unused, is a bit too strong on stereo music.
|
/* unused, is a bit too strong on stereo music.
|
||||||
float maxLevel = max(levels[0], levels[1]);
|
float maxLevel = max(levels[0], levels[1]);
|
||||||
@ -606,6 +635,8 @@ void Voice::closeDevice() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_applicationController->closeAudioInputDevice();
|
m_applicationController->closeAudioInputDevice();
|
||||||
|
if (!m_loopback)
|
||||||
|
m_clientSpeaker->playing = false;
|
||||||
|
|
||||||
m_deviceOpen = false;
|
m_deviceOpen = false;
|
||||||
}
|
}
|
||||||
|
@ -88,11 +88,13 @@ public:
|
|||||||
atomic<bool> muted = false;
|
atomic<bool> muted = false;
|
||||||
atomic<bool> playing = 0;
|
atomic<bool> playing = 0;
|
||||||
atomic<float> decibelLevel = -96.0f;
|
atomic<float> decibelLevel = -96.0f;
|
||||||
|
atomic<float> volume = 1.0f;
|
||||||
atomic<Array<float, 2>> channelVolumes = Array<float, 2>::filled(1);
|
atomic<Array<float, 2>> channelVolumes = Array<float, 2>::filled(1);
|
||||||
|
|
||||||
unsigned int minimumPlaySamples = 4096;
|
unsigned int minimumPlaySamples = 4096;
|
||||||
|
|
||||||
Speaker(SpeakerId speakerId);
|
Speaker(SpeakerId speakerId);
|
||||||
|
Json toJson() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Speaker> SpeakerPtr;
|
typedef std::shared_ptr<Speaker> SpeakerPtr;
|
||||||
@ -123,7 +125,9 @@ public:
|
|||||||
SpeakerPtr setLocalSpeaker(SpeakerId speakerId);
|
SpeakerPtr setLocalSpeaker(SpeakerId speakerId);
|
||||||
SpeakerPtr localSpeaker();
|
SpeakerPtr localSpeaker();
|
||||||
SpeakerPtr speaker(SpeakerId speakerId);
|
SpeakerPtr speaker(SpeakerId speakerId);
|
||||||
List<Voice::SpeakerPtr> speakers(bool onlyPlaying);
|
HashMap<SpeakerId, SpeakerPtr>& speakers();
|
||||||
|
List<Voice::SpeakerPtr> sortedSpeakers(bool onlyPlaying);
|
||||||
|
void clearSpeakers();
|
||||||
|
|
||||||
// Called when receiving input audio data from SDL, on its own thread.
|
// Called when receiving input audio data from SDL, on its own thread.
|
||||||
void readAudioData(uint8_t* stream, int len);
|
void readAudioData(uint8_t* stream, int len);
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
|
#include "StarLuaConverters.hpp"
|
||||||
#include "StarVoiceLuaBindings.hpp"
|
#include "StarVoiceLuaBindings.hpp"
|
||||||
#include "StarVoice.hpp"
|
#include "StarVoice.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
|
typedef Voice::SpeakerId SpeakerId;
|
||||||
LuaCallbacks LuaBindings::makeVoiceCallbacks(Voice* voice) {
|
LuaCallbacks LuaBindings::makeVoiceCallbacks(Voice* voice) {
|
||||||
LuaCallbacks callbacks;
|
LuaCallbacks callbacks;
|
||||||
|
|
||||||
|
callbacks.registerCallbackWithSignature<StringList>("devices", bind(&Voice::availableDevices, voice));
|
||||||
callbacks.registerCallback( "getSettings", [voice]() -> Json { return voice->saveJson(); });
|
callbacks.registerCallback( "getSettings", [voice]() -> Json { return voice->saveJson(); });
|
||||||
callbacks.registerCallback("mergeSettings", [voice](Json const& settings) { voice->loadJson(settings); });
|
callbacks.registerCallback("mergeSettings", [voice](Json const& settings) { voice->loadJson(settings); });
|
||||||
|
// i have an alignment addiction i'm so sorry
|
||||||
|
callbacks.registerCallback("setSpeakerMuted", [voice](SpeakerId speakerId, bool muted) { voice->speaker(speakerId)->muted = muted; });
|
||||||
|
callbacks.registerCallback( "speakerMuted", [voice](SpeakerId speakerId) { return (bool)voice->speaker(speakerId)->muted; });
|
||||||
|
// it just looks so neat to me!!
|
||||||
|
callbacks.registerCallback("setSpeakerVolume", [voice](SpeakerId speakerId, float volume) { voice->speaker(speakerId)->volume = volume; });
|
||||||
|
callbacks.registerCallback( "speakerVolume", [voice](SpeakerId speakerId) { return (float)voice->speaker(speakerId)->volume; });
|
||||||
|
|
||||||
|
callbacks.registerCallback("speakerPosition", [voice](SpeakerId speakerId) { return voice->speaker(speakerId)->position; });
|
||||||
|
|
||||||
|
callbacks.registerCallback("speaker", [voice](SpeakerId speakerId) { return voice->speaker(speakerId)->toJson(); });
|
||||||
callbacks.registerCallback("speakers", [voice](Maybe<bool> onlyPlaying) -> List<Json> {
|
callbacks.registerCallback("speakers", [voice](Maybe<bool> onlyPlaying) -> List<Json> {
|
||||||
List<Json> list;
|
List<Json> list;
|
||||||
|
|
||||||
for (auto& speaker : voice->speakers(onlyPlaying.value(true))) {
|
for (auto& speaker : voice->sortedSpeakers(onlyPlaying.value(true)))
|
||||||
list.append(JsonObject{
|
list.append(speaker->toJson());
|
||||||
{"speakerId", speaker->speakerId },
|
|
||||||
{"entityId", speaker->entityId },
|
|
||||||
{"name", speaker->name },
|
|
||||||
{"playing", (bool)speaker->playing },
|
|
||||||
{"muted", (bool)speaker->muted },
|
|
||||||
{"decibels", (float)speaker->decibelLevel },
|
|
||||||
{"smoothDecibels", (float)speaker->smoothDb },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user