source: roaraudio/roard/ssynth.c @ 5301:f3e9cd30574d

Last change on this file since 5301:f3e9cd30574d was 5301:f3e9cd30574d, checked in by phi, 12 years ago

move away from roar_buffer_add() (See: #126)

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