Fix scvim regsitry file for updated filename (thanks Carlo Capocasa)
[supercollider.git] / server / scsynth / SC_Jack.cpp
blobd8be9c6482606ef5d3dc086f55c6f09216f42648
1 /*
2 Jack audio driver interface.
3 Copyright (c) 2003-2006 stefan kersten.
5 ====================================================================
7 SuperCollider real time audio synthesis system
8 Copyright (c) 2002 James McCartney. All rights reserved.
9 http://www.audiosynth.com
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "SC_CoreAudio.h"
27 #include "SC_HiddenWorld.h"
28 #include "SC_Prototypes.h"
29 #include "SC_StringParser.h"
31 #include <jack/jack.h>
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <unistd.h>
39 // =====================================================================
40 // Constants
42 static const char* kJackDriverIdent = "JackDriver";
43 static const char* kJackDefaultClientName = "SuperCollider";
45 // =====================================================================
46 // Timing
48 // =====================================================================
49 // SC_JackDLL
51 // Delay-Locked-Loop after
52 // Fons Adriaensen, "Using a DLL to filter time"
54 #define SC_JACK_DLL_BW 0.012
56 class SC_JackDLL
58 public:
59 SC_JackDLL()
60 : m_b(0.), m_c(0.),
61 m_t0(0.), m_t1(0.), m_e2(0.),
62 m_np(0), m_ei(0.), m_ec(0)
63 { }
65 void Reset(double sampleRate, jack_nframes_t periodFrames, double bandWidth, double t)
67 // compute coefficients
68 m_np = periodFrames;
69 m_b = 2*M_PI*bandWidth*m_np/sampleRate;
70 m_c = m_b*m_b/2.;
71 // initialize filter
72 double tp = m_np/sampleRate;
73 m_e2 = tp;
74 m_t0 = t;
75 m_t1 = t + tp;
76 // initialize statistics
77 m_ei = 0.;
78 m_ec = 0;
81 void Update(double t)
83 // compute error
84 double e = m_e = t - m_t1;
85 // update filter
86 m_t0 = m_t1;
87 m_t1 += m_b * e + m_e2;
88 m_e2 += m_c * e;
89 // collect statistics
90 m_ei += e;
91 m_ec++;
94 double PeriodTime() const { return m_t0; }
95 double NextPeriodTime() const { return m_t1; }
96 double Period() const { return m_t1 - m_t0; }
97 double SampleRate() const { return m_np/Period(); }
98 double Error() const { return m_e; }
99 double AvgError() const { return m_ec > 0 ? m_ei/m_ec : 0; }
101 private:
102 double m_b, m_c;
103 double m_t0, m_t1, m_e, m_e2;
104 jack_nframes_t m_np;
105 double m_ei;
106 int m_ec;
109 static inline int64 sc_JackOSCTime(const struct timeval& tv)
111 return ((int64)(tv.tv_sec + kSECONDS_FROM_1900_to_1970) << 32)
112 + (int64)(tv.tv_usec * kMicrosToOSCunits);
115 static inline int64 sc_JackOSCTime()
117 struct timeval tv;
118 gettimeofday(&tv, 0);
119 return sc_JackOSCTime(tv);
122 static inline double sc_JackOSCTimeSeconds()
124 return (uint64)sc_JackOSCTime() * kOSCtoSecs;
127 int32 server_timeseed()
129 static int32 count = 0;
130 struct timeval tv;
131 gettimeofday(&tv, 0);
132 return (int32)tv.tv_sec ^ (int32)tv.tv_usec ^ count--;
135 int64 oscTimeNow()
137 return sc_JackOSCTime();
140 void initializeScheduler()
144 // =====================================================================
145 // Audio driver
147 static int sc_jack_process_cb(jack_nframes_t numFrames, void *arg);
148 static int sc_jack_bufsize_cb(jack_nframes_t numSamples, void *arg);
149 static int sc_jack_srate_cb(jack_nframes_t sampleRate, void *arg);
150 static int sc_jack_graph_order_cb(void *arg);
151 static void sc_jack_shutdown_cb(void *arg);
153 typedef jack_default_audio_sample_t sc_jack_sample_t;
155 struct SC_JackPortList
157 int mSize;
158 jack_port_t** mPorts;
159 sc_jack_sample_t** mBuffers;
161 SC_JackPortList(jack_client_t *client, int numPorts, int type);
162 ~SC_JackPortList();
165 class SC_JackDriver : public SC_AudioDriver
167 jack_client_t *mClient;
168 SC_JackPortList *mInputList;
169 SC_JackPortList *mOutputList;
170 double mMaxOutputLatency;
171 SC_JackDLL mDLL;
173 protected:
174 // driver interface methods
175 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
176 virtual bool DriverStart();
177 virtual bool DriverStop();
179 public:
180 SC_JackDriver(struct World *inWorld);
181 virtual ~SC_JackDriver();
183 // process loop
184 void Run();
186 // reset state
187 void Reset(double sampleRate, int bufferSize);
189 // notifications
190 bool BufferSizeChanged(int numSamples);
191 bool SampleRateChanged(double sampleRate);
192 bool GraphOrderChanged();
193 bool XRun();
195 private:
196 void ConnectPorts(const char * src, const char * dst)
198 int err = jack_connect(mClient, src, dst);
199 scprintf("%s: %s %s to %s\n",
200 kJackDriverIdent,
201 err ? "couldn't connect " : "connected ",
202 src, dst);
205 void ConnectClientInputs(const char * pattern);
206 void ConnectClientOutputs(const char * pattern);
209 SC_AudioDriver* SC_NewAudioDriver(struct World *inWorld)
211 return new SC_JackDriver(inWorld);
214 // =====================================================================
215 // SC_JackPortList
217 SC_JackPortList::SC_JackPortList(jack_client_t *client, int numPorts, int type)
218 : mSize(numPorts), mPorts(0), mBuffers(0)
220 const char *fmt = (type == JackPortIsInput ? "in_%d" : "out_%d");
221 char portname[32];
223 mPorts = new jack_port_t*[mSize];
224 mBuffers = new float*[mSize];
226 for (int i = 0; i < mSize; i++) {
227 snprintf(portname, 32, fmt, i+1);
228 mPorts[i] = jack_port_register(
229 client, portname,
230 JACK_DEFAULT_AUDIO_TYPE,
231 type, 0);
232 mBuffers[i] = 0;
236 SC_JackPortList::~SC_JackPortList()
238 delete [] mPorts;
239 delete [] mBuffers;
242 // =====================================================================
243 // JACK callbacks
245 int sc_jack_process_cb(jack_nframes_t numFrames, void *arg)
247 ((SC_JackDriver*)arg)->Run();
248 return 0;
251 int sc_jack_bufsize_cb(jack_nframes_t numSamples, void *arg)
253 return !((SC_JackDriver*)arg)->BufferSizeChanged((int)numSamples);
256 int sc_jack_srate_cb(jack_nframes_t sampleRate, void *arg)
258 return !((SC_JackDriver*)arg)->SampleRateChanged((double)sampleRate);
261 int sc_jack_graph_order_cb(void* arg)
263 return !((SC_JackDriver*)arg)->GraphOrderChanged();
266 int sc_jack_xrun_cb(void* arg)
268 return !((SC_JackDriver*)arg)->XRun();
271 void sc_jack_shutdown_cb(void* arg)
273 scprintf("%s: killed by jack\n", kJackDriverIdent);
274 World * world = (World*)arg;
275 world->hw->mTerminating = true;
276 world->hw->mQuitProgram->Release();
279 // =====================================================================
280 // SC_JackDriver (JACK)
282 SC_JackDriver::SC_JackDriver(struct World *inWorld)
283 : SC_AudioDriver(inWorld),
284 mClient(0),
285 mInputList(0),
286 mOutputList(0),
287 mMaxOutputLatency(0.)
290 SC_JackDriver::~SC_JackDriver()
292 if (mClient) {
293 jack_client_close(mClient);
296 delete mInputList;
297 delete mOutputList;
300 // ====================================================================
301 // NOTE: for now, in lieu of a mechanism that passes generic options to
302 // the platform driver, we rely on environment variables:
304 // SC_JACK_DEFAULT_INPUTS: which outports to connect to
305 // SC_JACK_DEFAULT_OUTPUTS: which inports to connect to
306 // ====================================================================
308 bool SC_JackDriver::DriverSetup(int* outNumSamples, double* outSampleRate)
310 char* clientName = 0;
311 char* serverName = 0;
313 if (mWorld->hw->mInDeviceName && (strlen(mWorld->hw->mInDeviceName) > 0)) {
314 // parse string <serverName>:<clientName>
315 SC_StringParser sp(mWorld->hw->mInDeviceName, ':');
316 if (!sp.AtEnd()) serverName = strdup(sp.NextToken());
317 if (!sp.AtEnd()) clientName = strdup(sp.NextToken());
318 if (clientName == 0) {
319 // no semicolon found
320 clientName = serverName;
321 serverName = 0;
322 } else if (strlen(clientName) == 0) {
323 free(clientName);
324 clientName = 0;
328 #ifdef SC_USE_JACK_CLIENT_NEW
329 // old style client startup for Jack <0.100 -- AG
330 if (clientName) {
331 mClient = jack_client_new(clientName);
332 } else {
333 clientName = strdup("SuperCollider");
334 mClient = jack_client_new(clientName);
335 if (mClient == 0) {
336 char uniqueName[64];
337 sprintf(uniqueName, "SuperCollider-%d", getpid());
338 clientName = strdup(uniqueName);
339 mClient = jack_client_new(uniqueName);
342 if (mClient) scprintf("%s: client name is '%s'\n", kJackDriverIdent, clientName);
343 if (serverName) free(serverName); if (clientName) free(clientName);
344 if (mClient == 0) return false;
345 #else
346 mClient = jack_client_open(
347 clientName ? clientName : kJackDefaultClientName,
348 serverName ? JackServerName : JackNullOption,
349 NULL, serverName);
350 if (serverName) free(serverName); if (clientName) free(clientName);
351 if (mClient == 0) return false;
353 scprintf("%s: client name is '%s'\n", kJackDriverIdent, jack_get_client_name(mClient));
354 #endif
356 // create jack I/O ports
357 mInputList = new SC_JackPortList(mClient, mWorld->mNumInputs, JackPortIsInput);
358 mOutputList = new SC_JackPortList(mClient, mWorld->mNumOutputs, JackPortIsOutput);
360 // register callbacks
361 jack_set_process_callback(mClient, sc_jack_process_cb, this);
362 jack_set_buffer_size_callback(mClient, sc_jack_bufsize_cb, this);
363 jack_set_sample_rate_callback(mClient, sc_jack_srate_cb, this);
364 jack_set_graph_order_callback(mClient, sc_jack_graph_order_cb, this);
365 jack_set_xrun_callback(mClient, sc_jack_xrun_cb, this);
366 jack_on_shutdown(mClient, sc_jack_shutdown_cb, mWorld);
368 *outNumSamples = (int)jack_get_buffer_size(mClient);
369 *outSampleRate = (double)jack_get_sample_rate(mClient);
371 return true;
374 void SC_JackDriver::ConnectClientInputs(const char * pattern)
376 const char **ports = jack_get_ports (mClient, pattern, NULL, JackPortIsOutput);
377 jack_port_t ** ourports = mInputList->mPorts;
379 if (!ports)
380 return;
382 int i = 0;
383 while (ports[i]) {
384 if (i == mInputList->mSize)
385 break;
387 const char * src = ports[i];
388 const char * dst = jack_port_name(ourports[i]);
390 ConnectPorts(src, dst);
391 ++i;
394 free(ports);
397 void SC_JackDriver::ConnectClientOutputs(const char * pattern)
399 const char **ports = jack_get_ports (mClient, pattern, NULL, JackPortIsInput);
400 jack_port_t ** ourports = mOutputList->mPorts;
402 if (!ports)
403 return;
405 int i = 0;
406 while (ports[i]) {
407 if (i == mOutputList->mSize)
408 break;
410 const char * src = jack_port_name(ourports[i]);
411 const char * dst = ports[i];
413 ConnectPorts(src, dst);
414 ++i;
417 free(ports);
420 bool SC_JackDriver::DriverStart()
422 if (!mClient) return false;
424 int err;
425 SC_StringParser sp;
426 jack_port_t **ports;
427 int numPorts;
429 // activate client
430 err = jack_activate(mClient);
431 if (err) {
432 scprintf("%s: couldn't activate jack client\n", kJackDriverIdent);
433 return false;
436 // connect default inputs
437 sp = SC_StringParser(getenv("SC_JACK_DEFAULT_INPUTS"), ',');
438 ports = mInputList->mPorts;
439 numPorts = mInputList->mSize;
440 for (int i = 0; !sp.AtEnd() && (i < numPorts); i++) {
441 const char *thatPortName = sp.NextToken();
443 if (i == 0 && sp.AtEnd() && (strchr(thatPortName, ':') == 0)) {
444 ConnectClientInputs(thatPortName);
445 break;
448 const char *thisPortName = jack_port_name(ports[i]);
449 if (thisPortName && thatPortName)
450 ConnectPorts(thatPortName, thisPortName);
453 // connect default outputs
454 sp = SC_StringParser(getenv("SC_JACK_DEFAULT_OUTPUTS"), ',');
455 ports = mOutputList->mPorts;
456 numPorts = mOutputList->mSize;
457 for (int i = 0; !sp.AtEnd() && (i < numPorts); i++) {
458 const char *thatPortName = sp.NextToken();
460 if (i == 0 && sp.AtEnd() && (strchr(thatPortName, ':') == 0)) {
461 ConnectClientOutputs(thatPortName);
462 break;
465 const char *thisPortName = jack_port_name(ports[i]);
466 if (thisPortName && thatPortName)
467 ConnectPorts(thisPortName, thatPortName);
470 return true;
473 bool SC_JackDriver::DriverStop()
475 int err = 0;
476 if (mClient) err = jack_deactivate(mClient);
477 return err == 0;
480 void SC_JackDriver::Run()
482 jack_client_t* client = mClient;
483 World* world = mWorld;
485 #if SC_JACK_USE_DLL
486 mDLL.Update(sc_JackOSCTimeSeconds());
487 #if SC_JACK_DEBUG_DLL
488 static int tick = 0;
489 if (++tick >= 10) {
490 tick = 0;
491 scprintf("DLL: t %.6f p %.9f sr %.6f e %.9f avg(e) %.9f inc %.9f\n",
492 mDLL.PeriodTime(), mDLL.Period(), mDLL.SampleRate(),
493 mDLL.Error(), mDLL.AvgError(), mOSCincrement * kOSCtoSecs);
495 #endif
496 #else
497 struct timeval hostTime;
498 gettimeofday(&hostTime, 0);
500 double hostSecs = (double)hostTime.tv_sec + (double)hostTime.tv_usec * 1e-6;
501 double sampleTime = (double)(jack_frame_time(client) + jack_frames_since_cycle_start(client));
503 if (mStartHostSecs == 0) {
504 mStartHostSecs = hostSecs;
505 mStartSampleTime = sampleTime;
506 } else {
507 double instSampleRate = (sampleTime - mPrevSampleTime) / (hostSecs - mPrevHostSecs);
508 double smoothSampleRate = mSmoothSampleRate;
509 smoothSampleRate = smoothSampleRate + 0.002 * (instSampleRate - smoothSampleRate);
510 if (fabs(smoothSampleRate - mSampleRate) > 10.) {
511 smoothSampleRate = mSampleRate;
513 mOSCincrement = (int64)(mOSCincrementNumerator / smoothSampleRate);
514 mSmoothSampleRate = smoothSampleRate;
515 #if 0
516 double avgSampleRate = (sampleTime - mStartSampleTime)/(hostSecs - mStartHostSecs);
517 double jitter = (smoothSampleRate * (hostSecs - mPrevHostSecs)) - (sampleTime - mPrevSampleTime);
518 double drift = (smoothSampleRate - mSampleRate) * (hostSecs - mStartHostSecs);
519 #endif
522 mPrevHostSecs = hostSecs;
523 mPrevSampleTime = sampleTime;
524 #endif
526 try {
527 mFromEngine.Free();
528 mToEngine.Perform();
529 mOscPacketsToEngine.Perform();
531 int numInputs = mInputList->mSize;
532 int numOutputs = mOutputList->mSize;
533 jack_port_t **inPorts = mInputList->mPorts;
534 jack_port_t **outPorts = mOutputList->mPorts;
535 sc_jack_sample_t **inBuffers = mInputList->mBuffers;
536 sc_jack_sample_t **outBuffers = mOutputList->mBuffers;
538 int numSamples = NumSamplesPerCallback();
539 int bufFrames = mWorld->mBufLength;
540 int numBufs = numSamples / bufFrames;
542 float *inBuses = mWorld->mAudioBus + mWorld->mNumOutputs * bufFrames;
543 float *outBuses = mWorld->mAudioBus;
544 int32 *inTouched = mWorld->mAudioBusTouched + mWorld->mNumOutputs;
545 int32 *outTouched = mWorld->mAudioBusTouched;
547 int minInputs = sc_min(numInputs, (int)mWorld->mNumInputs);
548 int minOutputs = sc_min(numOutputs, (int)mWorld->mNumOutputs);
550 int bufFramePos = 0;
552 // cache I/O buffers
553 for (int i = 0; i < minInputs; ++i) {
554 inBuffers[i] = (sc_jack_sample_t*)jack_port_get_buffer(inPorts[i], numSamples);
557 for (int i = 0; i < minOutputs; ++i) {
558 outBuffers[i] = (sc_jack_sample_t*)jack_port_get_buffer(outPorts[i], numSamples);
561 // main loop
562 #if SC_JACK_USE_DLL
563 int64 oscTime = mOSCbuftime = (int64)((mDLL.PeriodTime() - mMaxOutputLatency) * kSecondsToOSCunits + .5);
564 // int64 oscInc = mOSCincrement = (int64)(mOSCincrementNumerator / mDLL.SampleRate());
565 int64 oscInc = mOSCincrement = (int64)((mDLL.Period() / numBufs) * kSecondsToOSCunits + .5);
566 mSmoothSampleRate = mDLL.SampleRate();
567 double oscToSamples = mOSCtoSamples = mSmoothSampleRate * kOSCtoSecs /* 1/pow(2,32) */;
568 #else
569 int64 oscTime = mOSCbuftime = sc_JackOSCTime(hostTime) - (int64)(mMaxOutputLatency * kSecondsToOSCunits + .5);
570 int64 oscInc = mOSCincrement;
571 double oscToSamples = mOSCtoSamples;
572 #endif
574 for (int i = 0; i < numBufs; ++i, mWorld->mBufCounter++, bufFramePos += bufFrames) {
575 int32 bufCounter = mWorld->mBufCounter;
576 int32 *tch;
578 // copy+touch inputs
579 tch = inTouched;
580 for (int k = 0; k < minInputs; ++k) {
581 sc_jack_sample_t *src = inBuffers[k] + bufFramePos;
582 float *dst = inBuses + k * bufFrames;
583 for (int n = 0; n < bufFrames; ++n) {
584 *dst++ = *src++;
586 *tch++ = bufCounter;
589 // run engine
590 int64 schedTime;
591 int64 nextTime = oscTime + oscInc;
593 while ((schedTime = mScheduler.NextTime()) <= nextTime) {
594 float diffTime = (float)(schedTime - oscTime) * oscToSamples + 0.5;
595 float diffTimeFloor = floor(diffTime);
596 world->mSampleOffset = (int)diffTimeFloor;
597 world->mSubsampleOffset = diffTime - diffTimeFloor;
599 if (world->mSampleOffset < 0) world->mSampleOffset = 0;
600 else if (world->mSampleOffset >= world->mBufLength) world->mSampleOffset = world->mBufLength-1;
602 SC_ScheduledEvent event = mScheduler.Remove();
603 event.Perform();
606 world->mSampleOffset = 0;
607 world->mSubsampleOffset = 0.f;
608 World_Run(world);
610 // copy touched outputs
611 tch = outTouched;
612 for (int k = 0; k < minOutputs; ++k) {
613 sc_jack_sample_t *dst = outBuffers[k] + bufFramePos;
614 if (*tch++ == bufCounter) {
615 float *src = outBuses + k * bufFrames;
616 for (int n = 0; n < bufFrames; ++n) {
617 *dst++ = *src++;
619 } else {
620 for (int n = 0; n < bufFrames; ++n) {
621 *dst++ = 0.0f;
626 // advance OSC time
627 mOSCbuftime = oscTime = nextTime;
629 } catch (std::exception& exc) {
630 scprintf("%s: exception in real time: %s\n", kJackDriverIdent, exc.what());
631 } catch (...) {
632 scprintf("%s: unknown exception in real time\n", kJackDriverIdent);
635 double cpuUsage = (double)jack_cpu_load(mClient);
636 mAvgCPU = mAvgCPU + 0.1 * (cpuUsage - mAvgCPU);
637 if (cpuUsage > mPeakCPU || --mPeakCounter <= 0) {
638 mPeakCPU = cpuUsage;
639 mPeakCounter = mMaxPeakCounter;
642 mAudioSync.Signal();
645 void SC_JackDriver::Reset(double sampleRate, int bufferSize)
647 mSampleRate = mSmoothSampleRate = sampleRate;
648 mNumSamplesPerCallback = bufferSize;
650 World_SetSampleRate(mWorld, mSampleRate);
651 mBuffersPerSecond = mSampleRate / mNumSamplesPerCallback;
652 mMaxPeakCounter = (int)mBuffersPerSecond;
653 mOSCincrement = (int64)(mOSCincrementNumerator / mSampleRate);
655 #if SC_JACK_USE_DLL
656 mDLL.Reset(
657 mSampleRate,
658 mNumSamplesPerCallback,
659 SC_JACK_DLL_BW,
660 sc_JackOSCTimeSeconds());
661 #endif
664 bool SC_JackDriver::BufferSizeChanged(int numSamples)
666 Reset(jack_get_sample_rate(mClient), numSamples);
667 return true;
670 bool SC_JackDriver::SampleRateChanged(double sampleRate)
672 Reset(sampleRate, jack_get_buffer_size(mClient));
673 return true;
676 bool SC_JackDriver::GraphOrderChanged()
678 SC_JackPortList* outputs = mOutputList;
679 jack_nframes_t lat = 0;
681 for (int i=0; i < outputs->mSize; ++i) {
682 jack_nframes_t portLat = jack_port_get_total_latency(mClient, outputs->mPorts[i]);
683 if (portLat > lat) lat = portLat;
686 double maxLat = (double)lat / mSampleRate;
688 if (maxLat != mMaxOutputLatency) {
689 mMaxOutputLatency = maxLat;
690 scprintf("%s: max output latency %.1f ms\n", kJackDriverIdent, maxLat * 1e3);
693 return true;
696 bool SC_JackDriver::XRun()
698 Reset(mSampleRate, mNumSamplesPerCallback);
699 return true;
702 // EOF