SOUND4 x1.CLOUD Library [1.2.6]
sound4.x1.cloud.hpp
Go to the documentation of this file.
1 
4 #pragma once
5 
6 #include <string>
7 #include <exception>
8 #include <thread>
9 #include <functional>
10 #include <memory>
11 #include <array>
12 #include <assert.h>
13 #include <stdexcept>
14 
15 #ifdef __unix__
16 
17 #elif defined(_WIN32) || defined(WIN32)
18  #include <stringapiset.h>
19 #endif
20 
21 #include "sound4.x1.cloud.h"
22 
26 namespace sound4 {
30 namespace cloudx1 {
31  static constexpr const char *process_name = "SOUND4 x1.CLOUD";
32  static constexpr const char *process_shortname = "x1";
57 
61  namespace helper {
62  #ifdef _WIN32
68  static inline std::string WStringToUTF8(const std::wstring& wstr) {
69  if (wstr.empty()) return {};
70  int size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
71  std::string str(size, 0);
72  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size, NULL, NULL);
73  return str;
74  }
80  static inline std::wstring UTF8ToWString(const std::string& str) {
81  if (str.empty()) return std::wstring();
82  int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
83  std::wstring wstr(size, 0);
84  MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstr[0], size);
85  return wstr;
86  }
87  #endif // _WIN32
88 
94  template<typename T>
95  struct SampleFormat {
96  };
97  template<>
98  struct SampleFormat<int16_t> {
100  };
101  template<>
102  struct SampleFormat<int32_t> {
104  };
105  template<>
106  struct SampleFormat<float> {
108  };
109 
110  }; // namespace helper
111 
117  static inline std::string GetVersion()
118  {
119  return std::string(cloudx1_GetVersion());
120  }
121 
132  static inline uint GetChunkSizeInFrames()
133  {
135  }
136 
144  static inline uint GetChannelCount()
145  {
146  return cloudx1_GetChannelCount();
147  }
148 
157  static inline uint GetAudioInputCount()
158  {
160  }
161 
170  static inline uint GetAudioOutputCount()
171  {
173  }
174 
182  static inline uint GetSampleRate()
183  {
184  return cloudx1_GetSampleRate();
185  }
186 
192  static inline void SanityCheck()
193  {
194  // Do some sanity checks
196  throw std::runtime_error("Bad library sampling rate");
197  }
199  throw std::runtime_error("Bad library frame size");
200  }
202  throw std::runtime_error("Bad library channel count");
203  }
205  throw std::runtime_error("Bad library input count");
206  }
208  throw std::runtime_error("Bad library output count");
209  }
210  }
211 
219  using log_cb_t = std::function<void(LogSeverity,const std::string&)>;
220 
224  static log_cb_t _log_cb;
225  extern "C" {
226  static inline void _log_cb_c(cloudx1_LogSeverity severity, const char *c_msg) {
227  _log_cb(severity, std::string(c_msg));
228  }
229  }
233  static inline void SetLogSeverity(LogSeverity severity)
234  {
235  cloudx1_SetLogSeverity(severity);
236  }
240  static inline void SetLoggerCallback(log_cb_t cb)
241  {
242  _log_cb=cb;
243  cloudx1_SetLoggerCallback(&_log_cb_c);
244  }
245 
249  class CInstance {
250  public:
255  {
256  SanityCheck();
257  params = cloudx1_NewParameters();
258  if (!params) throw std::bad_alloc();
259  }
260  // non-copyable
261  CInstance( const CInstance& ) = delete;
262  CInstance& operator=( const CInstance& ) = delete;
267  {
268  Stop();
269  if (params) cloudx1_FreeParameters(params);
270  }
274  bool IsOk() const { return instance!=nullptr; }
280  void SetParam(const std::string& name, const std::string& value)
281  {
282  assert(params);
283  cloudx1_SetParameter(params, name.c_str(), value.c_str());
284  }
290  std::string GetParam(const std::string& name)
291  {
292  assert(params);
293  auto c_value=cloudx1_GetParameter(params, name.c_str());
294  std::string ret(c_value);
296  return ret;
297  }
311  bool Create(const std::string& LoginKey, const std::string& RadioName, const std::string& AWS_Access_ID, const std::string& AWS_Access_Secret, const std::string& save_path, int json_port = 0)
312  {
313  assert(!instance);
314  const char *pSavePath = save_path.empty() ? NULL : save_path.c_str(); // allow no storage
315  instance = cloudx1_InitProcess2(LoginKey.c_str(), RadioName.c_str(), AWS_Access_ID.c_str(), AWS_Access_Secret.c_str(), pSavePath, params);
316  if (!instance) return false;
317  update_thread = std::thread([this, json_port](){
318  cloudx1_StartUpdateThread(instance, json_port);
319  });
320  if (cloudx1_WaitUpdateThreadReady(instance, 5000)<0) {
321  return false;
322  }
323  return true;
324  }
330  bool StartWebServer(int http_port, int https_port=0)
331  {
332  assert(instance);
333  assert(webserver==SOUND4_INVALID_WEBSERVER_ID);
334  webserver = cloudx1_Webserver(http_port,https_port,instance);
335  if (webserver==SOUND4_INVALID_WEBSERVER_ID) {
336  return false;
337  }
338  int web_status=cloudx1_Webserver_Status(webserver);
339  if (http_port && (web_status & SOUND4_WEBSERVER_HTTP_OK) == 0) {
340  return false;
341  }
342  if (https_port && (web_status & SOUND4_WEBSERVER_HTTPS_OK) == 0) {
343  return false;
344  }
345  return true;
346  }
353  {
354  if (webserver != SOUND4_INVALID_WEBSERVER_ID) {
355  cloudx1_Webserver_Stop(webserver, 1000);
356  webserver = SOUND4_INVALID_WEBSERVER_ID;
357  }
358  }
364  void Stop()
365  {
366  if (!instance) return;
367  StopWebServer();
368  if (update_thread.joinable()) {
369  cloudx1_StopUpdateThread(instance); // this will exit the update thread
370  update_thread.join();
371  }
372  cloudx1_ExitProcess(instance);
373  instance=nullptr;
374  }
375 
382  {
383  assert(instance);
384  return cloudx1_GetEstimatedDelay(instance);
385  }
386 
397  std::array<float,InputSampleSize>& GetBufferIn()
398  {
399  assert(instance);
400  float *buf=cloudx1_GetBufferIn(instance);
401  return reinterpret_cast< std::array<float,InputSampleSize>& >(*buf);
402 
403  }
414  std::array<float,OutputSampleSize>& GetBufferOut()
415  {
416  assert(instance);
417  float *buf= cloudx1_GetBufferOut(instance);
418  return reinterpret_cast< std::array<float,OutputSampleSize>& >(*buf);
419  }
426  {
427  assert(instance);
428  cloudx1_ProcessAudio(instance, cloudx1_GetBufferIn(instance), cloudx1_GetBufferOut(instance));
429  }
443  // void ProcessAudio_Planar(const std::array< const std::array<const float,ChunkFrames>, InputChannels>& input, std::array< std::array<float,ChunkFrames>, OutputChannels>& output)
444  void ProcessAudio_Planar(float const * const (&input)[InputChannels], float * const (&output)[OutputChannels])
445  {
446  assert(instance);
447  cloudx1_ProcessAudio_Planar(instance, input, output);
448  }
449 
461  template<typename T>
462  std::vector<T> ProcessAnyAudio(const std::vector<T> input)
463  {
464  assert(instance);
465  std::vector<T> output;
466  uint out_offset=0;
467  uint in_offset=0;
468  uint todo = input.size();
469  while (todo>0) {
470  uint left = AddAudio(&input[in_offset], todo);
471  uint out_avail = cloudx1_GetOutputCount(instance);
472  output.resize(out_offset + out_avail);
473  GetAudio(&output[out_offset], out_avail);
474  out_offset+=out_avail;
475  in_offset += todo-left;
476  todo=left;
477  }
478  return output;
479  }
480 
486  class CClient {
487  public:
489  {
490  assert(instance);
491  client=cloudx1_NewClient(instance);
492  if (!client) throw std::bad_alloc();
493  }
494  // non-copyable
495  CClient( const CInstance& ) = delete;
496  CClient& operator=( const CInstance& ) = delete;
498  {
499  if (client) {
500  cloudx1_DeleteClient(client);
501  client=nullptr;
502  }
503  }
511  std::string ProcessJson(const std::string &request, bool *NeedSave = nullptr)
512  {
513  assert(client);
514  int need_save=0;
515  const char *canswer = cloudx1_ProcessJson(client, request.c_str(), &need_save);
516  if (!canswer) return {};
517  std::string answer(canswer);
518  cloudx1_FreeJsonAnswer (canswer);
519  if (NeedSave) {
520  *NeedSave=(need_save!=0);
521  }
522  return answer;
523  }
524  private:
525  cloudx1_CClientInstance *client = nullptr;
526  };
534  std::shared_ptr<CClient> NewClient()
535  {
536  assert(instance);
537  return std::make_shared<CClient>(instance);
538  }
539 
540  protected:
541  template<typename T>
542  uint AddAudio(const T* payload, uint nFrame)
543  {
544  assert(instance);
545  return cloudx1_AddAudio(instance, reinterpret_cast<const T*>(payload), nFrame, helper::SampleFormat<T>::format);
546  }
547  template<typename T>
548  uint GetAudio(T* payload, uint max_nFrame)
549  {
550  assert(instance);
551  return cloudx1_GetAudio(instance, reinterpret_cast<T*>(payload), max_nFrame, helper::SampleFormat<T>::format);
552  }
553 
554  private:
555  cloudx1_CParameters* params = nullptr;
556  cloudx1_CInstance* instance = nullptr;
557  std::thread update_thread;
558  uint64_t webserver = SOUND4_INVALID_WEBSERVER_ID;
559  };
560 
561 }; // namespace cloudx1
562 }; // namespace sound4
std::string ProcessJson(const std::string &request, bool *NeedSave=nullptr)
Process a JSON request and returns the answer.
CClient & operator=(const CInstance &)=delete
CClient(cloudx1_CInstance *instance)
CClient(const CInstance &)=delete
CInstance & operator=(const CInstance &)=delete
std::string GetParam(const std::string &name)
std::shared_ptr< CClient > NewClient()
bool Create(const std::string &LoginKey, const std::string &RadioName, const std::string &AWS_Access_ID, const std::string &AWS_Access_Secret, const std::string &save_path, int json_port=0)
uint GetAudio(T *payload, uint max_nFrame)
void ProcessAudio_Planar(float const *const (&input)[InputChannels], float *const (&output)[OutputChannels])
bool StartWebServer(int http_port, int https_port=0)
std::array< float, OutputSampleSize > & GetBufferOut()
uint AddAudio(const T *payload, uint nFrame)
std::vector< T > ProcessAnyAudio(const std::vector< T > input)
std::array< float, InputSampleSize > & GetBufferIn()
CInstance(const CInstance &)=delete
void SetParam(const std::string &name, const std::string &value)
cloudx1_SampleFormat
uint cloudx1_GetAudio(struct cloudx1_CInstance *instance, uint8_t *payload, uint max_nFrame, enum cloudx1_SampleFormat fmt)
uint cloudx1_GetOutputCount(struct cloudx1_CInstance *instance)
uint cloudx1_AddAudio(struct cloudx1_CInstance *instance, const uint8_t *payload, uint nFrame, enum cloudx1_SampleFormat fmt)
@ F32_NATIVE
32-bit floating-point, native
@ S16_NATIVE
16-bit signed integer, native
@ S32_NATIVE
32-bit signed integer, native
struct cloudx1_CClientInstance * cloudx1_NewClient(struct cloudx1_CInstance *instance)
void cloudx1_DeleteClient(struct cloudx1_CClientInstance *client)
void cloudx1_FreeJsonAnswer(const char *json_str)
const char * cloudx1_ProcessJson(struct cloudx1_CClientInstance *client, const char *json_str, int *need_save)
float * cloudx1_GetBufferIn(struct cloudx1_CInstance *instance)
void cloudx1_ProcessAudio(struct cloudx1_CInstance *instance, const float *input, float *output)
uint cloudx1_GetEstimatedDelay(struct cloudx1_CInstance *instance)
void cloudx1_ProcessAudio_Planar(struct cloudx1_CInstance *instance, float const *const (&input)[CLOUDX1_CHANNEL_COUNT *CLOUDX1_AUDIO_INPUT_COUNT], float *const (&output)[CLOUDX1_CHANNEL_COUNT *CLOUDX1_AUDIO_OUTPUT_COUNT])
float * cloudx1_GetBufferOut(struct cloudx1_CInstance *instance)
uint cloudx1_GetSampleRate()
#define CLOUDX1_AUDIO_INPUT_COUNT
uint cloudx1_GetChunkSizeInFrames()
const char * cloudx1_GetVersion()
uint cloudx1_GetAudioOutputCount()
cloudx1_LogSeverity
uint cloudx1_GetChannelCount()
#define CLOUDX1_AUDIOFRAME_COUNT
uint cloudx1_GetAudioInputCount()
void cloudx1_SetLoggerCallback(cloudx1_loggerfn logger)
#define CLOUDX1_SAMPLE_RATE
#define CLOUDX1_CHANNEL_COUNT
#define CLOUDX1_AUDIO_OUTPUT_COUNT
void cloudx1_SetLogSeverity(enum cloudx1_LogSeverity severity)
void cloudx1_FreeParameterValue(const char *value)
void cloudx1_ExitProcess(struct cloudx1_CInstance *instance)
void cloudx1_FreeParameters(struct cloudx1_CParameters *params)
struct cloudx1_CParameters * cloudx1_NewParameters()
void cloudx1_SetParameter(struct cloudx1_CParameters *params, const char *name, const char *value)
struct cloudx1_CInstance * cloudx1_InitProcess2(const char *LoginKey, const char *RadioName, const char *AWS_Access_ID, const char *AWS_Access_Secret, const char *save_path, const struct cloudx1_CParameters *parameters)
const char * cloudx1_GetParameter(struct cloudx1_CParameters *params, const char *name)
void cloudx1_StartUpdateThread(struct cloudx1_CInstance *instance, uint port)
int cloudx1_WaitUpdateThreadReady(struct cloudx1_CInstance *instance, int milliseconds)
void cloudx1_StopUpdateThread(struct cloudx1_CInstance *instance)
#define SOUND4_WEBSERVER_HTTPS_OK
int cloudx1_Webserver_Status(uint64_t id)
uint64_t cloudx1_Webserver(uint listenport, uint listenport_secure, struct cloudx1_CInstance *instance)
#define SOUND4_WEBSERVER_HTTP_OK
#define SOUND4_INVALID_WEBSERVER_ID
int cloudx1_Webserver_Stop(uint64_t id, int timeout_ms)
const size_t SampleRate
std::function< void(LogSeverity, const std::string &)> log_cb_t
const size_t InputChannels
const size_t OutputSampleSize
cloudx1_LogSeverity LogSeverity
const size_t InputSampleSize
const size_t ChunkFrames
const size_t OutputChannels
C interface for library.
unsigned int uint
Helper for Sample format types.