root/trunk/freebob/tests/test-freebob-audio.c

Revision 59, 8.6 kB (checked in by pieterpalmers, 19 years ago)

- Added two example programs based upon the libiec61883 examples:

  • tests/test-freebob-midi:

Implements an ALSA sequencer client that allows you to send/receive
from the FreeBoB device's MIDI ports. Due to lack of ALSA sequencer
knowledge the send functionallity only works for one port. Receiving
works for both ports.

  • tests/test-freebob-audio:

Implements very basic audio I/O. Records from a hardcoded channel to
a 48Khz, 16bit mono PCM stream. Plays a 48Khz, 16bit mono PCM stream
to all outputs at once.

NOTE: settings are hardcoded for an ESI QuataFire? 610.

- Added ALSA lib detection code to configure.ac (needed for ALSA seq).
- Added a Makefile for the tests/ directory

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * FreeBob Test Program
3  * Copyright (C) 2005 Pieter Palmers
4  *
5  * Timing code shamelessly copied from Mixxx source code
6  *   (C) 2002 by Tue and Ken Haste Andersen
7  */
8
9 /* Based upon code from:
10  * libiec61883 - Linux IEEE 1394 streaming media library.
11  * Copyright (C) 2004 Kristian Hogsberg and Dan Dennedy
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 /*
29  * To receive a stream (number is hardcoded by QUATAFIRE_INPUT_TARGET_CHANNEL) from the device at node 0
30  * and play it out through /dev/dsp using sox play
31  *
32  * ./test-freebob-audio -r 0 - | play -r 48000 -t raw -s w -f s -c 1 -   
33  *
34  */
35
36 /* To play a file on all outputs of the device at node 0
37  *
38  * sox test.wav -r 48000 -t raw -s -w -c 1 - | ./test-freebob-audio -t 0 -
39  *
40  */
41  
42 #include <libiec61883/iec61883.h>
43 #include <stdio.h>
44 #include <sys/select.h>
45 #include <signal.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <sys/time.h>
49
50 #include <time.h>
51        
52         #define QUATAFIRE_DEFAULT_SAMPLE_RATE 48000
53         #define QUATAFIRE_OUT_DIMENSION 11
54         #define QUATAFIRE_IN_DIMENSION 7
55         #define QUATAFIRE_INPUT_TARGET_CHANNEL 1
56         #define QUATAFIRE_MIDI_OUT_STREAM_POSITION 10
57
58 inline unsigned long currentTime2() {
59         struct timeval now;
60         gettimeofday(&now, NULL);
61         return now.tv_sec*1000+now.tv_usec/1000;
62 }
63
64 static int g_done = 0;
65
66 static void sighandler (int sig)
67 {
68         g_done = 1;
69 }
70
71 int fill_packet(char *data, int nevents, unsigned int dropped, void *callback_data)
72 {
73   FILE *fp = (FILE *) callback_data;
74  
75   static int total_packets = 0;
76        
77         static int prev_total_packets=0;
78         static unsigned long prevtime=0;
79         float packets_per_second;
80         unsigned long thistime=currentTime2();
81        
82         int i;
83         int j;
84         char *current_pos=data;
85         quadlet_t test=0;
86         short int sample;
87        
88         for (i=0; i < nevents; ++i) {
89                 current_pos=data+i*QUATAFIRE_OUT_DIMENSION*4;
90                
91                 // read in the sample from the file
92                 if (fread((char *)(&sample), 2, 1, fp) != 1)
93                         return -1;     
94                
95                 // make it 24 bit
96                 test = 0x40 << 24 | sample<<8; 
97                
98                 // copy to all channels
99                 for (j=0; j<QUATAFIRE_OUT_DIMENSION;++j) {
100                         memcpy(current_pos+j*4,&test,4);
101                 }
102                
103                 // make sure we don't start sending random midi values
104                 current_pos=data+i*QUATAFIRE_OUT_DIMENSION*4+QUATAFIRE_MIDI_OUT_STREAM_POSITION*4;
105                 test= 0x80 << 24 | 0x000000;
106                 memcpy(current_pos,&test,4);
107                
108         }
109
110         total_packets++;
111         if ((total_packets & 0xfff) == 0) {
112                 packets_per_second = (total_packets-prev_total_packets)/((float)(thistime-prevtime))*1000.0;
113                 fprintf (stderr, "\r%10d packets (%5.2f packets/sec, %5d dropped, %d events in last packet, packet dimension=%d)", total_packets, packets_per_second, dropped, nevents, QUATAFIRE_OUT_DIMENSION);
114                 fflush (stderr);
115                 prevtime=thistime;
116                 prev_total_packets=total_packets;
117         }
118
119   return 0;
120 }
121
122 static int read_packet(char *data, int nevents, int dimension, int rate,
123         enum iec61883_amdtp_format format,
124         enum iec61883_amdtp_sample_format sample_format,
125         unsigned int dropped,
126         void *callback_data)
127 {
128         FILE *f = (FILE*) callback_data;
129        
130         static int total_packets = 0;
131         static int prev_total_packets=0;
132         static unsigned long prevtime=0;
133         float packets_per_second;
134         int i;
135                
136         short int value;
137         unsigned long thistime=currentTime2();
138        
139         quadlet_t this_event;
140                
141         quadlet_t *events=(quadlet_t*) data;
142                
143         if (total_packets == 0)
144                 fprintf (stderr, "format=0x%x sample_format=0x%x channels=%d rate=%d\n",
145                         format, sample_format, dimension, rate);
146        
147         for (i=0; i<nevents;i++) {
148                 // no label check is done, so be carefull for the speakers!
149                 this_event=events[i*dimension+QUATAFIRE_INPUT_TARGET_CHANNEL];
150                 // truncate to 16 bits
151                 value=(this_event & 0x00FFFFFF)>>8;
152                
153                 if (fwrite(&value, 2, 1, f) != 1) {
154                         return -1;
155                 }
156         }
157        
158         total_packets++;
159         if ((total_packets & 0xfff) == 0) {
160                 packets_per_second = (total_packets-prev_total_packets)/((float)(thistime-prevtime))*1000.0;
161                 fprintf (stderr, "\r%10d packets (%5.2f packets/sec, %5d dropped, %d events in last packet, packet dimension=%d)", total_packets, packets_per_second, dropped, nevents, dimension);
162                 fflush (stderr);
163                 prevtime=thistime;
164                 prev_total_packets=total_packets;
165         }
166         return 0;
167 }
168
169 static void amdtp_receive( raw1394handle_t handle, FILE *f, int channel)
170 {       
171         iec61883_amdtp_t amdtp = iec61883_amdtp_recv_init (handle, read_packet, (void *)f );
172                
173         if ( amdtp && iec61883_amdtp_recv_start (amdtp, channel) == 0)
174         {
175                 int fd = raw1394_get_fd (handle);
176                 struct timeval tv;
177                 fd_set rfds;
178                 int result = 0;
179                
180                 signal (SIGINT, sighandler);
181                 signal (SIGPIPE, sighandler);
182                 fprintf (stderr, "Starting to receive\n");
183
184                 do {
185                         FD_ZERO (&rfds);
186                         FD_SET (fd, &rfds);
187                         tv.tv_sec = 0;
188                         tv.tv_usec = 20000;
189                        
190                         if (select (fd + 1, &rfds, NULL, NULL, &tv) > 0)
191                                 result = raw1394_loop_iterate (handle);
192                        
193                 } while (g_done == 0 && result == 0);
194                
195                 fprintf (stderr, "\ndone.\n");
196         }
197         iec61883_amdtp_close (amdtp);
198 }
199
200 static void amdtp_transmit( raw1394handle_t handle, FILE *f, int channel)
201 {       
202         iec61883_amdtp_t amdtp;
203        
204         amdtp = iec61883_amdtp_xmit_init (handle, 48000, IEC61883_AMDTP_FORMAT_RAW,
205                 IEC61883_MODE_BLOCKING, QUATAFIRE_OUT_DIMENSION, fill_packet, (void *)f );
206        
207         if (amdtp && iec61883_amdtp_xmit_start (amdtp, channel) == 0)
208         {
209                 int fd = raw1394_get_fd (handle);
210                 struct timeval tv;
211                 fd_set rfds;
212                 int result = 0;
213                
214                 signal (SIGINT, sighandler);
215                 signal (SIGPIPE, sighandler);
216                 fprintf (stderr, "Starting to transmit\n");
217
218                 do {
219                         FD_ZERO (&rfds);
220                         FD_SET (fd, &rfds);
221                         tv.tv_sec = 0;
222                         tv.tv_usec = 20000;
223                        
224                         if (select (fd + 1, &rfds, NULL, NULL, &tv) > 0)
225                                 result = raw1394_loop_iterate (handle);
226                        
227                 } while (g_done == 0 && result == 0);
228                
229                 fprintf (stderr, "\ndone.\n");
230         }
231         iec61883_amdtp_close (amdtp);
232 }
233
234 int main (int argc, char *argv[])
235 {
236         raw1394handle_t handle = raw1394_new_handle_on_port (0);
237         nodeid_t node = 0xffc0;
238         FILE *f = NULL;
239         int is_transmit = 0;
240         int node_specified = 0;
241         int i;
242         int channel;
243         int bandwidth = -1;
244        
245         for (i = 1; i < argc; i++) {
246                
247                 if (strncmp (argv[i], "-h", 2) == 0 ||
248                         strncmp (argv[i], "--h", 3) == 0)
249                 {
250                         fprintf (stderr,
251                         "usage: %s [[-r | -t] node-id] [- | file]\n"
252                         "       All audio data must be signed 16bit 48KHz stereo PCM\n"
253                         "       Use - to transmit raw PCM from stdin, or\n"
254                         "       supply a filename to to transmit from a raw PCM file.\n"
255                         "       Otherwise, capture raw PCM to stdout.\n", argv[0]);
256                         raw1394_destroy_handle (handle);
257                         return 1;
258                 } else if (strncmp (argv[i], "-t", 2) == 0) {
259                         node |= atoi (argv[++i]);
260                         is_transmit = 1;
261                         node_specified = 1;
262                 } else if (strncmp (argv[i], "-r", 2) == 0) {
263                         node |= atoi (argv[++i]);
264                         is_transmit = 0;
265                         node_specified = 1;
266                 } else if (strcmp (argv[i], "-") != 0) {
267                         if (node_specified && !is_transmit)
268                                 f = fopen (argv[i], "wb");
269                         else {
270                                 f = fopen (argv[i], "rb");
271                                 is_transmit = 1;
272                         }
273                 } else if (!node_specified) {
274                         is_transmit = 1;
275                 }
276         }
277                
278         if (handle) {
279                 if (is_transmit) {
280                         if (f == NULL)
281                                 f = stdin;
282                         if (node_specified) {
283                                 channel = iec61883_cmp_connect (handle,
284                                         raw1394_get_local_id (handle), node, &bandwidth);
285                                 if (channel > -1) {
286                                         amdtp_transmit (handle, f, channel);
287                                         iec61883_cmp_disconnect (handle,
288                                                 raw1394_get_local_id (handle), node, channel, bandwidth);
289                                 } else {
290                                         fprintf (stderr, "Connect failed, reverting to broadcast channel 63.\n");
291                                         amdtp_transmit (handle, f, 63);
292                                 }
293                         } else {
294                                 amdtp_transmit (handle, f, 63);
295                         }
296                         if (f != stdin)
297                                 fclose (f);
298                 } else {
299                         if (f == NULL)
300                                 f = stdout;
301                         if (node_specified) {
302                                 channel = iec61883_cmp_connect (handle, node,
303                                         raw1394_get_local_id (handle), &bandwidth);
304                                 if (channel > -1) {
305                                         amdtp_receive (handle, f, channel);
306                                         iec61883_cmp_disconnect (handle, node,
307                                                 raw1394_get_local_id (handle), channel, bandwidth);
308                                 } else {
309                                         fprintf (stderr, "Connect failed, reverting to broadcast channel 63.\n");
310                                         amdtp_receive (handle, f, 63);
311                                 }
312                         } else {
313                                 amdtp_receive (handle, f, 63);
314                         }
315                         if (f != stdout)
316                                 fclose (f);
317                 }
318                 raw1394_destroy_handle (handle);
319         } else {
320                 fprintf (stderr, "Failed to get libraw1394 handle\n");
321                 return -1;
322         }
323        
324         return 0;
325 }
Note: See TracBrowser for help on using the browser.