1 /*
2 * Copyright (C) 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 "audio/modulator_macro_processor.h"
21 #include "audio/port.h"
22 #include "utils/dsp.h"
23 #include "utils/debug.h"
24 #include "utils/objects.h"
25
26 #include <glib/gi18n.h>
27
28 void
modulator_macro_processor_init_loaded(ModulatorMacroProcessor * self,Track * track)29 modulator_macro_processor_init_loaded (
30 ModulatorMacroProcessor * self,
31 Track * track)
32 {
33 self->track = track;
34
35 port_init_loaded (self->macro, self);
36 port_init_loaded (self->cv_in, self);
37 port_init_loaded (self->cv_out, self);
38 }
39
40 Track *
modulator_macro_processor_get_track(ModulatorMacroProcessor * self)41 modulator_macro_processor_get_track (
42 ModulatorMacroProcessor * self)
43 {
44 return port_get_track (self->cv_in, true);
45 }
46
47 void
modulator_macro_processor_set_name(ModulatorMacroProcessor * self,const char * name)48 modulator_macro_processor_set_name (
49 ModulatorMacroProcessor * self,
50 const char * name)
51 {
52 self->name = g_strdup (name);
53 }
54
55 /**
56 * Process.
57 *
58 * @param g_start_frames Global frames.
59 * @param start_frame The local offset in this
60 * cycle.
61 * @param nframes The number of frames to process.
62 */
63 void
modulator_macro_processor_process(ModulatorMacroProcessor * self,long g_start_frames,nframes_t start_frame,const nframes_t nframes)64 modulator_macro_processor_process (
65 ModulatorMacroProcessor * self,
66 long g_start_frames,
67 nframes_t start_frame,
68 const nframes_t nframes)
69 {
70 z_return_if_fail_cmp (
71 start_frame + nframes, <=,
72 self->cv_out->last_buf_sz);
73
74 /* if there are inputs, multiply by the knov
75 * value */
76 if (self->cv_in->num_srcs > 0)
77 {
78 dsp_mix2 (
79 &self->cv_out->buf[start_frame],
80 &self->cv_in->buf[start_frame],
81 0.f, self->macro->control, nframes);
82 }
83 /* else if there are no inputs, set the knob value
84 * as the output */
85 else
86 {
87 Port * cv_out = self->cv_out;
88 g_return_if_fail (IS_PORT (cv_out));
89 dsp_fill (
90 &cv_out->buf[start_frame],
91 self->macro->control *
92 (cv_out->maxf - cv_out->minf) +
93 cv_out->minf,
94 nframes);
95 }
96 }
97
98 ModulatorMacroProcessor *
modulator_macro_processor_new(Track * track,int idx)99 modulator_macro_processor_new (
100 Track * track,
101 int idx)
102 {
103 ModulatorMacroProcessor * self =
104 object_new (ModulatorMacroProcessor);
105 self->schema_version =
106 MODULATOR_MACRO_PROCESSOR_SCHEMA_VERSION;
107 self->track = track;
108
109 char str[600];
110 sprintf (str, _("Macro %d"), idx + 1);
111 self->name = g_strdup (str);
112 self->macro =
113 port_new_with_type_and_owner (
114 TYPE_CONTROL, FLOW_INPUT, str,
115 PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR,
116 self);
117 Port * port = self->macro;
118 port->minf = 0.f;
119 port->maxf = 1.f;
120 port->deff = 0.f;
121 port_set_control_value (
122 port, 0.75f, false, false);
123 port->id.flags |=
124 PORT_FLAG_AUTOMATABLE;
125 port->id.flags |=
126 PORT_FLAG_MODULATOR_MACRO;
127 port->id.port_index = idx;
128
129 sprintf (str, _("Macro CV In %d"), idx + 1);
130 self->cv_in =
131 port_new_with_type_and_owner (
132 TYPE_CV, FLOW_INPUT, str,
133 PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR,
134 self);
135 port = self->cv_in;
136 port->id.flags |=
137 PORT_FLAG_MODULATOR_MACRO;
138 port->id.port_index = idx;
139
140 sprintf (str, _("Macro CV Out %d"), idx + 1);
141 self->cv_out =
142 port_new_with_type_and_owner (
143 TYPE_CV, FLOW_OUTPUT, str,
144 PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR,
145 self);
146 port = self->cv_out;
147 port->id.flags |=
148 PORT_FLAG_MODULATOR_MACRO;
149 port->id.port_index = idx;
150
151 return self;
152 }
153
154 void
modulator_macro_processor_free(ModulatorMacroProcessor * self)155 modulator_macro_processor_free (
156 ModulatorMacroProcessor * self)
157 {
158 object_free_w_func_and_null (
159 port_free, self->macro);
160 object_free_w_func_and_null (
161 port_free, self->cv_in);
162 object_free_w_func_and_null (
163 port_free, self->cv_out);
164
165 object_zero_and_free (self);
166 }
167