SOUND4 IMPACT.CL Library [1.0.5]
sound4.impact.cl.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.impact.cl.h"
22 
26 namespace sound4 {
30 namespace impact {
31  static constexpr const char *process_name = "SOUND4 IMPACT.CL";
32  static constexpr const char *process_shortname = "impact";
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(impact_GetVersion());
120  }
121 
132  static inline uint GetChunkSizeInFrames()
133  {
135  }
136 
144  static inline uint GetChannelCount()
145  {
146  return impact_GetChannelCount();
147  }
148 
157  static inline uint GetAudioInputCount()
158  {
159  return impact_GetAudioInputCount();
160  }
161 
170  static inline uint GetAudioOutputCount()
171  {
173  }
174 
182  static inline uint GetSampleRate()
183  {
184  return impact_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(impact_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  impact_SetLogSeverity(severity);
236  }
240  static inline void SetLoggerCallback(log_cb_t cb)
241  {
242  _log_cb=cb;
243  impact_SetLoggerCallback(&_log_cb_c);
244  }
245 
249  class CInstance {
250  public:
255  {
256  SanityCheck();
257  params = impact_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) impact_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  impact_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=impact_GetParameter(params, name.c_str());
294  std::string ret(c_value);
295  impact_FreeParameterValue(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 = impact_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](){
319  impact_StartUpdateThread(instance, json_port);
321  });
322  if (impact_WaitUpdateThreadReady(instance, 5000)<0) {
323  return false;
324  }
325  return true;
326  }
327 
328  // Can be overloaded, called at start of UpdateThread in the thread
329  virtual void OnUpdateThreadStart() {}
330  // Can be overloaded to call at end of UpdateThread in the thread
331  virtual void OnUpdateThreadStop() {}
332 
338  bool StartWebServer(int http_port, int https_port=0)
339  {
340  assert(instance);
341  assert(webserver==SOUND4_INVALID_WEBSERVER_ID);
342  webserver = impact_Webserver(http_port,https_port,instance);
343  if (webserver==SOUND4_INVALID_WEBSERVER_ID) {
344  return false;
345  }
346  int web_status=impact_Webserver_Status(webserver);
347  if (http_port && (web_status & SOUND4_WEBSERVER_HTTP_OK) == 0) {
348  return false;
349  }
350  if (https_port && (web_status & SOUND4_WEBSERVER_HTTPS_OK) == 0) {
351  return false;
352  }
353  return true;
354  }
361  {
362  if (webserver != SOUND4_INVALID_WEBSERVER_ID) {
363  impact_Webserver_Stop(webserver, 1000);
364  webserver = SOUND4_INVALID_WEBSERVER_ID;
365  }
366  }
372  void Stop()
373  {
374  if (!instance) return;
375  StopWebServer();
376  if (update_thread.joinable()) {
377  impact_StopUpdateThread(instance); // this will exit the update thread
378  update_thread.join();
379  }
380  impact_ExitProcess(instance);
381  instance=nullptr;
382  }
383 
390  {
391  assert(instance);
392  return impact_GetEstimatedDelay(instance);
393  }
394 
405  std::array<float,InputSampleSize>& GetBufferIn()
406  {
407  assert(instance);
408  float *buf=impact_GetBufferIn(instance);
409  return reinterpret_cast< std::array<float,InputSampleSize>& >(*buf);
410 
411  }
422  std::array<float,OutputSampleSize>& GetBufferOut()
423  {
424  assert(instance);
425  float *buf= impact_GetBufferOut(instance);
426  return reinterpret_cast< std::array<float,OutputSampleSize>& >(*buf);
427  }
434  {
435  assert(instance);
436  impact_ProcessAudio(instance, impact_GetBufferIn(instance), impact_GetBufferOut(instance));
437  }
451  // void ProcessAudio_Planar(const std::array< const std::array<const float,ChunkFrames>, InputChannels>& input, std::array< std::array<float,ChunkFrames>, OutputChannels>& output)
452  void ProcessAudio_Planar(float const * const (&input)[InputChannels], float * const (&output)[OutputChannels])
453  {
454  assert(instance);
455  impact_ProcessAudio_Planar(instance, input, output);
456  }
457 
469  template<typename T>
470  std::vector<T> ProcessAnyAudio(const std::vector<T> input)
471  {
472  assert(instance);
473  std::vector<T> output;
474  uint out_offset=0;
475  uint in_offset=0;
476  uint todo = input.size();
477  while (todo>0) {
478  uint left = AddAudio(&input[in_offset], todo);
479  uint out_avail = impact_GetOutputCount(instance);
480  output.resize(out_offset + out_avail);
481  GetAudio(&output[out_offset], out_avail);
482  out_offset+=out_avail;
483  in_offset += todo-left;
484  todo=left;
485  }
486  return output;
487  }
488 
494  class CClient {
495  public:
497  {
498  assert(instance);
499  client=impact_NewClient(instance);
500  if (!client) throw std::bad_alloc();
501  }
502  // non-copyable
503  CClient( const CInstance& ) = delete;
504  CClient& operator=( const CInstance& ) = delete;
506  {
507  if (client) {
508  impact_DeleteClient(client);
509  client=nullptr;
510  }
511  }
519  std::string ProcessJson(const std::string &request, bool *NeedSave = nullptr)
520  {
521  assert(client);
522  int need_save=0;
523  const char *canswer = impact_ProcessJson(client, request.c_str(), &need_save);
524  if (!canswer) return {};
525  std::string answer(canswer);
526  impact_FreeJsonAnswer (canswer);
527  if (NeedSave) {
528  *NeedSave=(need_save!=0);
529  }
530  return answer;
531  }
532  private:
533  impact_CClientInstance *client = nullptr;
534  };
542  std::shared_ptr<CClient> NewClient()
543  {
544  assert(instance);
545  return std::make_shared<CClient>(instance);
546  }
547 
548  protected:
549  template<typename T>
550  uint AddAudio(const T* payload, uint nFrame)
551  {
552  assert(instance);
553  return impact_AddAudio(instance, reinterpret_cast<const T*>(payload), nFrame, helper::SampleFormat<T>::format);
554  }
555  template<typename T>
556  uint GetAudio(T* payload, uint max_nFrame)
557  {
558  assert(instance);
559  return impact_GetAudio(instance, reinterpret_cast<T*>(payload), max_nFrame, helper::SampleFormat<T>::format);
560  }
561 
562  private:
563  impact_CParameters* params = nullptr;
564  impact_CInstance* instance = nullptr;
565  std::thread update_thread;
566  uint64_t webserver = SOUND4_INVALID_WEBSERVER_ID;
567  };
568 
569 }; // namespace impact
570 }; // namespace sound4
CClient(impact_CInstance *instance)
std::string ProcessJson(const std::string &request, bool *NeedSave=nullptr)
Process a JSON request and returns the answer.
CClient & operator=(const CInstance &)=delete
CClient(const CInstance &)=delete
std::shared_ptr< CClient > NewClient()
void SetParam(const std::string &name, const std::string &value)
void ProcessAudio_Planar(float const *const (&input)[InputChannels], float *const (&output)[OutputChannels])
std::string GetParam(const std::string &name)
CInstance(const CInstance &)=delete
CInstance & operator=(const CInstance &)=delete
uint GetAudio(T *payload, uint max_nFrame)
bool StartWebServer(int http_port, int https_port=0)
std::array< float, OutputSampleSize > & GetBufferOut()
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 AddAudio(const T *payload, uint nFrame)
std::vector< T > ProcessAnyAudio(const std::vector< T > input)
std::array< float, InputSampleSize > & GetBufferIn()
uint impact_GetAudio(struct impact_CInstance *instance, uint8_t *payload, uint max_nFrame, enum impact_SampleFormat fmt)
impact_SampleFormat
uint impact_GetOutputCount(struct impact_CInstance *instance)
uint impact_AddAudio(struct impact_CInstance *instance, const uint8_t *payload, uint nFrame, enum impact_SampleFormat fmt)
@ F32_NATIVE
32-bit floating-point, native
@ S16_NATIVE
16-bit signed integer, native
@ S32_NATIVE
32-bit signed integer, native
void impact_FreeJsonAnswer(const char *json_str)
void impact_DeleteClient(struct impact_CClientInstance *client)
const char * impact_ProcessJson(struct impact_CClientInstance *client, const char *json_str, int *need_save)
struct impact_CClientInstance * impact_NewClient(struct impact_CInstance *instance)
float * impact_GetBufferIn(struct impact_CInstance *instance)
void impact_ProcessAudio(struct impact_CInstance *instance, const float *input, float *output)
float * impact_GetBufferOut(struct impact_CInstance *instance)
uint impact_GetEstimatedDelay(struct impact_CInstance *instance)
void impact_ProcessAudio_Planar(struct impact_CInstance *instance, float const *const (&input)[IMPACT_CHANNEL_COUNT *IMPACT_AUDIO_INPUT_COUNT], float *const (&output)[IMPACT_CHANNEL_COUNT *IMPACT_AUDIO_OUTPUT_COUNT])
#define IMPACT_AUDIO_INPUT_COUNT
const char * impact_GetVersion()
#define IMPACT_SAMPLE_RATE
uint impact_GetAudioInputCount()
uint impact_GetChunkSizeInFrames()
uint impact_GetChannelCount()
void impact_SetLoggerCallback(impact_loggerfn logger)
#define IMPACT_CHANNEL_COUNT
#define IMPACT_AUDIOFRAME_COUNT
impact_LogSeverity
void impact_SetLogSeverity(enum impact_LogSeverity severity)
#define IMPACT_AUDIO_OUTPUT_COUNT
uint impact_GetSampleRate()
uint impact_GetAudioOutputCount()
void impact_SetParameter(struct impact_CParameters *params, const char *name, const char *value)
struct impact_CParameters * impact_NewParameters()
void impact_FreeParameters(struct impact_CParameters *params)
void impact_ExitProcess(struct impact_CInstance *instance)
const char * impact_GetParameter(struct impact_CParameters *params, const char *name)
void impact_FreeParameterValue(const char *value)
struct impact_CInstance * impact_InitProcess2(const char *LoginKey, const char *RadioName, const char *AWS_Access_ID, const char *AWS_Access_Secret, const char *save_path, const struct impact_CParameters *parameters)
void impact_StopUpdateThread(struct impact_CInstance *instance)
void impact_StartUpdateThread(struct impact_CInstance *instance, uint port)
int impact_WaitUpdateThreadReady(struct impact_CInstance *instance, int milliseconds)
#define SOUND4_WEBSERVER_HTTPS_OK
int impact_Webserver_Stop(uint64_t id, int timeout_ms)
int impact_Webserver_Status(uint64_t id)
#define SOUND4_WEBSERVER_HTTP_OK
#define SOUND4_INVALID_WEBSERVER_ID
uint64_t impact_Webserver(uint listenport, uint listenport_secure, struct impact_CInstance *instance)
const size_t OutputSampleSize
const size_t InputChannels
const size_t ChunkFrames
const size_t OutputChannels
impact_LogSeverity LogSeverity
const size_t SampleRate
const size_t InputSampleSize
std::function< void(LogSeverity, const std::string &)> log_cb_t
C interface for library.
unsigned int uint
Helper for Sample format types.