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.

202 lines
4.9KB

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