source: roaraudio/roard/ssynth.c @ 5381:430b1d26e12d

Last change on this file since 5381:430b1d26e12d was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

File size: 7.4 KB
Line 
1//ssynth.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2012
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
29
30static const float ssynth_polys[SSYNTH_POLY_POLYMAX][SSYNTH_POLY_COEFF] = {
31       {0.300000,  0.958333, -0.550000,  0.091667},
32       {0.700010, -0.083333, -0.150000,  0.033333}
33      };
34
35struct ssynth_conf ssynth_conf;
36
37struct ssynth_state {
38 int stream;
39 struct {
40  int stage;
41  char vv_down, vv_up;
42  struct roar_note_octave   note;
43  struct roar_synth_state   synth;
44  struct roar_fader_state   fader;
45  struct roar_buffer      * buf;
46 } notes[SSYNTH_NOTES_MAX];
47} g_ssynth;
48
49int ssynth_init_config(void) {
50 memset(&ssynth_conf, 0, sizeof(ssynth_conf));
51
52 return 0;
53}
54
55#define _err() streams_delete(sid); return -1
56int ssynth_init (void) {
57 struct roar_stream_server * ss;
58 struct roar_stream        *  s;
59 int sid;
60
61 if ( !ssynth_conf.enable )
62  return 0;
63
64 memset(&g_ssynth, 0, sizeof(g_ssynth));
65 g_ssynth.stream = -1;
66
67 if ( (sid = streams_new()) == -1 )
68  return -1;
69
70 if ( streams_set_client(sid, g_self_client) == -1 ) {
71  _err();
72 }
73
74 if ( streams_set_dir(sid, ROAR_DIR_BRIDGE, 1) == -1 ) {
75  _err();
76 }
77
78 if ( streams_set_flag(sid, ROAR_FLAG_PRIMARY) == -1 ) {
79  _err();
80 }
81
82 if ( streams_set_name(sid, "Simple Synthesizer") == -1 ) {
83  _err();
84 }
85
86 if ( streams_get(sid, &ss) == -1 ) {
87  _err();
88 }
89
90 s = ROAR_STREAM(ss);
91
92 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
93
94 s->info.channels = 1;
95 s->info.codec    = ROAR_CODEC_DEFAULT;
96
97 g_ssynth.stream  = sid;
98
99 return 0;
100}
101
102int ssynth_free (void) {
103 int i;
104
105 if ( !ssynth_conf.enable )
106  return 0;
107
108 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
109  if ( g_ssynth.notes[i].buf != NULL ) {
110   roar_buffer_free(g_ssynth.notes[i].buf);
111   g_ssynth.notes[i].buf = NULL;
112  }
113 }
114
115 return streams_delete(g_ssynth.stream);
116}
117
118int ssynth_update (void) {
119 struct roar_stream_server * ss;
120 struct roar_stream        *  s;
121 struct roar_buffer        * buf;
122 struct roar_buffer        * outbuf;
123 void                      * outbufdata;
124 void                      * indbufs[SSYNTH_NOTES_MAX+1];
125 int                         curin = 0;
126 size_t buflen;
127 size_t needlen;
128 int i;
129
130 if ( !ssynth_conf.enable )
131  return 0;
132
133 ROAR_DBG("ssynth_update(void) = ?");
134
135 if ( streams_get(g_ssynth.stream, &ss) == -1 ) {
136  return -1;
137 }
138
139 memset(indbufs, 0, sizeof(indbufs));
140
141 s = ROAR_STREAM(ss);
142
143 needlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info));
144
145 ROAR_DBG("ssynth_update(void): needlen=%lu", (unsigned long)needlen);
146
147 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
148  if ( g_ssynth.notes[i].stage != SSYNTH_STAGE_UNUSED ) {
149   ROAR_DBG("ssynth_update(void): used note slot: %i", i);
150   if ( g_ssynth.notes[i].buf == NULL ) {
151    if ( roar_buffer_new(&buf, needlen) == -1 )
152     continue;
153
154    g_ssynth.notes[i].buf = buf;
155   } else {
156    buf = g_ssynth.notes[i].buf;
157
158    if ( roar_buffer_get_len(buf, &buflen) == -1 )
159     continue;
160
161    if ( buflen < needlen ) {
162     if ( roar_buffer_set_len(buf, needlen) == -1 )
163      continue;
164    }
165   }
166
167   if ( roar_buffer_get_data(buf, &(indbufs[curin])) == -1 )
168    continue;
169
170   if ( ssynth_note_render(i, indbufs[curin]) == -1 )
171    continue;
172
173   curin++;
174  }
175 }
176
177 ROAR_DBG("ssynth_update(void): found streams: %i", curin);
178
179 if ( curin > 0 ) {
180  if ( roar_buffer_new(&outbuf, needlen) == -1 )
181   return -1;
182
183  if ( roar_buffer_get_data(outbuf, &outbufdata) == -1 ) {
184   roar_buffer_free(outbuf);
185   return -1;
186  }
187
188  if ( roar_mix_pcm(outbufdata, g_sa->bits, indbufs, ROAR_OUTPUT_BUFFER_SAMPLES) == -1 ) {
189   roar_buffer_free(outbuf);
190   return -1;
191  }
192
193  if ( stream_add_buffer(g_ssynth.stream, &outbuf) == -1 ) {
194   roar_buffer_free(outbuf);
195   return -1;
196  }
197 }
198
199 ROAR_DBG("ssynth_update(void) = 0");
200 return 0;
201}
202
203
204int ssynth_note_new(struct roar_note_octave * note, char vv) {
205 int i;
206
207 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = ?", note, vv);
208
209 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
210  if ( g_ssynth.notes[i].stage == SSYNTH_STAGE_UNUSED ) {
211   // TODO: do some error checking here
212   g_ssynth.notes[i].vv_down = vv;
213   memcpy(&(g_ssynth.notes[i].note), note, sizeof(struct roar_note_octave));
214   roar_synth_init(&(g_ssynth.notes[i].synth), &(g_ssynth.notes[i].note), g_sa->rate);
215   roar_synth_set_volume(&(g_ssynth.notes[i].synth), 0.25);
216   roar_synth_set_func(&(g_ssynth.notes[i].synth), ROAR_SYNTH_SYNF_TRAP);
217   ssynth_note_set_stage(i, SSYNTH_STAGE_KEYSTROKE);
218   ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = %i", note, vv, i);
219   return i;
220  }
221 }
222
223 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = -1", note, vv);
224 return -1;
225}
226
227int ssynth_note_free(int id) {
228 g_ssynth.notes[id].stage = SSYNTH_STAGE_UNUSED;
229 return 0;
230}
231
232int ssynth_note_find(struct roar_note_octave * note) {
233 struct roar_note_octave * cn;
234 int i;
235
236 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
237  if ( g_ssynth.notes[i].stage == SSYNTH_STAGE_UNUSED )
238   continue;
239
240  cn = &(g_ssynth.notes[i].note);
241
242  if ( !(note->note == cn->note && note->octave == cn->octave) )
243   continue;
244
245  return i;
246 }
247
248 return -1;
249}
250
251int ssynth_note_set_stage(int id, int stage) {
252 int r = -1;
253
254 switch (stage) {
255  case SSYNTH_STAGE_UNUSED:
256    r = ssynth_note_free(id);
257   break;
258  case SSYNTH_STAGE_KEYSTROKE:
259    r = roar_fader_init(&(g_ssynth.notes[id].fader), ssynth_polys[SSYNTH_POLY_KEYDOWN], SSYNTH_POLY_COEFF);
260   break;
261  case SSYNTH_STAGE_MIDSECTION:
262    r = 0;
263   break;
264  case SSYNTH_STAGE_KEYRELEASE:
265    r = roar_fader_init(&(g_ssynth.notes[id].fader), ssynth_polys[SSYNTH_POLY_KEYUP], SSYNTH_POLY_COEFF);
266   break;
267 }
268
269 if ( r == 0 )
270  g_ssynth.notes[id].stage = stage;
271
272 return r;
273}
274
275int ssynth_note_render   (int id, void * data) {
276 if ( g_sa->bits != 16 )
277  return -1;
278
279 return roar_synth_pcmout_i161(&(g_ssynth.notes[id].synth), data, ROAR_OUTPUT_BUFFER_SAMPLES);
280}
281
282int ssynth_note_on       (struct roar_note_octave * note, char vv) {
283 ROAR_DBG("ssynth_note_on(note=%p, vv=%i) = ?", note, vv);
284 return ssynth_note_new(note, vv);
285}
286
287int ssynth_note_off      (struct roar_note_octave * note, char vv) {
288 int id;
289
290 ROAR_DBG("ssynth_note_off(note=%p, vv=%i) = ?", note, vv);
291
292 if ( (id = ssynth_note_find(note)) == -1 )
293  return -1;
294
295 // add support to for keyups...
296
297 return ssynth_note_free(id);
298}
299
300int ssynth_eval_message (struct midi_message * mes) {
301 if ( !ssynth_conf.enable )
302  return -1;
303
304 ROAR_DBG("ssynth_eval_message(mes=%p) = ?", mes);
305
306 switch (mes->type) {
307  case MIDI_TYPE_NOTE_OFF:
308    return ssynth_note_off(&(mes->d.note), mes->vv);
309   break;
310  case MIDI_TYPE_NOTE_ON:
311    return ssynth_note_on(&(mes->d.note), mes->vv);
312   break;
313  default:
314    /* ignore all other events at the moment */
315    return 0;
316 }
317
318 ROAR_DBG("ssynth_eval_message(mes=%p) = -1", mes);
319 return -1;
320}
321
322#endif
323
324//ll
Note: See TracBrowser for help on using the repository browser.