1 /**
2  * @file aumix.c Audio Mixer
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 
7 #define _BSD_SOURCE 1
8 #define _DEFAULT_SOURCE 1
9 #include <unistd.h>
10 #include <pthread.h>
11 #include <string.h>
12 #include <re.h>
13 #include <rem_au.h>
14 #include <rem_aubuf.h>
15 #include <rem_aufile.h>
16 #include <rem_aumix.h>
17 
18 
19 /** Defines an Audio mixer */
20 struct aumix {
21 	pthread_mutex_t mutex;
22 	pthread_cond_t cond;
23 	struct list srcl;
24 	pthread_t thread;
25 	struct aufile *af;
26 	uint32_t ptime;
27 	uint32_t frame_size;
28 	uint32_t srate;
29 	uint8_t ch;
30 	bool run;
31 };
32 
33 /** Defines an Audio mixer source */
34 struct aumix_source {
35 	struct le le;
36 	int16_t *frame;
37 	struct aubuf *aubuf;
38 	struct aumix *mix;
39 	aumix_frame_h *fh;
40 	void *arg;
41 };
42 
43 
44 static void dummy_frame_handler(const int16_t *sampv, size_t sampc, void *arg)
45 {
46 	(void)sampv;
47 	(void)sampc;
48 	(void)arg;
49 }
50 
51 
52 static void destructor(void *arg)
53 {
54 	struct aumix *mix = arg;
55 
56 	if (mix->run) {
57 
58 		pthread_mutex_lock(&mix->mutex);
59 		mix->run = false;
60 		pthread_cond_signal(&mix->cond);
61 		pthread_mutex_unlock(&mix->mutex);
62 
63 		pthread_join(mix->thread, NULL);
64 	}
65 
66 	mem_deref(mix->af);
67 }
68 
69 
70 static void source_destructor(void *arg)
71 {
72 	struct aumix_source *src = arg;
73 
74 	if (src->le.list) {
75 		pthread_mutex_lock(&src->mix->mutex);
76 		list_unlink(&src->le);
77 		pthread_mutex_unlock(&src->mix->mutex);
78 	}
79 
80 	mem_deref(src->aubuf);
81 	mem_deref(src->frame);
82 	mem_deref(src->mix);
83 }
84 
85 
86 static void *aumix_thread(void *arg)
87 {
88 	uint8_t *silence, *frame, *base_frame;
89 	struct aumix *mix = arg;
90 	int16_t *mix_frame;
91 	uint64_t ts = 0;
92 
93 	silence   = mem_zalloc(mix->frame_size*2, NULL);
94 	frame     = mem_alloc(mix->frame_size*2, NULL);
95 	mix_frame = mem_alloc(mix->frame_size*2, NULL);
96 
97 	if (!silence || !frame || !mix_frame)
98 		goto out;
99 
100 	pthread_mutex_lock(&mix->mutex);
101 
102 	while (mix->run) {
103 
104 		struct le *le;
105 		uint64_t now;
106 
107 		if (!mix->srcl.head) {
108 			mix->af = mem_deref(mix->af);
109 			pthread_cond_wait(&mix->cond, &mix->mutex);
110 			ts = 0;
111 		}
112 		else {
113 			pthread_mutex_unlock(&mix->mutex);
114 			(void)usleep(4000);
115 			pthread_mutex_lock(&mix->mutex);
116 		}
117 
118 		now = tmr_jiffies();
119 		if (!ts)
120 			ts = now;
121 
122 		if (ts > now)
123 			continue;
124 
125 		if (mix->af) {
126 
127 			size_t n = mix->frame_size*2;
128 
129 			if (aufile_read(mix->af, frame, &n) || n == 0) {
130 				mix->af = mem_deref(mix->af);
131 				base_frame = silence;
132 			}
133 			else if (n < mix->frame_size*2) {
134 				memset(frame + n, 0, mix->frame_size*2 - n);
135 				mix->af = mem_deref(mix->af);
136 				base_frame = frame;
137 			}
138 			else {
139 				base_frame = frame;
140 			}
141 		}
142 		else {
143 			base_frame = silence;
144 		}
145 
146 		for (le=mix->srcl.head; le; le=le->next) {
147 
148 			struct aumix_source *src = le->data;
149 
150 			aubuf_read_samp(src->aubuf, src->frame,
151 					mix->frame_size);
152 		}
153 
154 		for (le=mix->srcl.head; le; le=le->next) {
155 
156 			struct aumix_source *src = le->data;
157 			struct le *cle;
158 
159 			memcpy(mix_frame, base_frame, mix->frame_size*2);
160 
161 			for (cle=mix->srcl.head; cle; cle=cle->next) {
162 
163 				struct aumix_source *csrc = cle->data;
164 				size_t i;
165 #if 1
166 				/* skip self */
167 				if (csrc == src)
168 					continue;
169 #endif
170 				for (i=0; i<mix->frame_size; i++)
171 					mix_frame[i] += csrc->frame[i];
172 			}
173 
174 			src->fh(mix_frame, mix->frame_size, src->arg);
175 		}
176 
177 		ts += mix->ptime;
178 	}
179 
180 	pthread_mutex_unlock(&mix->mutex);
181 
182  out:
183 	mem_deref(mix_frame);
184 	mem_deref(silence);
185 	mem_deref(frame);
186 
187 	return NULL;
188 }
189 
190 
191 /**
192  * Allocate a new Audio mixer
193  *
194  * @param mixp  Pointer to allocated audio mixer
195  * @param srate Sample rate in [Hz]
196  * @param ch    Number of channels
197  * @param ptime Packet time in [ms]
198  *
199  * @return 0 for success, otherwise error code
200  */
201 int aumix_alloc(struct aumix **mixp, uint32_t srate,
202 		uint8_t ch, uint32_t ptime)
203 {
204 	struct aumix *mix;
205 	int err;
206 
207 	if (!mixp || !srate || !ch || !ptime)
208 		return EINVAL;
209 
210 	mix = mem_zalloc(sizeof(*mix), destructor);
211 	if (!mix)
212 		return ENOMEM;
213 
214 	mix->ptime      = ptime;
215 	mix->frame_size = srate * ch * ptime / 1000;
216 	mix->srate      = srate;
217 	mix->ch         = ch;
218 
219 	err = pthread_mutex_init(&mix->mutex, NULL);
220 	if (err)
221 		goto out;
222 
223 	err = pthread_cond_init(&mix->cond, NULL);
224 	if (err)
225 		goto out;
226 
227 	mix->run = true;
228 
229 	err = pthread_create(&mix->thread, NULL, aumix_thread, mix);
230 	if (err) {
231 		mix->run = false;
232 		goto out;
233 	}
234 
235  out:
236 	if (err)
237 		mem_deref(mix);
238 	else
239 		*mixp = mix;
240 
241 	return err;
242 }
243 
244 
245 /**
246  * Load audio file for mixer announcements
247  *
248  * @param mix      Audio mixer
249  * @param filepath Filename of audio file with complete path
250  *
251  * @return 0 for success, otherwise error code
252  */
253 int aumix_playfile(struct aumix *mix, const char *filepath)
254 {
255 	struct aufile_prm prm;
256 	struct aufile *af;
257 	int err;
258 
259 	if (!mix || !filepath)
260 		return EINVAL;
261 
262 	err = aufile_open(&af, &prm, filepath, AUFILE_READ);
263 	if (err)
264 		return err;
265 
266 	if (prm.fmt != AUFMT_S16LE || prm.srate != mix->srate ||
267 	    prm.channels != mix->ch) {
268 		mem_deref(af);
269 		return EINVAL;
270 	}
271 
272 	pthread_mutex_lock(&mix->mutex);
273 	mem_deref(mix->af);
274 	mix->af = af;
275 	pthread_mutex_unlock(&mix->mutex);
276 
277 	return 0;
278 }
279 
280 
281 /**
282  * Count number of audio sources in the audio mixer
283  *
284  * @param mix Audio mixer
285  *
286  * @return Number of audio sources
287  */
288 uint32_t aumix_source_count(const struct aumix *mix)
289 {
290 	if (!mix)
291 		return 0;
292 
293 	return list_count(&mix->srcl);
294 }
295 
296 
297 /**
298  * Allocate an audio mixer source
299  *
300  * @param srcp Pointer to allocated audio source
301  * @param mix  Audio mixer
302  * @param fh   Mixer frame handler
303  * @param arg  Handler argument
304  *
305  * @return 0 for success, otherwise error code
306  */
307 int aumix_source_alloc(struct aumix_source **srcp, struct aumix *mix,
308 		       aumix_frame_h *fh, void *arg)
309 {
310 	struct aumix_source *src;
311 	size_t sz;
312 	int err;
313 
314 	if (!srcp || !mix)
315 		return EINVAL;
316 
317 	src = mem_zalloc(sizeof(*src), source_destructor);
318 	if (!src)
319 		return ENOMEM;
320 
321 	src->mix = mem_ref(mix);
322 	src->fh  = fh ? fh : dummy_frame_handler;
323 	src->arg = arg;
324 
325 	sz = mix->frame_size*2;
326 
327 	src->frame = mem_alloc(sz, NULL);
328 	if (!src->frame) {
329 		err = ENOMEM;
330 		goto out;
331 	}
332 
333 	err = aubuf_alloc(&src->aubuf, sz * 6, sz * 12);
334 	if (err)
335 		goto out;
336 
337  out:
338 	if (err)
339 		mem_deref(src);
340 	else
341 		*srcp = src;
342 
343 	return err;
344 }
345 
346 
347 /**
348  * Enable/disable aumix source
349  *
350  * @param src    Audio mixer source
351  * @param enable True to enable, false to disable
352  */
353 void aumix_source_enable(struct aumix_source *src, bool enable)
354 {
355 	struct aumix *mix;
356 
357 	if (!src)
358 		return;
359 
360 	if (src->le.list && enable)
361 		return;
362 
363 	if (!src->le.list && !enable)
364 		return;
365 
366 	mix = src->mix;
367 
368 	pthread_mutex_lock(&mix->mutex);
369 
370 	if (enable) {
371 		list_append(&mix->srcl, &src->le, src);
372 		pthread_cond_signal(&mix->cond);
373 	}
374 	else {
375 		list_unlink(&src->le);
376 	}
377 
378 	pthread_mutex_unlock(&mix->mutex);
379 }
380 
381 
382 /**
383  * Write PCM samples for a given source to the audio mixer
384  *
385  * @param src   Audio mixer source
386  * @param sampv PCM samples
387  * @param sampc Number of samples
388  *
389  * @return 0 for success, otherwise error code
390  */
391 int aumix_source_put(struct aumix_source *src, const int16_t *sampv,
392 		     size_t sampc)
393 {
394 	if (!src || !sampv)
395 		return EINVAL;
396 
397 	return aubuf_write_samp(src->aubuf, sampv, sampc);
398 }
399 
400 
401 /**
402  * Flush the audio buffer of a given audio mixer source
403  *
404  * @param src Audio mixer source
405  */
406 void aumix_source_flush(struct aumix_source *src)
407 {
408 	if (!src)
409 		return;
410 
411 	aubuf_flush(src->aubuf);
412 }
413