xref: /freebsd/usr.sbin/virtual_oss/virtual_oss/virtual_oss.c (revision 9cab9fde5edad9b409dd2317a2aec7815e6d6bed)
1 /*-
2  * Copyright (c) 2012-2022 Hans Petter Selasky
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/queue.h>
27 #include <sys/types.h>
28 #include <sys/soundcard.h>
29 
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <err.h>
36 #include <time.h>
37 #include <assert.h>
38 
39 #include "backend.h"
40 #include "int.h"
41 
42 uint64_t
virtual_oss_delay_ns(void)43 virtual_oss_delay_ns(void)
44 {
45 	uint64_t delay;
46 
47 	delay = voss_dsp_samples;
48 	delay *= 1000000000ULL;
49 	delay /= voss_dsp_sample_rate;
50 
51 	return (delay);
52 }
53 
54 void
virtual_oss_wait(void)55 virtual_oss_wait(void)
56 {
57 	struct timespec ts;
58 	uint64_t delay;
59 	uint64_t nsec;
60 
61 	clock_gettime(CLOCK_MONOTONIC, &ts);
62 
63 	nsec = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
64 
65 	/* TODO use virtual_oss_delay_ns() */
66 	delay = voss_dsp_samples;
67 	delay *= 1000000000ULL;
68 	delay /= voss_dsp_sample_rate;
69 
70 	usleep((delay - (nsec % delay)) / 1000);
71 }
72 
73 uint64_t
virtual_oss_timestamp(void)74 virtual_oss_timestamp(void)
75 {
76 	struct timespec ts;
77 	uint64_t nsec;
78 
79 	clock_gettime(CLOCK_MONOTONIC, &ts);
80 
81 	nsec = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
82 	return (nsec);
83 }
84 
85 static size_t
vclient_read_linear(struct virtual_client * pvc,struct virtual_ring * pvr,int64_t * dst,size_t total)86 vclient_read_linear(struct virtual_client *pvc, struct virtual_ring *pvr,
87     int64_t *dst, size_t total) __requires_exclusive(atomic_mtx)
88 {
89 	size_t total_read = 0;
90 
91 	pvc->sync_busy = 1;
92 	while (1) {
93 		size_t read = vring_read_linear(pvr, (uint8_t *)dst, 8 * total) / 8;
94 
95 		total_read += read;
96 		dst += read;
97 		total -= read;
98 
99 		if (!pvc->profile->synchronized || pvc->sync_wakeup ||
100 		    total == 0) {
101 			/* fill rest of buffer with silence, if any */
102 			if (total_read != 0 && total != 0)
103 				memset(dst, 0, 8 * total);
104 			break;
105 		}
106 		atomic_wait();
107 	}
108 	pvc->sync_busy = 0;
109 	if (pvc->sync_wakeup)
110 		atomic_wakeup();
111 
112 	vclient_tx_equalizer(pvc, dst - total_read, total_read);
113 
114 	return (total_read);
115 }
116 
117 static size_t
vclient_write_linear(struct virtual_client * pvc,struct virtual_ring * pvr,int64_t * src,size_t total)118 vclient_write_linear(struct virtual_client *pvc, struct virtual_ring *pvr,
119     int64_t *src, size_t total) __requires_exclusive(atomic_mtx)
120 {
121 	size_t total_written = 0;
122 
123 	vclient_rx_equalizer(pvc, src, total);
124 
125 	pvc->sync_busy = 1;
126 	while (1) {
127 		size_t written = vring_write_linear(pvr, (uint8_t *)src, total * 8) / 8;
128 
129 		total_written += written;
130 		src += written;
131 		total -= written;
132 
133 		if (!pvc->profile->synchronized || pvc->sync_wakeup ||
134 		    total == 0)
135 			break;
136 		atomic_wait();
137 	}
138 	pvc->sync_busy = 0;
139 	if (pvc->sync_wakeup)
140 		atomic_wakeup();
141 
142 	return (total_written);
143 }
144 
145 static inline void
virtual_oss_mixer_core_sub(const int64_t * src,int64_t * dst,uint32_t * pnoise,int src_chan,int dst_chan,int num,int64_t volume,int shift,int shift_orig,bool pol,bool assign)146 virtual_oss_mixer_core_sub(const int64_t *src, int64_t *dst,
147     uint32_t *pnoise, int src_chan, int dst_chan, int num,
148     int64_t volume, int shift, int shift_orig, bool pol,
149     bool assign)
150 {
151 	if (pol)
152 		volume = -volume;
153 
154 	if (shift < 0) {
155 		shift = -shift;
156 		while (num--) {
157 			if (assign)
158 				*dst = (*src * volume) >> shift;
159 			else
160 				*dst += (*src * volume) >> shift;
161 			if (__predict_true(pnoise != NULL))
162 				*dst += vclient_noise(pnoise, volume, shift_orig);
163 			src += src_chan;
164 			dst += dst_chan;
165 		}
166 	} else {
167 		while (num--) {
168 			if (assign)
169 				*dst = (*src * volume) << shift;
170 			else
171 				*dst += (*src * volume) << shift;
172 			if (__predict_true(pnoise != NULL))
173 				*dst += vclient_noise(pnoise, volume, shift_orig);
174 			src += src_chan;
175 			dst += dst_chan;
176 		}
177 	}
178 }
179 
180 static inline void
virtual_oss_mixer_core(const int64_t * src,int64_t * dst,uint32_t * pnoise,int src_chan,int dst_chan,int num,int64_t volume,int shift,int shift_orig,bool pol,bool assign)181 virtual_oss_mixer_core(const int64_t *src, int64_t *dst,
182     uint32_t *pnoise, int src_chan, int dst_chan, int num,
183     int64_t volume, int shift, int shift_orig, bool pol,
184     bool assign)
185 {
186 	const uint8_t selector = (shift_orig > 0) + assign * 2;
187 
188 	/* optimize some cases */
189 	switch (selector) {
190 	case 0:
191 		virtual_oss_mixer_core_sub(src, dst, NULL, src_chan, dst_chan,
192 		    num, volume, shift, shift_orig, pol, false);
193 		break;
194 	case 1:
195 		virtual_oss_mixer_core_sub(src, dst, pnoise, src_chan, dst_chan,
196 		    num, volume, shift, shift_orig, pol, false);
197 		break;
198 	case 2:
199 		virtual_oss_mixer_core_sub(src, dst, NULL, src_chan, dst_chan,
200 		    num, volume, shift, shift_orig, pol, true);
201 		break;
202 	case 3:
203 		virtual_oss_mixer_core_sub(src, dst, pnoise, src_chan, dst_chan,
204 		    num, volume, shift, shift_orig, pol, true);
205 		break;
206 	}
207 }
208 
209 void   *
virtual_oss_process(void * arg __unused)210 virtual_oss_process(void *arg __unused)
211 {
212 	vprofile_t *pvp;
213 	vclient_t *pvc;
214 	vmonitor_t *pvm;
215 	struct voss_backend *rx_be = voss_rx_backend;
216 	struct voss_backend *tx_be = voss_tx_backend;
217 	int rx_fmt;
218 	int tx_fmt;
219 	int rx_chn;
220 	int tx_chn;
221 	int off;
222 	int src_chans;
223 	int dst_chans;
224 	int src;
225 	int len;
226 	int samples;
227 	int shift;
228 	int shift_orig;
229 	int shift_fmt;
230 	int buffer_dsp_max_size;
231 	int buffer_dsp_half_size;
232 	int buffer_dsp_rx_sample_size;
233 	int buffer_dsp_rx_size;
234 	int buffer_dsp_tx_size_ref;
235 	int buffer_dsp_tx_size;
236 	uint64_t nice_timeout = 0;
237 	uint64_t last_timestamp;
238 	int blocks;
239 	int volume;
240 	int x_off;
241 	int x;
242 	int y;
243 
244 	uint8_t *buffer_dsp;
245 	int64_t *buffer_monitor;
246 	int64_t *buffer_temp;
247 	int64_t *buffer_data;
248 	int64_t *buffer_local;
249 	int64_t *buffer_orig;
250 
251 	bool need_delay = false;
252 
253 	buffer_dsp_max_size = voss_dsp_samples *
254 	    voss_dsp_max_channels * (voss_dsp_bits / 8);
255 	buffer_dsp_half_size = (voss_dsp_samples / 2) *
256 	    voss_dsp_max_channels * (voss_dsp_bits / 8);
257 
258 	buffer_dsp = malloc(buffer_dsp_max_size);
259 	buffer_temp = malloc(voss_dsp_samples * voss_max_channels * 8);
260 	buffer_monitor = malloc(voss_dsp_samples * voss_max_channels * 8);
261 	buffer_local = malloc(voss_dsp_samples * voss_max_channels * 8);
262 	buffer_data = malloc(voss_dsp_samples * voss_max_channels * 8);
263 	buffer_orig = malloc(voss_dsp_samples * voss_max_channels * 8);
264 
265 	if (buffer_dsp == NULL || buffer_temp == NULL ||
266 	    buffer_monitor == NULL || buffer_local == NULL ||
267 	    buffer_data == NULL || buffer_orig == NULL)
268 		errx(1, "Cannot allocate buffer memory");
269 
270 	while (1) {
271 		rx_be->close(rx_be);
272 		tx_be->close(tx_be);
273 
274 		if (voss_exit)
275 			break;
276 		if (need_delay)
277 			sleep(2);
278 
279 		voss_dsp_rx_refresh = 0;
280 		voss_dsp_tx_refresh = 0;
281 
282 		rx_be = voss_rx_backend;
283 		tx_be = voss_tx_backend;
284 
285 		switch (voss_dsp_bits) {
286 		case 8:
287 			rx_fmt = tx_fmt =
288 			    AFMT_S8 | AFMT_U8;
289 			break;
290 		case 16:
291 			rx_fmt = tx_fmt =
292 			    AFMT_S16_BE | AFMT_S16_LE |
293 			    AFMT_U16_BE | AFMT_U16_LE;
294 			break;
295 		case 24:
296 			rx_fmt = tx_fmt =
297 			    AFMT_S24_BE | AFMT_S24_LE |
298 			    AFMT_U24_BE | AFMT_U24_LE;
299 			break;
300 		case 32:
301 			rx_fmt = tx_fmt =
302 			    AFMT_S32_BE | AFMT_S32_LE |
303 			    AFMT_U32_BE | AFMT_U32_LE |
304 			    AFMT_F32_BE | AFMT_F32_LE;
305 			break;
306 		default:
307 			rx_fmt = tx_fmt = 0;
308 			break;
309 		}
310 
311 		rx_chn = voss_dsp_max_channels;
312 
313 		if (rx_be->open(rx_be, voss_dsp_rx_device, voss_dsp_sample_rate,
314 		    buffer_dsp_half_size, &rx_chn, &rx_fmt) < 0) {
315 			need_delay = true;
316 			continue;
317 		}
318 
319 		buffer_dsp_rx_sample_size = rx_chn * (voss_dsp_bits / 8);
320 		buffer_dsp_rx_size = voss_dsp_samples * buffer_dsp_rx_sample_size;
321 
322 		tx_chn = voss_dsp_max_channels;
323 		if (tx_be->open(tx_be, voss_dsp_tx_device, voss_dsp_sample_rate,
324 		    buffer_dsp_max_size, &tx_chn, &tx_fmt) < 0) {
325 			need_delay = true;
326 			continue;
327 		}
328 
329 		buffer_dsp_tx_size_ref = voss_dsp_samples *
330 		    tx_chn * (voss_dsp_bits / 8);
331 
332 		/* reset compressor gain */
333 		for (x = 0; x != VMAX_CHAN; x++)
334 			voss_output_compressor_gain[x] = 1.0;
335 
336 		/* reset local buffer */
337 		memset(buffer_local, 0, 8 * voss_dsp_samples * voss_max_channels);
338 
339 		while (1) {
340 			uint64_t delta_time;
341 
342 			/* Check if DSP device should be re-opened */
343 			if (voss_exit)
344 				break;
345 			if (voss_dsp_rx_refresh || voss_dsp_tx_refresh) {
346 				need_delay = false;
347 				break;
348 			}
349 			delta_time = nice_timeout - virtual_oss_timestamp();
350 
351 			/* Don't service more than 2x sample rate */
352 			nice_timeout = virtual_oss_delay_ns() / 2;
353 			if (delta_time >= 1000 && delta_time <= nice_timeout) {
354 				/* convert from ns to us */
355 				usleep(delta_time / 1000);
356 			}
357 			/* Compute next timeout */
358 			nice_timeout += virtual_oss_timestamp();
359 
360 			/* Read in samples */
361 			len = rx_be->transfer(rx_be, buffer_dsp, buffer_dsp_rx_size);
362 			if (len < 0 || (len % buffer_dsp_rx_sample_size) != 0) {
363 				need_delay = true;
364 				break;
365 			}
366 			if (len == 0)
367 				continue;
368 
369 			/* Convert to 64-bit samples */
370 			format_import(rx_fmt, buffer_dsp, len, buffer_data);
371 
372 			samples = len / buffer_dsp_rx_sample_size;
373 			src_chans = voss_mix_channels;
374 
375 			/* Compute master input peak values */
376 			format_maximum(buffer_data, voss_input_peak, rx_chn, samples, 0);
377 
378 			/* Remix format */
379 			format_remix(buffer_data, rx_chn, src_chans, samples);
380 
381 			/* Refresh timestamp */
382 			last_timestamp = virtual_oss_timestamp();
383 
384 			atomic_lock();
385 
386 			if (TAILQ_FIRST(&virtual_monitor_input) != NULL) {
387 				/* make a copy of the input data, in case of remote monitoring */
388 				memcpy(buffer_monitor, buffer_data, 8 * samples * src_chans);
389 			}
390 
391 			/* (0) Check for local monitoring of output data */
392 
393 			TAILQ_FOREACH(pvm, &virtual_monitor_local, entry) {
394 
395 				int64_t val;
396 
397 				if (pvm->mute != 0 || pvm->src_chan >= src_chans ||
398 				    pvm->dst_chan >= src_chans)
399 					continue;
400 
401 				src = pvm->src_chan;
402 				shift = pvm->shift;
403 				x = pvm->dst_chan;
404 
405 				if (pvm->pol) {
406 					if (shift < 0) {
407 						shift = -shift;
408 						for (y = 0; y != samples; y++) {
409 							val = -(buffer_local[(y * src_chans) + src] >> shift);
410 							buffer_data[(y * src_chans) + x] += val;
411 							if (val < 0)
412 								val = -val;
413 							if (val > pvm->peak_value)
414 								pvm->peak_value = val;
415 						}
416 					} else {
417 						for (y = 0; y != samples; y++) {
418 							val = -(buffer_local[(y * src_chans) + src] << shift);
419 							buffer_data[(y * src_chans) + x] += val;
420 							if (val < 0)
421 								val = -val;
422 							if (val > pvm->peak_value)
423 								pvm->peak_value = val;
424 						}
425 					}
426 				} else {
427 					if (shift < 0) {
428 						shift = -shift;
429 						for (y = 0; y != samples; y++) {
430 							val = (buffer_local[(y * src_chans) + src] >> shift);
431 							buffer_data[(y * src_chans) + x] += val;
432 							if (val < 0)
433 								val = -val;
434 							if (val > pvm->peak_value)
435 								pvm->peak_value = val;
436 						}
437 					} else {
438 						for (y = 0; y != samples; y++) {
439 							val = (buffer_local[(y * src_chans) + src] << shift);
440 							buffer_data[(y * src_chans) + x] += val;
441 							if (val < 0)
442 								val = -val;
443 							if (val > pvm->peak_value)
444 								pvm->peak_value = val;
445 						}
446 					}
447 				}
448 			}
449 
450 			/* make a copy of the input data */
451 			memcpy(buffer_orig, buffer_data, 8 * samples * src_chans);
452 
453 			/* (1) Distribute input samples to all clients */
454 
455 			TAILQ_FOREACH(pvp, &virtual_profile_client_head, entry) {
456 
457 			    if (TAILQ_FIRST(&pvp->head) == NULL)
458 				continue;
459 
460 			    /* check if compressor should be applied */
461 			    voss_compressor(buffer_data, pvp->rx_compressor_gain,
462 			        &pvp->rx_compressor_param, samples * src_chans,
463 				src_chans, (1ULL << (pvp->bits - 1)) - 1ULL);
464 
465 			    TAILQ_FOREACH(pvc, &pvp->head, entry) {
466 
467 				dst_chans = pvc->channels;
468 
469 				if (dst_chans > (int)voss_max_channels)
470 					continue;
471 
472 				shift_fmt = pvp->bits - (vclient_sample_bytes(pvc) * 8);
473 
474 				for (x = 0; x != dst_chans; x++) {
475 					src = pvp->rx_src[x];
476 					shift_orig = pvp->rx_shift[x] - shift_fmt;
477 					shift = shift_orig - VVOLUME_UNIT_SHIFT;
478 					volume = pvc->rx_volume;
479 
480 					if (pvp->rx_mute[x] || src >= src_chans || volume == 0) {
481 						for (y = 0; y != (samples * dst_chans); y += dst_chans)
482 							buffer_temp[y + x] = 0;
483 						continue;
484 					}
485 
486 					virtual_oss_mixer_core(buffer_data + src, buffer_temp + x,
487 					    &pvc->rx_noise_rem, src_chans, dst_chans, samples,
488 					    volume, shift, shift_orig, pvp->rx_pol[x], true);
489 				}
490 
491 				format_maximum(buffer_temp, pvp->rx_peak_value,
492 				    dst_chans, samples, shift_fmt);
493 
494 				/* check if recording is disabled */
495 				if (pvc->rx_enabled == 0 ||
496 				    (voss_is_recording == 0 && pvc->type != VTYPE_OSS_DAT))
497 					continue;
498 
499 				pvc->rx_timestamp = last_timestamp;
500 				pvc->rx_samples += samples * dst_chans;
501 
502 				/* store data into ring buffer */
503 				vclient_write_linear(pvc, &pvc->rx_ring[0],
504 				    buffer_temp, samples * dst_chans);
505 			    }
506 
507 			    /* restore buffer, if any */
508 			    if (pvp->rx_compressor_param.enabled)
509 				memcpy(buffer_data, buffer_orig, 8 * samples * src_chans);
510 			}
511 
512 			/* fill main output buffer with silence */
513 
514 			memset(buffer_temp, 0, sizeof(buffer_temp[0]) *
515 			    samples * src_chans);
516 
517 			/* (2) Run audio delay locator */
518 
519 			if (voss_ad_enabled != 0) {
520 				y = (samples * voss_mix_channels);
521 				for (x = 0; x != y; x += voss_mix_channels) {
522 					buffer_temp[x + voss_ad_output_channel] +=
523 					    voss_ad_getput_sample(buffer_data
524 					    [x + voss_ad_input_channel]);
525 				}
526 			}
527 
528 			/* (3) Load output samples from all clients */
529 
530 			TAILQ_FOREACH(pvp, &virtual_profile_client_head, entry) {
531 			    TAILQ_FOREACH(pvc, &pvp->head, entry) {
532 
533 				if (pvc->tx_enabled == 0)
534 					continue;
535 
536 				dst_chans = pvc->channels;
537 
538 				if (dst_chans > (int)voss_max_channels)
539 					continue;
540 
541 				/* update counters regardless of data presence */
542 				pvc->tx_timestamp = last_timestamp;
543 				pvc->tx_samples += samples * dst_chans;
544 
545 				/* read data from ring buffer */
546 				if (vclient_read_linear(pvc, &pvc->tx_ring[0],
547 				    buffer_data, samples * dst_chans) == 0)
548 					continue;
549 
550 				shift_fmt = pvp->bits - (vclient_sample_bytes(pvc) * 8);
551 
552 				format_maximum(buffer_data, pvp->tx_peak_value,
553 				    dst_chans, samples, shift_fmt);
554 
555 				for (x = 0; x != pvp->channels; x++) {
556 					src = pvp->tx_dst[x];
557 					shift_orig = pvp->tx_shift[x] + shift_fmt;
558 					shift = shift_orig - VVOLUME_UNIT_SHIFT;
559 					volume = pvc->tx_volume;
560 
561 					if (pvp->tx_mute[x] || src >= src_chans || volume == 0)
562 						continue;
563 
564 					/*
565 					 * Automagically re-map
566 					 * channels when the client is
567 					 * requesting fewer channels
568 					 * than specified in the
569 					 * profile. This typically
570 					 * allows automagic mono to
571 					 * stereo conversion.
572 					 */
573 					if (__predict_false(x >= dst_chans))
574 						x_off = x % dst_chans;
575 					else
576 						x_off = x;
577 
578 					virtual_oss_mixer_core(buffer_data + x_off, buffer_temp + src,
579 					    &pvc->tx_noise_rem, dst_chans, src_chans, samples,
580 					    volume, shift, shift_orig, pvp->tx_pol[x], false);
581 				}
582 			    }
583 			}
584 
585 			/* (4) Load output samples from all loopbacks */
586 
587 			TAILQ_FOREACH(pvp, &virtual_profile_loopback_head, entry) {
588 			    TAILQ_FOREACH(pvc, &pvp->head, entry) {
589 
590 				if (pvc->tx_enabled == 0)
591 					continue;
592 
593 				dst_chans = pvc->channels;
594 
595 				if (dst_chans > (int)voss_max_channels)
596 					continue;
597 
598 				/* read data from ring buffer */
599 				if (vclient_read_linear(pvc, &pvc->tx_ring[0],
600 				    buffer_data, samples * dst_chans) == 0)
601 					continue;
602 
603 				pvc->tx_timestamp = last_timestamp;
604 				pvc->tx_samples += samples * dst_chans;
605 
606 				shift_fmt = pvp->bits - (vclient_sample_bytes(pvc) * 8);
607 
608 				format_maximum(buffer_data, pvp->tx_peak_value,
609 				    dst_chans, samples, shift_fmt);
610 
611 				for (x = 0; x != pvp->channels; x++) {
612 					src = pvp->tx_dst[x];
613 					shift_orig = pvp->tx_shift[x] + shift_fmt;
614 					shift = shift_orig - VVOLUME_UNIT_SHIFT;
615 					volume = pvc->tx_volume;
616 
617 					if (pvp->tx_mute[x] || src >= src_chans || volume == 0)
618 						continue;
619 
620 					/*
621 					 * Automagically re-map
622 					 * channels when the client is
623 					 * requesting fewer channels
624 					 * than specified in the
625 					 * profile. This typically
626 					 * allows automagic mono to
627 					 * stereo conversion.
628 					 */
629 					if (__predict_false(x >= dst_chans))
630 						x_off = x % dst_chans;
631 					else
632 						x_off = x;
633 
634 					virtual_oss_mixer_core(buffer_data + x_off, buffer_temp + src,
635 					    &pvc->tx_noise_rem, dst_chans, src_chans, samples,
636 					    volume, shift, shift_orig, pvp->tx_pol[x], false);
637 				}
638 			    }
639 			}
640 
641 			/* (5) Check for input monitoring */
642 
643 			TAILQ_FOREACH(pvm, &virtual_monitor_input, entry) {
644 
645 				int64_t val;
646 
647 				if (pvm->mute != 0 || pvm->src_chan >= src_chans ||
648 				    pvm->dst_chan >= src_chans)
649 					continue;
650 
651 				src = pvm->src_chan;
652 				shift = pvm->shift;
653 				x = pvm->dst_chan;
654 
655 				if (pvm->pol) {
656 					if (shift < 0) {
657 						shift = -shift;
658 						for (y = 0; y != samples; y++) {
659 							val = -(buffer_monitor[(y * src_chans) + src] >> shift);
660 							buffer_temp[(y * src_chans) + x] += val;
661 							if (val < 0)
662 								val = -val;
663 							if (val > pvm->peak_value)
664 								pvm->peak_value = val;
665 						}
666 					} else {
667 						for (y = 0; y != samples; y++) {
668 							val = -(buffer_monitor[(y * src_chans) + src] << shift);
669 							buffer_temp[(y * src_chans) + x] += val;
670 							if (val < 0)
671 								val = -val;
672 							if (val > pvm->peak_value)
673 								pvm->peak_value = val;
674 						}
675 					}
676 				} else {
677 					if (shift < 0) {
678 						shift = -shift;
679 						for (y = 0; y != samples; y++) {
680 							val = (buffer_monitor[(y * src_chans) + src] >> shift);
681 							buffer_temp[(y * src_chans) + x] += val;
682 							if (val < 0)
683 								val = -val;
684 							if (val > pvm->peak_value)
685 								pvm->peak_value = val;
686 						}
687 					} else {
688 						for (y = 0; y != samples; y++) {
689 							val = (buffer_monitor[(y * src_chans) + src] << shift);
690 							buffer_temp[(y * src_chans) + x] += val;
691 							if (val < 0)
692 								val = -val;
693 							if (val > pvm->peak_value)
694 								pvm->peak_value = val;
695 						}
696 					}
697 				}
698 			}
699 
700 			if (TAILQ_FIRST(&virtual_monitor_output) != NULL) {
701 				memcpy(buffer_monitor, buffer_temp,
702 				    8 * samples * src_chans);
703 			}
704 
705 			/* (6) Check for output monitoring */
706 
707 			TAILQ_FOREACH(pvm, &virtual_monitor_output, entry) {
708 
709 				int64_t val;
710 
711 				if (pvm->mute != 0 || pvm->src_chan >= src_chans ||
712 				    pvm->dst_chan >= src_chans)
713 					continue;
714 
715 				src = pvm->src_chan;
716 				shift = pvm->shift;
717 				x = pvm->dst_chan;
718 
719 				if (pvm->pol) {
720 					if (shift < 0) {
721 						shift = -shift;
722 						for (y = 0; y != samples; y++) {
723 							val = -(buffer_monitor[(y * src_chans) + src] >> shift);
724 							buffer_temp[(y * src_chans) + x] += val;
725 							if (val < 0)
726 								val = -val;
727 							if (val > pvm->peak_value)
728 								pvm->peak_value = val;
729 						}
730 					} else {
731 						for (y = 0; y != samples; y++) {
732 							val = -(buffer_monitor[(y * src_chans) + src] << shift);
733 							buffer_temp[(y * src_chans) + x] += val;
734 							if (val < 0)
735 								val = -val;
736 							if (val > pvm->peak_value)
737 								pvm->peak_value = val;
738 						}
739 					}
740 				} else {
741 					if (shift < 0) {
742 						shift = -shift;
743 						for (y = 0; y != samples; y++) {
744 							val = (buffer_monitor[(y * src_chans) + src] >> shift);
745 							buffer_temp[(y * src_chans) + x] += val;
746 							if (val < 0)
747 								val = -val;
748 							if (val > pvm->peak_value)
749 								pvm->peak_value = val;
750 						}
751 					} else {
752 						for (y = 0; y != samples; y++) {
753 							val = (buffer_monitor[(y * src_chans) + src] << shift);
754 							buffer_temp[(y * src_chans) + x] += val;
755 							if (val < 0)
756 								val = -val;
757 							if (val > pvm->peak_value)
758 								pvm->peak_value = val;
759 						}
760 					}
761 				}
762 			}
763 
764 			/* make a copy of the output data */
765 			memcpy(buffer_data, buffer_temp, 8 * samples * src_chans);
766 
767 			/* make a copy for local monitoring, if any */
768 			if (TAILQ_FIRST(&virtual_monitor_local) != NULL) {
769 				const int end = src_chans * (voss_dsp_samples - samples);
770 				const int offs = src_chans * samples;
771 
772 				assert(end >= 0);
773 
774 				/* shift down samples */
775 				for (int xx = 0; xx != end; xx++)
776 					buffer_local[xx] = buffer_local[xx + offs];
777 				/* copy in new ones */
778 				memcpy(buffer_local + end, buffer_temp, 8 * samples * src_chans);
779 			}
780 
781 			/* (7) Check for output recording */
782 
783 			TAILQ_FOREACH(pvp, &virtual_profile_loopback_head, entry) {
784 
785 			    if (TAILQ_FIRST(&pvp->head) == NULL)
786 				continue;
787 
788 			    /* check if compressor should be applied */
789 			    voss_compressor(buffer_temp, pvp->rx_compressor_gain,
790 				&pvp->rx_compressor_param, samples,
791 			        samples * src_chans, (1ULL << (pvp->bits - 1)) - 1ULL);
792 
793 			    TAILQ_FOREACH(pvc, &pvp->head, entry) {
794 
795 				dst_chans = pvc->channels;
796 
797 				if (dst_chans > (int)voss_max_channels)
798 					continue;
799 
800 				shift_fmt = pvp->bits - (vclient_sample_bytes(pvc) * 8);
801 
802 				for (x = 0; x != dst_chans; x++) {
803 					src = pvp->rx_src[x];
804 					shift_orig = pvp->rx_shift[x] - shift_fmt;
805 					shift = shift_orig - VVOLUME_UNIT_SHIFT;
806 					volume = pvc->rx_volume;
807 
808 					if (pvp->rx_mute[x] || src >= src_chans || volume == 0) {
809 						for (y = 0; y != (samples * dst_chans); y += dst_chans)
810 							buffer_monitor[y + x] = 0;
811 						continue;
812 					}
813 
814 					virtual_oss_mixer_core(buffer_temp + src, buffer_monitor + x,
815 					    &pvc->rx_noise_rem, src_chans, dst_chans, samples,
816 					    volume, shift, shift_orig, pvp->rx_pol[x], true);
817 				}
818 
819 				format_maximum(buffer_monitor, pvp->rx_peak_value,
820 				    dst_chans, samples, shift_fmt);
821 
822 				/* check if recording is disabled */
823 				if (pvc->rx_enabled == 0 ||
824 				    (voss_is_recording == 0 && pvc->type != VTYPE_OSS_DAT))
825 					continue;
826 
827 				pvc->rx_timestamp = last_timestamp;
828 				pvc->rx_samples += samples * dst_chans;
829 
830 				/* store data into ring buffer */
831 				vclient_write_linear(pvc, &pvc->rx_ring[0],
832 				    buffer_monitor, samples * dst_chans);
833 			    }
834 
835 			    /* restore buffer, if any */
836 			    if (pvp->rx_compressor_param.enabled)
837 				memcpy(buffer_temp, buffer_data, 8 * samples * src_chans);
838 			}
839 
840 			atomic_wakeup();
841 
842 			format_remix(buffer_temp, voss_mix_channels, tx_chn, samples);
843 
844 			/* Compute master output peak values */
845 
846 			format_maximum(buffer_temp, voss_output_peak,
847 			    tx_chn, samples, 0);
848 
849 			/* Apply compressor, if any */
850 
851 			voss_compressor(buffer_temp, voss_output_compressor_gain,
852 			    &voss_output_compressor_param, samples * tx_chn,
853 			    tx_chn, format_max(tx_fmt));
854 
855 			/* Recompute buffer DSP transmit size according to received number of samples */
856 
857 			buffer_dsp_tx_size = samples * tx_chn * (voss_dsp_bits / 8);
858 
859 			/* Export and transmit resulting audio */
860 
861 			format_export(tx_fmt, buffer_temp, buffer_dsp,
862 			    buffer_dsp_tx_size);
863 
864 			atomic_unlock();
865 
866 			/* Get output delay in bytes */
867 			tx_be->delay(tx_be, &blocks);
868 
869 			/*
870 			 * Simple fix for jitter: Repeat data when too
871 			 * little. Skip data when too much. This
872 			 * should not happen during normal operation.
873 			 */
874 			if (blocks == 0) {
875 				blocks = 2;	/* buffer is empty */
876 				voss_jitter_up++;
877 			} else if (blocks >= (3 * buffer_dsp_tx_size_ref)) {
878 				blocks = 0;	/* too much data */
879 				voss_jitter_down++;
880 			} else {
881 				blocks = 1;	/* normal */
882 			}
883 
884 			len = 0;
885 			while (blocks--) {
886 				off = 0;
887 				while (off < (int)buffer_dsp_tx_size) {
888 					len = tx_be->transfer(tx_be, buffer_dsp + off,
889 					    buffer_dsp_tx_size - off);
890 					if (len <= 0)
891 						break;
892 					off += len;
893 				}
894 				if (len <= 0)
895 					break;
896 			}
897 
898 			/* check for error only */
899 			if (len < 0) {
900 				need_delay = true;
901 				break;
902 			}
903 		}
904 	}
905 
906 	free(buffer_dsp);
907 	free(buffer_temp);
908 	free(buffer_monitor);
909 	free(buffer_local);
910 	free(buffer_data);
911 	free(buffer_orig);
912 
913 	return (NULL);
914 }
915