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
28 #include "generator.h"
37 typedef enum OscKind
{
48 typedef struct OscData
{
55 typedef struct WavFormData
{
56 GtkWidget
*sin_button
, *sqr_button
, *saw_button
, *tri_button
;
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
;
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
));
91 d
->kind
= OSC_KIND_SQR
;
92 d
->sample_table
= sample_table
[d
->kind
];
99 PRIVATE
void destroy_instance(Generator
*g
) {
103 PRIVATE
void unpickle_instance(Generator
*g
, ObjectStoreItem
*item
, ObjectStore
*db
) {
104 OscData
*d
= safe_malloc(sizeof(OscData
));
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
) {
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
;
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
) {
149 d
->sample_table
= sample_table
[k
];
151 gen_update_controls(g
, 0);
154 PRIVATE
void wav_emit(Control
*c
, gdouble number
) {
160 gen_init_aevent(&e
, AE_NUMBER
, NULL
, 0, c
->g
, 2, gen_get_sampletime());
163 if (c
->desc
->is_dst_gen
)
164 gen_post_aevent(&e
); /* send to c->g as dest */
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
);
174 PRIVATE gboolean
wav_sqr_pressed( GtkWidget
*w
, Control
*c
) {
176 wav_emit( c
, OSC_KIND_SQR
);
179 PRIVATE gboolean
wav_saw_pressed( GtkWidget
*w
, Control
*c
) {
181 wav_emit( c
, OSC_KIND_SAW
);
184 PRIVATE gboolean
wav_tri_pressed( GtkWidget
*w
, Control
*c
) {
186 wav_emit( c
, OSC_KIND_TRI
);
190 PRIVATE
void init_wavform( Control
*control
) {
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
;
235 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata
->sin_button
), TRUE
);
238 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata
->sqr_button
), TRUE
);
241 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata
->saw_button
), TRUE
);
244 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(wdata
->tri_button
), TRUE
);
249 PRIVATE OutputSignalDescriptor output_sigs
[] = {
250 { "Output", SIG_FLAG_REALTIME
, { output_generator
, } },
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"),
278 PUBLIC
void init_plugin(void) {