source: roaraudio/roard/ssynth.c @ 2488:5d406a994ded

Last change on this file since 2488:5d406a994ded was 2476:6da5cf65271b, checked in by phi, 15 years ago

set a non sine function

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