MCPcopy Create free account
hub / github.com/RunanywhereAI/RCLI / rcli_speak_streaming

Function rcli_speak_streaming

src/api/rcli_api.cpp:1491–1608  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1489// =============================================================================
1490
1491int rcli_speak_streaming(RCLIHandle handle, const char* text,
1492 RCLIEventCallback callback, void* user_data) {
1493 if (!handle || !text) return -1;
1494 auto* engine = static_cast<RCLIEngine*>(handle);
1495 if (!engine->initialized) return -1;
1496
1497 std::lock_guard<std::mutex> lock(engine->mutex);
1498 engine->streaming_cancelled.store(false, std::memory_order_release);
1499
1500 auto t_start = std::chrono::steady_clock::now();
1501
1502 auto* rb = engine->pipeline.playback_ring_buffer();
1503 if (!rb) return rcli_speak(handle, text); // fallback to afplay
1504
1505 // Ensure CoreAudio playback is running
1506 if (!engine->pipeline.audio().is_running()) {
1507 engine->pipeline.audio().start();
1508 }
1509 rb->clear();
1510
1511 // Split text into sentences and stream through TTS
1512 std::mutex tts_queue_mutex;
1513 std::condition_variable tts_queue_cv;
1514 std::vector<std::string> tts_queue;
1515 bool feeding_done = false;
1516 bool first_audio_fired = false;
1517 double total_tts_ms = 0;
1518 int sentence_count = 0;
1519
1520 // TTS worker thread
1521 std::thread tts_worker([&]() {
1522 pthread_setname_np("rcli.tts.speak");
1523 while (true) {
1524 std::string sentence;
1525 {
1526 std::unique_lock<std::mutex> lk(tts_queue_mutex);
1527 tts_queue_cv.wait(lk, [&]() {
1528 return !tts_queue.empty() || feeding_done;
1529 });
1530 if (tts_queue.empty() && feeding_done) break;
1531 if (tts_queue.empty()) continue;
1532 sentence = std::move(tts_queue.front());
1533 tts_queue.erase(tts_queue.begin());
1534 }
1535
1536 if (engine->streaming_cancelled.load(std::memory_order_acquire)) break;
1537
1538 std::vector<float> samples;
1539 if (engine->pipeline.using_metalrt_tts()) {
1540 samples = engine->pipeline.metalrt_tts().synthesize(sentence);
1541 total_tts_ms += engine->pipeline.metalrt_tts().last_synthesis_ms();
1542 } else {
1543 samples = engine->pipeline.tts().synthesize(sentence);
1544 }
1545 // Write with backpressure
1546 size_t offset = 0;
1547 while (offset < samples.size() &&
1548 !engine->streaming_cancelled.load(std::memory_order_acquire)) {

Callers 3

stop_recordingMethod · 0.85
run_screen_vlmMethod · 0.85
process_inputMethod · 0.85

Calls 15

rcli_speakFunction · 0.85
sanitize_for_ttsFunction · 0.85
playback_ring_bufferMethod · 0.80
is_runningMethod · 0.80
clearMethod · 0.80
emptyMethod · 0.80
using_metalrt_ttsMethod · 0.80
last_synthesis_msMethod · 0.80
writeMethod · 0.80
feedMethod · 0.80
available_readMethod · 0.80
startMethod · 0.45

Tested by

no test coverage detected