summaryrefslogtreecommitdiff
path: root/src/ladspa_run_synth.c
blob: 115c4f53965edcbd393cf4e77854be799309e588 (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "dssi-render.h"
#include "midi/midi_loader.h" 
#define DEBUG 0
  /* 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;
}
// where is nframes defined?

void ladspa_run_sample_callback(event_table_t *event_table, void *userdata){
  nframes = event_table->nframes_since_last;
  nframes = nframes > 0 ? nframes : 1;
//is it nframes that has the negative value? or event_table length? well they are both size_t, can't be negative. i guess need to add prints to see what's going on
  if(DEBUG){
    printf("nframes: 0x%x\n", nframes);
    printf("outs: 0x%x\n", outs);
  }
  for (int i = 0; i < outs; i++) {
    pluginOutputBuffers[i] = (float *)realloc(pluginOutputBuffers[i], nframes * sizeof(float)); 
    if (DEBUG){
      printf("i: 0x%x buff: 0x%x\n", i, pluginOutputBuffers[i]);
    }
    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];
      }
    }
    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 */
//here it writes to file, and it has a buffer sf_output, most likely filled from plugin. anyway, tempo problem, if it doesn't pick correct note duration it must be something
//with either reading tempo/setting tempo settings to player, or calulcations of time then it calulate each note. I don't think so...it's because it doesn't do the 
//calculations gradually, seems to do them all at the end (like a final loop) and whatever the last tempo was, it uses that for the whole piece, you know what I mean?
//well it's not how send_events works, it send events one by one, so it should work fine. how did you test tempo? ok I'm going to make some perfect test-cases, sound good? yep
//
    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;
    }
    if(DEBUG){
      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, sample_rate, ladspa_run_sample_callback, NULL);
}