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.

OutMgr.cpp 4.5KB

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