1 #include <limits.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <audio.h>
5 #include <cmdline.h>
6 #include <list.h>
7 #include <log.h>
8 
9 #define DEFAULT_SAMPLING_RATE 48000
10 
11 struct resample_data {
12 	enum audio_format format;
13 	int num_channels;
14 	float mul;
15 	float step;
16 	int count;
17 	int left;
18 	int right;
19 };
20 
21 static int16_t audio_get_sample(void **buffer);
22 
23 /* Command-line parameter */
24 static char *audio_fe_name;
25 PARAM(audio_fe_name, string, "audio", NULL, "Selects audio frontend")
26 static int sampling_rate = DEFAULT_SAMPLING_RATE;
27 PARAM(sampling_rate, int, "sampling-rate", NULL, "Sets audio sampling rate")
28 
29 struct list_link *audio_frontends;
30 static struct audio_frontend *frontend;
31 static struct resample_data resample_data;
32 
audio_get_sample(void ** buffer)33 int16_t audio_get_sample(void **buffer)
34 {
35 	int16_t v = 0;
36 
37 	/* Get value based on format */
38 	switch (resample_data.format) {
39 	case AUDIO_FORMAT_U8:
40 		v = *((uint8_t *)*buffer);
41 		v -= UCHAR_MAX / 2;
42 		v <<= 8;
43 		(*(uint8_t **)buffer)++;
44 		break;
45 	case AUDIO_FORMAT_S8:
46 		v = *((int8_t *)*buffer);
47 		v <<= 8;
48 		(*(int8_t **)buffer)++;
49 		break;
50 	case AUDIO_FORMAT_U16:
51 		v = *((uint16_t *)*buffer);
52 		v -= USHRT_MAX / 2;
53 		(*(uint16_t **)buffer)++;
54 		break;
55 	case AUDIO_FORMAT_S16:
56 		v = *((int16_t *)*buffer);
57 		(*(int16_t **)buffer)++;
58 		break;
59 	}
60 
61 	/* Return value */
62 	return v;
63 }
64 
audio_init(struct audio_specs * specs)65 bool audio_init(struct audio_specs *specs)
66 {
67 	struct list_link *link = audio_frontends;
68 	struct audio_frontend *fe;
69 
70 	if (frontend) {
71 		LOG_E("Audio frontend already initialized!\n");
72 		return false;
73 	}
74 
75 	/* Validate audio option */
76 	if (!audio_fe_name) {
77 		LOG_W("No audio frontend selected!\n");
78 		return true;
79 	}
80 
81 	/* Validate audio sampling rate */
82 	switch (sampling_rate) {
83 	case 11025:
84 	case 22050:
85 	case 44100:
86 	case 48000:
87 		break;
88 	default:
89 		LOG_W("%u Hz sampling rate not supported.\n", sampling_rate);
90 		LOG_W("Please select 11025, 22050, 44100, or 48000 Hz.\n");
91 		sampling_rate = DEFAULT_SAMPLING_RATE;
92 		break;
93 	}
94 
95 	/* Find audio frontend */
96 	while ((fe = list_get_next(&link))) {
97 		/* Skip if name does not match */
98 		if (strcmp(audio_fe_name, fe->name))
99 			continue;
100 
101 		/* Initialize frontend */
102 		if (fe->init && !fe->init(fe, sampling_rate))
103 			return false;
104 
105 		/* Save frontend */
106 		frontend = fe;
107 
108 		/* Initialize resampling data */
109 		resample_data.format = specs->format;
110 		resample_data.num_channels = specs->channels;
111 		resample_data.mul = sampling_rate / specs->freq;
112 		resample_data.step = 0.0f;
113 		resample_data.count = 0;
114 		resample_data.left = 0;
115 		resample_data.right = 0;
116 
117 		/* Return success */
118 		return true;
119 	}
120 
121 	/* Warn as audio frontend was not found */
122 	LOG_E("Audio frontend \"%s\" not recognized!\n", audio_fe_name);
123 	return false;
124 }
125 
audio_enqueue(void * buffer,int length)126 void audio_enqueue(void *buffer, int length)
127 {
128 	bool stereo = (resample_data.num_channels == 2);
129 	bool reset;
130 	float prev_step;
131 	int16_t left;
132 	int16_t right;
133 	int i;
134 
135 	/* Return if needed */
136 	if (!frontend || !frontend->enqueue)
137 		return;
138 
139 	/* Parse all input buffer samples */
140 	for (i = 0; i < length; i++) {
141 		/* Get left (or mono) value */
142 		resample_data.left += audio_get_sample(&buffer);
143 
144 		/* Get right value if needed */
145 		if (stereo)
146 			resample_data.right += audio_get_sample(&buffer);
147 
148 		/* Increment resample data count */
149 		resample_data.count++;
150 
151 		/* Compute next step until output is no longer generated */
152 		reset = false;
153 		prev_step = resample_data.step;
154 		resample_data.step = prev_step + resample_data.mul;
155 		while ((int)prev_step != (int)resample_data.step) {
156 			/* Compute final left/right (or mono) samples */
157 			left = resample_data.left / resample_data.count;
158 			right = !stereo ?
159 				left :
160 				resample_data.right / resample_data.count;
161 
162 			/* Push left/right pair to frontend */
163 			frontend->enqueue(frontend, left, right);
164 
165 			/* Update step and request state reset */
166 			resample_data.step -= 1.0f;
167 			reset = true;
168 		}
169 
170 		/* Reset state if required */
171 		if (reset) {
172 			resample_data.count = 0;
173 			resample_data.left = 0;
174 			resample_data.right = 0;
175 		}
176 	}
177 }
178 
audio_start()179 void audio_start()
180 {
181 	if (frontend && frontend->start)
182 		frontend->start(frontend);
183 }
184 
audio_stop()185 void audio_stop()
186 {
187 	if (frontend && frontend->stop)
188 		frontend->stop(frontend);
189 }
190 
audio_deinit()191 void audio_deinit()
192 {
193 	if (!frontend)
194 		return;
195 
196 	if (frontend->deinit)
197 		frontend->deinit(frontend);
198 	frontend = NULL;
199 }
200 
201