make midimap obey channels
[galan.git] / plugins / libosc.c
blob6ce5e54cf69816e93ae4eca423ca081c25c688c3
1 /* gAlan - Graphical Audio Language
2 * Copyright (C) 1999 Tony Garnock-Jones
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <stddef.h>
24 #include <gdk/gdk.h>
25 #include <gtk/gtk.h>
27 #include "global.h"
28 #include "generator.h"
29 #include "comp.h"
30 #include "control.h"
31 #include "gencomp.h"
33 #define EVT_TRIGGER 0
34 #define EVT_FREQ 1
35 #define EVT_KIND 2
37 typedef enum OscKind {
38 OSC_MIN_KIND = 0,
40 OSC_KIND_SIN = 0,
41 OSC_KIND_SQR,
42 OSC_KIND_SAW,
43 OSC_KIND_TRI,
45 OSC_NUM_KINDS
46 } OscKind;
48 typedef struct OscData {
49 gint32 kind;
50 SAMPLE *sample_table;
51 gdouble phase;
52 gdouble frequency;
53 } OscData;
55 typedef struct WavFormData {
56 GtkWidget *sin_button, *sqr_button, *saw_button, *tri_button;
57 } WavFormData;
59 PRIVATE SAMPLE *sample_table[OSC_NUM_KINDS];
61 PRIVATE void setup_tables(void) {
62 const gdouble rad_per_sample = 2.0 * M_PI / SAMPLE_RATE;
63 const gdouble saw_step = (SAMPLE_MAX - SAMPLE_MIN) / SAMPLE_RATE;
64 const gdouble tri_step = 2*saw_step;
65 int i;
67 for( i=0; i<OSC_NUM_KINDS; i++ )
68 sample_table[i] = safe_malloc( sizeof(SAMPLE) * SAMPLE_RATE );
70 for (i = 0; i < SAMPLE_RATE; i++)
71 sample_table[OSC_KIND_SIN][i] = SAMPLE_MUL(SAMPLE_UNIT, sin(i * rad_per_sample));
73 for (i = 0; i < SAMPLE_RATE / 2; i++)
74 sample_table[OSC_KIND_SQR][i] = SAMPLE_MAX;
75 for (i = SAMPLE_RATE / 2; i < SAMPLE_RATE; i++)
76 sample_table[OSC_KIND_SQR][i] = SAMPLE_MIN;
78 for (i = 0; i < SAMPLE_RATE; i++)
79 sample_table[OSC_KIND_SAW][i] = SAMPLE_MIN + i * saw_step;
81 for (i = 0; i < SAMPLE_RATE / 2; i++)
82 sample_table[OSC_KIND_TRI][i] = SAMPLE_MIN + i * tri_step;
83 for (i = SAMPLE_RATE / 2; i < SAMPLE_RATE; i++)
84 sample_table[OSC_KIND_TRI][i] = SAMPLE_MAX - (i-SAMPLE_RATE/2) * tri_step;
87 PRIVATE int init_instance(Generator *g) {
88 OscData *d = safe_malloc(sizeof(OscData));
89 g->data = d;
91 d->kind = OSC_KIND_SQR;
92 d->sample_table = sample_table[d->kind];
93 d->phase = 0;
94 d->frequency = 60;
96 return 1;
99 PRIVATE void destroy_instance(Generator *g) {
100 free(g->data);
103 PRIVATE void unpickle_instance(Generator *g, ObjectStoreItem *item, ObjectStore *db) {
104 OscData *d = safe_malloc(sizeof(OscData));
105 g->data = d;
107 d->kind = objectstore_item_get_integer(item, "osc_kind", OSC_KIND_SAW);
108 d->sample_table = sample_table[d->kind];
109 d->phase = objectstore_item_get_double(item, "osc_phase", 0);
110 d->frequency = objectstore_item_get_double(item, "osc_frequency", 440);
113 PRIVATE void pickle_instance(Generator *g, ObjectStoreItem *item, ObjectStore *db) {
114 OscData *d = g->data;
115 objectstore_item_set_integer(item, "osc_kind", d->kind);
116 objectstore_item_set_double(item, "osc_phase", d->phase);
117 objectstore_item_set_double(item, "osc_frequency", d->frequency);
120 PRIVATE gboolean output_generator(Generator *g, SAMPLE *buf, int buflen) {
121 int i;
122 OscData *d = g->data;
124 for (i = 0; i < buflen; i++) {
125 buf[i] = d->sample_table[(int) d->phase];
126 d->phase += d->frequency;
127 if (d->phase >= SAMPLE_RATE)
128 d->phase -= SAMPLE_RATE;
131 return TRUE;
134 PRIVATE void evt_trigger_handler(Generator *g, AEvent *event) {
135 ((OscData *) g->data)->phase = 0;
138 PRIVATE void evt_freq_handler(Generator *g, AEvent *event) {
139 ((OscData *) g->data)->frequency = MIN(MAX(event->d.number, 0), SAMPLE_RATE>>1);
140 gen_update_controls(g, 1);
143 PRIVATE void evt_kind_handler(Generator *g, AEvent *event) {
144 OscData *d = g->data;
145 gint32 k = GEN_DOUBLE_TO_INT(event->d.number);
147 if (k >= OSC_MIN_KIND && k < OSC_NUM_KINDS) {
148 d->kind = k;
149 d->sample_table = sample_table[k];
151 gen_update_controls(g, 0);
154 PRIVATE void wav_emit(Control *c, gdouble number) {
155 AEvent e;
157 if (!c->events_flow)
158 return;
160 gen_init_aevent(&e, AE_NUMBER, NULL, 0, c->g, 2, gen_get_sampletime());
161 e.d.number = number;
163 if (c->desc->is_dst_gen)
164 gen_post_aevent(&e); /* send to c->g as dest */
165 else
166 gen_send_events(c->g, 2, -1, &e); /* send *from* c->g */
169 PRIVATE gboolean wav_sin_pressed( GtkWidget *w, Control *c ) {
171 wav_emit( c, OSC_KIND_SIN );
172 return FALSE;
174 PRIVATE gboolean wav_sqr_pressed( GtkWidget *w, Control *c ) {
176 wav_emit( c, OSC_KIND_SQR );
177 return FALSE;
179 PRIVATE gboolean wav_saw_pressed( GtkWidget *w, Control *c ) {
181 wav_emit( c, OSC_KIND_SAW );
182 return FALSE;
184 PRIVATE gboolean wav_tri_pressed( GtkWidget *w, Control *c ) {
186 wav_emit( c, OSC_KIND_TRI );
187 return FALSE;
190 PRIVATE void init_wavform( Control *control ) {
192 GtkWidget *vbox;
194 WavFormData *wdata = safe_malloc( sizeof( WavFormData ) );
195 control->data = wdata;
197 vbox = gtk_vbox_new(FALSE, 0);
198 gtk_widget_show(vbox);
200 wdata->sin_button = gtk_radio_button_new_with_label(NULL, "sin");
201 gtk_signal_connect( GTK_OBJECT(wdata->sin_button), "pressed", GTK_SIGNAL_FUNC(wav_sin_pressed), (gpointer) control );
203 wdata->sqr_button = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(wdata->sin_button)), "sqr");
204 gtk_signal_connect( GTK_OBJECT(wdata->sqr_button), "pressed", GTK_SIGNAL_FUNC(wav_sqr_pressed), (gpointer) control );
206 wdata->saw_button = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(wdata->sqr_button)), "saw");
207 gtk_signal_connect( GTK_OBJECT(wdata->saw_button), "pressed", GTK_SIGNAL_FUNC(wav_saw_pressed), (gpointer) control );
209 wdata->tri_button = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(wdata->saw_button)), "tri");
210 gtk_signal_connect( GTK_OBJECT(wdata->tri_button), "pressed", GTK_SIGNAL_FUNC(wav_tri_pressed), (gpointer) control );
212 gtk_box_pack_start(GTK_BOX(vbox), wdata->sin_button, TRUE, TRUE, 0);
213 gtk_widget_show(wdata->sin_button);
214 gtk_box_pack_start(GTK_BOX(vbox), wdata->sqr_button, TRUE, TRUE, 0);
215 gtk_widget_show(wdata->sqr_button);
216 gtk_box_pack_start(GTK_BOX(vbox), wdata->saw_button, TRUE, TRUE, 0);
217 gtk_widget_show(wdata->saw_button);
218 gtk_box_pack_start(GTK_BOX(vbox), wdata->tri_button, TRUE, TRUE, 0);
219 gtk_widget_show(wdata->tri_button);
221 control->widget = vbox;
225 PRIVATE void done_wavform(Control *control) {
228 PRIVATE void refresh_wavform(Control *control) {
229 OscData *data = control->g->data;
230 WavFormData *wdata = control->data;
232 switch( data->kind )
234 case OSC_KIND_SIN:
235 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata->sin_button), TRUE );
236 break;
237 case OSC_KIND_SQR:
238 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata->sqr_button), TRUE );
239 break;
240 case OSC_KIND_SAW:
241 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata->saw_button), TRUE );
242 break;
243 case OSC_KIND_TRI:
244 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata->tri_button), TRUE );
245 break;
249 PRIVATE OutputSignalDescriptor output_sigs[] = {
250 { "Output", SIG_FLAG_REALTIME, { output_generator, } },
251 { NULL, }
254 PRIVATE ControlDescriptor osc_controls[] = {
255 { CONTROL_KIND_KNOB, "Waveform", 0,3,0,1, 0,FALSE, TRUE,EVT_KIND,
256 NULL,NULL, control_int32_updater, (gpointer) offsetof(OscData, kind) },
257 { CONTROL_KIND_USERDEF, "Waveform Radio", 0,0,0,0, 0,FALSE, TRUE,0, init_wavform, done_wavform, refresh_wavform, NULL },
258 { CONTROL_KIND_SLIDER, "Freq", 20,22049,10,1, 0,TRUE, TRUE,EVT_FREQ,
259 NULL,NULL, control_double_updater, (gpointer) offsetof(OscData, frequency) },
260 { CONTROL_KIND_NONE, }
263 PRIVATE void setup_class(void) {
264 GeneratorClass *k = gen_new_generatorclass("vco", FALSE, 3, 0,
265 NULL, output_sigs, osc_controls,
266 init_instance, destroy_instance,
267 unpickle_instance, pickle_instance);
269 gen_configure_event_input(k, EVT_TRIGGER, "Trigger", evt_trigger_handler);
270 gen_configure_event_input(k, EVT_FREQ, "Frequency", evt_freq_handler);
271 gen_configure_event_input(k, EVT_KIND, "Oscillator Kind", evt_kind_handler);
273 gencomp_register_generatorclass(k, FALSE, "Sources/Simple Oscillator",
274 PIXMAPDIRIFY("osc.xpm"),
275 NULL);
278 PUBLIC void init_plugin(void) {
279 setup_tables();
280 setup_class();