source: roaraudio/roard/ssynth.c @ 5192:4237437ca526

Last change on this file since 5192:4237437ca526 was 5192:4237437ca526, checked in by phi, 13 years ago

declare some stuff 'extern', this saves like 5.3KB of diskspace in plugin files and make them more resistant against changes in roard

File size: 7.1 KB
Line 
1//ssynth.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2011
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
30float 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_state g_ssynth;
36
37int ssynth_init_config(void) {
38 memset(&ssynth_conf, 0, sizeof(ssynth_conf));
39
40 return 0;
41}
42
43#define _err() streams_delete(sid); return -1
44int ssynth_init (void) {
45 struct roar_stream_server * ss;
46 struct roar_stream        *  s;
47 int sid;
48
49 if ( !ssynth_conf.enable )
50  return 0;
51
52 memset(&g_ssynth, 0, sizeof(g_ssynth));
53 g_ssynth.stream = -1;
54
55 if ( (sid = streams_new()) == -1 )
56  return -1;
57
58 if ( streams_set_client(sid, g_self_client) == -1 ) {
59  _err();
60 }
61
62 if ( streams_set_dir(sid, ROAR_DIR_BRIDGE, 1) == -1 ) {
63  _err();
64 }
65
66 if ( streams_set_flag(sid, ROAR_FLAG_PRIMARY) == -1 ) {
67  _err();
68 }
69
70 if ( streams_set_name(sid, "Simple Synthesizer") == -1 ) {
71  _err();
72 }
73
74 if ( streams_get(sid, &ss) == -1 ) {
75  _err();
76 }
77
78 s = ROAR_STREAM(ss);
79
80 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
81
82 s->info.channels = 1;
83 s->info.codec    = ROAR_CODEC_DEFAULT;
84
85 g_ssynth.stream  = sid;
86
87 return 0;
88}
89
90int ssynth_free (void) {
91 int i;
92
93 if ( !ssynth_conf.enable )
94  return 0;
95
96 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
97  if ( g_ssynth.notes[i].buf != NULL ) {
98   roar_buffer_free(g_ssynth.notes[i].buf);
99   g_ssynth.notes[i].buf = NULL;
100  }
101 }
102
103 return streams_delete(g_ssynth.stream);
104}
105
106int ssynth_update (void) {
107 struct roar_stream_server * ss;
108 struct roar_stream        *  s;
109 struct roar_buffer        * buf;
110 struct roar_buffer        * outbuf;
111 void                      * outbufdata;
112 void                      * indbufs[SSYNTH_NOTES_MAX+1];
113 int                         curin = 0;
114 size_t buflen;
115 size_t needlen;
116 int i;
117
118 if ( !ssynth_conf.enable )
119  return 0;
120
121 ROAR_DBG("ssynth_update(void) = ?");
122
123 if ( streams_get(g_ssynth.stream, &ss) == -1 ) {
124  return -1;
125 }
126
127 memset(indbufs, 0, sizeof(indbufs));
128
129 s = ROAR_STREAM(ss);
130
131 needlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info));
132
133 ROAR_DBG("ssynth_update(void): needlen=%lu", (unsigned long)needlen);
134
135 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
136  if ( g_ssynth.notes[i].stage != SSYNTH_STAGE_UNUSED ) {
137   ROAR_DBG("ssynth_update(void): used note slot: %i", i);
138   if ( g_ssynth.notes[i].buf == NULL ) {
139    if ( roar_buffer_new(&buf, needlen) == -1 )
140     continue;
141
142    g_ssynth.notes[i].buf = buf;
143   } else {
144    buf = g_ssynth.notes[i].buf;
145
146    if ( roar_buffer_get_len(buf, &buflen) == -1 )
147     continue;
148
149    if ( buflen < needlen ) {
150     if ( roar_buffer_set_len(buf, needlen) == -1 )
151      continue;
152    }
153   }
154
155   if ( roar_buffer_get_data(buf, &(indbufs[curin])) == -1 )
156    continue;
157
158   if ( ssynth_note_render(i, indbufs[curin]) == -1 )
159    continue;
160
161   curin++;
162  }
163 }
164
165 ROAR_DBG("ssynth_update(void): found streams: %i", curin);
166
167 if ( curin > 0 ) {
168  if ( roar_buffer_new(&outbuf, needlen) == -1 )
169   return -1;
170
171  if ( roar_buffer_get_data(outbuf, &outbufdata) == -1 ) {
172   roar_buffer_free(outbuf);
173   return -1;
174  }
175
176  if ( roar_mix_pcm(outbufdata, g_sa->bits, indbufs, ROAR_OUTPUT_BUFFER_SAMPLES) == -1 ) {
177   roar_buffer_free(outbuf);
178   return -1;
179  }
180
181  if ( stream_add_buffer(g_ssynth.stream, outbuf) == -1 ) {
182   roar_buffer_free(outbuf);
183   return -1;
184  }
185 }
186
187 ROAR_DBG("ssynth_update(void) = 0");
188 return 0;
189}
190
191
192int ssynth_note_new(struct roar_note_octave * note, char vv) {
193 int i;
194
195 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = ?", note, vv);
196
197 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
198  if ( g_ssynth.notes[i].stage == SSYNTH_STAGE_UNUSED ) {
199   // TODO: do some error checking here
200   g_ssynth.notes[i].vv_down = vv;
201   memcpy(&(g_ssynth.notes[i].note), note, sizeof(struct roar_note_octave));
202   roar_synth_init(&(g_ssynth.notes[i].synth), &(g_ssynth.notes[i].note), g_sa->rate);
203   roar_synth_set_volume(&(g_ssynth.notes[i].synth), 0.25);
204   roar_synth_set_func(&(g_ssynth.notes[i].synth), ROAR_SYNTH_SYNF_TRAP);
205   ssynth_note_set_stage(i, SSYNTH_STAGE_KEYSTROKE);
206   ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = %i", note, vv, i);
207   return i;
208  }
209 }
210
211 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = -1", note, vv);
212 return -1;
213}
214
215int ssynth_note_free(int id) {
216 g_ssynth.notes[id].stage = SSYNTH_STAGE_UNUSED;
217 return 0;
218}
219
220int ssynth_note_find(struct roar_note_octave * note) {
221 struct roar_note_octave * cn;
222 int i;
223
224 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
225  if ( g_ssynth.notes[i].stage == SSYNTH_STAGE_UNUSED )
226   continue;
227
228  cn = &(g_ssynth.notes[i].note);
229
230  if ( !(note->note == cn->note && note->octave == cn->octave) )
231   continue;
232
233  return i;
234 }
235
236 return -1;
237}
238
239int ssynth_note_set_stage(int id, int stage) {
240 int r = -1;
241
242 switch (stage) {
243  case SSYNTH_STAGE_UNUSED:
244    r = ssynth_note_free(id);
245   break;
246  case SSYNTH_STAGE_KEYSTROKE:
247    r = roar_fader_init(&(g_ssynth.notes[id].fader), ssynth_polys[SSYNTH_POLY_KEYDOWN], SSYNTH_POLY_COEFF);
248   break;
249  case SSYNTH_STAGE_MIDSECTION:
250    r = 0;
251   break;
252  case SSYNTH_STAGE_KEYRELEASE:
253    r = roar_fader_init(&(g_ssynth.notes[id].fader), ssynth_polys[SSYNTH_POLY_KEYUP], SSYNTH_POLY_COEFF);
254   break;
255 }
256
257 if ( r == 0 )
258  g_ssynth.notes[id].stage = stage;
259
260 return r;
261}
262
263int ssynth_note_render   (int id, void * data) {
264 if ( g_sa->bits != 16 )
265  return -1;
266
267 return roar_synth_pcmout_i161(&(g_ssynth.notes[id].synth), data, ROAR_OUTPUT_BUFFER_SAMPLES);
268}
269
270int ssynth_note_on       (struct roar_note_octave * note, char vv) {
271 ROAR_DBG("ssynth_note_on(note=%p, vv=%i) = ?", note, vv);
272 return ssynth_note_new(note, vv);
273}
274
275int ssynth_note_off      (struct roar_note_octave * note, char vv) {
276 int id;
277
278 ROAR_DBG("ssynth_note_off(note=%p, vv=%i) = ?", note, vv);
279
280 if ( (id = ssynth_note_find(note)) == -1 )
281  return -1;
282
283 // add support to for keyups...
284
285 return ssynth_note_free(id);
286}
287
288int ssynth_eval_message (struct midi_message * mes) {
289 if ( !ssynth_conf.enable )
290  return -1;
291
292 ROAR_DBG("ssynth_eval_message(mes=%p) = ?", mes);
293
294 switch (mes->type) {
295  case MIDI_TYPE_NOTE_OFF:
296    return ssynth_note_off(&(mes->d.note), mes->vv);
297   break;
298  case MIDI_TYPE_NOTE_ON:
299    return ssynth_note_on(&(mes->d.note), mes->vv);
300   break;
301  default:
302    /* ignore all other events at the moment */
303    return 0;
304 }
305
306 ROAR_DBG("ssynth_eval_message(mes=%p) = -1", mes);
307 return -1;
308}
309
310#endif
311
312//ll
Note: See TracBrowser for help on using the repository browser.