implement Milestone 13: audio output with volume limits and concurrent sound management
This commit is contained in:
@@ -26,6 +26,7 @@ add_library(mosis-sandbox STATIC
|
||||
../src/main/cpp/sandbox/websocket_manager.cpp
|
||||
../src/main/cpp/sandbox/camera_interface.cpp
|
||||
../src/main/cpp/sandbox/microphone_interface.cpp
|
||||
../src/main/cpp/sandbox/audio_output.cpp
|
||||
)
|
||||
target_include_directories(mosis-sandbox PUBLIC
|
||||
../src/main/cpp/sandbox
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "websocket_manager.h"
|
||||
#include "camera_interface.h"
|
||||
#include "microphone_interface.h"
|
||||
#include "audio_output.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
@@ -2175,6 +2176,153 @@ bool Test_MicrophoneLuaIntegration(std::string& error_msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// MILESTONE 13: Audio Output
|
||||
//=============================================================================
|
||||
|
||||
bool Test_AudioPlaysSound(std::string& error_msg) {
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
|
||||
mosis::AudioData data;
|
||||
data.sample_rate = 44100;
|
||||
data.channels = 1;
|
||||
data.bits_per_sample = 16;
|
||||
data.data = std::vector<uint8_t>(1000); // Dummy data
|
||||
|
||||
mosis::PlaybackConfig config;
|
||||
std::string err;
|
||||
auto player = audio.Play(data, config, err);
|
||||
|
||||
EXPECT_TRUE(player != nullptr);
|
||||
EXPECT_TRUE(player->GetState() == mosis::AudioState::Playing);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_AudioRespectsSystemVolume(std::string& error_msg) {
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
audio.SetSystemVolume(0.5f);
|
||||
|
||||
mosis::AudioData data;
|
||||
data.data = std::vector<uint8_t>(1000);
|
||||
|
||||
mosis::PlaybackConfig config;
|
||||
config.volume = 1.0f; // App requests full volume
|
||||
|
||||
std::string err;
|
||||
auto player = audio.Play(data, config, err);
|
||||
|
||||
// Player is created with requested volume
|
||||
EXPECT_TRUE(player != nullptr);
|
||||
EXPECT_TRUE(player->GetVolume() == 1.0f);
|
||||
|
||||
// But effective volume is capped by system
|
||||
// (In real implementation, audio subsystem applies this)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_AudioLimitsConcurrent(std::string& error_msg) {
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
|
||||
mosis::AudioData data;
|
||||
data.data = std::vector<uint8_t>(1000);
|
||||
mosis::PlaybackConfig config;
|
||||
|
||||
// Create MAX_CONCURRENT_SOUNDS players
|
||||
std::vector<std::shared_ptr<mosis::SoundPlayer>> players;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
std::string err;
|
||||
auto player = audio.Play(data, config, err);
|
||||
EXPECT_TRUE(player != nullptr);
|
||||
players.push_back(player);
|
||||
}
|
||||
|
||||
// 11th should fail
|
||||
std::string err;
|
||||
auto extra = audio.Play(data, config, err);
|
||||
EXPECT_TRUE(extra == nullptr);
|
||||
EXPECT_TRUE(err.find("limit") != std::string::npos ||
|
||||
err.find("concurrent") != std::string::npos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_AudioStopAll(std::string& error_msg) {
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
|
||||
mosis::AudioData data;
|
||||
data.data = std::vector<uint8_t>(1000);
|
||||
mosis::PlaybackConfig config;
|
||||
|
||||
std::string err;
|
||||
auto player1 = audio.Play(data, config, err);
|
||||
auto player2 = audio.Play(data, config, err);
|
||||
|
||||
EXPECT_TRUE(audio.GetActivePlayerCount() == 2);
|
||||
|
||||
audio.StopAll();
|
||||
|
||||
EXPECT_TRUE(audio.GetActivePlayerCount() == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_AudioStopsOnShutdown(std::string& error_msg) {
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
|
||||
mosis::AudioData data;
|
||||
data.data = std::vector<uint8_t>(1000);
|
||||
mosis::PlaybackConfig config;
|
||||
|
||||
std::string err;
|
||||
auto player = audio.Play(data, config, err);
|
||||
EXPECT_TRUE(player != nullptr);
|
||||
|
||||
// Simulate app stop
|
||||
audio.Shutdown();
|
||||
|
||||
EXPECT_TRUE(audio.GetActivePlayerCount() == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_AudioLuaIntegration(std::string& error_msg) {
|
||||
SandboxContext ctx = TestContext();
|
||||
LuaSandbox sandbox(ctx);
|
||||
|
||||
mosis::AudioOutputInterface audio("test.app");
|
||||
mosis::RegisterAudioAPI(sandbox.GetState(), &audio);
|
||||
|
||||
std::string script = R"lua(
|
||||
-- Test that audio global exists
|
||||
if not audio then
|
||||
error("audio global not found")
|
||||
end
|
||||
if not audio.play then
|
||||
error("audio.play not found")
|
||||
end
|
||||
if not audio.stopAll then
|
||||
error("audio.stopAll not found")
|
||||
end
|
||||
if not audio.getActiveCount then
|
||||
error("audio.getActiveCount not found")
|
||||
end
|
||||
|
||||
-- Active count should be 0 initially
|
||||
if audio.getActiveCount() ~= 0 then
|
||||
error("should have no active sounds initially")
|
||||
end
|
||||
)lua";
|
||||
|
||||
bool ok = sandbox.LoadString(script, "audio_test");
|
||||
if (!ok) {
|
||||
error_msg = "Lua test failed: " + sandbox.GetLastError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// MAIN
|
||||
//=============================================================================
|
||||
@@ -2332,6 +2480,14 @@ int main(int argc, char* argv[]) {
|
||||
harness.AddTest("MicrophoneStopsOnShutdown", Test_MicrophoneStopsOnShutdown);
|
||||
harness.AddTest("MicrophoneLuaIntegration", Test_MicrophoneLuaIntegration);
|
||||
|
||||
// Milestone 13: Audio Output
|
||||
harness.AddTest("AudioPlaysSound", Test_AudioPlaysSound);
|
||||
harness.AddTest("AudioRespectsSystemVolume", Test_AudioRespectsSystemVolume);
|
||||
harness.AddTest("AudioLimitsConcurrent", Test_AudioLimitsConcurrent);
|
||||
harness.AddTest("AudioStopAll", Test_AudioStopAll);
|
||||
harness.AddTest("AudioStopsOnShutdown", Test_AudioStopsOnShutdown);
|
||||
harness.AddTest("AudioLuaIntegration", Test_AudioLuaIntegration);
|
||||
|
||||
// Run tests
|
||||
auto results = harness.Run(filter);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user