1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <ao/ao.h>
7 
8 #include "uadeconstants.h"
9 #include "audio.h"
10 #include "uade123.h"
11 
12 ao_sample_format format;
13 
14 static ao_device *libao_device = NULL;
15 
16 static ao_option *options = NULL;
17 
audio_close(void)18 void audio_close(void)
19 {
20   if (libao_device) {
21 
22     /* Work-around libao/alsa, sleep 10ms to drain audio stream. */
23     if (uade_output_file_name[0] == 0)
24       usleep(10000);
25 
26     ao_close(libao_device);
27   }
28 }
29 
process_config_options(const struct uade_config * uc)30 void process_config_options(const struct uade_config *uc)
31 {
32   char *s;
33   char *key;
34   char *value;
35 
36   if (uc->buffer_time > 0) {
37       char val[32];
38       /* buffer_time is given in milliseconds, so convert to microseconds */
39       snprintf(val, sizeof val, "%d", 1000 * uc->buffer_time);
40       ao_append_option(&options, "buffer_time", val);
41   }
42 
43   format.bits = UADE_BYTES_PER_SAMPLE * 8;
44   format.channels = UADE_CHANNELS;
45   format.rate = uc->frequency;
46   format.byte_format = AO_FMT_NATIVE;
47 
48   s = (char *) uc->ao_options.o;
49   while (s != NULL && *s != 0) {
50     key = s;
51 
52     s = strchr(s, '\n');
53     if (s == NULL)
54       break;
55     *s = 0;
56     s++;
57 
58     value = strchr(key, ':');
59     if (value == NULL) {
60       fprintf(stderr, "uade: Invalid ao option: %s\n", key);
61       continue;
62     }
63     *value = 0;
64     value++;
65 
66     ao_append_option(&options, key, value);
67   }
68 }
69 
audio_init(const struct uade_config * uc)70 int audio_init(const struct uade_config *uc)
71 {
72   int driver;
73 
74   if (uade_no_audio_output)
75     return 1;
76 
77   process_config_options(uc);
78 
79   ao_initialize();
80 
81   if (uade_output_file_name[0]) {
82     driver = ao_driver_id(uade_output_file_format[0] ? uade_output_file_format : "wav");
83     if (driver < 0) {
84       fprintf(stderr, "Invalid libao driver\n");
85       return 0;
86     }
87     libao_device = ao_open_file(driver, uade_output_file_name, 1, &format, NULL);
88   } else {
89     driver = ao_default_driver_id();
90     libao_device = ao_open_live(driver, &format, options);
91   }
92 
93   if (libao_device == NULL) {
94     fprintf(stderr, "Can not open ao device: %d\n", errno);
95     return 0;
96   }
97 
98   return 1;
99 }
100 
101 
audio_play(unsigned char * samples,int bytes)102 int audio_play(unsigned char *samples, int bytes)
103 {
104   if (libao_device == NULL)
105     return bytes;
106 
107   /* ao_play returns 0 on failure */
108   return ao_play(libao_device, (char *) samples, bytes);
109 }
110