Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.6KB

  1. #include "OutMgr.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <cassert>
  5. #include "AudioOut.h"
  6. #include "Engine.h"
  7. #include "EngineMgr.h"
  8. #include "InMgr.h"
  9. #include "WavEngine.h"
  10. #include "../Misc/Master.h"
  11. #include "../Misc/Util.h" //for set_realtime()
  12. using namespace std;
  13. OutMgr &OutMgr::getInstance(const SYNTH_T *synth)
  14. {
  15. static OutMgr instance(synth);
  16. return instance;
  17. }
  18. OutMgr::OutMgr(const SYNTH_T *synth_)
  19. :wave(new WavEngine(*synth_)),
  20. priBuf(new float[4096],
  21. new float[4096]), priBuffCurrent(priBuf),
  22. master(NULL), stales(0), synth(*synth_)
  23. {
  24. assert(synth_);
  25. currentOut = NULL;
  26. //init samples
  27. outr = new float[synth.buffersize];
  28. outl = new float[synth.buffersize];
  29. memset(outl, 0, synth.bufferbytes);
  30. memset(outr, 0, synth.bufferbytes);
  31. }
  32. OutMgr::~OutMgr()
  33. {
  34. delete wave;
  35. delete [] priBuf.l;
  36. delete [] priBuf.r;
  37. delete [] outr;
  38. delete [] outl;
  39. }
  40. /* Sequence of a tick
  41. * 1) Lets remove old/stale samples
  42. * 2) Apply appliciable midi events
  43. * 3) Lets see if we need to generate samples
  44. * 4) Lets generate some
  45. * 5) Goto 2 if more are needed
  46. * 6) Lets return those samples to the primary and secondary outputs
  47. * 7) Lets wait for another tick
  48. */
  49. const Stereo<float *> OutMgr::tick(unsigned int frameSize)
  50. {
  51. InMgr &midi = InMgr::getInstance();
  52. //SysEv->execute();
  53. removeStaleSmps();
  54. int i=0;
  55. while(frameSize > storedSmps()) {
  56. if(!midi.empty()) {
  57. midi.flush(i*synth.buffersize, (i+1)*synth.buffersize);
  58. }
  59. master->AudioOut(outl, outr);
  60. addSmps(outl, outr);
  61. i++;
  62. }
  63. stales = frameSize;
  64. return priBuf;
  65. }
  66. AudioOut *OutMgr::getOut(string name)
  67. {
  68. return dynamic_cast<AudioOut *>(EngineMgr::getInstance().getEng(name));
  69. }
  70. string OutMgr::getDriver() const
  71. {
  72. return currentOut->name;
  73. }
  74. bool OutMgr::setSink(string name)
  75. {
  76. AudioOut *sink = getOut(name);
  77. if(!sink)
  78. return false;
  79. if(currentOut)
  80. currentOut->setAudioEn(false);
  81. currentOut = sink;
  82. currentOut->setAudioEn(true);
  83. bool success = currentOut->getAudioEn();
  84. //Keep system in a valid state (aka with a running driver)
  85. if(!success)
  86. (currentOut = getOut("NULL"))->setAudioEn(true);
  87. return success;
  88. }
  89. string OutMgr::getSink() const
  90. {
  91. if(currentOut)
  92. return currentOut->name;
  93. else {
  94. cerr << "BUG: No current output in OutMgr " << __LINE__ << endl;
  95. return "ERROR";
  96. }
  97. return "ERROR";
  98. }
  99. void OutMgr::setMaster(Master *master_)
  100. {
  101. master=master_;
  102. }
  103. void OutMgr::applyOscEventRt(const char *msg)
  104. {
  105. master->applyOscEvent(msg);
  106. }
  107. //perform a cheap linear interpolation for resampling
  108. //This will result in some distortion at frame boundries
  109. //returns number of samples produced
  110. static size_t resample(float *dest,
  111. const float *src,
  112. float s_in,
  113. float s_out,
  114. size_t elms)
  115. {
  116. size_t out_elms = elms * s_out / s_in;
  117. float r_pos = 0.0f;
  118. for(int i = 0; i < (int)out_elms; ++i, r_pos += s_in / s_out)
  119. dest[i] = interpolate(src, elms, r_pos);
  120. return out_elms;
  121. }
  122. void OutMgr::addSmps(float *l, float *r)
  123. {
  124. //allow wave file to syphon off stream
  125. wave->push(Stereo<float *>(l, r), synth.buffersize);
  126. const int s_out = currentOut->getSampleRate(),
  127. s_sys = synth.samplerate;
  128. if(s_out != s_sys) { //we need to resample
  129. const size_t steps = resample(priBuffCurrent.l,
  130. l,
  131. s_sys,
  132. s_out,
  133. synth.buffersize);
  134. resample(priBuffCurrent.r, r, s_sys, s_out, synth.buffersize);
  135. priBuffCurrent.l += steps;
  136. priBuffCurrent.r += steps;
  137. }
  138. else { //just copy the samples
  139. memcpy(priBuffCurrent.l, l, synth.bufferbytes);
  140. memcpy(priBuffCurrent.r, r, synth.bufferbytes);
  141. priBuffCurrent.l += synth.buffersize;
  142. priBuffCurrent.r += synth.buffersize;
  143. }
  144. }
  145. void OutMgr::removeStaleSmps()
  146. {
  147. if(!stales)
  148. return;
  149. const int leftover = storedSmps() - stales;
  150. assert(leftover > -1);
  151. //leftover samples [seen at very low latencies]
  152. if(leftover) {
  153. memmove(priBuf.l, priBuffCurrent.l - leftover, leftover * sizeof(float));
  154. memmove(priBuf.r, priBuffCurrent.r - leftover, leftover * sizeof(float));
  155. priBuffCurrent.l = priBuf.l + leftover;
  156. priBuffCurrent.r = priBuf.r + leftover;
  157. }
  158. else
  159. priBuffCurrent = priBuf;
  160. stales = 0;
  161. }