DSSIPluginInstance.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 /*
16  This is a modified version of a source file from the
17  Rosegarden MIDI and audio sequencer and notation editor.
18  This file copyright 2000-2006 Chris Cannam.
19 */
20 
21 #include <iostream>
22 #include <cassert>
23 
24 #include "DSSIPluginInstance.h"
25 #include "PluginIdentifier.h"
26 #include "LADSPAPluginFactory.h"
27 
28 #include <cstdlib>
29 
30 #ifndef Q_OS_WIN32
31 #include <alloca.h>
32 #else
33 #include <memory.h>
34 #endif
35 
36 //#define DEBUG_DSSI 1
37 //#define DEBUG_DSSI_PROCESS 1
38 
39 #define EVENT_BUFFER_SIZE 1023
40 
41 #ifdef DEBUG_DSSI
42 static std::ostream &operator<<(std::ostream& o, const QString &s)
43 {
44  o << s;
45  return o;
46 }
47 #endif
48 
50 snd_seq_event_t **DSSIPluginInstance::m_groupLocalEventBuffers = nullptr;
53 std::map<LADSPA_Handle, std::set<DSSIPluginInstance::NonRTPluginThread *> > DSSIPluginInstance::m_threads;
54 
55 
57  int clientId,
58  QString identifier,
59  int position,
60  sv_samplerate_t sampleRate,
61  int blockSize,
62  int idealChannelCount,
63  const DSSI_Descriptor* descriptor) :
64  RealTimePluginInstance(factory, identifier),
65  m_client(clientId),
66  m_position(position),
67  m_instanceHandle(nullptr),
68  m_descriptor(descriptor),
69  m_programCacheValid(false),
70  m_eventBuffer(EVENT_BUFFER_SIZE),
71  m_blockSize(blockSize),
72  m_idealChannelCount(idealChannelCount),
73  m_sampleRate(sampleRate),
74  m_latencyPort(nullptr),
75  m_run(false),
76  m_bypassed(false),
77  m_grouped(false),
78  m_haveLastEventSendTime(false)
79 {
80 #ifdef DEBUG_DSSI
81  SVDEBUG << "DSSIPluginInstance::DSSIPluginInstance(" << identifier << ")"
82  << endl;
83 #endif
84 
85  init();
86 
87  m_inputBuffers = new sample_t*[m_audioPortsIn.size()];
89 
90  for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
91  m_inputBuffers[i] = new sample_t[blockSize];
92  }
93  for (int i = 0; i < m_outputBufferCount; ++i) {
94  m_outputBuffers[i] = new sample_t[blockSize];
95  }
96 
97  m_ownBuffers = true;
98 
100 
101  instantiate(sampleRate);
102  if (isOK()) {
103  connectPorts();
104  activate();
106  }
107 }
108 
109 std::string
111 {
112  return m_descriptor->LADSPA_Plugin->Label;
113 }
114 
115 std::string
117 {
118  return m_descriptor->LADSPA_Plugin->Name;
119 }
120 
121 std::string
123 {
124  return "";
125 }
126 
127 std::string
129 {
130  return m_descriptor->LADSPA_Plugin->Maker;
131 }
132 
133 int
135 {
136  return -1;
137 }
138 
139 std::string
141 {
142  return m_descriptor->LADSPA_Plugin->Copyright;
143 }
144 
145 DSSIPluginInstance::ParameterList
147 {
148  ParameterList list;
149  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
150  if (!f) return list;
151 
152  for (int i = 0; in_range_for(m_controlPortsIn, i); ++i) {
153 
154  ParameterDescriptor pd;
155  int pn = (int)m_controlPortsIn[i].first;
156 
157  pd.identifier = m_descriptor->LADSPA_Plugin->PortNames[pn];
158  pd.name = pd.identifier;
159  pd.description = "";
160  pd.minValue = f->getPortMinimum(m_descriptor->LADSPA_Plugin, pn);
161  pd.maxValue = f->getPortMaximum(m_descriptor->LADSPA_Plugin, pn);
162  pd.defaultValue = f->getPortDefault(m_descriptor->LADSPA_Plugin, pn);
163 
164  float q = f->getPortQuantization(m_descriptor->LADSPA_Plugin, pn);
165  if (q == 0.0) {
166  pd.isQuantized = false;
167  } else {
168  pd.isQuantized = true;
169  pd.quantizeStep = q;
170  }
171 
172  list.push_back(pd);
173  }
174 
175  return list;
176 }
177 
178 float
179 DSSIPluginInstance::getParameter(std::string id) const
180 {
181 #ifdef DEBUG_DSSI
182  SVDEBUG << "DSSIPluginInstance::getParameter(" << id << ")" << endl;
183 #endif
184  for (int i = 0; in_range_for(m_controlPortsIn, i); ++i) {
185  if (id == m_descriptor->LADSPA_Plugin->PortNames[m_controlPortsIn[i].first]) {
186 #ifdef DEBUG_DSSI
187  cerr << "Matches port " << i << endl;
188 #endif
189  float v = getParameterValue(i);
190 #ifdef DEBUG_DSSI
191  SVDEBUG << "Returning " << v << endl;
192 #endif
193  return v;
194  }
195  }
196 
197  return 0.0;
198 }
199 
200 void
201 DSSIPluginInstance::setParameter(std::string id, float value)
202 {
203 #ifdef DEBUG_DSSI
204  SVDEBUG << "DSSIPluginInstance::setParameter(" << id << ", " << value << ")" << endl;
205 #endif
206 
207  for (int i = 0; in_range_for(m_controlPortsIn, i); ++i) {
208  if (id == m_descriptor->LADSPA_Plugin->PortNames[m_controlPortsIn[i].first]) {
209  setParameterValue(i, value);
210  break;
211  }
212  }
213 }
214 
215 void
217 {
218 #ifdef DEBUG_DSSI
219  SVDEBUG << "DSSIPluginInstance::init" << endl;
220 #endif
221 
222  // Discover ports numbers and identities
223  //
224  const LADSPA_Descriptor *descriptor = m_descriptor->LADSPA_Plugin;
225 
226  for (int i = 0; i < (int)descriptor->PortCount; ++i)
227  {
228  if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[i]))
229  {
230  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
231  m_audioPortsIn.push_back(i);
232  } else {
233  m_audioPortsOut.push_back(i);
234  }
235  }
236  else
237  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]))
238  {
239  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
240 
241  LADSPA_Data *data = new LADSPA_Data(0.0);
242 
243  m_controlPortsIn.push_back(std::pair<long, LADSPA_Data*>
244  (i, data));
245 
246  m_backupControlPortsIn.push_back(0.0);
247 
248  } else {
249  LADSPA_Data *data = new LADSPA_Data(0.0);
250  m_controlPortsOut.push_back(
251  std::pair<long, LADSPA_Data*>(i, data));
252  if (!strcmp(descriptor->PortNames[i], "latency") ||
253  !strcmp(descriptor->PortNames[i], "_latency")) {
254 #ifdef DEBUG_DSSI
255  cerr << "Wooo! We have a latency port!" << endl;
256 #endif
257  m_latencyPort = data;
258  }
259  }
260  }
261 #ifdef DEBUG_DSSI
262  else
263  SVDEBUG << "DSSIPluginInstance::DSSIPluginInstance - "
264  << "unrecognised port type" << endl;
265 #endif
266  }
267 
269  (int)m_audioPortsOut.size());
270 }
271 
274 {
275  sv_frame_t latency = 0;
276 
277 #ifdef DEBUG_DSSI_PROCESS
278  SVDEBUG << "DSSIPluginInstance::getLatency(): m_latencyPort " << m_latencyPort << ", m_run " << m_run << endl;
279 #endif
280 
281  if (m_latencyPort) {
282  if (!m_run) {
283  for (int i = 0; i < getAudioInputCount(); ++i) {
284  for (int j = 0; j < m_blockSize; ++j) {
285  m_inputBuffers[i][j] = 0.f;
286  }
287  }
288  run(Vamp::RealTime::zeroTime);
289  }
290  latency = (sv_frame_t)(*m_latencyPort + 0.1);
291  }
292 
293 #ifdef DEBUG_DSSI_PROCESS
294  SVDEBUG << "DSSIPluginInstance::getLatency(): latency is " << latency << endl;
295 #endif
296 
297  return latency;
298 }
299 
300 void
302 {
303  if (m_instanceHandle != nullptr) {
304  deactivate();
305  activate();
306  }
307 }
308 
309 void
311 {
313 }
314 
315 void
317 {
318 #ifdef DEBUG_DSSI
319  SVDEBUG << "DSSIPluginInstance::setIdealChannelCount: channel count "
320  << channels << " (was " << m_idealChannelCount << ")" << endl;
321 #endif
322 
323  if (channels == m_idealChannelCount) {
324  silence();
325  return;
326  }
327 
328  if (m_instanceHandle != nullptr) {
329  deactivate();
330  }
331 
332  m_idealChannelCount = channels;
333 
334  if (channels > m_outputBufferCount) {
335 
336  for (int i = 0; i < m_outputBufferCount; ++i) {
337  delete[] m_outputBuffers[i];
338  }
339 
340  delete[] m_outputBuffers;
341 
342  m_outputBufferCount = channels;
343 
345 
346  for (int i = 0; i < m_outputBufferCount; ++i) {
348  }
349 
350  connectPorts();
351  }
352 
353  if (m_instanceHandle != nullptr) {
354  activate();
355  }
356 }
357 
358 void
360 {
361  if (!m_grouped) return;
362  m_groupMap[m_identifier].erase(this);
363  m_grouped = false;
364 }
365 
366 void
368 {
369  if (!m_descriptor->run_multiple_synths) {
370  m_grouped = false;
371  return;
372  }
373 
375 
376  size_t pluginsInGroup = m_groupMap[m_identifier].size();
377 
378  if (++pluginsInGroup > m_groupLocalEventBufferCount) {
379 
380  size_t nextBufferCount = pluginsInGroup * 2;
381 
382  snd_seq_event_t **eventLocalBuffers = new snd_seq_event_t *[nextBufferCount];
383 
384  for (size_t i = 0; i < m_groupLocalEventBufferCount; ++i) {
385  eventLocalBuffers[i] = m_groupLocalEventBuffers[i];
386  }
387  for (size_t i = m_groupLocalEventBufferCount; i < nextBufferCount; ++i) {
388  eventLocalBuffers[i] = new snd_seq_event_t[EVENT_BUFFER_SIZE];
389  }
390 
394  }
395 
396  m_groupLocalEventBuffers = eventLocalBuffers;
397  m_groupLocalEventBufferCount = nextBufferCount;
398  }
399 
400  m_grouped = true;
401  m_groupMap[m_identifier].insert(this);
402 }
403 
405 {
406 #ifdef DEBUG_DSSI
407  SVDEBUG << "DSSIPluginInstance::~DSSIPluginInstance" << endl;
408 #endif
409 
410  if (m_threads.find(m_instanceHandle) != m_threads.end()) {
411 
412  for (std::set<NonRTPluginThread *>::iterator i =
413  m_threads[m_instanceHandle].begin();
414  i != m_threads[m_instanceHandle].end(); ++i) {
415 
416  (*i)->setExiting();
417  (*i)->wait();
418  delete *i;
419  }
420 
422  }
423 
424  detachFromGroup();
425 
426  if (m_instanceHandle != nullptr) {
427  deactivate();
428  }
429 
430  cleanup();
431 
432  for (int i = 0; in_range_for(m_controlPortsIn, i); ++i)
433  delete m_controlPortsIn[i].second;
434 
435  for (int i = 0; in_range_for(m_controlPortsOut, i); ++i)
436  delete m_controlPortsOut[i].second;
437 
438  m_controlPortsIn.clear();
439  m_controlPortsOut.clear();
440 
441  if (m_ownBuffers) {
442  for (int i = 0; i < getAudioInputCount(); ++i) {
443  delete[] m_inputBuffers[i];
444  }
445  for (int i = 0; i < m_outputBufferCount; ++i) {
446  delete[] m_outputBuffers[i];
447  }
448 
449  delete[] m_inputBuffers;
450  delete[] m_outputBuffers;
451  }
452 
453  m_audioPortsIn.clear();
454  m_audioPortsOut.clear();
455 }
456 
457 
458 void
460 {
461  if (!m_descriptor) return;
462 
463 #ifdef DEBUG_DSSI
464  cout << "DSSIPluginInstance::instantiate - plugin \"unique\" id = "
465  << m_descriptor->LADSPA_Plugin->UniqueID << endl;
466 #endif
467  const LADSPA_Descriptor *descriptor = m_descriptor->LADSPA_Plugin;
468 
469  if (!descriptor->instantiate) {
470  cerr << "Bad plugin: plugin id " << descriptor->UniqueID
471  << ":" << descriptor->Label
472  << " has no instantiate method!" << endl;
473  return;
474  }
475 
476  unsigned long pluginRate = (unsigned long)(sampleRate);
477  if (sampleRate != sv_samplerate_t(pluginRate)) {
478  cerr << "DSSIPluginInstance: WARNING: Non-integer sample rate "
479  << sampleRate << " presented, rounding to " << pluginRate
480  << endl;
481  }
482  m_instanceHandle = descriptor->instantiate(descriptor, pluginRate);
483 
484  if (m_instanceHandle) {
485 
486  if (m_descriptor->get_midi_controller_for_port) {
487 
488  for (int i = 0; i < (int)descriptor->PortCount; ++i) {
489 
490  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]) &&
491  LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
492 
493  int controller = m_descriptor->get_midi_controller_for_port
494  (m_instanceHandle, i);
495 
496  if (controller != 0 && controller != 32 &&
497  DSSI_IS_CC(controller)) {
498 
499  m_controllerMap[DSSI_CC_NUMBER(controller)] = i;
500  }
501  }
502  }
503  }
504  }
505 }
506 
507 void
509 {
510  if (m_programCacheValid) return;
511  m_cachedPrograms.clear();
512 
513 #ifdef DEBUG_DSSI
514  SVDEBUG << "DSSIPluginInstance::checkProgramCache" << endl;
515 #endif
516 
517  if (!m_descriptor || !m_descriptor->get_program) {
518  m_programCacheValid = true;
519  return;
520  }
521 
522  int index = 0;
523  const DSSI_Program_Descriptor *programDescriptor;
524  while ((programDescriptor = m_descriptor->get_program(m_instanceHandle, index))) {
525  ++index;
527  d.bank = (int)programDescriptor->Bank;
528  d.program = (int)programDescriptor->Program;
529  d.name = programDescriptor->Name;
530  m_cachedPrograms.push_back(d);
531  }
532 
533 #ifdef DEBUG_DSSI
534  SVDEBUG << "DSSIPluginInstance::checkProgramCache: have " << m_cachedPrograms.size() << " programs" << endl;
535 #endif
536 
537  m_programCacheValid = true;
538 }
539 
540 DSSIPluginInstance::ProgramList
542 {
543 #ifdef DEBUG_DSSI
544  SVDEBUG << "DSSIPluginInstance::getPrograms" << endl;
545 #endif
546 
547  if (!m_descriptor) return ProgramList();
548 
550 
551  ProgramList programs;
552 
553  for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
554  i != m_cachedPrograms.end(); ++i) {
555  programs.push_back(i->name);
556  }
557 
558  return programs;
559 }
560 
561 std::string
562 DSSIPluginInstance::getProgram(int bank, int program) const
563 {
564 #ifdef DEBUG_DSSI
565  SVDEBUG << "DSSIPluginInstance::getProgram(" << bank << "," << program << ")" << endl;
566 #endif
567 
568  if (!m_descriptor) return std::string();
569 
571 
572  for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
573  i != m_cachedPrograms.end(); ++i) {
574  if (i->bank == bank && i->program == program) return i->name;
575  }
576 
577  return std::string();
578 }
579 
580 int
581 DSSIPluginInstance::getProgram(std::string name) const
582 {
583 #ifdef DEBUG_DSSI
584  SVDEBUG << "DSSIPluginInstance::getProgram(" << name << ")" << endl;
585 #endif
586 
587  if (!m_descriptor) return 0;
588 
590 
591  int rv;
592 
593  for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
594  i != m_cachedPrograms.end(); ++i) {
595  if (i->name == name) {
596  rv = i->bank;
597  rv = (rv << 16) + i->program;
598  return rv;
599  }
600  }
601 
602  return 0;
603 }
604 
605 std::string
607 {
608  return m_program;
609 }
610 
611 void
613 {
614  selectProgramAux(program, true);
615 }
616 
617 void
618 DSSIPluginInstance::selectProgramAux(std::string program, bool backupPortValues)
619 {
620 #ifdef DEBUG_DSSI
621  SVDEBUG << "DSSIPluginInstance::selectProgram(" << program << ")" << endl;
622 #endif
623 
624  if (!m_descriptor) return;
625 
627 
628  if (!m_descriptor->select_program) return;
629 
630  bool found = false;
631  int bankNo = 0, programNo = 0;
632 
633  for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
634  i != m_cachedPrograms.end(); ++i) {
635 
636  if (i->name == program) {
637 
638  bankNo = i->bank;
639  programNo = i->program;
640  found = true;
641 
642 #ifdef DEBUG_DSSI
643  SVDEBUG << "DSSIPluginInstance::selectProgram(" << program << "): found at bank " << bankNo << ", program " << programNo << endl;
644 #endif
645 
646  break;
647  }
648  }
649 
650  if (!found) return;
651  m_program = program;
652 
653  // DSSI select_program is an audio context call
654  m_processLock.lock();
655  m_descriptor->select_program(m_instanceHandle, bankNo, programNo);
656  m_processLock.unlock();
657 
658 #ifdef DEBUG_DSSI
659  SVDEBUG << "DSSIPluginInstance::selectProgram(" << program << "): made select_program(" << bankNo << "," << programNo << ") call" << endl;
660 #endif
661 
662  if (backupPortValues) {
663  for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
665  }
666  }
667 }
668 
669 void
671 {
672 #ifdef DEBUG_DSSI
673  SVDEBUG << "DSSIPluginInstance::activate" << endl;
674 #endif
675 
676  if (!m_descriptor || !m_descriptor->LADSPA_Plugin->activate) return;
677  m_descriptor->LADSPA_Plugin->activate(m_instanceHandle);
678 
679  if (m_program != "") {
680 #ifdef DEBUG_DSSI
681  SVDEBUG << "DSSIPluginInstance::activate: restoring program " << m_program << endl;
682 #endif
683  selectProgramAux(m_program, false);
684  }
685 
686  for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
687 #ifdef DEBUG_DSSI
688  SVDEBUG << "DSSIPluginInstance::activate: setting port " << m_controlPortsIn[i].first << " to " << m_backupControlPortsIn[i] << endl;
689 #endif
691  }
692 }
693 
694 void
696 {
697  if (!m_descriptor || !m_descriptor->LADSPA_Plugin->connect_port) return;
698 #ifdef DEBUG_DSSI
699  SVDEBUG << "DSSIPluginInstance::connectPorts: " << getAudioInputCount()
700  << " audio ports in, " << m_audioPortsOut.size() << " out, "
701  << m_outputBufferCount << " output buffers" << endl;
702 #endif
703 
704  assert(sizeof(LADSPA_Data) == sizeof(float));
705  assert(sizeof(sample_t) == sizeof(float));
706 
707  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
708  int inbuf = 0, outbuf = 0;
709 
710  for (int i = 0; i < getAudioInputCount(); ++i) {
711  m_descriptor->LADSPA_Plugin->connect_port
713  m_audioPortsIn[i],
714  (LADSPA_Data *)m_inputBuffers[inbuf]);
715  ++inbuf;
716  }
717 
718  for (size_t i = 0; i < m_audioPortsOut.size(); ++i) {
719  m_descriptor->LADSPA_Plugin->connect_port
721  m_audioPortsOut[i],
722  (LADSPA_Data *)m_outputBuffers[outbuf]);
723  ++outbuf;
724  }
725 
726  for (size_t i = 0; i < m_controlPortsIn.size(); ++i) {
727  m_descriptor->LADSPA_Plugin->connect_port
729  m_controlPortsIn[i].first,
730  m_controlPortsIn[i].second);
731 
732  if (f) {
733  float defaultValue = f->getPortDefault
734  (m_descriptor->LADSPA_Plugin, (int)m_controlPortsIn[i].first);
735  *m_controlPortsIn[i].second = defaultValue;
736  m_backupControlPortsIn[i] = defaultValue;
737 #ifdef DEBUG_DSSI
738  SVDEBUG << "DSSIPluginInstance::connectPorts: set control port " << i << " to default value " << defaultValue << endl;
739 #endif
740  }
741  }
742 
743  for (size_t i = 0; i < m_controlPortsOut.size(); ++i) {
744  m_descriptor->LADSPA_Plugin->connect_port
746  m_controlPortsOut[i].first,
747  m_controlPortsOut[i].second);
748  }
749 }
750 
751 int
753 {
754  return (int)m_controlPortsIn.size();
755 }
756 
757 void
758 DSSIPluginInstance::setParameterValue(int parameter, float value)
759 {
760 #ifdef DEBUG_DSSI
761  SVDEBUG << "DSSIPluginInstance::setParameterValue(" << parameter << ") to " << value << endl;
762 #endif
763  if (!in_range_for(m_controlPortsIn, parameter)) return;
764 
765  int portNumber = m_controlPortsIn[parameter].first;
766 
767  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
768  if (f) {
769  if (value < f->getPortMinimum(m_descriptor->LADSPA_Plugin, portNumber)) {
770  value = f->getPortMinimum(m_descriptor->LADSPA_Plugin, portNumber);
771  }
772  if (value > f->getPortMaximum(m_descriptor->LADSPA_Plugin, portNumber)) {
773  value = f->getPortMaximum(m_descriptor->LADSPA_Plugin, portNumber);
774  }
775  }
776 
777  (*m_controlPortsIn[parameter].second) = value;
778  m_backupControlPortsIn[parameter] = value;
779 }
780 
781 void
783 {
784 #ifdef DEBUG_DSSI
785  SVDEBUG << "DSSIPluginInstance::setPortValueFromController(" << port << ") to " << cv << endl;
786 #endif
787 
788  const LADSPA_Descriptor *p = m_descriptor->LADSPA_Plugin;
789  LADSPA_PortRangeHintDescriptor d = p->PortRangeHints[port].HintDescriptor;
790  LADSPA_Data lb = p->PortRangeHints[port].LowerBound;
791  LADSPA_Data ub = p->PortRangeHints[port].UpperBound;
792 
793  float value = (float)cv;
794 
795  if (!LADSPA_IS_HINT_BOUNDED_BELOW(d)) {
796  if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
797  /* unbounded: might as well leave the value alone. */
798  } else {
799  /* bounded above only. just shift the range. */
800  value = ub - 127.0f + value;
801  }
802  } else {
803  if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
804  /* bounded below only. just shift the range. */
805  value = lb + value;
806  } else {
807  /* bounded both ends. more interesting. */
808  /* XXX !!! todo: fill in logarithmic, sample rate &c */
809  value = lb + ((ub - lb) * value / 127.0f);
810  }
811  }
812 
813  for (int i = 0; in_range_for(m_controlPortsIn, i); ++i) {
814  if (m_controlPortsIn[i].first == port) {
815  setParameterValue(i, value);
816  }
817  }
818 }
819 
820 float
822 {
823  if (!in_range_for(m_controlPortsOut, output)) return 0.0;
824  return (*m_controlPortsOut[output].second);
825 }
826 
827 float
829 {
830 #ifdef DEBUG_DSSI
831  SVDEBUG << "DSSIPluginInstance::getParameterValue(" << parameter << ")" << endl;
832 #endif
833  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
834  return (*m_controlPortsIn[parameter].second);
835 }
836 
837 float
839 {
840  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
841 
842  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
843  if (f) {
844  return f->getPortDefault(m_descriptor->LADSPA_Plugin,
845  m_controlPortsIn[parameter].first);
846  } else {
847  return 0.0f;
848  }
849 }
850 
851 int
853 {
854  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
855 
856  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
857  if (f) {
858  return f->getPortDisplayHint(m_descriptor->LADSPA_Plugin,
859  m_controlPortsIn[parameter].first);
860  } else {
861  return PortHint::NoHint;
862  }
863 }
864 
865 std::string
867  std::string value)
868 {
869  if (!m_descriptor || !m_descriptor->configure) return std::string();
870 
871  if (key == PluginIdentifier::RESERVED_PROJECT_DIRECTORY_KEY.toStdString()) {
872 #ifdef DSSI_PROJECT_DIRECTORY_KEY
873  key = DSSI_PROJECT_DIRECTORY_KEY;
874 #else
875  return std::string();
876 #endif
877  }
878 
879 
880 #ifdef DEBUG_DSSI
881  SVDEBUG << "DSSIPluginInstance::configure(" << key << "," << value << ")" << endl;
882 #endif
883 
884  char *message = m_descriptor->configure(m_instanceHandle,
885  key.c_str(),
886  value.c_str());
887 
888  m_programCacheValid = false;
889 
890  m_configurationData[key] = value;
891 
892  std::string qm;
893 
894  // Ignore return values from reserved key configuration calls such
895  // as project directory
896 #ifdef DSSI_RESERVED_CONFIGURE_PREFIX
897  if (QString(key.c_str()).startsWith(DSSI_RESERVED_CONFIGURE_PREFIX)) {
898  return qm;
899  }
900 #endif
901 
902  if (message) {
903  if (m_descriptor->LADSPA_Plugin && m_descriptor->LADSPA_Plugin->Label) {
904  qm = std::string(m_descriptor->LADSPA_Plugin->Label) + ": ";
905  }
906  qm = qm + message;
907  free(message);
908 
909  cerr << "DSSIPluginInstance::configure: warning: configure returned message: \"" << qm << "\"" << endl;
910  }
911 
912  return qm;
913 }
914 
915 void
917  const void *e)
918 {
919 #ifdef DEBUG_DSSI_PROCESS
920  SVDEBUG << "DSSIPluginInstance::sendEvent: last was " << m_lastEventSendTime << " (valid " << m_haveLastEventSendTime << "), this is " << eventTime << endl;
921 #endif
922 
923  // The process mechanism only works correctly if the events are
924  // sorted. It's the responsibility of the caller to ensure that:
925  // we will happily drop events here if we find the timeline going
926  // backwards.
928  m_lastEventSendTime > eventTime) {
929 #ifdef DEBUG_DSSI_PROCESS
930  cerr << "... clearing down" << endl;
931 #endif
932  m_haveLastEventSendTime = false;
933  clearEvents();
934  }
935 
936  snd_seq_event_t *event = (snd_seq_event_t *)e;
937 #ifdef DEBUG_DSSI_PROCESS
938  SVDEBUG << "DSSIPluginInstance::sendEvent at " << eventTime << endl;
939 #endif
940  snd_seq_event_t ev(*event);
941 
942  ev.time.time.tv_sec = eventTime.sec;
943  ev.time.time.tv_nsec = eventTime.nsec;
944 
945  // DSSI doesn't use MIDI channels, it uses run_multiple_synths instead.
946  ev.data.note.channel = 0;
947 
948  m_eventBuffer.write(&ev, 1);
949 
950  m_lastEventSendTime = eventTime;
952 }
953 
954 void
956 {
957  m_haveLastEventSendTime = false;
959 }
960 
961 bool
963 {
964  int controller = ev->data.control.param;
965 
966 #ifdef DEBUG_DSSI_PROCESS
967  SVDEBUG << "DSSIPluginInstance::handleController " << controller << endl;
968 #endif
969 
970  if (controller == 0) { // bank select MSB
971 
972  m_pending.msb = ev->data.control.value;
973 
974  } else if (controller == 32) { // bank select LSB
975 
976  m_pending.lsb = ev->data.control.value;
977 
978  } else if (controller > 0 && controller < 128) {
979 
980  if (m_controllerMap.find(controller) != m_controllerMap.end()) {
981  int port = m_controllerMap[controller];
982  setPortValueFromController(port, ev->data.control.value);
983  } else {
984  return true; // pass through to plugin
985  }
986  }
987 
988  return false;
989 }
990 
991 void
992 DSSIPluginInstance::run(const RealTime &blockTime, int count)
993 {
994  static snd_seq_event_t localEventBuffer[EVENT_BUFFER_SIZE];
995  int evCount = 0;
996 
997  if (count == 0) count = m_blockSize;
998 
999  bool needLock = false;
1000  if (m_descriptor && m_descriptor->select_program) needLock = true;
1001 
1002  if (needLock) {
1003  if (!m_processLock.tryLock()) {
1004  for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
1005  memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
1006  }
1007  return;
1008  }
1009  }
1010 
1011  if (m_grouped) {
1012  runGrouped(blockTime);
1013  goto done;
1014  }
1015 
1016  if (!m_descriptor || !m_descriptor->run_synth) {
1018  m_haveLastEventSendTime = false;
1019  if (m_descriptor && m_descriptor->LADSPA_Plugin->run) {
1020  m_descriptor->LADSPA_Plugin->run(m_instanceHandle, count);
1021  } else {
1022  for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
1023  memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
1024  }
1025  }
1026  m_run = true;
1027  if (needLock) m_processLock.unlock();
1028  return;
1029  }
1030 
1031 #ifdef DEBUG_DSSI_PROCESS
1032  SVDEBUG << "DSSIPluginInstance::run(" << blockTime << ")" << endl;
1033 #endif
1034 
1035 #ifdef DEBUG_DSSI_PROCESS
1036  if (m_eventBuffer.getReadSpace() > 0) {
1037  SVDEBUG << "DSSIPluginInstance::run: event buffer has "
1038  << m_eventBuffer.getReadSpace() << " event(s) in it" << endl;
1039  }
1040 #endif
1041 
1042  while (m_eventBuffer.getReadSpace() > 0) {
1043 
1044  snd_seq_event_t *ev = localEventBuffer + evCount;
1045  *ev = m_eventBuffer.peekOne();
1046  bool accept = true;
1047 
1048  RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
1049 
1050  sv_frame_t frameOffset = 0;
1051  if (evTime > blockTime) {
1052  frameOffset = RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
1053  }
1054 
1055 #ifdef DEBUG_DSSI_PROCESS
1056  SVDEBUG << "DSSIPluginInstance::run: evTime " << evTime << ", blockTime " << blockTime << ", frameOffset " << frameOffset
1057  << ", blockSize " << m_blockSize << endl;
1058  cerr << "Type: " << int(ev->type) << ", pitch: " << int(ev->data.note.note) << ", velocity: " << int(ev->data.note.velocity) << endl;
1059 #endif
1060 
1061  if (frameOffset >= (long)count) break;
1062  if (frameOffset < 0) {
1063  frameOffset = 0;
1064  if (ev->type == SND_SEQ_EVENT_NOTEON) {
1065  m_eventBuffer.skip(1);
1066  continue;
1067  }
1068  }
1069 
1070  ev->time.tick = (snd_seq_tick_time_t)frameOffset;
1071  m_eventBuffer.skip(1);
1072 
1073  if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
1074  accept = handleController(ev);
1075  } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
1076  m_pending.program = ev->data.control.value;
1077  accept = false;
1078  }
1079 
1080  if (accept) {
1081  if (++evCount >= EVENT_BUFFER_SIZE) break;
1082  }
1083  }
1084 
1085  if (m_pending.program >= 0 && m_descriptor->select_program) {
1086 
1087  int program = m_pending.program;
1088  int bank = m_pending.lsb + 128 * m_pending.msb;
1089 
1090 #ifdef DEBUG_DSSI
1091  SVDEBUG << "DSSIPluginInstance::run: making select_program(" << bank << "," << program << ") call" << endl;
1092 #endif
1093 
1095  m_descriptor->select_program(m_instanceHandle, bank, program);
1096 
1097 #ifdef DEBUG_DSSI
1098  SVDEBUG << "DSSIPluginInstance::run: made select_program(" << bank << "," << program << ") call" << endl;
1099 #endif
1100  }
1101 
1102 #ifdef DEBUG_DSSI_PROCESS
1103  SVDEBUG << "DSSIPluginInstance::run: running with " << evCount << " events"
1104  << endl;
1105 #endif
1106 
1107  m_descriptor->run_synth(m_instanceHandle, count,
1108  localEventBuffer, evCount);
1109 
1110 #ifdef DEBUG_DSSI_PROCESS
1111 // for (int i = 0; i < count; ++i) {
1112 // cout << m_outputBuffers[0][i] << " ";
1113 // if (i % 8 == 0) cout << endl;
1114 // }
1115 #endif
1116 
1117  done:
1118  if (needLock) m_processLock.unlock();
1119 
1120  int numAudioOuts = int(m_audioPortsOut.size());
1121 
1122  if (numAudioOuts == 0) {
1123  // copy inputs to outputs
1124  for (int ch = 0; ch < m_idealChannelCount; ++ch) {
1125  int sch = ch % getAudioInputCount();
1126  for (int i = 0; i < m_blockSize; ++i) {
1127  m_outputBuffers[ch][i] = m_inputBuffers[sch][i];
1128  }
1129  }
1130  } else if (m_idealChannelCount < numAudioOuts) {
1131  if (m_idealChannelCount == 1) {
1132  // mix down to mono
1133  for (int ch = 1; ch < numAudioOuts; ++ch) {
1134  for (int i = 0; i < m_blockSize; ++i) {
1135  m_outputBuffers[0][i] += m_outputBuffers[ch][i];
1136  }
1137  }
1138  }
1139  } else if (m_idealChannelCount > numAudioOuts) {
1140  // duplicate
1141  for (int ch = numAudioOuts; ch < m_idealChannelCount; ++ch) {
1142  int sch = (ch - numAudioOuts) % numAudioOuts;
1143  for (int i = 0; i < m_blockSize; ++i) {
1144  m_outputBuffers[ch][i] = m_outputBuffers[sch][i];
1145  }
1146  }
1147  }
1148 
1149  m_lastRunTime = blockTime;
1150  m_run = true;
1151 }
1152 
1153 void
1155 {
1156  // If something else in our group has just been called for this
1157  // block time (but we haven't) then we should just write out the
1158  // results and return; if we have just been called for this block
1159  // time or nothing else in the group has been, we should run the
1160  // whole group.
1161 
1162  bool needRun = true;
1163 
1165 
1166 #ifdef DEBUG_DSSI_PROCESS
1167  SVDEBUG << "DSSIPluginInstance::runGrouped(" << blockTime << "): this is " << this << "; " << s.size() << " elements in m_groupMap[" << m_identifier << "]" << endl;
1168 #endif
1169 
1170  if (m_lastRunTime != blockTime) {
1171  for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
1173  if (instance != this && instance->m_lastRunTime == blockTime) {
1174 #ifdef DEBUG_DSSI_PROCESS
1175  SVDEBUG << "DSSIPluginInstance::runGrouped(" << blockTime << "): plugin " << instance << " has already been run" << endl;
1176 #endif
1177  needRun = false;
1178  }
1179  }
1180  }
1181 
1182  if (!needRun) {
1183 #ifdef DEBUG_DSSI_PROCESS
1184  SVDEBUG << "DSSIPluginInstance::runGrouped(" << blockTime << "): already run, returning" << endl;
1185 #endif
1186  return;
1187  }
1188 
1189 #ifdef DEBUG_DSSI_PROCESS
1190  SVDEBUG << "DSSIPluginInstance::runGrouped(" << blockTime << "): I'm the first, running" << endl;
1191 #endif
1192 
1193  size_t index = 0;
1194  unsigned long *counts = (unsigned long *)
1195  alloca(m_groupLocalEventBufferCount * sizeof(unsigned long));
1196  LADSPA_Handle *instances = (LADSPA_Handle *)
1197  alloca(m_groupLocalEventBufferCount * sizeof(LADSPA_Handle));
1198 
1199  for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
1200 
1201  if (index >= m_groupLocalEventBufferCount) break;
1202 
1204  counts[index] = 0;
1205  instances[index] = instance->m_instanceHandle;
1206 
1207 #ifdef DEBUG_DSSI_PROCESS
1208  SVDEBUG << "DSSIPluginInstance::runGrouped(" << blockTime << "): running " << instance << endl;
1209 #endif
1210 
1211  if (instance->m_pending.program >= 0 &&
1212  instance->m_descriptor->select_program) {
1213  int program = instance->m_pending.program;
1214  int bank = instance->m_pending.lsb + 128 * instance->m_pending.msb;
1215  instance->m_pending.lsb = instance->m_pending.msb = instance->m_pending.program = -1;
1216  instance->m_descriptor->select_program
1217  (instance->m_instanceHandle, bank, program);
1218  }
1219 
1220  while (instance->m_eventBuffer.getReadSpace() > 0) {
1221 
1222  snd_seq_event_t *ev = m_groupLocalEventBuffers[index] + counts[index];
1223  *ev = instance->m_eventBuffer.peekOne();
1224  bool accept = true;
1225 
1226  RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
1227 
1228  sv_frame_t frameOffset = 0;
1229  if (evTime > blockTime) {
1230  frameOffset = RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
1231  }
1232 
1233 #ifdef DEBUG_DSSI_PROCESS
1234  SVDEBUG << "DSSIPluginInstance::runGrouped: evTime " << evTime << ", frameOffset " << frameOffset
1235  << ", block size " << m_blockSize << endl;
1236 #endif
1237 
1238  if (frameOffset >= int(m_blockSize)) break;
1239  if (frameOffset < 0) frameOffset = 0;
1240 
1241  ev->time.tick = snd_seq_tick_time_t(frameOffset);
1242  instance->m_eventBuffer.skip(1);
1243 
1244  if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
1245  accept = instance->handleController(ev);
1246  } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
1247  instance->m_pending.program = ev->data.control.value;
1248  accept = false;
1249  }
1250 
1251  if (accept) {
1252  if (++counts[index] >= EVENT_BUFFER_SIZE) break;
1253  }
1254  }
1255 
1256  ++index;
1257  }
1258 
1259  m_descriptor->run_multiple_synths(index,
1260  instances,
1261  m_blockSize,
1263  counts);
1264 }
1265 
1266 int
1267 DSSIPluginInstance::requestMidiSend(LADSPA_Handle /* instance */,
1268  unsigned char /* ports */,
1269  unsigned char /* channels */)
1270 {
1271  // This is called from a non-RT context (during instantiate)
1272 
1273  SVDEBUG << "DSSIPluginInstance::requestMidiSend" << endl;
1274  return 1;
1275 }
1276 
1277 void
1278 DSSIPluginInstance::midiSend(LADSPA_Handle /* instance */,
1279  snd_seq_event_t * /* events */,
1280  unsigned long /* eventCount */)
1281 {
1282  // This is likely to be called from an RT context
1283 
1284  SVDEBUG << "DSSIPluginInstance::midiSend" << endl;
1285 }
1286 
1287 void
1289 {
1290  while (!m_exiting) {
1291  m_runFunction(m_handle);
1292  usleep(100000);
1293  }
1294 }
1295 
1296 int
1298  void (*runFunction)(LADSPA_Handle))
1299 {
1300  NonRTPluginThread *thread = new NonRTPluginThread(instance, runFunction);
1301  m_threads[instance].insert(thread);
1302  thread->start();
1303  return 0;
1304 }
1305 
1306 void
1308 {
1309 #ifdef DEBUG_DSSI
1310  SVDEBUG << "DSSIPluginInstance::deactivate " << m_identifier << endl;
1311 #endif
1312  if (!m_descriptor || !m_descriptor->LADSPA_Plugin->deactivate) return;
1313 
1314  for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
1315  m_backupControlPortsIn[i] = *m_controlPortsIn[i].second;
1316  }
1317 
1318  m_descriptor->LADSPA_Plugin->deactivate(m_instanceHandle);
1319 #ifdef DEBUG_DSSI
1320  SVDEBUG << "DSSIPluginInstance::deactivate " << m_identifier << " done" << endl;
1321 #endif
1322 
1324 }
1325 
1326 void
1328 {
1329 #ifdef DEBUG_DSSI
1330  SVDEBUG << "DSSIPluginInstance::cleanup " << m_identifier << endl;
1331 #endif
1332  if (!m_descriptor) return;
1333 
1334  if (!m_descriptor->LADSPA_Plugin->cleanup) {
1335  cerr << "Bad plugin: plugin id "
1336  << m_descriptor->LADSPA_Plugin->UniqueID
1337  << ":" << m_descriptor->LADSPA_Plugin->Label
1338  << " has no cleanup method!" << endl;
1339  return;
1340  }
1341 
1342  m_descriptor->LADSPA_Plugin->cleanup(m_instanceHandle);
1343  m_instanceHandle = nullptr;
1344 #ifdef DEBUG_DSSI
1345  SVDEBUG << "DSSIPluginInstance::cleanup " << m_identifier << " done" << endl;
1346 #endif
1347 }
1348 
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
T peekOne(int R=0) const
Read one sample from the buffer, if available, without advancing the read pointer – i...
Definition: RingBuffer.h:409
std::vector< LADSPA_Data > m_backupControlPortsIn
std::vector< std::pair< int, LADSPA_Data * > > m_controlPortsOut
static int requestMidiSend(LADSPA_Handle instance, unsigned char ports, unsigned char channels)
std::string configure(std::string key, std::string value) override
static std::map< LADSPA_Handle, std::set< NonRTPluginThread * > > m_threads
int getPortDisplayHint(const LADSPA_Descriptor *, int port)
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
static QString RESERVED_PROJECT_DIRECTORY_KEY
float getControlOutputValue(int n) const override
static const int NoHint
static void midiSend(LADSPA_Handle instance, snd_seq_event_t *events, unsigned long eventCount)
std::map< int, int > m_controllerMap
int getPluginVersion() const override
int nsec
Definition: RealTime.h:45
bool handleController(snd_seq_event_t *ev)
A very simple class that facilitates running things like plugins without locking, by collecting unwan...
Definition: Scavenger.h:44
void start()
Definition: Thread.cpp:34
void setParameterValue(int parameter, float value) override
static snd_seq_event_t ** m_groupLocalEventBuffers
void scavenge(bool clearNow=false)
Call from a non-RT thread.
Definition: Scavenger.h:150
ConfigurationPairMap m_configurationData
std::string getName() const override
RingBuffer< snd_seq_event_t > m_eventBuffer
int getParameterDisplayHint(int parameter) const override
std::string getMaker() const override
void selectProgram(std::string program) override
void selectProgramAux(std::string program, bool backupPortValues)
void reset()
Reset read and write pointers, thus emptying the buffer.
Definition: RingBuffer.h:222
float getPortDefault(const LADSPA_Descriptor *, int port)
void run(const RealTime &, int count=0) override
Run for one block, starting at the given time.
std::vector< ProgramDescriptor > m_cachedPrograms
int getParameterCount() const override
std::vector< int > m_audioPortsOut
void setIdealChannelCount(int channels) override
static sv_samplerate_t m_sampleRate
std::string getProgram(int bank, int program) const override
float getPortMaximum(const LADSPA_Descriptor *, int port)
const DSSI_Descriptor * m_descriptor
float getParameter(std::string) const override
sv_frame_t getLatency() override
float getPortQuantization(const LADSPA_Descriptor *, int port)
static Scavenger< ScavengerArrayWrapper< snd_seq_event_t * > > m_bufferScavenger
int sec
Definition: RealTime.h:44
A wrapper to permit arrays to be scavenged.
Definition: Scavenger.h:84
ParameterList getParameterDescriptors() const override
void setParameter(std::string, float) override
bool isOK() const override
int write(const T *source, int n)
Write n samples to the buffer.
Definition: RingBuffer.h:449
#define EVENT_BUFFER_SIZE
static int requestNonRTThread(LADSPA_Handle instance, void(*runFunction)(LADSPA_Handle))
std::string getDescription() const override
int getReadSpace(int R=0) const
Return the amount of data available for reading by reader R, in samples.
Definition: RingBuffer.h:236
ProgramList getPrograms() const override
static sv_frame_t realTime2Frame(const RealTime &r, sv_samplerate_t sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
Definition: RealTimeSV.cpp:490
std::string getCurrentProgram() const override
bool in_range_for(const C &container, T i)
Check whether an integer index is in range for a container, avoiding overflows and signed/unsigned co...
Definition: BaseTypes.h:37
#define SVDEBUG
Definition: Debug.h:106
void checkProgramCache() const
void instantiate(sv_samplerate_t sampleRate)
RealTimePluginFactory * m_factory
static RealTimePluginFactory * instance(QString pluginType)
sv_samplerate_t m_sampleRate
std::ostream & operator<<(std::ostream &ostr, const TypedId< T > &id)
Definition: ById.h:140
std::vector< std::pair< int, LADSPA_Data * > > m_controlPortsIn
float getParameterDefault(int parameter) const override
void setPortValueFromController(int portNumber, int controlValue)
void runGrouped(const RealTime &)
float getParameterValue(int parameter) const override
int skip(int n, int R=0)
Pretend to read n samples from the buffer, for reader R, without actually returning them (i...
Definition: RingBuffer.h:428
std::string getCopyright() const override
std::string getIdentifier() const override
void claim(T *t)
Call from an RT thread etc., to pass ownership of t to us.
Definition: Scavenger.h:125
static size_t m_groupLocalEventBufferCount
ProgramControl m_pending
static GroupMap m_groupMap
void discardEvents() override
void sendEvent(const RealTime &eventTime, const void *event) override
virtual void detachFromGroup()
std::vector< int > m_audioPortsIn
float getPortMinimum(const LADSPA_Descriptor *, int port)
std::map< QString, PluginSet > GroupMap
int getAudioInputCount() const override
void clearEvents() override
std::set< DSSIPluginInstance * > PluginSet
LADSPA_Handle m_instanceHandle
DSSIPluginInstance(RealTimePluginFactory *factory, int client, QString identifier, int position, sv_samplerate_t sampleRate, int blockSize, int idealChannelCount, const DSSI_Descriptor *descriptor)
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
Definition: RealTime.h:42