root/branches/echoaudio/tests/streaming/testmidistreaming1.c

Revision 540, 13.9 kB (checked in by ppalmers, 17 years ago)

improve midi test util

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * FFADO is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * FFADO is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with FFADO; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA.
22  */
23
24
25 /**
26  * Test application for the direct decode stream API
27  * for floating point use
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <signal.h>
39 #include <libiec61883/iec61883.h>
40 #include <stdio.h>
41 #include <sys/select.h>
42 #include <signal.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <alsa/asoundlib.h>
46
47 #include "libffado/ffado.h"
48
49 #include "debugtools.h"
50 #define IEC61883_AM824_LABEL_MIDI_NO_DATA 0x80
51 #define IEC61883_AM824_LABEL_MIDI_1X      0x81
52 #define IEC61883_AM824_LABEL_MIDI_2X      0x82
53 #define IEC61883_AM824_LABEL_MIDI_3X      0x83
54        
55 #define ALSA_SEQ_BUFF_SIZE 1024
56 #define MAX_MIDI_PORTS   20
57 #define MIDI_TRANSMIT_BUFFER_SIZE 1024
58
59 int run;
60
61 static void sighandler (int sig)
62 {
63         run = 0;
64 }
65
66 typedef struct {
67         int seq_port_nr;
68         snd_midi_event_t *parser;
69         snd_seq_t *seq_handle;
70 } ffado_midi_port_t;
71
72 typedef struct {
73         snd_seq_t *seq_handle;
74         int nb_seq_ports;
75         ffado_midi_port_t *ports[MAX_MIDI_PORTS];
76 } ffado_midi_ports_t;
77
78 int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out);
79
80 /* Open ALSA sequencer with num_in writeable ports and num_out readable ports. */
81 /* The sequencer handle and the port IDs are returned.                        */ 
82 int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out) {
83
84         int l1;
85         char portname[64];
86
87         if (snd_seq_open(seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
88                 fprintf(stderr, "Error opening ALSA sequencer.\n");
89                 return(-1);
90         }
91        
92         snd_seq_set_client_name(*seq_handle, "FreeBob MIDI I/O test");
93        
94         for (l1 = 0; l1 < num_in; l1++) {
95                 sprintf(portname, "MIDI OUT %d", l1);
96                 if ((in_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname,
97                          SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
98                          SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) {
99                                  fprintf(stderr, "Error creating sequencer port.\n");
100                                  return(-1);
101                          }
102         }
103         for (l1 = 0; l1 < num_out; l1++) {
104                 sprintf(portname, "MIDI IN %d", l1);
105                 if ((out_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname,
106                          SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
107                          SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) {
108                                  fprintf(stderr, "Error creating sequencer port.\n");
109                                  return(-1);
110                          }
111         }
112         return(0);
113 }
114
115 void decode_midi_byte (ffado_midi_port_t *port, int byte) {
116         snd_seq_event_t ev;
117         if ((snd_midi_event_encode_byte(port->parser,byte, &ev)) > 0) {
118 //              printf("message ok, sending it to %d\n", port->seq_port_nr);
119                 // a midi message is complete, send it out to ALSA
120                 snd_seq_ev_set_subs(&ev); 
121                 snd_seq_ev_set_direct(&ev);
122                 snd_seq_ev_set_source(&ev, port->seq_port_nr);
123                 snd_seq_event_output_direct(port->seq_handle, &ev);                                             
124         }       else {
125                
126         }
127 }
128
129 int encode_midi_bytes(ffado_midi_port_t *port, unsigned char *byte_buff, int len) {
130     static int cnt=0;
131     cnt++;
132     if (cnt>64) {
133         *byte_buff=0xFF;
134         return 1;
135     }
136     return 0;
137 }
138
139 int main(int argc, char *argv[])
140 {
141
142         #define PERIOD_SIZE 1024
143
144         int samplesread=0, sampleswritten=0;
145         int nb_in_channels=0, nb_out_channels=0;
146         int retval=0;
147         int i=0;
148         int start_flag = 0;
149
150         int nb_periods=0;
151
152         ffado_sample_t **audiobuffers_in;
153         ffado_sample_t **audiobuffers_out;
154         ffado_sample_t *nullbuffer;
155        
156         run=1;
157
158         printf("Ffado MIDI streaming test application (1)\n");
159
160         signal (SIGINT, sighandler);
161         signal (SIGPIPE, sighandler);
162
163         ffado_device_info_t device_info;
164
165         ffado_options_t dev_options;
166
167         dev_options.sample_rate=48000; // -1 = detect from discovery
168         dev_options.period_size=PERIOD_SIZE;
169
170         dev_options.nb_buffers=3;
171
172         dev_options.port=0;
173         dev_options.node_id=-1;
174        
175         dev_options.realtime=0;
176         dev_options.packetizer_priority=60;
177        
178         dev_options.directions=0;
179        
180         dev_options.verbose=5;
181        
182         dev_options.slave_mode=0;
183         dev_options.snoop_mode=0;
184
185         ffado_device_t *dev=ffado_streaming_init(&device_info, dev_options);
186         if (!dev) {
187                 fprintf(stderr,"Could not init Ffado Streaming layer\n");
188                 exit(-1);
189         }
190
191         nb_in_channels=ffado_streaming_get_nb_capture_streams(dev);
192         nb_out_channels=ffado_streaming_get_nb_playback_streams(dev);
193
194         int midi_in_nbchannels=0;
195         int midi_out_nbchannels=0;
196        
197         /* allocate intermediate buffers */
198         audiobuffers_in=calloc(nb_in_channels,sizeof(ffado_sample_t *));
199         audiobuffers_out=calloc(nb_in_channels,sizeof(ffado_sample_t));
200         for (i=0;i<nb_in_channels;i++) {
201                 audiobuffers_in[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
202                 audiobuffers_out[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
203                        
204                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
205                         case ffado_stream_type_audio:
206                                 /* assign the audiobuffer to the stream */
207                                 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
208                                 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float);
209                                 break;
210                                
211                         // this is done with read/write routines because the nb of bytes can differ.
212                         case ffado_stream_type_midi:
213                                 midi_in_nbchannels++;
214                         default:
215                                 break;
216                 }
217         }
218        
219         nullbuffer=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
220        
221         for (i=0;i<nb_out_channels;i++) {
222                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
223                         case ffado_stream_type_audio:
224                                 if (i<nb_in_channels) {
225                                         /* assign the audiobuffer to the stream */
226                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
227                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float);
228                                 } else {
229                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)nullbuffer);
230                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_int24);     
231                                 }
232                                 break;
233                                 // this is done with read/write routines because the nb of bytes can differ.
234                         case ffado_stream_type_midi:
235                                 midi_out_nbchannels++;
236                         default:
237                                 break;
238                 }
239         }
240        
241         /* open the files to write to*/
242         FILE* fid_out[nb_out_channels];
243         FILE* fid_in[nb_in_channels];
244         char name[256];
245
246         for (i=0;i<nb_out_channels;i++) {
247                 snprintf(name,sizeof(name),"out_ch_%02d",i);
248
249                 fid_out[i]=fopen(name,"w");
250
251                 ffado_streaming_get_playback_stream_name(dev,i,name,sizeof(name));
252                 fprintf(fid_out[i],"Channel name: %s\n",name);
253                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
254                 case ffado_stream_type_audio:
255                         fprintf(fid_out[i],"Channel type: audio\n");
256                         break;
257                 case ffado_stream_type_midi:
258                         fprintf(fid_out[i],"Channel type: midi\n");
259                         break;
260                 case ffado_stream_type_unknown:
261                         fprintf(fid_out[i],"Channel type: unknown\n");
262                         break;
263                 default:
264                 case ffado_stream_type_invalid:
265                         fprintf(fid_out[i],"Channel type: invalid\n");
266                         break;
267                 }
268
269         }
270         for (i=0;i<nb_in_channels;i++) {
271                 snprintf(name,sizeof(name),"in_ch_%02d",i);
272                 fid_in[i]=fopen(name,"w");
273
274                 ffado_streaming_get_capture_stream_name(dev,i,name,sizeof(name));
275                 fprintf(fid_in[i], "Channel name: %s\n", name);
276                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
277                 case ffado_stream_type_audio:
278                         fprintf(fid_in[i], "Channel type: audio\n");
279                         break;
280                 case ffado_stream_type_midi:
281                         fprintf(fid_in[i], "Channel type: midi\n");
282                         break;
283                 case ffado_stream_type_unknown:
284                         fprintf(fid_in[i],"Channel type: unknown\n");
285                         break;
286                 default:
287                 case ffado_stream_type_invalid:
288                         fprintf(fid_in[i],"Channel type: invalid\n");
289                         break;
290                 }
291         }
292
293         // setup the ALSA midi seq clients
294         snd_seq_t *seq_handle;
295         int in_ports[midi_in_nbchannels], out_ports[midi_out_nbchannels];
296        
297     // open sequencer
298         // the number of midi ports is statically set to 2
299         if (open_seq(&seq_handle, in_ports, out_ports, midi_in_nbchannels, midi_out_nbchannels) < 0) {
300                 fprintf(stderr, "ALSA Error.\n");
301                 exit(1);
302         }
303
304         ffado_midi_port_t* midi_out_portmap[nb_out_channels];
305         ffado_midi_port_t* midi_in_portmap[nb_in_channels];
306        
307         int cnt=0;
308        
309         for (i=0;i<nb_out_channels;i++) {
310                 ffado_midi_port_t *midi_out_port;
311                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
312                         case ffado_stream_type_audio:
313                                 midi_out_portmap[i]=NULL;
314                                 break;
315                         case ffado_stream_type_midi:
316                                 midi_out_port=malloc(sizeof(ffado_midi_port_t));
317                                 if(!midi_out_port) {
318                                         fprintf(stderr, "Could not allocate memory for MIDI OUT port %d\n",i);
319                                         exit(1); // this could be/is a memory leak, I know...
320                                 } else {
321                                         midi_out_port->seq_port_nr=in_ports[cnt++];
322                                         midi_out_port->seq_handle=seq_handle;
323                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_out_port->parser)) < 0) {
324                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI OUT port %d\n",i);
325                                                 exit(1); // this too
326                                         }   
327                                         midi_out_portmap[i]=midi_out_port;
328                                 }
329                                 break;
330                         default: break;
331                 }
332         }
333        
334         cnt=0;
335         for (i=0;i<nb_in_channels;i++) {
336                 ffado_midi_port_t *midi_in_port;
337                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
338                         case ffado_stream_type_audio:
339                                 midi_in_portmap[i]=NULL;
340                                 break;
341                         case ffado_stream_type_midi:
342                
343                                 midi_in_port=malloc(sizeof(ffado_midi_port_t));
344                                 if(!midi_in_port) {
345                                         fprintf(stderr, "Could not allocate memory for MIDI IN port %d\n",i);
346                                         exit(1); // this could be/is a memory leak, I know...
347                                 } else {
348                                         midi_in_port->seq_port_nr=out_ports[cnt++];
349                                         midi_in_port->seq_handle=seq_handle;
350                        
351                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_in_port->parser)) < 0) {
352                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI IN port %d\n",i);
353                                                 exit(1); // this too
354                                         }   
355                                         midi_in_portmap[i]=midi_in_port;
356                                 }
357                                 break;
358                         default: break;
359                 }
360         }       
361        
362         // start the streaming layer
363         ffado_streaming_prepare(dev);
364         start_flag = ffado_streaming_start(dev);
365
366         fprintf(stderr,"Entering receive loop (%d,%d)\n",nb_in_channels,nb_out_channels);
367         while(run && start_flag==0) {
368                 retval = ffado_streaming_wait(dev);
369                 if (retval < 0) {
370                         fprintf(stderr,"Xrun\n");
371                         ffado_streaming_reset(dev);
372                         continue;
373                 }
374                
375 //              ffado_streaming_transfer_buffers(dev);
376                 ffado_streaming_transfer_capture_buffers(dev);
377                 ffado_streaming_transfer_playback_buffers(dev);
378                
379                 nb_periods++;
380
381                 if((nb_periods % 32)==0) {
382 //                      fprintf(stderr,"\r%05d periods",nb_periods);
383                 }
384
385                 for(i=0;i<nb_in_channels;i++) {
386                         int s;
387                        
388                         switch (ffado_streaming_get_capture_stream_type(dev,i)) {
389                         case ffado_stream_type_audio:
390                                 // no need to get the buffers manually, we have set the API internal buffers to the audiobuffer[i]'s
391 //                              //samplesread=ffado_streaming_read(dev, i, audiobuffer[i], PERIOD_SIZE);
392                                 samplesread=PERIOD_SIZE;
393                                 break;
394                         case ffado_stream_type_midi:
395                                 samplesread=ffado_streaming_read(dev, i, audiobuffers_in[i], 64);
396                                 quadlet_t *buff=(quadlet_t *)audiobuffers_in[i];
397                                 if (samplesread) printf("RECV (CH %02X): ", i);
398                                 for (s=0;s<samplesread;s++) {
399                                         quadlet_t *byte=(buff+s) ;
400                                         printf("%08X ",*byte);
401                                         decode_midi_byte (midi_in_portmap[i], (*byte) & 0xFF);
402                                 }
403                                 if (samplesread) printf("\n");
404                                 if(samplesread>0) {
405                                         fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
406                                         hexDumpToFile(fid_in[i],(unsigned char*)audiobuffers_in[i],samplesread*sizeof(ffado_sample_t));
407                                 }
408                                 break;
409                         default: break;
410                         }
411 //                      fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
412 //                      hexDumpToFile(fid_in[i],(unsigned char*)buff,samplesread*sizeof(ffado_sample_t));
413        
414                 }
415
416                 for(i=0;i<nb_out_channels;i++) {
417                         ffado_sample_t *buff;
418                         int b=0;
419                         unsigned char* byte_buff;
420                        
421                         if (i<nb_in_channels) {
422                                 buff=audiobuffers_out[i];
423                         } else {
424                                 buff=nullbuffer;
425                         }
426                        
427                         switch (ffado_streaming_get_playback_stream_type(dev,i)) {
428                         case ffado_stream_type_audio:
429 //                              sampleswritten=ffado_streaming_write(dev, i, buff, PERIOD_SIZE);
430 //                              sampleswritten=PERIOD_SIZE;
431                                 break;
432                         case ffado_stream_type_midi:
433                                
434                                 #define max_midi_bytes_to_write PERIOD_SIZE/8
435                                 byte_buff=(unsigned char*)buff;
436                                
437                                 sampleswritten=encode_midi_bytes(midi_out_portmap[i], byte_buff, max_midi_bytes_to_write);
438                                 if (sampleswritten) printf("SEND (CH %02X): ", i);
439                                 for(b=0;b<sampleswritten;b++) {
440                                         ffado_sample_t tmp_event=*(byte_buff+b);
441                                         printf("%08X ",*(byte_buff+b));
442                                         ffado_streaming_write(dev, i, &tmp_event, 1);
443                                 }
444                                 if (sampleswritten) printf("\n");
445
446                                 fprintf(fid_out[i], "---- Period write (%d samples) ----\n",sampleswritten);
447                                 hexDumpToFile(fid_out[i],(unsigned char*)buff,sampleswritten*sizeof(ffado_sample_t));
448                                 break;
449                         default: break;
450                         }
451                 }
452
453         }
454
455         fprintf(stderr,"\n");
456
457         fprintf(stderr,"Exiting receive loop\n");
458        
459         ffado_streaming_stop(dev);
460
461         ffado_streaming_finish(dev);
462
463         for (i=0;i<nb_out_channels;i++) {
464                 fclose(fid_out[i]);
465
466         }
467         for (i=0;i<nb_in_channels;i++) {
468                 fclose(fid_in[i]);
469         }
470        
471         for (i=0;i<nb_in_channels;i++) {
472                 free(audiobuffers_in[i]);
473                 free(audiobuffers_out[i]);
474         }
475         free(nullbuffer);
476         free(audiobuffers_in);
477         free(audiobuffers_out);
478        
479         // free the MIDI to seq parsers and port structures
480         for(i=0;i<midi_in_nbchannels;i++) {
481                 ffado_midi_port_t *midi_in_port=midi_in_portmap[i];
482                
483                 if(midi_in_port) {
484                         snd_midi_event_free  (  midi_in_port->parser );
485                         free(midi_in_port);
486                 }
487         }
488         // free the MIDI to seq parsers and port structures
489         for(i=0;i<midi_out_nbchannels;i++) {
490                 ffado_midi_port_t *midi_out_port=midi_out_portmap[i];
491
492                 if(midi_out_port) {
493                         snd_midi_event_free  (  midi_out_port->parser );
494                         free(midi_out_port);
495                 }
496         }
497
498   return EXIT_SUCCESS;
499 }
Note: See TracBrowser for help on using the browser.