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
RevLine 
[2448]1//ssynth.c:
2
3/*
[4708]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2011
[2448]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
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[2448]23 *
24 */
25
26#include "roard.h"
27
[2489]28#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
29
[2453]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
[5192]35struct ssynth_state g_ssynth;
36
[2450]37int ssynth_init_config(void) {
38 memset(&ssynth_conf, 0, sizeof(ssynth_conf));
39
40 return 0;
41}
42
[2452]43#define _err() streams_delete(sid); return -1
[2450]44int ssynth_init (void) {
[2452]45 struct roar_stream_server * ss;
46 struct roar_stream        *  s;
47 int sid;
48
[2450]49 if ( !ssynth_conf.enable )
50  return 0;
51
[2452]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
[2468]85 g_ssynth.stream  = sid;
[2452]86
87 return 0;
[2450]88}
89
90int ssynth_free (void) {
[2469]91 int i;
92
[2450]93 if ( !ssynth_conf.enable )
94  return 0;
95
[2469]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
[2452]103 return streams_delete(g_ssynth.stream);
[2450]104}
105
[2467]106int ssynth_update (void) {
[2469]107 struct roar_stream_server * ss;
108 struct roar_stream        *  s;
109 struct roar_buffer        * buf;
[2470]110 struct roar_buffer        * outbuf;
111 void                      * outbufdata;
112 void                      * indbufs[SSYNTH_NOTES_MAX+1];
113 int                         curin = 0;
[2469]114 size_t buflen;
115 size_t needlen;
116 int i;
117
118 if ( !ssynth_conf.enable )
119  return 0;
120
[2472]121 ROAR_DBG("ssynth_update(void) = ?");
122
[2469]123 if ( streams_get(g_ssynth.stream, &ss) == -1 ) {
124  return -1;
125 }
126
[2470]127 memset(indbufs, 0, sizeof(indbufs));
128
[2469]129 s = ROAR_STREAM(ss);
130
131 needlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info));
132
[2472]133 ROAR_DBG("ssynth_update(void): needlen=%lu", (unsigned long)needlen);
134
[2469]135 for (i = 0; i < SSYNTH_NOTES_MAX; i++) {
136  if ( g_ssynth.notes[i].stage != SSYNTH_STAGE_UNUSED ) {
[2472]137   ROAR_DBG("ssynth_update(void): used note slot: %i", i);
[2469]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   }
[2470]154
155   if ( roar_buffer_get_data(buf, &(indbufs[curin])) == -1 )
156    continue;
157
[2471]158   if ( ssynth_note_render(i, indbufs[curin]) == -1 )
159    continue;
160
[2470]161   curin++;
[2469]162  }
163 }
164
[2472]165 ROAR_DBG("ssynth_update(void): found streams: %i", curin);
166
[2470]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
[2932]176  if ( roar_mix_pcm(outbufdata, g_sa->bits, indbufs, ROAR_OUTPUT_BUFFER_SAMPLES) == -1 ) {
[2470]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
[2472]187 ROAR_DBG("ssynth_update(void) = 0");
[2470]188 return 0;
[2467]189}
190
191
[2457]192int ssynth_note_new(struct roar_note_octave * note, char vv) {
193 int i;
194
[2472]195 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = ?", note, vv);
196
[2457]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);
[2473]203   roar_synth_set_volume(&(g_ssynth.notes[i].synth), 0.25);
[2476]204   roar_synth_set_func(&(g_ssynth.notes[i].synth), ROAR_SYNTH_SYNF_TRAP);
[2457]205   ssynth_note_set_stage(i, SSYNTH_STAGE_KEYSTROKE);
[2472]206   ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = %i", note, vv, i);
[2457]207   return i;
208  }
209 }
210
[2472]211 ROAR_DBG("ssynth_note_new(note=%p, vv=%i) = -1", note, vv);
[2457]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) {
[2465]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
[2457]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
[2471]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
[2463]270int ssynth_note_on       (struct roar_note_octave * note, char vv) {
[2472]271 ROAR_DBG("ssynth_note_on(note=%p, vv=%i) = ?", note, vv);
[2464]272 return ssynth_note_new(note, vv);
[2463]273}
274
275int ssynth_note_off      (struct roar_note_octave * note, char vv) {
[2464]276 int id;
277
[2472]278 ROAR_DBG("ssynth_note_off(note=%p, vv=%i) = ?", note, vv);
279
[2464]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);
[2463]286}
287
[2460]288int ssynth_eval_message (struct midi_message * mes) {
[2463]289 if ( !ssynth_conf.enable )
290  return -1;
291
[2472]292 ROAR_DBG("ssynth_eval_message(mes=%p) = ?", mes);
293
[2463]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:
[2472]299    return ssynth_note_on(&(mes->d.note), mes->vv);
[2463]300   break;
301  default:
302    /* ignore all other events at the moment */
303    return 0;
304 }
305
[2472]306 ROAR_DBG("ssynth_eval_message(mes=%p) = -1", mes);
[2460]307 return -1;
308}
309
[2489]310#endif
311
[2448]312//ll
Note: See TracBrowser for help on using the repository browser.