root/trunk/libffado/tests/streaming/testmidistreaming1.c

Revision 532, 13.6 kB (checked in by ppalmers, 17 years ago)

fix & enhance the streaming test tools

  • 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         return 0;
131 }
132
133 int main(int argc, char *argv[])
134 {
135
136         #define PERIOD_SIZE 512
137
138         int samplesread=0, sampleswritten=0;
139         int nb_in_channels=0, nb_out_channels=0;
140         int retval=0;
141         int i=0;
142         int start_flag = 0;
143
144         int nb_periods=0;
145
146         ffado_sample_t **audiobuffers_in;
147         ffado_sample_t **audiobuffers_out;
148         ffado_sample_t *nullbuffer;
149        
150         run=1;
151
152         printf("Ffado MIDI streaming test application (1)\n");
153
154         signal (SIGINT, sighandler);
155         signal (SIGPIPE, sighandler);
156
157         ffado_device_info_t device_info;
158
159         ffado_options_t dev_options;
160
161         dev_options.sample_rate=48000; // -1 = detect from discovery
162         dev_options.period_size=PERIOD_SIZE;
163
164         dev_options.nb_buffers=3;
165
166         dev_options.port=0;
167         dev_options.node_id=-1;
168        
169         dev_options.realtime=0;
170         dev_options.packetizer_priority=60;
171        
172         dev_options.directions=0;
173        
174         dev_options.verbose=5;
175        
176         dev_options.slave_mode=0;
177         dev_options.snoop_mode=0;
178
179         ffado_device_t *dev=ffado_streaming_init(&device_info, dev_options);
180         if (!dev) {
181                 fprintf(stderr,"Could not init Ffado Streaming layer\n");
182                 exit(-1);
183         }
184
185         nb_in_channels=ffado_streaming_get_nb_capture_streams(dev);
186         nb_out_channels=ffado_streaming_get_nb_playback_streams(dev);
187
188         int midi_in_nbchannels=0;
189         int midi_out_nbchannels=0;
190        
191         /* allocate intermediate buffers */
192         audiobuffers_in=calloc(nb_in_channels,sizeof(ffado_sample_t *));
193         audiobuffers_out=calloc(nb_in_channels,sizeof(ffado_sample_t));
194         for (i=0;i<nb_in_channels;i++) {
195                 audiobuffers_in[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
196                 audiobuffers_out[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
197                        
198                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
199                         case ffado_stream_type_audio:
200                                 /* assign the audiobuffer to the stream */
201                                 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
202                                 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float);
203                                 break;
204                                
205                         // this is done with read/write routines because the nb of bytes can differ.
206                         case ffado_stream_type_midi:
207                                 midi_in_nbchannels++;
208                         default:
209                                 break;
210                 }
211         }
212        
213         nullbuffer=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
214        
215         for (i=0;i<nb_out_channels;i++) {
216                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
217                         case ffado_stream_type_audio:
218                                 if (i<nb_in_channels) {
219                                         /* assign the audiobuffer to the stream */
220                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
221                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float);
222                                 } else {
223                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)nullbuffer);
224                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_int24);     
225                                 }
226                                 break;
227                                 // this is done with read/write routines because the nb of bytes can differ.
228                         case ffado_stream_type_midi:
229                                 midi_out_nbchannels++;
230                         default:
231                                 break;
232                 }
233         }
234        
235         /* open the files to write to*/
236         FILE* fid_out[nb_out_channels];
237         FILE* fid_in[nb_in_channels];
238         char name[256];
239
240         for (i=0;i<nb_out_channels;i++) {
241                 snprintf(name,sizeof(name),"out_ch_%02d",i);
242
243                 fid_out[i]=fopen(name,"w");
244
245                 ffado_streaming_get_playback_stream_name(dev,i,name,sizeof(name));
246                 fprintf(fid_out[i],"Channel name: %s\n",name);
247                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
248                 case ffado_stream_type_audio:
249                         fprintf(fid_out[i],"Channel type: audio\n");
250                         break;
251                 case ffado_stream_type_midi:
252                         fprintf(fid_out[i],"Channel type: midi\n");
253                         break;
254                 case ffado_stream_type_unknown:
255                         fprintf(fid_out[i],"Channel type: unknown\n");
256                         break;
257                 default:
258                 case ffado_stream_type_invalid:
259                         fprintf(fid_out[i],"Channel type: invalid\n");
260                         break;
261                 }
262
263         }
264         for (i=0;i<nb_in_channels;i++) {
265                 snprintf(name,sizeof(name),"in_ch_%02d",i);
266                 fid_in[i]=fopen(name,"w");
267
268                 ffado_streaming_get_capture_stream_name(dev,i,name,sizeof(name));
269                 fprintf(fid_in[i], "Channel name: %s\n", name);
270                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
271                 case ffado_stream_type_audio:
272                         fprintf(fid_in[i], "Channel type: audio\n");
273                         break;
274                 case ffado_stream_type_midi:
275                         fprintf(fid_in[i], "Channel type: midi\n");
276                         break;
277                 case ffado_stream_type_unknown:
278                         fprintf(fid_in[i],"Channel type: unknown\n");
279                         break;
280                 default:
281                 case ffado_stream_type_invalid:
282                         fprintf(fid_in[i],"Channel type: invalid\n");
283                         break;
284                 }
285         }
286
287         // setup the ALSA midi seq clients
288         snd_seq_t *seq_handle;
289         int in_ports[midi_in_nbchannels], out_ports[midi_out_nbchannels];
290        
291     // open sequencer
292         // the number of midi ports is statically set to 2
293         if (open_seq(&seq_handle, in_ports, out_ports, midi_in_nbchannels, midi_out_nbchannels) < 0) {
294                 fprintf(stderr, "ALSA Error.\n");
295                 exit(1);
296         }
297
298         ffado_midi_port_t* midi_out_portmap[nb_out_channels];
299         ffado_midi_port_t* midi_in_portmap[nb_in_channels];
300        
301         int cnt=0;
302        
303         for (i=0;i<nb_out_channels;i++) {
304                 ffado_midi_port_t *midi_out_port;
305                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
306                         case ffado_stream_type_audio:
307                                 midi_out_portmap[i]=NULL;
308                                 break;
309                         case ffado_stream_type_midi:
310                                 midi_out_port=malloc(sizeof(ffado_midi_port_t));
311                                 if(!midi_out_port) {
312                                         fprintf(stderr, "Could not allocate memory for MIDI OUT port %d\n",i);
313                                         exit(1); // this could be/is a memory leak, I know...
314                                 } else {
315                                         midi_out_port->seq_port_nr=in_ports[cnt++];
316                                         midi_out_port->seq_handle=seq_handle;
317                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_out_port->parser)) < 0) {
318                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI OUT port %d\n",i);
319                                                 exit(1); // this too
320                                         }   
321                                         midi_out_portmap[i]=midi_out_port;
322                                 }
323                                 break;
324                         default: break;
325                 }
326         }
327        
328         cnt=0;
329         for (i=0;i<nb_in_channels;i++) {
330                 ffado_midi_port_t *midi_in_port;
331                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
332                         case ffado_stream_type_audio:
333                                 midi_in_portmap[i]=NULL;
334                                 break;
335                         case ffado_stream_type_midi:
336                
337                                 midi_in_port=malloc(sizeof(ffado_midi_port_t));
338                                 if(!midi_in_port) {
339                                         fprintf(stderr, "Could not allocate memory for MIDI IN port %d\n",i);
340                                         exit(1); // this could be/is a memory leak, I know...
341                                 } else {
342                                         midi_in_port->seq_port_nr=out_ports[cnt++];
343                                         midi_in_port->seq_handle=seq_handle;
344                        
345                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_in_port->parser)) < 0) {
346                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI IN port %d\n",i);
347                                                 exit(1); // this too
348                                         }   
349                                         midi_in_portmap[i]=midi_in_port;
350                                 }
351                                 break;
352                         default: break;
353                 }
354         }       
355        
356         // start the streaming layer
357         ffado_streaming_prepare(dev);
358         start_flag = ffado_streaming_start(dev);
359
360         fprintf(stderr,"Entering receive loop (%d,%d)\n",nb_in_channels,nb_out_channels);
361         while(run && start_flag==0) {
362                 retval = ffado_streaming_wait(dev);
363                 if (retval < 0) {
364                         fprintf(stderr,"Xrun\n");
365                         ffado_streaming_reset(dev);
366                         continue;
367                 }
368                
369 //              ffado_streaming_transfer_buffers(dev);
370                 ffado_streaming_transfer_capture_buffers(dev);
371                 ffado_streaming_transfer_playback_buffers(dev);
372                
373                 nb_periods++;
374
375                 if((nb_periods % 32)==0) {
376 //                      fprintf(stderr,"\r%05d periods",nb_periods);
377                 }
378
379                 for(i=0;i<nb_in_channels;i++) {
380                         int s;
381                        
382                         switch (ffado_streaming_get_capture_stream_type(dev,i)) {
383                         case ffado_stream_type_audio:
384                                 // no need to get the buffers manually, we have set the API internal buffers to the audiobuffer[i]'s
385 //                              //samplesread=ffado_streaming_read(dev, i, audiobuffer[i], PERIOD_SIZE);
386                                 samplesread=PERIOD_SIZE;
387                                 break;
388                         case ffado_stream_type_midi:
389                                 samplesread=ffado_streaming_read(dev, i, audiobuffers_in[i], PERIOD_SIZE);
390                                 quadlet_t *buff=(quadlet_t *)audiobuffers_in[i];
391                                 for (s=0;s<samplesread;s++) {
392                                         quadlet_t *byte=(buff+s) ;
393 //                                      printf("%08X ",*byte);
394                                         decode_midi_byte (midi_in_portmap[i], (*byte) & 0xFF);
395                                 }
396                                 if(samplesread>0) {
397                                         fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
398                                         hexDumpToFile(fid_in[i],(unsigned char*)audiobuffers_in[i],samplesread*sizeof(ffado_sample_t));
399                                 }
400                                 break;
401                         default: break;
402                         }
403 //                      fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
404 //                      hexDumpToFile(fid_in[i],(unsigned char*)buff,samplesread*sizeof(ffado_sample_t));
405        
406                 }
407
408                 for(i=0;i<nb_out_channels;i++) {
409                         ffado_sample_t *buff;
410                         int b=0;
411                         unsigned char* byte_buff;
412                        
413                         if (i<nb_in_channels) {
414                                 buff=audiobuffers_out[i];
415                         } else {
416                                 buff=nullbuffer;
417                         }
418                        
419                         switch (ffado_streaming_get_playback_stream_type(dev,i)) {
420                         case ffado_stream_type_audio:
421 //                              sampleswritten=ffado_streaming_write(dev, i, buff, PERIOD_SIZE);
422 //                              sampleswritten=PERIOD_SIZE;
423                                 break;
424                         case ffado_stream_type_midi:
425                                
426                                 #define max_midi_bytes_to_write PERIOD_SIZE/8
427                                 byte_buff=(unsigned char*)buff;
428                                
429                                 sampleswritten=encode_midi_bytes(midi_out_portmap[i], byte_buff, max_midi_bytes_to_write);
430                                
431                                 for(b=0;b<sampleswritten;b++) {
432                                         ffado_sample_t tmp_event=*(byte_buff+b);
433                                         ffado_streaming_write(dev, i, &tmp_event, 1);
434                                 }
435                                
436                                
437                                 fprintf(fid_out[i], "---- Period write (%d samples) ----\n",sampleswritten);
438                                 hexDumpToFile(fid_out[i],(unsigned char*)buff,sampleswritten*sizeof(ffado_sample_t));
439                                 break;
440                         default: break;
441                         }
442                 }
443
444         }
445
446         fprintf(stderr,"\n");
447
448         fprintf(stderr,"Exiting receive loop\n");
449        
450         ffado_streaming_stop(dev);
451
452         ffado_streaming_finish(dev);
453
454         for (i=0;i<nb_out_channels;i++) {
455                 fclose(fid_out[i]);
456
457         }
458         for (i=0;i<nb_in_channels;i++) {
459                 fclose(fid_in[i]);
460         }
461        
462         for (i=0;i<nb_in_channels;i++) {
463                 free(audiobuffers_in[i]);
464                 free(audiobuffers_out[i]);
465         }
466         free(nullbuffer);
467         free(audiobuffers_in);
468         free(audiobuffers_out);
469        
470         // free the MIDI to seq parsers and port structures
471         for(i=0;i<midi_in_nbchannels;i++) {
472                 ffado_midi_port_t *midi_in_port=midi_in_portmap[i];
473                
474                 if(midi_in_port) {
475                         snd_midi_event_free  (  midi_in_port->parser );
476                         free(midi_in_port);
477                 }
478         }
479         // free the MIDI to seq parsers and port structures
480         for(i=0;i<midi_out_nbchannels;i++) {
481                 ffado_midi_port_t *midi_out_port=midi_out_portmap[i];
482
483                 if(midi_out_port) {
484                         snd_midi_event_free  (  midi_out_port->parser );
485                         free(midi_out_port);
486                 }
487         }
488
489   return EXIT_SUCCESS;
490 }
Note: See TracBrowser for help on using the browser.