scide: MainWindow - fix crash in focusCodeEditor
[supercollider.git] / server / scsynth / SC_Jack.cpp
blob74bc0fcb82d8f8a4dd3ff4353b095a4680174677
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"
30 #include "SC_WorldOptions.h"
32 #include <jack/jack.h>
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <unistd.h>
40 // =====================================================================
41 // Constants
43 static const char* kJackDriverIdent = "JackDriver";
44 static const char* kJackDefaultClientName = "SuperCollider";
46 // =====================================================================
47 // Timing
49 // =====================================================================
50 // SC_JackDLL
52 // Delay-Locked-Loop after
53 // Fons Adriaensen, "Using a DLL to filter time"
55 #define SC_JACK_DLL_BW 0.012
57 class SC_JackDLL
59 public:
60 SC_JackDLL()
61 : m_b(0.), m_c(0.),
62 m_t0(0.), m_t1(0.), m_e2(0.),
63 m_np(0), m_ei(0.), m_ec(0)
64 { }
66 void Reset(double sampleRate, jack_nframes_t periodFrames, double bandWidth, double t)
68 // compute coefficients
69 m_np = periodFrames;
70 m_b = 2*M_PI*bandWidth*m_np/sampleRate;
71 m_c = m_b*m_b/2.;
72 // initialize filter
73 double tp = m_np/sampleRate;
74 m_e2 = tp;
75 m_t0 = t;
76 m_t1 = t + tp;
77 // initialize statistics
78 m_ei = 0.;
79 m_ec = 0;
82 void Update(double t)
84 // compute error
85 double e = m_e = t - m_t1;
86 // update filter
87 m_t0 = m_t1;
88 m_t1 += m_b * e + m_e2;
89 m_e2 += m_c * e;
90 // collect statistics
91 m_ei += e;
92 m_ec++;
95 double PeriodTime() const { return m_t0; }
96 double NextPeriodTime() const { return m_t1; }
97 double Period() const { return m_t1 - m_t0; }
98 double SampleRate() const { return m_np/Period(); }
99 double Error() const { return m_e; }
100 double AvgError() const { return m_ec > 0 ? m_ei/m_ec : 0; }
102 private:
103 double m_b, m_c;
104 double m_t0, m_t1, m_e, m_e2;
105 jack_nframes_t m_np;
106 double m_ei;
107 int m_ec;
110 static inline int64 sc_JackOSCTime(const struct timeval& tv)
112 return ((int64)(tv.tv_sec + kSECONDS_FROM_1900_to_1970) << 32)
113 + (int64)(tv.tv_usec * kMicrosToOSCunits);
116 static inline int64 sc_JackOSCTime()
118 struct timeval tv;
119 gettimeofday(&tv, 0);
120 return sc_JackOSCTime(tv);
123 static inline double sc_JackOSCTimeSeconds()
125 return (uint64)sc_JackOSCTime() * kOSCtoSecs;
128 int32 server_timeseed()
130 static int32 count = 0;
131 struct timeval tv;
132 gettimeofday(&tv, 0);
133 return (int32)tv.tv_sec ^ (int32)tv.tv_usec ^ count--;
136 int64 oscTimeNow()
138 return sc_JackOSCTime();
141 void initializeScheduler()
145 // =====================================================================
146 // Audio driver
148 static int sc_jack_process_cb(jack_nframes_t numFrames, void *arg);
149 static int sc_jack_bufsize_cb(jack_nframes_t numSamples, void *arg);
150 static int sc_jack_srate_cb(jack_nframes_t sampleRate, void *arg);
151 static int sc_jack_graph_order_cb(void *arg);
152 static void sc_jack_shutdown_cb(void *arg);
154 typedef jack_default_audio_sample_t sc_jack_sample_t;
156 struct SC_JackPortList
158 int mSize;
159 jack_port_t** mPorts;
160 sc_jack_sample_t** mBuffers;
162 SC_JackPortList(jack_client_t *client, int numPorts, int type);
163 ~SC_JackPortList();
166 class SC_JackDriver : public SC_AudioDriver
168 jack_client_t *mClient;
169 SC_JackPortList *mInputList;
170 SC_JackPortList *mOutputList;
171 double mMaxOutputLatency;
172 SC_JackDLL mDLL;
174 protected:
175 // driver interface methods
176 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
177 virtual bool DriverStart();
178 virtual bool DriverStop();
180 public:
181 SC_JackDriver(struct World *inWorld);
182 virtual ~SC_JackDriver();
184 // process loop
185 void Run();
187 // reset state
188 void Reset(double sampleRate, int bufferSize);
190 // notifications
191 bool BufferSizeChanged(int numSamples);
192 bool SampleRateChanged(double sampleRate);
193 bool GraphOrderChanged();
194 bool XRun();
196 private:
197 void ConnectPorts(const char * src, const char * dst)
199 int err = jack_connect(mClient, src, dst);
200 scprintf("%s: %s %s to %s\n",
201 kJackDriverIdent,
202 err ? "couldn't connect " : "connected ",
203 src, dst);
206 void ConnectClientInputs(const char * pattern);
207 void ConnectClientOutputs(const char * pattern);
210 SC_AudioDriver* SC_NewAudioDriver(struct World *inWorld)
212 return new SC_JackDriver(inWorld);
215 // =====================================================================
216 // SC_JackPortList
218 SC_JackPortList::SC_JackPortList(jack_client_t *client, int numPorts, int type)
219 : mSize(numPorts), mPorts(0), mBuffers(0)
221 const char *fmt = (type == JackPortIsInput ? "in_%d" : "out_%d");
222 char portname[32];
224 mPorts = new jack_port_t*[mSize];
225 mBuffers = new float*[mSize];
227 for (int i = 0; i < mSize; i++) {
228 snprintf(portname, 32, fmt, i+1);
229 mPorts[i] = jack_port_register(
230 client, portname,
231 JACK_DEFAULT_AUDIO_TYPE,
232 type, 0);
233 mBuffers[i] = 0;
237 SC_JackPortList::~SC_JackPortList()
239 delete [] mPorts;
240 delete [] mBuffers;
243 // =====================================================================
244 // JACK callbacks
246 int sc_jack_process_cb(jack_nframes_t numFrames, void *arg)
248 ((SC_JackDriver*)arg)->Run();
249 return 0;
252 int sc_jack_bufsize_cb(jack_nframes_t numSamples, void *arg)
254 return !((SC_JackDriver*)arg)->BufferSizeChanged((int)numSamples);
257 int sc_jack_srate_cb(jack_nframes_t sampleRate, void *arg)
259 return !((SC_JackDriver*)arg)->SampleRateChanged((double)sampleRate);
262 int sc_jack_graph_order_cb(void* arg)
264 return !((SC_JackDriver*)arg)->GraphOrderChanged();
267 int sc_jack_xrun_cb(void* arg)
269 return !((SC_JackDriver*)arg)->XRun();
272 void sc_jack_shutdown_cb(void* arg)
274 scprintf("%s: killed by jack\n", kJackDriverIdent);
275 World * world = (World*)arg;
276 world->hw->mTerminating = true;
277 world->hw->mQuitProgram->Release();
280 // =====================================================================
281 // SC_JackDriver (JACK)
283 SC_JackDriver::SC_JackDriver(struct World *inWorld)
284 : SC_AudioDriver(inWorld),
285 mClient(0),
286 mInputList(0),
287 mOutputList(0),
288 mMaxOutputLatency(0.)
291 SC_JackDriver::~SC_JackDriver()
293 if (mClient) {
294 jack_client_close(mClient);
297 delete mInputList;
298 delete mOutputList;
301 // ====================================================================
302 // NOTE: for now, in lieu of a mechanism that passes generic options to
303 // the platform driver, we rely on environment variables:
305 // SC_JACK_DEFAULT_INPUTS: which outports to connect to
306 // SC_JACK_DEFAULT_OUTPUTS: which inports to connect to
307 // ====================================================================
309 bool SC_JackDriver::DriverSetup(int* outNumSamples, double* outSampleRate)
311 char* clientName = 0;
312 char* serverName = 0;
314 if (mWorld->hw->mInDeviceName && (strlen(mWorld->hw->mInDeviceName) > 0)) {
315 // parse string <serverName>:<clientName>
316 SC_StringParser sp(mWorld->hw->mInDeviceName, ':');
317 if (!sp.AtEnd()) serverName = strdup(sp.NextToken());
318 if (!sp.AtEnd()) clientName = strdup(sp.NextToken());
319 if (clientName == 0) {
320 // no semicolon found
321 clientName = serverName;
322 serverName = 0;
323 } else if (strlen(clientName) == 0) {
324 free(clientName);
325 clientName = 0;
329 #ifdef SC_USE_JACK_CLIENT_NEW
330 // old style client startup for Jack <0.100 -- AG
331 if (clientName) {
332 mClient = jack_client_new(clientName);
333 } else {
334 clientName = strdup("SuperCollider");
335 mClient = jack_client_new(clientName);
336 if (mClient == 0) {
337 char uniqueName[64];
338 sprintf(uniqueName, "SuperCollider-%d", getpid());
339 clientName = strdup(uniqueName);
340 mClient = jack_client_new(uniqueName);
343 if (mClient) scprintf("%s: client name is '%s'\n", kJackDriverIdent, clientName);
344 if (serverName) free(serverName); if (clientName) free(clientName);
345 if (mClient == 0) return false;
346 #else
347 mClient = jack_client_open(
348 clientName ? clientName : kJackDefaultClientName,
349 serverName ? JackServerName : JackNullOption,
350 NULL, serverName);
351 if (serverName) free(serverName); if (clientName) free(clientName);
352 if (mClient == 0) return false;
354 scprintf("%s: client name is '%s'\n", kJackDriverIdent, jack_get_client_name(mClient));
355 #endif
357 // create jack I/O ports
358 mInputList = new SC_JackPortList(mClient, mWorld->mNumInputs, JackPortIsInput);
359 mOutputList = new SC_JackPortList(mClient, mWorld->mNumOutputs, JackPortIsOutput);
361 // register callbacks
362 jack_set_process_callback(mClient, sc_jack_process_cb, this);
363 jack_set_buffer_size_callback(mClient, sc_jack_bufsize_cb, this);
364 jack_set_sample_rate_callback(mClient, sc_jack_srate_cb, this);
365 jack_set_graph_order_callback(mClient, sc_jack_graph_order_cb, this);
366 jack_set_xrun_callback(mClient, sc_jack_xrun_cb, this);
367 jack_on_shutdown(mClient, sc_jack_shutdown_cb, mWorld);
369 *outNumSamples = (int)jack_get_buffer_size(mClient);
370 *outSampleRate = (double)jack_get_sample_rate(mClient);
372 return true;
375 void SC_JackDriver::ConnectClientInputs(const char * pattern)
377 const char **ports = jack_get_ports (mClient, pattern, NULL, JackPortIsOutput);
378 jack_port_t ** ourports = mInputList->mPorts;
380 if (!ports)
381 return;
383 int i = 0;
384 while (ports[i]) {
385 if (i == mInputList->mSize)
386 break;
388 const char * src = ports[i];
389 const char * dst = jack_port_name(ourports[i]);
391 ConnectPorts(src, dst);
392 ++i;
395 free(ports);
398 void SC_JackDriver::ConnectClientOutputs(const char * pattern)
400 const char **ports = jack_get_ports (mClient, pattern, NULL, JackPortIsInput);
401 jack_port_t ** ourports = mOutputList->mPorts;
403 if (!ports)
404 return;
406 int i = 0;
407 while (ports[i]) {
408 if (i == mOutputList->mSize)
409 break;
411 const char * src = jack_port_name(ourports[i]);
412 const char * dst = ports[i];
414 ConnectPorts(src, dst);
415 ++i;
418 free(ports);
421 bool SC_JackDriver::DriverStart()
423 if (!mClient) return false;
425 int err;
426 SC_StringParser sp;
427 jack_port_t **ports;
428 int numPorts;
430 // activate client
431 err = jack_activate(mClient);
432 if (err) {
433 scprintf("%s: couldn't activate jack client\n", kJackDriverIdent);
434 return false;
437 // connect default inputs
438 sp = SC_StringParser(getenv("SC_JACK_DEFAULT_INPUTS"), ',');
439 ports = mInputList->mPorts;
440 numPorts = mInputList->mSize;
441 for (int i = 0; !sp.AtEnd() && (i < numPorts); i++) {
442 const char *thatPortName = sp.NextToken();
444 if (i == 0 && sp.AtEnd() && (strchr(thatPortName, ':') == 0)) {
445 ConnectClientInputs(thatPortName);
446 break;
449 const char *thisPortName = jack_port_name(ports[i]);
450 if (thisPortName && thatPortName)
451 ConnectPorts(thatPortName, thisPortName);
454 // connect default outputs
455 sp = SC_StringParser(getenv("SC_JACK_DEFAULT_OUTPUTS"), ',');
456 ports = mOutputList->mPorts;
457 numPorts = mOutputList->mSize;
458 for (int i = 0; !sp.AtEnd() && (i < numPorts); i++) {
459 const char *thatPortName = sp.NextToken();
461 if (i == 0 && sp.AtEnd() && (strchr(thatPortName, ':') == 0)) {
462 ConnectClientOutputs(thatPortName);
463 break;
466 const char *thisPortName = jack_port_name(ports[i]);
467 if (thisPortName && thatPortName)
468 ConnectPorts(thisPortName, thatPortName);
471 return true;
474 bool SC_JackDriver::DriverStop()
476 int err = 0;
477 if (mClient) err = jack_deactivate(mClient);
478 return err == 0;
481 void SC_JackDriver::Run()
483 jack_client_t* client = mClient;
484 World* world = mWorld;
486 #if SC_JACK_USE_DLL
487 mDLL.Update(sc_JackOSCTimeSeconds());
488 #if SC_JACK_DEBUG_DLL
489 static int tick = 0;
490 if (++tick >= 10) {
491 tick = 0;
492 scprintf("DLL: t %.6f p %.9f sr %.6f e %.9f avg(e) %.9f inc %.9f\n",
493 mDLL.PeriodTime(), mDLL.Period(), mDLL.SampleRate(),
494 mDLL.Error(), mDLL.AvgError(), mOSCincrement * kOSCtoSecs);
496 #endif
497 #else
498 struct timeval hostTime;
499 gettimeofday(&hostTime, 0);
501 double hostSecs = (double)hostTime.tv_sec + (double)hostTime.tv_usec * 1e-6;
502 double sampleTime = (double)(jack_frame_time(client) + jack_frames_since_cycle_start(client));
504 if (mStartHostSecs == 0) {
505 mStartHostSecs = hostSecs;
506 mStartSampleTime = sampleTime;
507 } else {
508 double instSampleRate = (sampleTime - mPrevSampleTime) / (hostSecs - mPrevHostSecs);
509 double smoothSampleRate = mSmoothSampleRate;
510 smoothSampleRate = smoothSampleRate + 0.002 * (instSampleRate - smoothSampleRate);
511 if (fabs(smoothSampleRate - mSampleRate) > 10.) {
512 smoothSampleRate = mSampleRate;
514 mOSCincrement = (int64)(mOSCincrementNumerator / smoothSampleRate);
515 mSmoothSampleRate = smoothSampleRate;
516 #if 0
517 double avgSampleRate = (sampleTime - mStartSampleTime)/(hostSecs - mStartHostSecs);
518 double jitter = (smoothSampleRate * (hostSecs - mPrevHostSecs)) - (sampleTime - mPrevSampleTime);
519 double drift = (smoothSampleRate - mSampleRate) * (hostSecs - mStartHostSecs);
520 #endif
523 mPrevHostSecs = hostSecs;
524 mPrevSampleTime = sampleTime;
525 #endif
527 try {
528 mFromEngine.Free();
529 mToEngine.Perform();
530 mOscPacketsToEngine.Perform();
532 int numInputs = mInputList->mSize;
533 int numOutputs = mOutputList->mSize;
534 jack_port_t **inPorts = mInputList->mPorts;
535 jack_port_t **outPorts = mOutputList->mPorts;
536 sc_jack_sample_t **inBuffers = mInputList->mBuffers;
537 sc_jack_sample_t **outBuffers = mOutputList->mBuffers;
539 int numSamples = NumSamplesPerCallback();
540 int bufFrames = mWorld->mBufLength;
541 int numBufs = numSamples / bufFrames;
543 float *inBuses = mWorld->mAudioBus + mWorld->mNumOutputs * bufFrames;
544 float *outBuses = mWorld->mAudioBus;
545 int32 *inTouched = mWorld->mAudioBusTouched + mWorld->mNumOutputs;
546 int32 *outTouched = mWorld->mAudioBusTouched;
548 int minInputs = sc_min(numInputs, (int)mWorld->mNumInputs);
549 int minOutputs = sc_min(numOutputs, (int)mWorld->mNumOutputs);
551 int bufFramePos = 0;
553 // cache I/O buffers
554 for (int i = 0; i < minInputs; ++i) {
555 inBuffers[i] = (sc_jack_sample_t*)jack_port_get_buffer(inPorts[i], numSamples);
558 for (int i = 0; i < minOutputs; ++i) {
559 outBuffers[i] = (sc_jack_sample_t*)jack_port_get_buffer(outPorts[i], numSamples);
562 // main loop
563 #if SC_JACK_USE_DLL
564 int64 oscTime = mOSCbuftime = (int64)((mDLL.PeriodTime() - mMaxOutputLatency) * kSecondsToOSCunits + .5);
565 // int64 oscInc = mOSCincrement = (int64)(mOSCincrementNumerator / mDLL.SampleRate());
566 int64 oscInc = mOSCincrement = (int64)((mDLL.Period() / numBufs) * kSecondsToOSCunits + .5);
567 mSmoothSampleRate = mDLL.SampleRate();
568 double oscToSamples = mOSCtoSamples = mSmoothSampleRate * kOSCtoSecs /* 1/pow(2,32) */;
569 #else
570 int64 oscTime = mOSCbuftime = sc_JackOSCTime(hostTime) - (int64)(mMaxOutputLatency * kSecondsToOSCunits + .5);
571 int64 oscInc = mOSCincrement;
572 double oscToSamples = mOSCtoSamples;
573 #endif
575 for (int i = 0; i < numBufs; ++i, mWorld->mBufCounter++, bufFramePos += bufFrames) {
576 int32 bufCounter = mWorld->mBufCounter;
577 int32 *tch;
579 // copy+touch inputs
580 tch = inTouched;
581 for (int k = 0; k < minInputs; ++k) {
582 sc_jack_sample_t *src = inBuffers[k] + bufFramePos;
583 float *dst = inBuses + k * bufFrames;
584 for (int n = 0; n < bufFrames; ++n) {
585 *dst++ = *src++;
587 *tch++ = bufCounter;
590 // run engine
591 int64 schedTime;
592 int64 nextTime = oscTime + oscInc;
594 while ((schedTime = mScheduler.NextTime()) <= nextTime) {
595 float diffTime = (float)(schedTime - oscTime) * oscToSamples + 0.5;
596 float diffTimeFloor = floor(diffTime);
597 world->mSampleOffset = (int)diffTimeFloor;
598 world->mSubsampleOffset = diffTime - diffTimeFloor;
600 if (world->mSampleOffset < 0) world->mSampleOffset = 0;
601 else if (world->mSampleOffset >= world->mBufLength) world->mSampleOffset = world->mBufLength-1;
603 SC_ScheduledEvent event = mScheduler.Remove();
604 event.Perform();
607 world->mSampleOffset = 0;
608 world->mSubsampleOffset = 0.f;
609 World_Run(world);
611 // copy touched outputs
612 tch = outTouched;
613 for (int k = 0; k < minOutputs; ++k) {
614 sc_jack_sample_t *dst = outBuffers[k] + bufFramePos;
615 if (*tch++ == bufCounter) {
616 float *src = outBuses + k * bufFrames;
617 for (int n = 0; n < bufFrames; ++n) {
618 *dst++ = *src++;
620 } else {
621 for (int n = 0; n < bufFrames; ++n) {
622 *dst++ = 0.0f;
627 // advance OSC time
628 mOSCbuftime = oscTime = nextTime;
630 } catch (std::exception& exc) {
631 scprintf("%s: exception in real time: %s\n", kJackDriverIdent, exc.what());
632 } catch (...) {
633 scprintf("%s: unknown exception in real time\n", kJackDriverIdent);
636 double cpuUsage = (double)jack_cpu_load(mClient);
637 mAvgCPU = mAvgCPU + 0.1 * (cpuUsage - mAvgCPU);
638 if (cpuUsage > mPeakCPU || --mPeakCounter <= 0) {
639 mPeakCPU = cpuUsage;
640 mPeakCounter = mMaxPeakCounter;
643 mAudioSync.Signal();
646 void SC_JackDriver::Reset(double sampleRate, int bufferSize)
648 mSampleRate = mSmoothSampleRate = sampleRate;
649 mNumSamplesPerCallback = bufferSize;
651 World_SetSampleRate(mWorld, mSampleRate);
652 mBuffersPerSecond = mSampleRate / mNumSamplesPerCallback;
653 mMaxPeakCounter = (int)mBuffersPerSecond;
654 mOSCincrement = (int64)(mOSCincrementNumerator / mSampleRate);
656 #if SC_JACK_USE_DLL
657 mDLL.Reset(
658 mSampleRate,
659 mNumSamplesPerCallback,
660 SC_JACK_DLL_BW,
661 sc_JackOSCTimeSeconds());
662 #endif
665 bool SC_JackDriver::BufferSizeChanged(int numSamples)
667 Reset(jack_get_sample_rate(mClient), numSamples);
668 return true;
671 bool SC_JackDriver::SampleRateChanged(double sampleRate)
673 Reset(sampleRate, jack_get_buffer_size(mClient));
674 return true;
677 bool SC_JackDriver::GraphOrderChanged()
679 SC_JackPortList* outputs = mOutputList;
680 jack_nframes_t lat = 0;
682 for (int i=0; i < outputs->mSize; ++i) {
683 jack_nframes_t portLat = jack_port_get_total_latency(mClient, outputs->mPorts[i]);
684 if (portLat > lat) lat = portLat;
687 double maxLat = (double)lat / mSampleRate;
689 if (maxLat != mMaxOutputLatency) {
690 mMaxOutputLatency = maxLat;
691 scprintf("%s: max output latency %.1f ms\n", kJackDriverIdent, maxLat * 1e3);
694 return true;
697 bool SC_JackDriver::XRun()
699 Reset(mSampleRate, mNumSamplesPerCallback);
700 return true;
703 // EOF