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