1 /*
2  * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3  *
4  * This file is part of Zrythm
5  *
6  * Zrythm is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Zrythm is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with Zrythm.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "zrythm-config.h"
21 
22 #include "audio/audio_region.h"
23 #include "audio/audio_track.h"
24 #include "audio/channel.h"
25 #include "audio/clip.h"
26 #include "audio/control_port.h"
27 #include "audio/control_room.h"
28 #include "audio/engine.h"
29 #include "audio/fader.h"
30 #include "audio/midi_event.h"
31 #include "audio/midi_mapping.h"
32 #include "audio/midi_track.h"
33 #include "audio/recording_manager.h"
34 #include "audio/track.h"
35 #include "project.h"
36 #include "settings/settings.h"
37 #include "utils/arrays.h"
38 #include "utils/dsp.h"
39 #include "utils/flags.h"
40 #include "utils/math.h"
41 #include "utils/mem.h"
42 #include "utils/objects.h"
43 #include "zrythm.h"
44 
45 #include <glib/gi18n.h>
46 
47 static void
init_common(TrackProcessor * self)48 init_common (
49   TrackProcessor * self)
50 {
51   if (self->midi_cc[0])
52     {
53       self->cc_mappings = midi_mappings_new ();
54 
55       for (size_t i = 0; i < 16; i++)
56         {
57           for (size_t j = 0; j < 128; j++)
58             {
59               Port * cc_port =
60                 self->midi_cc[i * 128 + j];
61               g_return_if_fail (cc_port);
62 
63               /* set model bytes for CC:
64                * [0] = ctrl change + channel
65                * [1] = controller
66                * [2] (unused) = control */
67               midi_byte_t buf[3];
68               buf[0] =
69                 (midi_byte_t)
70                 (MIDI_CH1_CTRL_CHANGE | (midi_byte_t) i);
71               buf[1] = (midi_byte_t) j;
72               buf[2] = 0;
73 
74               /* bind */
75               midi_mappings_bind_track (
76                 self->cc_mappings, buf,
77                 cc_port, F_NO_PUBLISH_EVENTS);
78             }
79         }
80     }
81 }
82 
83 /**
84  * Inits fader after a project is loaded.
85  */
86 void
track_processor_init_loaded(TrackProcessor * self,Track * track)87 track_processor_init_loaded (
88   TrackProcessor * self,
89   Track *          track)
90 {
91   self->magic = TRACK_PROCESSOR_MAGIC;
92   self->track = track;
93 
94   GPtrArray * ports = g_ptr_array_new ();
95   track_processor_append_ports (self, ports);
96   for (size_t i = 0; i < ports->len; i++)
97     {
98       Port * port = g_ptr_array_index (ports, i);
99       port_init_loaded (port, self);
100     }
101   object_free_w_func_and_null (
102     g_ptr_array_unref, ports)
103 
104   init_common (self);
105 }
106 
107 /**
108  * Inits the MIDI In port of the Channel while
109  * exposing it to JACK.
110  *
111  * This assumes the caller already checked that
112  * this channel should have the given MIDI port
113  * enabled.
114  *
115  * @param in 1 for input, 0 for output.
116  * @param loading 1 if loading a channel, 0 if
117  *   new.
118  */
119 static void
init_midi_port(TrackProcessor * self,int in)120 init_midi_port (
121   TrackProcessor * self,
122   int              in)
123 {
124   if (in)
125     {
126       self->midi_in =
127         port_new_with_type_and_owner (
128           TYPE_EVENT, FLOW_INPUT, "TP MIDI in",
129           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
130       g_warn_if_fail (IS_PORT (self->midi_in));
131       self->midi_in->id.flags |=
132         PORT_FLAG_SEND_RECEIVABLE;
133     }
134   else
135     {
136       self->midi_out =
137         port_new_with_type_and_owner (
138           TYPE_EVENT, FLOW_OUTPUT, "TP MIDI out",
139           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
140       g_warn_if_fail (IS_PORT (self->midi_out));
141     }
142 }
143 
144 static void
init_midi_cc_ports(TrackProcessor * self,int loading)145 init_midi_cc_ports (
146   TrackProcessor * self,
147   int              loading)
148 {
149 #define INIT_MIDI_PORT(x,idx) \
150   x->id.flags |= PORT_FLAG_MIDI_AUTOMATABLE; \
151   x->id.flags |= PORT_FLAG_AUTOMATABLE; \
152   x->id.port_index = idx; \
153 
154   char name[400];
155   for (int i = 0; i < 16; i++)
156     {
157       /* starting from 1 */
158       int channel = i + 1;
159 
160       for (int j = 0; j < 128; j++)
161         {
162           sprintf (
163             name, "Ch%d %s", channel,
164             midi_get_cc_name (j));
165           Port * cc =
166             port_new_with_type_and_owner (
167               TYPE_CONTROL, FLOW_INPUT, name,
168               PORT_OWNER_TYPE_TRACK_PROCESSOR,
169               self);
170           INIT_MIDI_PORT (cc, i * 128 + j);
171           self->midi_cc[i * 128 + j] = cc;
172         }
173 
174       sprintf (
175         name, "Ch%d Pitch bend", i + 1);
176       Port * cc =
177         port_new_with_type_and_owner (
178           TYPE_CONTROL, FLOW_INPUT, name,
179           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
180       INIT_MIDI_PORT (cc, i);
181       cc->maxf = 8191.f;
182       cc->minf = -8192.f;
183       cc->deff = 0.f;
184       cc->zerof = 0.f;
185       cc->id.flags2 |= PORT_FLAG2_MIDI_PITCH_BEND;
186       self->pitch_bend[i] = cc;
187 
188       sprintf (
189         name, "Ch%d Poly key pressure", i + 1);
190       cc =
191         port_new_with_type_and_owner (
192           TYPE_CONTROL, FLOW_INPUT, name,
193           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
194       INIT_MIDI_PORT (cc, i);
195       cc->id.flags2 |=
196         PORT_FLAG2_MIDI_POLY_KEY_PRESSURE;
197       self->poly_key_pressure[i] = cc;
198 
199       sprintf (
200         name, "Ch%d Channel pressure", i + 1);
201       cc =
202         port_new_with_type_and_owner (
203           TYPE_CONTROL, FLOW_INPUT, name,
204           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
205       INIT_MIDI_PORT (cc, i);
206       cc->id.flags2 |=
207         PORT_FLAG2_MIDI_CHANNEL_PRESSURE;
208       self->channel_pressure[i] = cc;
209     }
210 
211 #undef INIT_MIDI_PORT
212 }
213 
214 /**
215  * Inits the stereo ports of the Channel while
216  * exposing them to the backend.
217  *
218  * This assumes the caller already checked that
219  * this channel should have the given ports
220  * enabled.
221  *
222  * @param in 1 for input, 0 for output.
223  * @param loading 1 if loading a channel, 0 if
224  *   new.
225  */
226 static void
init_stereo_out_ports(TrackProcessor * self,bool in)227 init_stereo_out_ports (
228   TrackProcessor * self,
229   bool             in)
230 {
231   Port * l, * r;
232   StereoPorts ** sp =
233     in ? &self->stereo_in : &self->stereo_out;
234   PortFlow flow = in ? FLOW_INPUT : FLOW_OUTPUT;
235 
236   l =
237     port_new_with_type_and_owner (
238       TYPE_AUDIO, flow,
239       in ? "TP Stereo in L" : "TP Stereo out L",
240       PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
241 
242   r =
243     port_new_with_type_and_owner (
244       TYPE_AUDIO, flow,
245       in ? "TP Stereo in R" : "TP Stereo out R",
246       PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
247 
248   *sp = stereo_ports_new_from_existing (l, r);
249 
250   if (in)
251     {
252       l->id.flags |= PORT_FLAG_SEND_RECEIVABLE;
253       r->id.flags |= PORT_FLAG_SEND_RECEIVABLE;
254     }
255 }
256 
257 /**
258  * Creates a new track processor for the given
259  * track.
260  */
261 TrackProcessor *
track_processor_new(Track * tr)262 track_processor_new (
263   Track *          tr)
264 {
265   TrackProcessor * self =
266     object_new (TrackProcessor);
267   self->schema_version =
268     TRACK_PROCESSOR_SCHEMA_VERSION;
269   self->magic = TRACK_PROCESSOR_MAGIC;
270   self->track = tr;
271 
272   self->l_port_db = 0.f;
273   self->r_port_db = 0.f;
274 
275   switch  (tr->in_signal_type)
276     {
277     case TYPE_EVENT:
278       init_midi_port (self, 0);
279       init_midi_port (self, 1);
280 
281       /* set up piano roll port */
282       if (track_type_has_piano_roll (tr->type) ||
283           tr->type == TRACK_TYPE_CHORD)
284         {
285           self->piano_roll =
286             port_new_with_type_and_owner (
287               TYPE_EVENT, FLOW_INPUT,
288               "TP Piano Roll",
289               PORT_OWNER_TYPE_TRACK_PROCESSOR,
290               self);
291           self->piano_roll->id.flags =
292             PORT_FLAG_PIANO_ROLL;
293           if (tr->type != TRACK_TYPE_CHORD)
294             {
295               init_midi_cc_ports (self, false);
296             }
297         }
298       break;
299     case TYPE_AUDIO:
300       init_stereo_out_ports (self, false);
301       init_stereo_out_ports (self, true);
302       if (tr->type == TRACK_TYPE_AUDIO)
303         {
304           self->mono =
305             port_new_with_type_and_owner (
306               TYPE_CONTROL, FLOW_INPUT,
307               "TP Mono Toggle",
308               PORT_OWNER_TYPE_TRACK_PROCESSOR,
309               self);
310           self->mono->id.flags |= PORT_FLAG_TOGGLE;
311           self->mono->id.flags |= PORT_FLAG_TP_MONO;
312           self->input_gain =
313             port_new_with_type_and_owner (
314               TYPE_CONTROL, FLOW_INPUT,
315               "TP Input Gain",
316               PORT_OWNER_TYPE_TRACK_PROCESSOR,
317               self);
318           self->input_gain->minf = 0.f;
319           self->input_gain->maxf = 4.f;
320           self->input_gain->zerof = 0.f;
321           self->input_gain->deff = 1.f;
322           self->input_gain->id.flags |=
323             PORT_FLAG_TP_INPUT_GAIN;
324           port_set_control_value (
325             self->input_gain, 1.f, F_NOT_NORMALIZED,
326             F_NO_PUBLISH_EVENTS);
327         }
328       break;
329     default:
330       break;
331     }
332 
333   if (tr->type == TRACK_TYPE_AUDIO)
334     {
335       self->output_gain =
336         port_new_with_type_and_owner (
337           TYPE_CONTROL, FLOW_INPUT,
338           "TP Output Gain",
339           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
340       self->output_gain->minf = 0.f;
341       self->output_gain->maxf = 4.f;
342       self->output_gain->zerof = 0.f;
343       self->output_gain->deff = 1.f;
344       self->output_gain->id.flags2 |=
345         PORT_FLAG2_TP_OUTPUT_GAIN;
346       port_set_control_value (
347         self->output_gain, 1.f, F_NOT_NORMALIZED,
348         F_NO_PUBLISH_EVENTS);
349 
350       self->monitor_audio =
351         port_new_with_type_and_owner (
352           TYPE_CONTROL, FLOW_INPUT,
353           "Monitor audio",
354           PORT_OWNER_TYPE_TRACK_PROCESSOR, self);
355       self->monitor_audio->id.flags |=
356         PORT_FLAG_TOGGLE;
357       self->monitor_audio->id.flags2 |=
358         PORT_FLAG2_TP_MONITOR_AUDIO;
359       port_set_control_value (
360         self->monitor_audio, 0.f, F_NOT_NORMALIZED,
361         F_NO_PUBLISH_EVENTS);
362     }
363 
364   init_common (self);
365 
366   return self;
367 }
368 
369 void
track_processor_append_ports(TrackProcessor * self,GPtrArray * ports)370 track_processor_append_ports (
371   TrackProcessor * self,
372   GPtrArray *      ports)
373 {
374 #define _ADD(port) \
375   g_warn_if_fail (port); \
376   g_ptr_array_add (ports, port)
377 
378   if (self->stereo_in)
379     {
380       _ADD (self->stereo_in->l);
381       _ADD (self->stereo_in->r);
382     }
383   if (self->mono)
384     {
385       _ADD (self->mono);
386     }
387   if (self->input_gain)
388     {
389       _ADD (self->input_gain);
390     }
391   if (self->output_gain)
392     {
393       _ADD (self->output_gain);
394     }
395   if (self->monitor_audio)
396     {
397       _ADD (self->monitor_audio);
398     }
399   if (self->stereo_out)
400     {
401       _ADD (self->stereo_out->l);
402       _ADD (self->stereo_out->r);
403     }
404   if (self->midi_in)
405     {
406       _ADD (self->midi_in);
407     }
408   if (self->midi_out)
409     {
410       _ADD (self->midi_out);
411     }
412   if (self->piano_roll)
413     {
414       _ADD (self->piano_roll);
415     }
416   for (int i = 0; i < 16; i++)
417     {
418       for (int j = 0; j < 128; j++)
419         {
420           if (self->midi_cc[i * 128 + j])
421             {
422               _ADD (self->midi_cc[i * 128 + j]);
423             }
424         }
425       if (self->pitch_bend[i])
426         {
427           _ADD (self->pitch_bend[i]);
428         }
429       if (self->poly_key_pressure[i])
430         {
431           _ADD (self->poly_key_pressure[i]);
432         }
433       if (self->channel_pressure[i])
434         {
435           _ADD (self->channel_pressure[i]);
436         }
437     }
438 }
439 
440 /**
441  * Clears all buffers.
442  */
443 void
track_processor_clear_buffers(TrackProcessor * self)444 track_processor_clear_buffers (
445   TrackProcessor * self)
446 {
447   /*Track * track =*/
448     /*track_processor_get_track (self);*/
449 
450   if (self->stereo_in)
451     {
452       port_clear_buffer (self->stereo_in->l);
453       port_clear_buffer (self->stereo_in->r);
454     }
455   if (self->stereo_out)
456     {
457       port_clear_buffer (self->stereo_out->l);
458       port_clear_buffer (self->stereo_out->r);
459     }
460   if (self->midi_in)
461     {
462       port_clear_buffer (self->midi_in);
463     }
464   if (self->midi_out)
465     {
466       port_clear_buffer (self->midi_out);
467     }
468   if (self->piano_roll)
469     {
470       port_clear_buffer (self->piano_roll);
471     }
472 }
473 
474 /**
475  * Disconnects all ports connected to the
476  * TrackProcessor.
477  */
478 void
track_processor_disconnect_all(TrackProcessor * self)479 track_processor_disconnect_all (
480   TrackProcessor * self)
481 {
482   Track * track =
483     track_processor_get_track (self);
484   g_return_if_fail (track);
485 
486   switch (track->in_signal_type)
487     {
488     case TYPE_AUDIO:
489       port_disconnect_all (self->mono);
490       port_disconnect_all (self->input_gain);
491       port_disconnect_all (self->output_gain);
492       port_disconnect_all (self->monitor_audio);
493       port_disconnect_all (self->stereo_in->l);
494       port_disconnect_all (self->stereo_in->r);
495       port_disconnect_all (self->stereo_out->l);
496       port_disconnect_all (self->stereo_out->r);
497       break;
498     case TYPE_EVENT:
499       port_disconnect_all (self->midi_in);
500       port_disconnect_all (self->midi_out);
501       if (track_type_has_piano_roll (track->type))
502         port_disconnect_all (self->piano_roll);
503       break;
504     default:
505       break;
506     }
507 }
508 
509 Track *
track_processor_get_track(const TrackProcessor * self)510 track_processor_get_track (
511   const TrackProcessor * self)
512 {
513   g_return_val_if_fail (
514     IS_TRACK_PROCESSOR (self) &&
515       IS_TRACK (self->track), NULL);
516 
517   return self->track;
518 }
519 
520 /**
521  * Splits the cycle and handles recording for each
522  * slot.
523  */
524 static void
handle_recording(const TrackProcessor * self,const EngineProcessTimeInfo * const time_nfo)525 handle_recording (
526   const TrackProcessor * self,
527   const EngineProcessTimeInfo * const time_nfo)
528 {
529 #if 0
530   g_message ("handle recording %ld %" PRIu32,
531     g_start_frames, nframes);
532 #endif
533 
534   long split_points[6];
535   long each_nframes[6];
536   int num_split_points = 1;
537 
538   long start_frames = time_nfo->g_start_frames;
539   long end_frames =
540     start_frames + time_nfo->nframes;
541 
542   /* split the cycle at loop and punch points and
543    * record */
544   bool loop_hit = false;
545   bool punch_in_hit = false;
546   /*bool punch_out_hit = false;*/
547   /*int loop_end_idx = -1;*/
548   split_points[0] = start_frames;
549   each_nframes[0] = time_nfo->nframes;
550   if (TRANSPORT->loop)
551     {
552       if (TRANSPORT->loop_end_pos.frames ==
553             end_frames)
554         {
555           loop_hit = true;
556           num_split_points = 3;
557 
558           /* adjust start slot until loop end */
559           each_nframes[0] =
560             TRANSPORT->loop_end_pos.frames -
561             start_frames;
562           /*loop_end_idx = 0;*/
563 
564           /* add loop end pause */
565           split_points[1] =
566             TRANSPORT->loop_end_pos.frames;
567           each_nframes[1] = 0;
568 
569           /* add part after looping */
570           split_points[2] =
571             TRANSPORT->loop_start_pos.frames;
572           each_nframes[2] =
573             time_nfo->nframes - each_nframes[0];
574         }
575     }
576   if (TRANSPORT->punch_mode)
577     {
578       if (loop_hit)
579         {
580           /* before loop */
581           if (position_between_frames_excl2 (
582                 &TRANSPORT->punch_in_pos,
583                 start_frames,
584                 TRANSPORT->loop_end_pos.frames))
585             {
586               punch_in_hit = true;
587               num_split_points = 4;
588 
589               /* move loop start to next slot */
590               each_nframes[3] = each_nframes[2];
591               split_points[3] = split_points[2];
592               each_nframes[2] = each_nframes[1];
593               split_points[2] = split_points[1];
594 
595               /* add punch in pos */
596               split_points[1] =
597                 TRANSPORT->punch_in_pos.frames;
598               each_nframes[1] =
599                 TRANSPORT->loop_end_pos.frames -
600                 TRANSPORT->punch_in_pos.frames;
601               /*loop_end_idx = 1;*/
602 
603               /* adjust num frames for initial
604                * pos */
605               each_nframes[0] -= each_nframes[1];
606             }
607           if (position_between_frames_excl2 (
608                 &TRANSPORT->punch_out_pos,
609                 start_frames,
610                 TRANSPORT->loop_end_pos.frames))
611             {
612               /*punch_out_hit = true;*/
613               if (punch_in_hit)
614                 {
615                   num_split_points = 6;
616 
617                   /* move loop start to next slot */
618                   each_nframes[5] = each_nframes[3];
619                   split_points[5] = split_points[3];
620                   each_nframes[4] = each_nframes[2];
621                   split_points[4] = split_points[2];
622 
623                   /* add punch out pos */
624                   split_points[2] =
625                     TRANSPORT->punch_out_pos.frames;
626                   each_nframes[2] =
627                     TRANSPORT->loop_end_pos.frames -
628                     TRANSPORT->punch_out_pos.frames;
629 
630                   /* add pause */
631                   split_points[3] =
632                     split_points[2] +
633                     each_nframes[2];
634                   each_nframes[3] = 0;
635                   /*loop_end_idx = 2;*/
636 
637                   /* adjust num frames for punch in
638                    * pos */
639                   each_nframes[1] -= each_nframes[2];
640                 }
641               else
642                 {
643                   num_split_points = 5;
644 
645                   /* move loop start to next slot */
646                   each_nframes[4] = each_nframes[2];
647                   split_points[4] = split_points[2];
648                   each_nframes[3] = each_nframes[1];
649                   split_points[3] = split_points[1];
650 
651                   /* add punch out pos */
652                   split_points[1] =
653                     TRANSPORT->punch_out_pos.frames;
654                   each_nframes[1] =
655                     TRANSPORT->loop_end_pos.frames -
656                     TRANSPORT->punch_out_pos.frames;
657                   /*loop_end_idx = 1;*/
658 
659                   /* add pause */
660                   split_points[2] =
661                     split_points[1] +
662                     each_nframes[1];
663                   each_nframes[2] = 0;
664 
665                   /* adjust num frames for init
666                    * pos */
667                   each_nframes[0] -= each_nframes[1];
668                 }
669             }
670         }
671       else /* loop not hit */
672         {
673           if (position_between_frames_excl2 (
674                 &TRANSPORT->punch_in_pos,
675                 start_frames, end_frames))
676             {
677               punch_in_hit = true;
678               num_split_points = 2;
679 
680               /* add punch in pos */
681               split_points[1] =
682                 TRANSPORT->punch_in_pos.frames;
683               each_nframes[1] =
684                 end_frames -
685                 TRANSPORT->punch_in_pos.frames;
686 
687               /* adjust num frames for initial
688                * pos */
689               each_nframes[0] -= each_nframes[1];
690             }
691           if (position_between_frames_excl2 (
692                 &TRANSPORT->punch_out_pos,
693                 start_frames, end_frames))
694             {
695               /*punch_out_hit = true;*/
696               if (punch_in_hit)
697                 {
698                   num_split_points = 4;
699 
700                   /* add punch out pos */
701                   split_points[2] =
702                     TRANSPORT->punch_out_pos.frames;
703                   each_nframes[2] =
704                     end_frames -
705                     TRANSPORT->punch_out_pos.frames;
706 
707                   /* add pause */
708                   split_points[3] =
709                     split_points[2] +
710                     each_nframes[2];
711                   each_nframes[3] = 0;
712 
713                   /* adjust num frames for punch in
714                    * pos */
715                   each_nframes[1] -= each_nframes[2];
716                 }
717               else
718                 {
719                   num_split_points = 3;
720 
721                   /* add punch out pos */
722                   split_points[1] =
723                     TRANSPORT->punch_out_pos.frames;
724                   each_nframes[1] =
725                     end_frames -
726                     TRANSPORT->punch_out_pos.frames;
727 
728                   /* add pause */
729                   split_points[2] =
730                     split_points[1] +
731                     each_nframes[1];
732                   each_nframes[2] = 0;
733 
734                   /* adjust num frames for init
735                    * pos */
736                   each_nframes[0] -=
737                     each_nframes[1];
738                 }
739             }
740         }
741     }
742 
743   long split_point = -1;
744   /*bool is_loop_end_idx = false;*/
745   for (int i = 0; i < num_split_points; i++)
746     {
747       g_warn_if_fail (
748         split_points[i] >= 0 &&
749         each_nframes[i] >= 0);
750 
751       /* skip if same as previous point */
752       if (split_points[i] == split_point)
753         continue;
754 
755       split_point = split_points[i];
756 
757       /*is_loop_end_idx =*/
758         /*loop_hit && i == loop_end_idx;*/
759 
760 #if 0
761       g_message ("sending %ld for %ld frames",
762         split_point, each_nframes[i]);
763 #endif
764 
765       EngineProcessTimeInfo cur_time_nfo = {
766         .g_start_frames = split_point,
767         .local_offset = 0,
768         .nframes = each_nframes[i], };
769       recording_manager_handle_recording (
770         RECORDING_MANAGER, self, &cur_time_nfo);
771     }
772 }
773 
774 /**
775  * Adds events to midi out based on any changes in
776  * MIDI CC control ports.
777  */
778 static inline void
add_events_from_midi_cc_control_ports(const TrackProcessor * self,const nframes_t local_offset)779 add_events_from_midi_cc_control_ports (
780   const TrackProcessor * self,
781   const nframes_t        local_offset)
782 {
783   /* FIXME optimize (use caches) */
784   for (int i = 0; i < 16; i++)
785     {
786       /* starting from 1 */
787       int channel = i + 1;
788       Port * cc = NULL;
789       int offset = i * 128;
790       for (int j = 0; j < 128; j++)
791         {
792           cc = self->midi_cc[offset + j];
793           if (G_LIKELY (
794                 math_floats_equal (
795                   cc->last_sent_control,
796                   cc->control)))
797             continue;
798 
799           midi_events_add_control_change (
800             self->midi_out->midi_events,
801             channel, (midi_byte_t) j,
802             math_round_float_to_type (
803               cc->control * 127.f, midi_byte_t),
804             local_offset, false);
805           cc->last_sent_control = cc->control;
806         }
807 
808       cc = self->pitch_bend[i];
809       if (!math_floats_equal (
810             cc->last_sent_control, cc->control))
811         {
812           midi_events_add_pitchbend (
813             self->midi_out->midi_events,
814             channel,
815             math_round_float_to_int (cc->control),
816             local_offset, false);
817           cc->last_sent_control = cc->control;
818         }
819 
820       /* TODO */
821 #if 0
822       cc = self->poly_key_pressure[i];
823       midi_events_add_pitchbend (
824         self->midi_out->midi_events,
825         channel,
826         math_round_float_to_int (cc->control),
827         local_offset, false);
828       cc->last_sent_control = cc->control;
829 
830       cc = self->channel_pressure[i];
831       midi_events_add_pitchbend (
832         self->midi_out->midi_events,
833         channel,
834         math_round_float_to_int (cc->control),
835         local_offset, false);
836       cc->last_sent_control = cc->control;
837 #endif
838     }
839 }
840 
841 /**
842  * Process the TrackProcessor.
843  *
844  * This function performs the following:
845  * - produce output audio/MIDI into stereo out or
846  *   midi out, based on any audio/MIDI regions,
847  *   if has piano roll or is audio track
848  * - produce additional output MIDI events based on
849  *   any MIDI CC automation regions, if applicable
850  * - change MIDI CC control port values based on any
851  *   MIDI input, if recording
852  *   --- at this point the output is ready ---
853  * - handle recording (create events in regions and
854  *   automation, including MIDI CC automation,
855  *   based on the MIDI CC control ports)
856  *
857  * @param g_start_frames The global start frames.
858  * @param local_offset The local start frames.
859  * @param nframes The number of frames to process.
860  */
861 void
track_processor_process(const TrackProcessor * self,const EngineProcessTimeInfo * const time_nfo)862 track_processor_process (
863   const TrackProcessor *              self,
864   const EngineProcessTimeInfo * const time_nfo)
865 {
866 #define g_start_frames (time_nfo->g_start_frames)
867 #define local_offset (time_nfo->local_offset)
868 #define nframes (time_nfo->nframes)
869 
870   Track * tr = track_processor_get_track (self);
871   g_return_if_fail (tr);
872 
873   /* if frozen or disabled, skip */
874   if (tr->frozen || !track_is_enabled (tr))
875     {
876       return;
877     }
878 
879   /* set the audio clip contents to stereo out */
880   if (tr->type == TRACK_TYPE_AUDIO)
881     {
882       track_fill_events (
883         tr, time_nfo, NULL, self->stereo_out);
884     }
885 
886   /* set the piano roll contents to midi out */
887   if (track_type_has_piano_roll (tr->type) ||
888       tr->type == TRACK_TYPE_CHORD)
889     {
890       Port * pr = self->piano_roll;
891 
892       /* panic MIDI if necessary */
893       if (g_atomic_int_get (
894             &AUDIO_ENGINE->panic))
895         {
896           midi_events_panic (
897             pr->midi_events, 1);
898         }
899       /* get events from track if playing */
900       else if (TRANSPORT->play_state ==
901                  PLAYSTATE_ROLLING ||
902                track_is_auditioner (tr))
903         {
904           /* fill midi events from piano roll
905            * data */
906 #if 0
907           g_message (
908             "filling midi events for %s from %ld",
909             tr->name, g_start_frames);
910 #endif
911           track_fill_events (
912             tr, time_nfo, pr->midi_events, NULL);
913         }
914       midi_events_dequeue (pr->midi_events);
915 #if 0
916       if (pr->midi_events->num_events > 0)
917         {
918           g_message (
919             "%s piano roll has %d events",
920             tr->name,
921             pr->midi_events->num_events);
922         }
923 #endif
924 
925       /* append midi events from modwheel and
926        * pitchbend control ports to MIDI out */
927       if (tr->type != TRACK_TYPE_CHORD)
928         {
929           add_events_from_midi_cc_control_ports (
930             self, local_offset);
931         }
932       if (self->midi_out->midi_events->num_events > 0)
933         {
934 #if 0
935           g_debug (
936             "%s midi processor out has %d events",
937             tr->name,
938             self->midi_out->midi_events->num_events);
939 #endif
940         }
941 
942       /* append the midi events from piano roll to
943        * MIDI out */
944       midi_events_append (
945         pr->midi_events,
946         self->midi_out->midi_events, local_offset,
947         nframes, false);
948 
949 #if 0
950       if (pr->midi_events->num_events > 0)
951         {
952           g_message ("PR");
953           midi_events_print (
954             pr->midi_events, F_NOT_QUEUED);
955         }
956 
957       if (self->midi_out->midi_events->num_events >
958             0)
959         {
960           g_message ("midi out");
961           midi_events_print (
962             self->midi_out->midi_events,
963             F_NOT_QUEUED);
964         }
965 #endif
966     } /* if has piano roll or is chord track */
967 
968   /* if currently active track on the piano roll,
969    * fetch events */
970   if (tr->in_signal_type == TYPE_EVENT
971       && CLIP_EDITOR->has_region)
972     {
973       Track * clip_editor_track =
974         clip_editor_get_track (CLIP_EDITOR);
975       if (clip_editor_track == tr)
976         {
977           /* if not set to "all channels",
978            * filter-append */
979           if (!tr->channel->all_midi_channels)
980             {
981               midi_events_append_w_filter (
982                 AUDIO_ENGINE->
983                   midi_editor_manual_press->
984                     midi_events,
985                 self->midi_in->midi_events,
986                 tr->channel->midi_channels,
987                 local_offset,
988                 nframes, F_NOT_QUEUED);
989             }
990           /* otherwise append normally */
991           else
992             {
993               midi_events_append (
994                 AUDIO_ENGINE->
995                   midi_editor_manual_press->
996                     midi_events,
997                 self->midi_in->midi_events,
998                 local_offset, nframes,
999                 F_NOT_QUEUED);
1000             }
1001         }
1002     }
1003 
1004   /* add inputs to outputs */
1005   switch (tr->in_signal_type)
1006     {
1007     case TYPE_AUDIO:
1008       if (tr->type != TRACK_TYPE_AUDIO ||
1009           (tr->type == TRACK_TYPE_AUDIO &&
1010              control_port_is_toggled (
1011                self->monitor_audio)))
1012         {
1013           dsp_mix2 (
1014             &self->stereo_out->l->buf[local_offset],
1015             &self->stereo_in->l->buf[local_offset],
1016             1.f,
1017             self->input_gain ?
1018               self->input_gain->control : 1.f,
1019             nframes);
1020 
1021           if (self->mono &&
1022               control_port_is_toggled (self->mono))
1023             {
1024               dsp_mix2 (
1025                 &self->stereo_out->r->buf[local_offset],
1026                 &self->stereo_in->l->buf[local_offset],
1027                 1.f,
1028                 self->input_gain ?
1029                   self->input_gain->control : 1.f,
1030                 nframes);
1031             }
1032           else
1033             {
1034               dsp_mix2 (
1035                 &self->stereo_out->r->buf[local_offset],
1036                 &self->stereo_in->r->buf[local_offset],
1037                 1.f,
1038                 self->input_gain ?
1039                   self->input_gain->control : 1.f,
1040                 nframes);
1041             }
1042         }
1043       break;
1044     case TYPE_EVENT:
1045       /* change the MIDI channel on the midi input
1046        * to the channel set on the track */
1047       if (!tr->passthrough_midi_input)
1048         {
1049           midi_events_set_channel (
1050             self->midi_in->midi_events, 0,
1051             tr->midi_ch);
1052         }
1053 
1054       /* process midi bindings */
1055       if (self->cc_mappings && TRANSPORT->recording)
1056         {
1057           midi_mappings_apply_from_cc_events (
1058             self->cc_mappings,
1059             self->midi_in->midi_events,
1060             F_NOT_QUEUED);
1061         }
1062 
1063       midi_events_append (
1064         self->midi_in->midi_events,
1065         self->midi_out->midi_events, local_offset,
1066         nframes, F_NOT_QUEUED);
1067       break;
1068     default:
1069       break;
1070     }
1071 
1072   if (!track_is_auditioner (tr)
1073       && TRANSPORT->preroll_frames_remaining == 0
1074       &&
1075       (track_type_can_record (tr->type)
1076        || tr->automation_tracklist.num_ats > 0))
1077     {
1078       /* handle recording. this will only create
1079        * events in regions. it will not copy the
1080        * input content to the output ports.
1081        * this will also create automation for MIDI
1082        * CC, if any (see
1083        * midi_mappings_apply_cc_events above) */
1084       handle_recording (self, time_nfo);
1085     }
1086 
1087   /* apply output gain */
1088   if (tr->type == TRACK_TYPE_AUDIO)
1089     {
1090       dsp_mul_k2 (
1091         &self->stereo_out->l->buf[local_offset],
1092         self->output_gain->control, nframes);
1093       dsp_mul_k2 (
1094         &self->stereo_out->r->buf[local_offset],
1095         self->output_gain->control, nframes);
1096     }
1097 
1098 #undef g_start_frames
1099 #undef local_offset
1100 #undef nframes
1101 }
1102 
1103 /**
1104  * Copy port values from \ref src to \ref dest.
1105  */
1106 void
track_processor_copy_values(TrackProcessor * dest,TrackProcessor * src)1107 track_processor_copy_values (
1108   TrackProcessor * dest,
1109   TrackProcessor * src)
1110 {
1111   if (src->input_gain)
1112     {
1113       dest->input_gain->control =
1114         src->input_gain->control;
1115     }
1116   if (src->monitor_audio)
1117     {
1118       dest->monitor_audio->control =
1119         src->monitor_audio->control;
1120     }
1121   if (src->output_gain)
1122     {
1123       dest->output_gain->control =
1124         src->output_gain->control;
1125     }
1126   if (src->mono)
1127     {
1128       dest->mono->control = src->mono->control;
1129     }
1130 }
1131 
1132 /**
1133  * Disconnect stereo in ports from the fader.
1134  *
1135  * Used when there is no plugin in the channel.
1136  */
1137 void
track_processor_disconnect_from_prefader(TrackProcessor * self)1138 track_processor_disconnect_from_prefader (
1139   TrackProcessor * self)
1140 {
1141   Track * tr = track_processor_get_track (self);
1142   g_return_if_fail (IS_TRACK_AND_NONNULL (tr));
1143 
1144   Fader * prefader = tr->channel->prefader;
1145   switch (tr->in_signal_type)
1146     {
1147     case TYPE_AUDIO:
1148       if (tr->out_signal_type == TYPE_AUDIO)
1149         {
1150           port_disconnect (
1151             self->stereo_out->l,
1152             prefader->stereo_in->l);
1153           port_disconnect (
1154             self->stereo_out->r,
1155             prefader->stereo_in->r);
1156         }
1157       break;
1158     case TYPE_EVENT:
1159       if (tr->out_signal_type == TYPE_EVENT)
1160         {
1161           port_disconnect (
1162             self->midi_out, prefader->midi_in);
1163         }
1164       break;
1165     default:
1166       break;
1167     }
1168 }
1169 
1170 /**
1171  * Connects the TrackProcessor's stereo out ports to
1172  * the Channel's prefader in ports.
1173  *
1174  * Used when deleting the only plugin left.
1175  */
1176 void
track_processor_connect_to_prefader(TrackProcessor * self)1177 track_processor_connect_to_prefader (
1178   TrackProcessor * self)
1179 {
1180   Track * tr = track_processor_get_track (self);
1181   g_return_if_fail (IS_TRACK_AND_NONNULL (tr));
1182 
1183   Fader * prefader = tr->channel->prefader;
1184   g_return_if_fail (IS_FADER (prefader));
1185 
1186   /* connect only if signals match */
1187   if (tr->in_signal_type == TYPE_AUDIO &&
1188       tr->out_signal_type == TYPE_AUDIO)
1189     {
1190       port_connect (
1191         self->stereo_out->l,
1192         prefader->stereo_in->l, 1);
1193       port_connect (
1194         self->stereo_out->r,
1195         prefader->stereo_in->r, 1);
1196     }
1197   if (tr->in_signal_type == TYPE_EVENT &&
1198       tr->out_signal_type == TYPE_EVENT)
1199     {
1200       port_connect (
1201         self->midi_out, prefader->midi_in, 1);
1202     }
1203 }
1204 
1205 /**
1206  * Disconnect the TrackProcessor's out ports
1207  * from the Plugin's input ports.
1208  */
1209 void
track_processor_disconnect_from_plugin(TrackProcessor * self,Plugin * pl)1210 track_processor_disconnect_from_plugin (
1211   TrackProcessor * self,
1212   Plugin         * pl)
1213 {
1214   Track * tr = track_processor_get_track (self);
1215   g_return_if_fail (IS_TRACK_AND_NONNULL (tr));
1216 
1217   int i;
1218   Port * in_port;
1219   PortType type = tr->in_signal_type;
1220 
1221   for (i = 0; i < pl->num_in_ports; i++)
1222     {
1223       in_port = pl->in_ports[i];
1224 
1225       if (type == TYPE_AUDIO)
1226         {
1227           if (in_port->id.type !=
1228                 TYPE_AUDIO)
1229             continue;
1230 
1231           if (ports_connected (
1232                 self->stereo_out->l,
1233                 in_port))
1234             port_disconnect (
1235               self->stereo_out->l,
1236               in_port);
1237           if (ports_connected (
1238                 self->stereo_out->r,
1239                 in_port))
1240             port_disconnect (
1241               self->stereo_out->r,
1242               in_port);
1243         }
1244       else if (type == TYPE_EVENT)
1245         {
1246           if (in_port->id.type != TYPE_EVENT)
1247             continue;
1248 
1249           if (ports_connected (
1250                 self->midi_out, in_port))
1251             port_disconnect (
1252               self->midi_out, in_port);
1253         }
1254     }
1255 }
1256 
1257 /**
1258  * Connect the TrackProcessor's out ports to the
1259  * Plugin's input ports.
1260  */
1261 void
track_processor_connect_to_plugin(TrackProcessor * self,Plugin * pl)1262 track_processor_connect_to_plugin (
1263   TrackProcessor * self,
1264   Plugin         * pl)
1265 {
1266   Track * tr = track_processor_get_track (self);
1267   g_return_if_fail (IS_TRACK_AND_NONNULL (tr));
1268 
1269   int last_index, num_ports_to_connect, i;
1270   Port * in_port;
1271 
1272   if (tr->in_signal_type == TYPE_EVENT)
1273     {
1274       /* Connect MIDI port to the plugin */
1275       for (i = 0; i < pl->num_in_ports; i++)
1276         {
1277           in_port = pl->in_ports[i];
1278           if (in_port->id.type == TYPE_EVENT &&
1279               in_port->id.flow == FLOW_INPUT)
1280             {
1281               port_connect (
1282                 self->midi_out, in_port, 1);
1283             }
1284         }
1285     }
1286   else if (tr->in_signal_type == TYPE_AUDIO)
1287     {
1288       num_ports_to_connect = 0;
1289       if (pl->setting->descr->num_audio_ins == 1)
1290         {
1291           num_ports_to_connect = 1;
1292         }
1293       else if (pl->setting->descr->num_audio_ins > 1)
1294         {
1295           num_ports_to_connect = 2;
1296         }
1297 
1298       last_index = 0;
1299       for (i = 0; i < num_ports_to_connect; i++)
1300         {
1301           for (;
1302                last_index < pl->num_in_ports;
1303                last_index++)
1304             {
1305               in_port =
1306                 pl->in_ports[
1307                   last_index];
1308               if (in_port->id.type == TYPE_AUDIO)
1309                 {
1310                   if (i == 0)
1311                     {
1312                       port_connect (
1313                         self->stereo_out->l,
1314                         in_port, 1);
1315                       last_index++;
1316                       break;
1317                     }
1318                   else if (i == 1)
1319                     {
1320                       port_connect (
1321                         self->stereo_out->r,
1322                         in_port, 1);
1323                       last_index++;
1324                       break;
1325                     }
1326                 }
1327             }
1328         }
1329     }
1330 }
1331 
1332 /**
1333  * Frees the members of the TrackProcessor.
1334  */
1335 void
track_processor_free(TrackProcessor * self)1336 track_processor_free (
1337   TrackProcessor * self)
1338 {
1339   object_free_w_func_and_null (
1340     midi_mappings_free, self->cc_mappings);
1341 
1342   if (IS_PORT_AND_NONNULL (self->mono))
1343     {
1344       port_disconnect_all (self->mono);
1345       object_free_w_func_and_null (
1346         port_free, self->mono);
1347     }
1348   if (IS_PORT_AND_NONNULL (self->input_gain))
1349     {
1350       port_disconnect_all (self->input_gain);
1351       object_free_w_func_and_null (
1352         port_free, self->input_gain);
1353     }
1354   if (IS_PORT_AND_NONNULL (self->output_gain))
1355     {
1356       port_disconnect_all (self->output_gain);
1357       object_free_w_func_and_null (
1358         port_free, self->output_gain);
1359     }
1360   if (IS_PORT_AND_NONNULL (self->monitor_audio))
1361     {
1362       port_disconnect_all (self->monitor_audio);
1363       object_free_w_func_and_null (
1364         port_free, self->monitor_audio);
1365     }
1366   if (self->stereo_in)
1367     {
1368       stereo_ports_disconnect (self->stereo_in);
1369       object_free_w_func_and_null (
1370         stereo_ports_free, self->stereo_in);
1371     }
1372   if (IS_PORT_AND_NONNULL (self->midi_in))
1373     {
1374       port_disconnect_all (self->midi_in);
1375       object_free_w_func_and_null (
1376         port_free, self->midi_in);
1377     }
1378   if (IS_PORT_AND_NONNULL (self->piano_roll))
1379     {
1380       port_disconnect_all (self->piano_roll);
1381       object_free_w_func_and_null (
1382         port_free, self->piano_roll);
1383     }
1384 
1385 #define FREE_CC(cc) \
1386   if (cc) \
1387     { \
1388       port_disconnect_all (cc); \
1389       object_free_w_func_and_null ( \
1390         port_free, cc); \
1391     }
1392 
1393   for (int i = 0; i < 16; i++)
1394     {
1395       Port * cc = NULL;
1396       for (int j = 0; j < 128; j++)
1397         {
1398           cc = self->midi_cc[i * 128 + j];
1399           FREE_CC (cc);
1400         }
1401 
1402       cc = self->pitch_bend[i];
1403       FREE_CC (cc);
1404 
1405       cc = self->poly_key_pressure[i];
1406       FREE_CC (cc);
1407 
1408       cc = self->channel_pressure[i];
1409       FREE_CC (cc);
1410     }
1411 
1412 #undef FREE_CC
1413 
1414   if (self->stereo_out)
1415     {
1416       stereo_ports_disconnect (self->stereo_out);
1417       object_free_w_func_and_null (
1418         stereo_ports_free, self->stereo_out);
1419     }
1420   if (IS_PORT_AND_NONNULL (self->midi_out))
1421     {
1422       port_disconnect_all (self->midi_out);
1423       object_free_w_func_and_null (
1424         port_free, self->midi_out);
1425     }
1426 
1427   object_zero_and_free (self);
1428 }
1429