Ajout sample CPP

This commit is contained in:
2026-02-21 20:48:10 +01:00
parent d8957625f8
commit f23acc8c1c
15 changed files with 985 additions and 4 deletions

View File

@@ -0,0 +1,23 @@
#pragma once
#include <functional>
#include <vector>
class AudioInterface {
public:
using AudioCallback = std::function<void(const std::vector<char>&)>;
virtual ~AudioInterface() = default;
// Starts the audio interface. The callback will be invoked with raw 16-bit PCM mono samples at 16kHz.
virtual void start(AudioCallback inputCallback) = 0;
// Stops audio I/O and releases underlying resources.
virtual void stop() = 0;
// Play audio to the user; audio is 16-bit PCM mono 16kHz.
virtual void output(const std::vector<char>& audio) = 0;
// Immediately stop any buffered / ongoing output.
virtual void interrupt() = 0;
};

View File

@@ -0,0 +1,72 @@
#pragma once
#include "AudioInterface.hpp"
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <nlohmann/json.hpp>
#include <thread>
#include <atomic>
#include <functional>
class Conversation {
public:
using CallbackAgentResponse = std::function<void(const std::string&)>;
using CallbackAgentResponseCorrection = std::function<void(const std::string&, const std::string&)>;
using CallbackUserTranscript = std::function<void(const std::string&)>;
using CallbackLatencyMeasurement = std::function<void(int)>;
Conversation(
const std::string& agentId,
bool requiresAuth,
std::shared_ptr<AudioInterface> audioInterface,
CallbackAgentResponse callbackAgentResponse = nullptr,
CallbackAgentResponseCorrection callbackAgentResponseCorrection = nullptr,
CallbackUserTranscript callbackUserTranscript = nullptr,
CallbackLatencyMeasurement callbackLatencyMeasurement = nullptr
);
~Conversation();
void startSession();
void endSession();
std::string waitForSessionEnd();
void sendUserMessage(const std::string& text);
void registerUserActivity();
void sendContextualUpdate(const std::string& content);
private:
void run();
void handleMessage(const nlohmann::json& message);
std::string getWssUrl() const;
// networking members
boost::asio::io_context ioc_;
boost::asio::ssl::context sslCtx_{boost::asio::ssl::context::tlsv12_client};
using tcp = boost::asio::ip::tcp;
using websocket_t = boost::beast::websocket::stream<
boost::beast::ssl_stream<tcp::socket>>;
std::unique_ptr<websocket_t> ws_;
// general state
std::string agentId_;
bool requiresAuth_;
std::shared_ptr<AudioInterface> audioInterface_;
CallbackAgentResponse callbackAgentResponse_;
CallbackAgentResponseCorrection callbackAgentResponseCorrection_;
CallbackUserTranscript callbackUserTranscript_;
CallbackLatencyMeasurement callbackLatencyMeasurement_;
std::thread workerThread_;
std::atomic<bool> shouldStop_{false};
std::string conversationId_;
std::atomic<int> lastInterruptId_{0};
};

View File

@@ -0,0 +1,45 @@
#pragma once
#include "AudioInterface.hpp"
#include <portaudio.h>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <atomic>
class DefaultAudioInterface : public AudioInterface {
public:
static constexpr int INPUT_FRAMES_PER_BUFFER = 4000; // 250ms @ 16kHz
static constexpr int OUTPUT_FRAMES_PER_BUFFER = 1000; // 62.5ms @ 16kHz
DefaultAudioInterface();
~DefaultAudioInterface() override;
void start(AudioCallback inputCallback) override;
void stop() override;
void output(const std::vector<char>& audio) override;
void interrupt() override;
private:
static int inputCallbackStatic(const void* input, void* output, unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags,
void* userData);
int inputCallbackInternal(const void* input, unsigned long frameCount);
void outputThreadFunc();
PaStream* inputStream_{};
PaStream* outputStream_{};
AudioCallback inputCallback_;
std::queue<std::vector<char>> outputQueue_;
std::mutex queueMutex_;
std::condition_variable queueCv_;
std::thread outputThread_;
std::atomic<bool> shouldStop_{false};
std::atomic<bool> outputPlaying_{false};
};