1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include "dssi-render.h"
#include "midi/midi_loader.h"
/* Instead of creating an alsa midi input, we fill in two events
* note-on and note-off */
inline int
min(int x, int y) {
return (x < y) ? x : y;
}
void ladspa_run_sample_callback(event_table_t *event_table, void *userdata){
nframes = event_table->nframes_since_last;
nframes = nframes > 0 ? nframes : 1;
for (int i = 0; i < outs; i++) {
pluginOutputBuffers[i] = (float *)realloc(pluginOutputBuffers[i], nframes * sizeof(float));
memset(pluginOutputBuffers[i], 0, nframes * sizeof(float));
}
connect_ports();
if (descriptor->run_synth) {
descriptor->run_synth(instanceHandle,
nframes,
event_table->events,
event_table->length
);
} else if (descriptor->run_multiple_synths) {
descriptor->run_multiple_synths(1,
&instanceHandle,
nframes,
&event_table->events,
&event_table->length);
}
/* Interleaving for libsndfile. */
float sf_output[nchannels * nframes];
for (int i = 0; i < nframes; i++) {
/* First, write all the obvious channels */
for (int j = 0; j < min(outs, nchannels); j++) {
/* If outs > nchannels, we *could* do mixing - but don't. */
sf_output[i * nchannels + j] = pluginOutputBuffers[j][i];
}
/* Then, if user wants *more* output channels than there are
* audio output ports (ie outs < nchannels), copy the last audio
* out to all the remaining channels. If outs >= nchannels, this
* loop is never entered. */
for (int j = outs; j < nchannels; j++) {
sf_output[i * nchannels + j] = pluginOutputBuffers[outs - 1][i];
}
}
//clip = 1; // FIXME
if (clip) {
for (int i = 0; i < nframes * nchannels; i++) {
if (!finite(sf_output[i])) {
if (!have_warned) {
have_warned = 1;
fprintf(stderr,
"%s: Warning: clipping NaN or Inf in synthesized data\n",
my_name);
}
if (sf_output[i] < 0.0f) {
sf_output[i] = -1.0f;
} else {
sf_output[i] = 1.0f;
}
} else {
if (sf_output[i] < -1.0f) {
if (!have_warned) {
have_warned = 1;
fprintf(stderr,
"%s: Warning: clipping out-of-bounds value in synthesized data\n",
my_name);
}
sf_output[i] = -1.0f;
} else if (sf_output[i] > 1.0f) {
if (!have_warned) {
have_warned = 1;
fprintf(stderr,
"%s: Warning: clipping out-of-bounds value in synthesized data\n",
my_name);
}
sf_output[i] = 1.0f;
}
}
}
} else {
for (int i = 0; i < nframes * nchannels; i++) {
if (!finite(sf_output[i])) {
fprintf(stderr, "%s: Error: NaN or Inf in synthesized data\n",
my_name);
exit(1);
}
if (sf_output[i] > 1.0f
|| sf_output[i] < -1.0f) {
fprintf(stderr, "%s: Error: sample data out of bounds\n",
my_name);
exit(1);
}
}
}
/* Write the audio */
if ((items_written = sf_writef_float(outfile,
sf_output,
nframes)) != nframes) {
fprintf(stderr, "%s: Error: can't write data to output file %s\n",
my_name, output_file);
fprintf(stderr, "%s: %s\n", my_name, sf_strerror(outfile));
return;
}
fprintf(stdout, "%s: Wrote %d frames to %s\n",
my_name, items_written, output_file);
}
void ladspa_run_synth(void){
load_midi_file(midi_filename, ladspa_run_sample_callback, NULL);
}
|