/[paths]/src/jack.c
ViewVC logotype

Contents of /src/jack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 74 - (show annotations)
Tue Aug 28 01:37:01 2012 UTC (7 years, 1 month ago) by ben
File MIME type: text/plain
File size: 5634 byte(s)
use more pointers, permit multiple instruments layout to sound (still random)
1 #include <assert.h>
2 #include <jack/jack.h>
3 #include <jack/midiport.h>
4
5 #include "main.h"
6 #include "egg_node.h"
7
8 void jack_info_function(const char* str)
9 {
10 }
11
12 void jack_error_function(const char* str)
13 {
14 }
15
16 static int send_prog_change(struct app *app, int inst, int frame)
17 {
18 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst]->out_buf, frame, 2);
19 if (!buf) {
20 error("no memory, event lost");
21 return 1;
22 }
23 buf[1] = app->instruments[inst]->prog;
24 buf[0] = 0xc0|app->instruments[inst]->chan;
25 return 0;
26 }
27
28 void paint_note_on(struct app *app, struct node *n)
29 {
30 int i;
31 if (!n->event.ref)
32 egg_node_set_color(EGG_NODE(n->egg), 0.0, 0.0, 0.0);
33 n->event.ref++;
34 }
35
36 void paint_note_off(struct app *app, struct node *n)
37 {
38 int i;
39 if (n->event.ref == 1)
40 egg_node_set_color(EGG_NODE(n->egg), 1.0, 1.0, 1.0);
41 if (n->event.ref)
42 n->event.ref--;
43 }
44
45 int send_note_off(struct app *app, int inst, int frame, struct event *ev)
46 {
47 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst]->out_buf, frame, 3);
48 if (!buf) {
49 error("no memory, event lost");
50 return 1;
51 }
52 buf[2] = ev->velocity;
53 buf[1] = ev->pitch;
54 buf[0] = 0x80|app->instruments[inst]->chan; /* note off */
55 fprintf(stderr, "off %d (%p)\n", ev->pitch, ev);
56 return 0;
57 }
58
59 int send_note_on(struct app *app, int inst, int frame, struct event *ev)
60 {
61 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst]->out_buf, frame, 3);
62 if (!buf) {
63 error("no memory, event lost");
64 return 1;
65 }
66 buf[2] = ev->velocity;
67 buf[1] = ev->pitch;
68 buf[0] = 0x90|app->instruments[inst]->chan; /* note on */
69 fprintf(stderr, "on %d (%p)\n", ev->pitch, ev);
70 return 0;
71 }
72
73 int broadcast_note_off(struct app *app, jack_nframes_t nframes)
74 {
75 int inst, voice;
76
77 for (inst = 0; inst < app->count; inst++) {
78 for (voice = 0; voice < app->instruments[inst]->count; voice++) {
79 if (app->instruments[inst]->voices[voice]->press) {
80 int cur = app->instruments[inst]->voices[voice]->cur;
81 struct node *n = app->instruments[inst]->voices[voice]->route[cur];
82 send_note_off(app, inst, 0, &n->event);
83 paint_note_off(app, n);
84 }
85 }
86 }
87 return 0;
88 }
89
90 int jack_process_callback(jack_nframes_t nframes, void *ctx)
91 {
92 struct app *app;
93 jack_transport_state_t state;
94 int i, voice, inst;
95
96 app = ctx;
97
98 if (nframes <= 0) {
99 error("called process w/o frames");
100 return 0;
101 }
102
103 /* prepare all out buffers before writing into them */
104 for (i = 0; i < app->count; i++) {
105 void *port_buf = jack_port_get_buffer(app->instruments[i]->out, nframes);
106 jack_midi_clear_buffer(port_buf);
107 app->instruments[i]->out_buf = port_buf;
108 }
109
110 /* get transport state, act in consequence */
111 state = jack_transport_query(app->jack->client, NULL);
112 if (state == JackTransportStopped) {
113 if (app->jack->state == JackTransportRolling) {
114 broadcast_note_off(app, nframes);
115 }
116 app->jack->state = state;
117 return 0;
118 }
119 app->jack->state = state;
120
121 /* check end of all voices of all instruments */
122 if (app->end >= app->count)
123 return 0;
124
125 /* go browse all voice states and send events */
126 for (i = 0; i < nframes; i++) {
127 if (app->end >= app->count) {
128 fprintf(stderr, "tune ended (%d instruments)\n", app->end);
129 return 0;
130 }
131 for (inst = 0; inst < app->count; inst++) {
132 if (app->instruments[inst]->end >= app->instruments[inst]->count) {
133 if (app->instruments[inst]->end == app->instruments[inst]->count) {
134 app->end++;
135 fprintf(stderr, "instrument %d ended (%d voices)\n", inst, app->instruments[inst]->end);
136 app->instruments[inst]->end++; /* do not pass here again */
137 }
138 continue;
139 }
140 for (voice = 0; voice < app->instruments[inst]->count; voice++) {
141 jack_time_t *press = &app->instruments[inst]->voices[voice]->press;
142 int *cur = &app->instruments[inst]->voices[voice]->cur;
143 struct node *n = app->instruments[inst]->voices[voice]->route[*cur];
144 jack_time_t now = jack_get_time();
145
146 if (*cur >= app->instruments[inst]->voices[voice]->count) {
147 if (*cur == app->instruments[inst]->voices[voice]->count) {
148 app->instruments[inst]->end++;
149 fprintf(stderr, "instr. %d: voice %d ended (%d notes)\n", inst, voice, *cur);
150 (*cur)++; /* do not pass here again */
151 }
152 continue;
153 }
154
155
156 if (*press) { /* note must be released before passing to next note */
157 if (*press + n->event.duration <= now) {
158 /* send a note off */
159 paint_note_off(app, n);
160 send_note_off(app, inst, i, &n->event);
161 *press = 0; /* release */
162 (*cur)++; /* go to next node */
163 } else {
164 /* nothing to do for now */
165 }
166 } else { /* this is a new note */
167 /* set program change on start only */
168 if (app->instruments[inst]->prog != app->instruments[inst]->last_prog) {
169 send_prog_change(app, inst, i);
170 app->instruments[inst]->last_prog = app->instruments[inst]->prog;
171 }
172 paint_note_on(app, n);
173 send_note_on(app, inst, i, &n->event);
174 *press = now;
175 }
176 }
177 }
178 }
179
180 return 0;
181 }
182 int jack_sync_callback(jack_transport_state_t state, jack_position_t *position, void *ctx)
183 {
184 struct app *app;
185
186 app = ctx;
187
188 if (state == JackTransportStarting) {
189 /* seek in paths (???) according to position->frame */
190 } else if (state == JackTransportStopped) {
191 if (position->frame == 0) {
192 /* reset voices */
193 int inst, voice;
194 for (inst = 0; inst < app->count; inst++) {
195 for (voice = 0; voice < app->instruments[inst]->count; voice++) {
196 app->instruments[inst]->voices[voice]->cur = 0;
197 app->instruments[inst]->voices[voice]->press = 0;
198 }
199 }
200 }
201 }
202
203 return 1;
204 }
205
206 void jack_shutdown(void* ctx)
207 {
208 puts("jack vanished...");
209 }

  ViewVC Help
Powered by ViewVC 1.1.26