10
10
11
11
namespace Synthimi
12
12
{
13
- constexpr int upsample_factor = 3 ;
13
+ constexpr int upsample_factor = 1 ;
14
14
/*
15
15
struct nan_detector
16
16
{
@@ -90,10 +90,20 @@ void Synthimi::prepare(halp::setup info)
90
90
double upsample = upsample_factor * info.rate ;
91
91
this ->settings = info;
92
92
this ->mono .init (upsample);
93
- this ->resample_l = std::make_unique<r8b::CDSPResampler>(
94
- upsample, info.rate , upsample_factor * info.frames , 3.0 , 206.91 , r8b::fprMinPhase);
95
- this ->resample_r = std::make_unique<r8b::CDSPResampler>(
96
- upsample, info.rate , upsample_factor * info.frames , 3.0 , 206.91 , r8b::fprMinPhase);
93
+ if constexpr (upsample_factor > 1 ) {
94
+ this ->resample_l = std::make_unique<r8b::CDSPResampler>(upsample,
95
+ info.rate ,
96
+ upsample_factor * info.frames ,
97
+ 3.0 ,
98
+ 206.91 ,
99
+ r8b::fprMinPhase);
100
+ this ->resample_r = std::make_unique<r8b::CDSPResampler>(upsample,
101
+ info.rate ,
102
+ upsample_factor * info.frames ,
103
+ 3.0 ,
104
+ 206.91 ,
105
+ r8b::fprMinPhase);
106
+ }
97
107
}
98
108
99
109
void Synthimi::update_pitches ()
@@ -135,10 +145,17 @@ void Synthimi::operator()(halp::tick t)
135
145
136
146
// - noise channel would be cool :)
137
147
148
+ double *l{};
149
+ double *r{};
138
150
const int upsample_frames = t.frames * upsample_factor;
139
- auto * l = (double *)alloca (sizeof (double ) * upsample_frames);
151
+ if constexpr (upsample_factor > 1 ) {
152
+ l = (double *) alloca (sizeof (double ) * upsample_frames);
153
+ r = (double *) alloca (sizeof (double ) * upsample_frames);
154
+ } else {
155
+ l = outputs.audio .samples [0 ];
156
+ r = outputs.audio .samples [1 ];
157
+ }
140
158
std::fill_n (l, upsample_frames, 0 .);
141
- auto * r = (double *)alloca (sizeof (double ) * upsample_frames);
142
159
std::fill_n (r, upsample_frames, 0 .);
143
160
144
161
process_midi ();
@@ -150,120 +167,92 @@ void Synthimi::operator()(halp::tick t)
150
167
151
168
void Synthimi::process_midi ()
152
169
{
153
- auto & voices = this ->voices .active ;
154
- for (auto m : this ->inputs .midi .midi_messages )
155
- {
156
- // We get a note -> we add a voice
157
- // let's use libremidi to see if we have a note
158
-
159
- switch ((libremidi::message_type)(m.bytes [0 ] & 0xF0 ))
160
- {
161
- case libremidi::message_type::NOTE_ON:
162
- {
163
- auto note = m.bytes [1 ];
164
- if (auto ampl = m.bytes [2 ] / 127 .; ampl > 0 )
165
- {
166
- voices.emplace_back (note, ampl);
167
- voices.back ().init (settings.rate * upsample_factor);
168
- voices.back ().set_freq (*this );
169
- if (voices.size () >= 2 )
170
- {
171
- porta_samples
172
- = 0.1 + this ->inputs .portamento * upsample_factor * this ->settings .rate ;
173
- if (porta_cur_samples > 0 )
174
- {
175
- porta_cur_samples = 0 ;
176
- }
177
- else
178
- {
179
- porta_from = voices[voices.size () - 2 ].main .pitch ;
180
- }
181
- porta_to = voices[voices.size () - 1 ].main .pitch ;
182
- }
183
- else
184
- {
185
- porta_samples = 0 ;
186
- porta_cur_samples = 0 ;
187
- porta_from = voices.back ().main .pitch ;
188
- porta_to = voices.back ().main .pitch ;
189
- const bool had_released = mono.amp_adsr .released ();
190
- mono = std::move (voices.back ());
191
- if (!had_released)
192
- {
193
- mono.amp_adsr .resetSoft ();
194
- mono.filt_adsr .resetSoft ();
195
- }
196
- else
197
- {
198
- mono.amp_adsr .reset ();
199
- mono.filt_adsr .reset ();
200
- }
201
- }
202
- }
203
- else
204
- {
205
- goto note_off; // hehe.jpg
206
- }
207
- // this is because some synths sadly send a note_on with vel. 0 to say note off
208
- break ;
209
- }
210
- case libremidi::message_type::NOTE_OFF:
211
- {
212
- note_off:
213
- for (auto it = voices.rbegin (); it != voices.rend ();)
214
- {
215
- if (it->main .pitch == m.bytes [1 ])
216
- {
217
- switch (inputs.poly_mode )
218
- {
219
- case decltype (inputs.poly_mode .value )::Mono:
220
- {
221
- if (voices.size () == 1 )
222
- {
223
- // The currently playing note needs release if we kill it
224
- mono.stop ();
225
- voices.clear ();
226
- return ;
227
- }
228
- else
229
- {
230
- it = decltype (it)(voices.erase (std::next (it).base ()));
231
-
232
- if (voices.size () >= 2 )
233
- {
234
- porta_from = voices[voices.size () - 2 ].main .pitch ;
170
+ auto &voices = this ->voices .active ;
171
+ for (auto m : this ->inputs .midi .midi_messages ) {
172
+ // We get a note -> we add a voice
173
+ // let's use libremidi to see if we have a note
174
+
175
+ switch ((libremidi::message_type)(m.bytes [0 ] & 0xF0 )) {
176
+ case libremidi::message_type::NOTE_ON: {
177
+ auto note = m.bytes [1 ];
178
+ if (auto ampl = m.bytes [2 ] / 127 .; ampl > 0 ) {
179
+ voices.emplace_back (note, ampl);
180
+ voices.back ().init (settings.rate * upsample_factor);
181
+ voices.back ().set_freq (*this );
182
+ if (voices.size () >= 2 ) {
183
+ porta_samples = 0.1
184
+ + this ->inputs .portamento * upsample_factor
185
+ * this ->settings .rate ;
186
+ if (porta_cur_samples > 0 ) {
187
+ porta_cur_samples = 0 ;
188
+ } else {
189
+ porta_from = voices[voices.size () - 2 ].main .pitch ;
190
+ }
235
191
porta_to = voices[voices.size () - 1 ].main .pitch ;
236
- }
237
- else
238
- {
192
+ } else {
193
+ porta_samples = 0 ;
194
+ porta_cur_samples = 0 ;
239
195
porta_from = voices.back ().main .pitch ;
240
196
porta_to = voices.back ().main .pitch ;
241
- }
197
+ const bool had_released = mono.amp_adsr .released ();
198
+ mono = std::move (voices.back ());
199
+ if (!had_released) {
200
+ mono.amp_adsr .resetSoft ();
201
+ mono.filt_adsr .resetSoft ();
202
+ } else {
203
+ mono.amp_adsr .reset ();
204
+ mono.filt_adsr .reset ();
205
+ }
242
206
}
243
- break ;
244
- }
245
- case decltype (inputs.poly_mode .value )::Poly:
246
- {
247
- // We don't remove it directly, we just signal the ADSR that it gotta
248
- // start the release
249
- it->stop ();
250
- ++it;
251
- break ;
252
- }
207
+ } else {
208
+ goto note_off; // hehe.jpg
253
209
}
210
+ // this is because some synths sadly send a note_on with vel. 0 to say note off
211
+ break ;
212
+ }
213
+ case libremidi::message_type::NOTE_OFF: {
214
+ note_off:
215
+ for (auto it = voices.rbegin (); it != voices.rend ();) {
216
+ if (it->main .pitch == m.bytes [1 ]) {
217
+ switch (inputs.poly_mode ) {
218
+ case decltype (inputs.poly_mode .value )::Mono: {
219
+ if (voices.size () == 1 ) {
220
+ // The currently playing note needs release if we kill it
221
+ mono.stop ();
222
+ voices.clear ();
223
+ return ;
224
+ } else {
225
+ it = decltype (it)(voices.erase (std::next (it).base ()));
226
+
227
+ if (voices.size () >= 2 ) {
228
+ porta_from = voices[voices.size () - 2 ].main .pitch ;
229
+ porta_to = voices[voices.size () - 1 ].main .pitch ;
230
+ } else {
231
+ porta_from = voices.back ().main .pitch ;
232
+ porta_to = voices.back ().main .pitch ;
233
+ }
234
+ }
235
+ break ;
236
+ }
237
+ case decltype (inputs.poly_mode .value )::Poly: {
238
+ // We don't remove it directly, we just signal the ADSR that it gotta
239
+ // start the release
240
+ it->stop ();
241
+ ++it;
242
+ break ;
243
+ }
244
+ }
245
+ break ;
246
+ } else {
247
+ ++it;
248
+ }
249
+ }
250
+ break ;
251
+ }
252
+ default :
254
253
break ;
255
- }
256
- else
257
- {
258
- ++it;
259
- }
260
254
}
261
- break ;
262
- }
263
- default :
264
- break ;
265
255
}
266
- }
267
256
}
268
257
269
258
void Synthimi::process_voices (int frames, double * l, double * r)
@@ -346,13 +335,15 @@ void Synthimi::postprocess(int frames, double* l, double* r)
346
335
}
347
336
}
348
337
349
- // Resample
350
- double * lptr;
351
- double * rptr;
352
- this ->resample_l ->process (l, upsample_frames, lptr);
353
- this ->resample_r ->process (r, upsample_frames, rptr);
354
- std::copy_n (lptr, frames, outputs.audio .samples [0 ]);
355
- std::copy_n (rptr, frames, outputs.audio .samples [1 ]);
338
+ if constexpr (upsample_factor > 1 ) {
339
+ // Resample
340
+ double *lptr;
341
+ double *rptr;
342
+ this ->resample_l ->process (l, upsample_frames, lptr);
343
+ this ->resample_r ->process (r, upsample_frames, rptr);
344
+ std::copy_n (lptr, frames, outputs.audio .samples [0 ]);
345
+ std::copy_n (rptr, frames, outputs.audio .samples [1 ]);
346
+ }
356
347
}
357
348
358
349
static double wave (Waveform::enum_type t, const double ph) noexcept
0 commit comments