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

Contents of /src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations)
Sat Aug 18 15:06:17 2012 UTC (7 years, 11 months ago) by ben
File MIME type: text/plain
File size: 7782 byte(s)
fix program change
1 /* Copyright (c) 2012, Benoit Rouits <brouits@free.fr>
2 * Some rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
14 * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
17 * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <jack/jack.h>
32 #include <jack/midiport.h>
33
34 #include <config.h>
35 #include "graph.h"
36
37 #define MAX_VOICE 64
38 #define MAX_INST 128
39
40 #define error(str) fprintf(stderr, "[error]\t%s\n", str)
41
42 struct jack {
43 jack_client_t *client;
44 jack_transport_state_t state;
45 };
46
47 struct voice {
48 struct event* route;
49 int count;
50 int cur;
51 jack_time_t press;
52 };
53
54 struct instrument {
55 struct voice voices[MAX_VOICE];
56 int count;
57 int end;
58
59 unsigned char chan:4; /* 0-15 */
60 unsigned char prog; /* 0-127 */
61
62 jack_port_t *out;
63 void* out_buf;
64
65 struct graph *graph;
66 };
67
68 struct app {
69 struct instrument* instruments;
70 int count;
71 int end;
72
73 struct jack *jack;
74 };
75
76 static int jack_process_callback(jack_nframes_t nframes, void *ctx)
77 {
78 struct app *app;
79 jack_transport_state_t state;
80 int i, voice, inst;
81 static unsigned char last_prog = 0;
82
83 app = ctx;
84
85 if (nframes <= 0) {
86 error("called process w/o frames");
87 return 0;
88 }
89
90 /* prepare all out buffers before writing into them */
91 for (i = 0; i < app->count; i++) {
92 void *port_buf = jack_port_get_buffer(app->instruments[i].out, nframes);
93 jack_midi_clear_buffer(port_buf);
94 app->instruments[i].out_buf = port_buf;
95 }
96
97 /* get transport state, act in consequence */
98 state = jack_transport_query(app->jack->client, NULL);
99 if (state == JackTransportStopped) {
100 if (app->jack->state == JackTransportRolling)
101 { /* send not off everywhere! */ }
102 app->jack->state = state;
103 return 0;
104 }
105 app->jack->state = state;
106
107 /* check end of all voices of all instruments */
108 if (app->end >= app->count)
109 return 0;
110
111 /* go browse all voice states and send events */
112 for (i = 0; i < nframes; i++) {
113 if (app->end >= app->count) {
114 fprintf(stderr, "tune ended (%d instruments)\n", app->end);
115 return 0;
116 }
117 for (inst = 0; inst < app->count; inst++) {
118 if (app->instruments[inst].end >= app->instruments[inst].count) {
119 app->end++;
120 fprintf(stderr, "instrument %d ended (%d voices)\n", inst, app->instruments[inst].end);
121 continue;
122 }
123 if (app->instruments[inst].prog != last_prog) {
124 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, i, 2);
125 if (!buf) {
126 error("no memory, event lost");
127 return 0;
128 }
129 buf[1] = app->instruments[inst].prog;
130 buf[0] = 0xc0|app->instruments[inst].chan;
131 last_prog = app->instruments[inst].prog;
132 }
133 for (voice = 0; voice < app->instruments[inst].count; voice++) {
134 jack_time_t *press = &app->instruments[inst].voices[voice].press;
135 int *cur = &app->instruments[inst].voices[voice].cur;
136 if (*cur >= app->instruments[inst].voices[voice].count) {
137 app->instruments[inst].end++;
138 fprintf(stderr, "voice %d ended (%d notes)\n", voice, *cur);
139 continue;
140 }
141 struct event *ev = &app->instruments[inst].voices[voice].route[*cur];
142
143 jack_time_t now = jack_get_time();
144
145 if (*press) { /* note must be released before passing to next note */
146 if (*press + ev->duration <= now) {
147 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, i, 3);
148 if (!buf) {
149 error("no memory, event lost");
150 return 0;
151 }
152 buf[2] = ev->velocity;
153 buf[1] = ev->pitch;
154 buf[0] = 0x80|app->instruments[inst].chan; /* note off */
155 *press = 0; /* release */
156 (*cur)++; /* go to next node */
157 fprintf(stderr, "off %d (%p)\n", ev->pitch, ev);
158 }
159 } else { /* this is a new note */
160 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, i, 3);
161 if (!buf) {
162 error("no memory, event lost");
163 return 0;
164 }
165 buf[2] = ev->velocity;
166 buf[1] = ev->pitch;
167 buf[0] = 0x90|app->instruments[inst].chan; /* note on */
168 *press = now;
169 fprintf(stderr, "on %d (%p)\n", ev->pitch, ev);
170 }
171 }
172 }
173 }
174
175 return 0;
176 }
177
178 static int jack_sync_callback(jack_transport_state_t state, jack_position_t *position, void *ctx)
179 {
180 struct app *app;
181
182 app = ctx;
183
184 if (state == JackTransportStarting) {
185 /* seek in paths (???) according to position->frame */
186 } else if (state == JackTransportStopped) {
187 }
188
189 return 1;
190 }
191
192 void jack_shutdown(void* ctx)
193 {
194 puts("jack vanished...");
195 }
196
197 int main (int argc, char *argv[])
198 {
199 struct graph *graph;
200 struct instrument instrument;
201 struct voice voice;
202 struct jack jack;
203 struct app app;
204
205 int i, err;
206
207 /* create random graph */
208 graph = graph_new(100);
209 graph_randomize2(graph, 3);
210
211 /* initialize a solo instrument */
212 memset(&instrument, 0, sizeof(instrument));
213 instrument.graph = graph;
214
215 /* initialize application context */
216 memset(&app, 0, sizeof(app));
217 app.jack = &jack;
218 app.instruments = &instrument;
219 app.count = 1;
220
221 /* create a random route (lol) */
222 memset(&voice, 0, sizeof(voice));
223 voice.route = &graph->nodes[0].event;
224 voice.count = 1;
225 instrument.voices[0] = voice;
226 instrument.count = 1;
227
228 /* mark it (...) */
229 app.instruments[0].chan = 0;
230 app.instruments[0].prog = 0;
231 app.instruments[0].voices[0].route[0].pitch = 42;
232 app.instruments[0].voices[0].route[0].duration = 4200000;
233
234 /* init jack */
235 jack.client = jack_client_open(PACKAGE_NAME, JackNullOption, NULL);
236 if (jack.client == NULL) {
237 error("could not connect to jackd");
238 exit(EXIT_FAILURE);
239 }
240
241 err = jack_set_process_callback(jack.client, jack_process_callback, &app);
242
243 if (err) {
244 error("could not set jack process callback");
245 exit(EXIT_FAILURE);
246 }
247
248 err = jack_set_sync_callback(jack.client, jack_sync_callback, &app);
249
250 if (err) {
251 error("could not set jack sync callback");
252 exit(EXIT_FAILURE);
253 }
254
255 jack_on_shutdown(jack.client, jack_shutdown, &app);
256
257 /* allocate one jack port per instrument (midi outs) */
258 for (i = 0; i < app.count; i++) {
259 char name[32];
260 snprintf(name, 32, "out %d", i);
261 app.instruments[i].out = jack_port_register(jack.client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
262 if (app.instruments[i].out == NULL) {
263 error("could not register a jack midi out port");
264 exit(EXIT_FAILURE);
265 }
266 }
267
268 /* activate jack */
269 if (jack_activate(jack.client)) {
270 error("could not activate jack client");
271 exit(EXIT_FAILURE);
272 }
273
274
275 fprintf(stderr, "==========\n");
276 /* start playing (event loop) */
277 sleep(60);
278 fprintf(stderr, "==========\n");
279
280 /* close jack */
281 jack_client_close (jack.client);
282
283 /* exit */
284 graph_destroy(graph);
285
286 exit(EXIT_SUCCESS);
287 }

  ViewVC Help
Powered by ViewVC 1.1.26