|
- #include "OutMgr.h"
- #include <algorithm>
- #include <iostream>
- #include <cassert>
- #include "AudioOut.h"
- #include "Engine.h"
- #include "EngineMgr.h"
- #include "InMgr.h"
- #include "WavEngine.h"
- #include "../Misc/Master.h"
- #include "../Misc/Util.h" //for set_realtime()
-
- using namespace std;
-
- OutMgr &OutMgr::getInstance()
- {
- static OutMgr instance;
- return instance;
- }
-
- OutMgr::OutMgr()
- :wave(new WavEngine()),
- priBuf(new float[4096],
- new float[4096]), priBuffCurrent(priBuf),
- master(Master::getInstance())
- {
- currentOut = NULL;
- stales = 0;
- master = Master::getInstance();
-
- //init samples
- outr = new float[synth->buffersize];
- outl = new float[synth->buffersize];
- memset(outl, 0, synth->bufferbytes);
- memset(outr, 0, synth->bufferbytes);
- }
-
- OutMgr::~OutMgr()
- {
- delete wave;
- delete [] priBuf.l;
- delete [] priBuf.r;
- delete [] outr;
- delete [] outl;
- }
-
- /* Sequence of a tick
- * 1) lets see if we have any stuff to do via midi
- * 2) Lets do that stuff
- * 3) Lets see if the event queue has anything for us
- * 4) Lets empty that out
- * 5) Lets remove old/stale samples
- * 6) Lets see if we need to generate samples
- * 7) Lets generate some
- * 8) Lets return those samples to the primary and secondary outputs
- * 9) Lets wait for another tick
- */
- const Stereo<float *> OutMgr::tick(unsigned int frameSize)
- {
- pthread_mutex_lock(&(master.mutex));
- InMgr::getInstance().flush();
- pthread_mutex_unlock(&(master.mutex));
- //SysEv->execute();
- removeStaleSmps();
- while(frameSize > storedSmps()) {
- pthread_mutex_lock(&(master.mutex));
- master.AudioOut(outl, outr);
- pthread_mutex_unlock(&(master.mutex));
- addSmps(outl, outr);
- }
- stales = frameSize;
- return priBuf;
- }
-
- AudioOut *OutMgr::getOut(string name)
- {
- return dynamic_cast<AudioOut *>(EngineMgr::getInstance().getEng(name));
- }
-
- string OutMgr::getDriver() const
- {
- return currentOut->name;
- }
-
- bool OutMgr::setSink(string name)
- {
- AudioOut *sink = getOut(name);
-
- if(!sink)
- return false;
-
- if(currentOut)
- currentOut->setAudioEn(false);
-
- currentOut = sink;
- currentOut->setAudioEn(true);
-
- bool success = currentOut->getAudioEn();
-
- //Keep system in a valid state (aka with a running driver)
- if(!success)
- (currentOut = getOut("NULL"))->setAudioEn(true);
-
- return success;
- }
-
- string OutMgr::getSink() const
- {
- if(currentOut)
- return currentOut->name;
- else {
- cerr << "BUG: No current output in OutMgr " << __LINE__ << endl;
- return "ERROR";
- }
- return "ERROR";
- }
-
- //perform a cheap linear interpolation for resampling
- //This will result in some distortion at frame boundries
- //returns number of samples produced
- static size_t resample(float *dest,
- const float *src,
- float s_in,
- float s_out,
- size_t elms)
- {
- size_t out_elms = elms * s_out / s_in;
- float r_pos = 0.0f;
- for(int i = 0; i < (int)out_elms; ++i, r_pos += s_in / s_out)
- dest[i] = interpolate(src, elms, r_pos);
-
- return out_elms;
- }
-
- void OutMgr::addSmps(float *l, float *r)
- {
- //allow wave file to syphon off stream
- wave->push(Stereo<float *>(l, r), synth->buffersize);
-
- const int s_out = currentOut->getSampleRate(),
- s_sys = synth->samplerate;
-
- if(s_out != s_sys) { //we need to resample
- const size_t steps = resample(priBuffCurrent.l,
- l,
- s_sys,
- s_out,
- synth->buffersize);
- resample(priBuffCurrent.r, r, s_sys, s_out, synth->buffersize);
-
- priBuffCurrent.l += steps;
- priBuffCurrent.r += steps;
- }
- else { //just copy the samples
- memcpy(priBuffCurrent.l, l, synth->bufferbytes);
- memcpy(priBuffCurrent.r, r, synth->bufferbytes);
- priBuffCurrent.l += synth->buffersize;
- priBuffCurrent.r += synth->buffersize;
- }
- }
-
- void OutMgr::removeStaleSmps()
- {
- if(!stales)
- return;
-
- const int leftover = storedSmps() - stales;
-
- assert(leftover > -1);
-
- //leftover samples [seen at very low latencies]
- if(leftover) {
- memmove(priBuf.l, priBuffCurrent.l - leftover, leftover * sizeof(float));
- memmove(priBuf.r, priBuffCurrent.r - leftover, leftover * sizeof(float));
- priBuffCurrent.l = priBuf.l + leftover;
- priBuffCurrent.r = priBuf.r + leftover;
- }
- else
- priBuffCurrent = priBuf;
-
- stales = 0;
- }
|