Asterisk - The Open Source Telephony Project  18.5.0
bridge_softmix_binaural.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2016, Frank Haase, Dennis Guse
5  *
6  * Frank Haase <[email protected]>
7  * Dennis Guse <[email protected]>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*! \file
21  *
22  * \brief Multi-party software based binaural mixing
23  *
24  * \author Frank Haase <[email protected]>
25  * \author Dennis Guse <[email protected]>
26  *
27  * \ingroup bridges
28  */
29 
31 
32 #ifdef BINAURAL_RENDERING
34 #endif
35 
36 /*! The number of prealloced channels when a bridge will be created. */
37 #define CONVOLVE_CHANNEL_PREALLOC 3
38 /*! Max size of the convolve buffer. */
39 #define CONVOLVE_MAX_BUFFER 4096
40 /*! The default sample size in an binaural environment with a two-channel
41  * codec at 48kHz is 960 samples.
42  */
43 #define CONVOLUTION_SAMPLE_SIZE 960
44 
45 #ifdef BINAURAL_RENDERING
46  #if SOFTMIX_BINAURAL_SAMPLE_RATE != HRIRS_SAMPLE_RATE
47  #error HRIRs are required to be SOFTMIX_BINAURAL_SAMPLE_RATE Hz. Please adjust hrirs.h accordingly.
48  #endif
49  #if CONVOLUTION_SAMPLE_SIZE < HRIRS_IMPULSE_LEN
50  #error HRIRS_IMPULSE_LEN cannot be longer than CONVOLUTION_SAMPLE_SIZE. Please adjust hrirs.h accordingly.
51  #endif
52 #endif
53 
54 void reset_channel_pair(struct convolve_channel_pair *channel_pair,
55  unsigned int default_sample_size)
56 {
57  memset(channel_pair->chan_left.overlap_add, 0, sizeof(float) * default_sample_size);
58  memset(channel_pair->chan_right.overlap_add, 0, sizeof(float) * default_sample_size);
59 }
60 
62 {
63  /*
64  * We perform a shuffle of all channels, even the ones that aren't used at the
65  * moment of shuffling now. This has the efect that new members will be placed
66  * randomly too.
67  */
68  unsigned int i;
69  unsigned int j;
70  struct convolve_channel_pair *tmp;
71 
72  if (softmix_data->convolve.chan_size < 2) {
73  return;
74  }
75 
76  srand(time(NULL));
77  for (i = softmix_data->convolve.chan_size - 1; i > 0; i--) {
78  j = rand() % (i + 1);
79  tmp = softmix_data->convolve.cchan_pair[i];
80  reset_channel_pair(tmp, softmix_data->default_sample_size);
81  softmix_data->convolve.cchan_pair[i] = softmix_data->convolve.cchan_pair[j];
82  softmix_data->convolve.cchan_pair[j] = tmp;
83  }
84 }
85 
86 int do_convolve(struct convolve_channel *chan, int16_t *in_samples,
87  unsigned int in_sample_size, unsigned int hrtf_length)
88 {
89 #ifdef BINAURAL_RENDERING
90  unsigned int i;
91 
92  if (in_sample_size != CONVOLUTION_SAMPLE_SIZE) {
93  return -1;
94  }
95 
96  /* FFT setting real part */
97  for (i = 0; i < CONVOLUTION_SAMPLE_SIZE; i++) {
98  chan->fftw_in[i] = in_samples[i] * (FLT_MAX / SHRT_MAX);
99  }
100 
101  for (i = CONVOLUTION_SAMPLE_SIZE; i < hrtf_length; i++) {
102  chan->fftw_in[i] = 0;
103  }
104  fftw_execute(chan->fftw_plan);
105 
106  /* Imaginary mulitplication (frequency space). */
107  /* First FFTW result has never an imaginary part. */
108  chan->fftw_in[0] = chan->fftw_out[0] * chan->hrtf[0];
109  for (i = 1; i < (hrtf_length / 2); i++) {
110  /* Real part */
111  chan->fftw_in[i] = (chan->fftw_out[i] * chan->hrtf[i]) -
112  (chan->fftw_out[hrtf_length - i] * chan->hrtf[hrtf_length - i]);
113  /* Imaginary part */
114  chan->fftw_in[hrtf_length - i] = (chan->fftw_out[i] * chan->hrtf[hrtf_length - i]) +
115  (chan->fftw_out[hrtf_length - i] * chan->hrtf[i]);
116  }
117 
118  /* The last (if even) FFTW result has never an imaginary part. */
119  if (hrtf_length % 2 == 0) {
120  chan->fftw_in[hrtf_length / 2] = chan->fftw_out[hrtf_length / 2] *
121  chan->hrtf[hrtf_length / 2];
122  }
123 
124  /* iFFT */
125  fftw_execute(chan->fftw_plan_inverse);
126  /* Remove signal increase due to iFFT. */
127  for (i = 0; i < hrtf_length; i++) {
128  chan->fftw_out[i] = chan->fftw_out[i] / (hrtf_length / 2);
129  }
130 
131  /* Save the block for overlapp add in the next itteration. */
132  for (i = 0; i < in_sample_size; i++) {
133  chan->overlap_add[i] += chan->fftw_out[i];
134  }
135 
136  /* Copy real part to the output, ignore the complex part. */
137  for (i = 0; i < in_sample_size; i++) {
138  chan->out_data[i] = chan->overlap_add[i] * (SHRT_MAX / FLT_MAX);
139  chan->overlap_add[i] = chan->fftw_out[i + in_sample_size];
140  }
141 #endif
142  return 0;
143 }
144 
146  unsigned int pos_id, int16_t *in_samples, unsigned int in_sample_size,
147  const char *channel_name)
148 {
149  struct convolve_channel_pair *chan_pair;
150 
151  /* If a position has no active member we will not convolve. */
152  if (data->pos_ids[pos_id] != 1) {
153  ast_log(LOG_ERROR, "Channel %s: Channel pair has no active member! (pos id = %d)\n",
154  channel_name, pos_id);
155  return NULL;
156  }
157 
158  chan_pair = data->cchan_pair[pos_id];
159  if (do_convolve(&chan_pair->chan_left, in_samples, in_sample_size, data->hrtf_length)) {
160  ast_log(LOG_ERROR, "Channel %s: Binaural processing failed.", channel_name);
161  return NULL;
162  }
163 
164  if (do_convolve(&chan_pair->chan_right, in_samples, in_sample_size, data->hrtf_length)) {
165  ast_log(LOG_ERROR, "Channel %s: Binaural processing failed.", channel_name);
166  return NULL;
167  }
168 
169  return chan_pair;
170 }
171 
172 float *get_hrir(unsigned int chan_pos, unsigned int chan_side)
173 {
174 #ifdef BINAURAL_RENDERING
175  if (chan_side == HRIRS_CHANNEL_LEFT) {
176  return hrirs_left[ast_binaural_positions[chan_pos]];
177  } else if (chan_side == HRIRS_CHANNEL_RIGHT) {
178  return hrirs_right[ast_binaural_positions[chan_pos]];
179  }
180 #else
181  ast_log(LOG_ERROR, "Requesting data for the binaural conference feature without "
182  "it beeing active.\n");
183 #endif
184 
185  return NULL;
186 }
187 
188 int init_convolve_channel(struct convolve_channel *channel, unsigned int hrtf_len,
189  unsigned int chan_pos, unsigned int chan_side, unsigned int default_sample_size)
190 {
191 #ifdef BINAURAL_RENDERING
192  unsigned int j;
193  float *hrir;
194 
195  /* Prepare FFTW. */
196  channel->fftw_in = (double *) fftw_malloc(sizeof(double) * (hrtf_len + 1));
197  if (channel->fftw_in == NULL) {
198  return -1;
199  }
200 
201  channel->fftw_out = (double *) fftw_malloc(sizeof(double) * (hrtf_len + 1));
202  if (channel->fftw_out == NULL) {
203  fftw_free(channel->fftw_in);
204  return -1;
205  }
206 
207  memset(channel->fftw_in, 0, sizeof(double) * (hrtf_len + 1));
208  memset(channel->fftw_out, 0, sizeof(double) * (hrtf_len + 1));
209 
210  channel->fftw_plan = fftw_plan_r2r_1d(hrtf_len, channel->fftw_in, channel->fftw_out,
211  FFTW_R2HC, FFTW_PATIENT);
212  channel->fftw_plan_inverse = fftw_plan_r2r_1d(hrtf_len, channel->fftw_in, channel->fftw_out,
213  FFTW_HC2R, FFTW_PATIENT);
214  channel->out_data = ast_calloc(CONVOLVE_MAX_BUFFER, sizeof(int16_t));
215  if (channel->out_data == NULL) {
216  fftw_free(channel->fftw_in);
217  fftw_free(channel->fftw_out);
218  return -1;
219  }
220 
221  /* Reuse positions if all positions are already used. */
222  chan_pos = chan_pos % HRIRS_IMPULSE_SIZE;
223 
224  /* Get HRTF for the channels spatial position. */
225  hrir = get_hrir(chan_pos, chan_side);
226  if (hrir == NULL) {
227  fftw_free(channel->fftw_in);
228  fftw_free(channel->fftw_out);
229  ast_free(channel->out_data);
230  return -1;
231  }
232 
233  for (j = 0; j < HRIRS_IMPULSE_LEN; j++) {
234  channel->fftw_in[j] = hrir[j];
235  }
236 
237  for (j = HRIRS_IMPULSE_LEN; j < hrtf_len; j++) {
238  channel->fftw_in[j] = 0;
239  }
240 
241  fftw_execute(channel->fftw_plan);
242  channel->hrtf = (double *) fftw_malloc(sizeof(double) * hrtf_len);
243  if (channel->hrtf == NULL) {
244  fftw_free(channel->fftw_in);
245  fftw_free(channel->fftw_out);
246  ast_free(channel->out_data);
247  return -1;
248  }
249 
250  for (j = 0; j < hrtf_len; j++) {
251  channel->hrtf[j] = channel->fftw_out[j];
252  }
253  channel->overlap_add = ast_calloc(default_sample_size, sizeof(float));
254 
255  return 0;
256 #endif
257  return -1;
258 }
259 
261  unsigned int hrtf_len, unsigned int chan_pos, unsigned int default_sample_size)
262 {
263 #ifdef BINAURAL_RENDERING
264  unsigned int hrirs_pos = chan_pos * 2;
265  int success = 0;
266 
267  ast_debug(3, "Binaural pos for the new channel pair will be L: %d R: %d (pos id = %d)\n",
268  hrirs_pos, hrirs_pos + 1, chan_pos);
269  success = init_convolve_channel(&cchan_pair->chan_left, hrtf_len, chan_pos, HRIRS_CHANNEL_LEFT,
270  default_sample_size);
271  if (success == -1) {
272  return success;
273  }
274 
275  success = init_convolve_channel(&cchan_pair->chan_right, hrtf_len, chan_pos,
276  HRIRS_CHANNEL_RIGHT, default_sample_size);
277  if (success == -1) {
278  free_convolve_channel(&cchan_pair->chan_left);
279  }
280 
281  return success;
282 #else
283  ast_log(LOG_ERROR, "Requesting data for the binaural conference feature "
284  "without it beeing active.\n");
285 
286  return -1;
287 #endif
288 }
289 
290 int init_convolve_data(struct convolve_data *data, unsigned int default_sample_size)
291 {
292  unsigned int i;
293  unsigned int j;
294  int success;
295  success = 0;
296 
297  data->pos_ids = ast_calloc(sizeof(int), sizeof(int) * CONVOLVE_CHANNEL_PREALLOC);
298  if (data->pos_ids == NULL) {
299  return -1;
300  }
302  data->number_channels = 0;
303  data->cchan_pair = ast_malloc(sizeof(struct convolve_channel_pair *) *
304  CONVOLVE_CHANNEL_PREALLOC);
305  if (data->cchan_pair == NULL) {
306  ast_free(data->pos_ids);
307  return -1;
308  }
309 
310  for (i = 0; i < CONVOLVE_CHANNEL_PREALLOC; i++) {
311  data->cchan_pair[i] = ast_malloc(sizeof(struct convolve_channel_pair));
312  if (data->cchan_pair[i] == NULL) {
313  ast_free(data->pos_ids);
314  for (j = 0; j < i; j++) {
315  ast_free(data->cchan_pair[j]);
316  }
317  ast_free(data->cchan_pair);
318  return -1;
319  }
320  }
321 
322  data->hrtf_length = (default_sample_size * 2) - 1;
323  for (i = 0; i < CONVOLVE_CHANNEL_PREALLOC; i++) {
324  success = init_convolve_channel_pair(data->cchan_pair[i], data->hrtf_length, i,
325  default_sample_size);
326  if (success == -1) {
327  ast_free(data->pos_ids);
328  for (j = 0; j < i; j++) {
330  }
331  for (j = 0; j < CONVOLVE_CHANNEL_PREALLOC; j++) {
332  ast_free(data->cchan_pair[j]);
333  }
334  return -1;
335  }
336  }
337 
338  return success;
339 }
340 
342 {
343 #ifdef BINAURAL_RENDERING
344  fftw_free(cchan->fftw_out);
345  fftw_free(cchan->fftw_in);
346  fftw_free(cchan->hrtf);
347  ast_free(cchan->overlap_add);
348  ast_free(cchan->out_data);
349  fftw_destroy_plan(cchan->fftw_plan);
350  fftw_destroy_plan(cchan->fftw_plan_inverse);
351 #endif
352 }
353 
355 {
356  free_convolve_channel(&cchan_pair->chan_left);
357  free_convolve_channel(&cchan_pair->chan_right);
358 }
359 
361 {
362  unsigned int i;
363  ast_free(data->pos_ids);
364  for (i = 0; i < data->chan_size; i++) {
366  ast_free(data->cchan_pair[i]);
367  }
368  ast_free(data->cchan_pair);
369 }
370 
371 int set_binaural_data_join(struct convolve_data *data, unsigned int default_sample_size)
372 {
373  struct convolve_channel_pair **cchan_pair_tmp;
374  unsigned int i;
375  int *pos_ids_tmp;
376 
377  /* Raise the number of input channels. */
378  data->number_channels++;
379  /* We realloc another channel pair if we are out of prealloced ones. */
380  /* We have prealloced one at the beginning of a conference and if a member leaves. */
381  if (data->chan_size < data->number_channels) {
382  data->chan_size += 1;
383 
384  pos_ids_tmp = ast_realloc(data->pos_ids, data->chan_size * sizeof(int));
385  if (pos_ids_tmp) {
386  data->pos_ids = pos_ids_tmp;
387  } else {
388  goto binaural_join_fails;
389  }
390 
391  data->pos_ids[data->chan_size - 1] = 0;
392  cchan_pair_tmp = ast_realloc(data->cchan_pair,
393  data->chan_size * sizeof(struct convolve_channel_pair *));
394  if (cchan_pair_tmp) {
395  data->cchan_pair = cchan_pair_tmp;
396  } else {
397  goto binaural_join_fails;
398  }
399 
400  data->cchan_pair[data->chan_size - 1] = ast_malloc(sizeof(struct convolve_channel_pair));
401  if (data->cchan_pair[data->chan_size - 1] == NULL) {
402  goto binaural_join_fails;
403  }
404 
405  i = init_convolve_channel_pair(data->cchan_pair[data->chan_size - 1], data->hrtf_length,
406  data->chan_size - 1, default_sample_size);
407  if (i == -1) {
408  goto binaural_join_fails;
409  }
410  }
411 
412  for (i = 0; i < data->chan_size; i++) {
413  if (data->pos_ids[i] == 0) {
414  data->pos_ids[i] = 1;
415  break;
416  }
417  }
418 
419  return i;
420 
421 binaural_join_fails:
422  data->number_channels--;
423  data->chan_size -= 1;
424 
425  return -1;
426 }
427 
428 void set_binaural_data_leave(struct convolve_data *data, unsigned int pos,
429  unsigned int default_sample_size)
430 {
431  if (pos >= data->chan_size || data->pos_ids[pos] == 0) {
432  return;
433  }
434 
435  reset_channel_pair(data->cchan_pair[pos], default_sample_size);
436  data->number_channels--;
437  data->pos_ids[pos] = 0;
438 }
439 
441  unsigned int default_sample_size)
442 {
443  unsigned int i;
444 
445  if (sc->write_frame.samples % default_sample_size != 0) {
446  return;
447  }
448 
449  /* If binaural is suspended, the source audio (mono) will be removed. */
450  if (sc->binaural_suspended) {
451  for (i = 0; i < default_sample_size; i++) {
452  ast_slinear_saturated_subtract(&sc->final_buf[i * 2], &sc->our_buf[i]);
453  ast_slinear_saturated_subtract(&sc->final_buf[(i * 2) + 1], &sc->our_buf[i]);
454  }
455  return;
456  }
457 
458  /* If binaural is NOT suspended, the source audio (binaural) will be removed. */
459  for (i = 0; i < default_sample_size; i++) {
461  &sc->our_chan_pair->chan_left.out_data[i]);
462  ast_slinear_saturated_subtract(&sc->final_buf[(i * 2) + 1],
464  }
465 }
466 
468  struct softmix_bridge_data *softmix_data)
469 {
470  unsigned int pos_change;
471  struct ast_bridge_channel *bridge_channel;
472 
473  /*
474  * We only check binaural things if binaural is activated by the config
475  * and at least one binaural channel joined.
476  */
477  if (!(bridge->softmix.binaural_active && softmix_data->convolve.binaural_active)) {
478  return;
479  }
480  /*
481  * Before we pull any audio, we must check if any channel requests a
482  * change of binaural positions.
483  */
484  pos_change = 0;
485  AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
486  if (!bridge_channel->binaural_pos_change) {
487  continue;
488  }
489  ast_bridge_channel_lock_bridge(bridge_channel);
490  bridge_channel->binaural_pos_change = 0;
491  ast_bridge_unlock(bridge_channel->bridge);
492  pos_change = 1;
493  }
494 
495  if (pos_change) {
496  random_binaural_pos_change(softmix_data);
497  }
498 }
499 
500 void add_binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data,
501  unsigned int softmix_samples, struct softmix_mixing_array *mixing_array,
502  struct softmix_channel *sc, const char *channel_name)
503 {
504  struct convolve_channel_pair *pair;
505 
506  pair = NULL;
507  /* We only check binaural things if at least one binaural channel joined. */
508  if (!(bridge->softmix.binaural_active && softmix_data->convolve.binaural_active
509  && (softmix_samples % CONVOLUTION_SAMPLE_SIZE) == 0)) {
510  return;
511  }
512 
513  if (!sc->is_announcement) {
514  pair = do_convolve_pair(&softmix_data->convolve, sc->binaural_pos,
515  mixing_array->buffers[mixing_array->used_entries], softmix_samples, channel_name);
516  }
517  sc->our_chan_pair = pair;
518  mixing_array->chan_pairs[mixing_array->used_entries] = pair;
519 }
520 
521 void binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data,
522  struct softmix_mixing_array *mixing_array, int16_t *bin_buf, int16_t *ann_buf)
523 {
524  unsigned int idx;
525  unsigned int x;
526 
527  if (!(bridge->softmix.binaural_active && softmix_data->convolve.binaural_active)) {
528  return;
529  }
530  /* mix it like crazy (binaural channels) */
531  memset(bin_buf, 0, MAX_DATALEN);
532  memset(ann_buf, 0, MAX_DATALEN);
533 
534  for (idx = 0; idx < mixing_array->used_entries; idx++) {
535  if (mixing_array->chan_pairs[idx] == NULL) {
536  for (x = 0; x < softmix_data->default_sample_size; x++) {
537  ast_slinear_saturated_add(bin_buf + (x * 2), mixing_array->buffers[idx] + x);
538  ast_slinear_saturated_add(bin_buf + (x * 2) + 1, mixing_array->buffers[idx] + x);
539  ann_buf[x * 2] = mixing_array->buffers[idx][x];
540  ann_buf[(x * 2) + 1] = mixing_array->buffers[idx][x];
541  }
542  } else {
543  for (x = 0; x < softmix_data->default_sample_size; x++) {
544  ast_slinear_saturated_add(bin_buf + (x * 2),
545  mixing_array->chan_pairs[idx]->chan_left.out_data + x);
546  ast_slinear_saturated_add(bin_buf + (x * 2) + 1,
547  mixing_array->chan_pairs[idx]->chan_right.out_data + x);
548  }
549  }
550  }
551 }
552 
553 void create_binaural_frame(struct ast_bridge_channel *bridge_channel,
554  struct softmix_channel *sc, int16_t *bin_buf, int16_t *ann_buf,
555  unsigned int softmix_datalen, unsigned int softmix_samples, int16_t *buf)
556 {
557  unsigned int i;
558 
559  sc->write_frame.datalen = softmix_datalen * 2;
560  sc->write_frame.samples = softmix_samples * 2;
561  if (!bridge_channel->binaural_suspended) {
562  sc->binaural_suspended = 0;
563  if (sc->is_announcement) {
564  memcpy(sc->final_buf, ann_buf, softmix_datalen * 2);
565  } else {
566  memcpy(sc->final_buf, bin_buf, softmix_datalen * 2);
567  }
568  return;
569  }
570 
571  /*
572  * Mark that binaural output is suspended, since we use two channel audio
573  * we copy the same signals into both channels.
574  */
575  sc->binaural_suspended = 1;
576  for (i = 0; i < softmix_samples; i++) {
577  sc->final_buf[i * 2] = buf[i];
578  sc->final_buf[(i * 2) + 1] = buf[i];
579  }
580 }
void check_binaural_position_change(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data)
Checks if a position change in the virual enviroment is requested by one of the participants.
Multi-party software based channel mixing (header)
#define CONVOLUTION_SAMPLE_SIZE
struct convolve_channel_pair ** chan_pairs
#define HRIRS_IMPULSE_SIZE
Definition: hrirs.h:46
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
float hrirs_left[HRIRS_IMPULSE_SIZE][HRIRS_IMPULSE_LEN]
Definition: hrirs.h:49
int init_convolve_data(struct convolve_data *data, unsigned int default_sample_size)
Preinits a specific number of channels (CONVOVLE_CHANNEL_PREALLOC) at the beginning of a conference...
short int16_t
Definition: db.h:59
float * get_hrir(unsigned int chan_pos, unsigned int chan_side)
Provides a head related impulse response for the given position in the virtual enviroment.
struct convolve_channel_pair * do_convolve_pair(struct convolve_data *data, unsigned int pos_id, int16_t *in_samples, unsigned int in_sample_size, const char *channel_name)
Binaural convolving of audio data for a channel pair (left and right channel).
struct convolve_channel chan_left
int init_convolve_channel(struct convolve_channel *channel, unsigned int hrtf_len, unsigned int chan_pos, unsigned int chan_side, unsigned int default_sample_size)
Initializes all data needed for binaural audio processing.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int do_convolve(struct convolve_channel *chan, int16_t *in_samples, unsigned int in_sample_size, unsigned int hrtf_length)
Binaural convolving of audio data for a channel.
struct convolve_channel_pair * our_chan_pair
static int tmp()
Definition: bt_open.c:389
#define CONVOLVE_MAX_BUFFER
short our_buf[MAX_DATALEN]
unsigned int binaural_suspended
#define CONVOLVE_CHANNEL_PREALLOC
unsigned int binaural_suspended
Definition: muted.c:95
void softmix_process_write_binaural_audio(struct softmix_channel *sc, unsigned int default_sample_size)
Writes the binaural audio to a channel.
#define NULL
Definition: resample.c:96
static unsigned int ast_binaural_positions[POSITION_SIZE]
float hrirs_right[HRIRS_IMPULSE_SIZE][HRIRS_IMPULSE_LEN]
Definition: hrirs.h:25390
short final_buf[MAX_DATALEN]
struct ast_bridge_softmix softmix
Definition: bridge.h:375
void random_binaural_pos_change(struct softmix_bridge_data *softmix_data)
Randomly changes the virtual positions of conference participants.
struct ast_bridge * bridge
Bridge this channel is participating in.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
Multi-party software binaural channel mixing (header)
void free_convolve_channel(struct convolve_channel *cchan)
Frees all data needed for binaural processing by an audio channel.
int init_convolve_channel_pair(struct convolve_channel_pair *cchan_pair, unsigned int hrtf_len, unsigned int chan_pos, unsigned int default_sample_size)
Initializies all data needed for binaural audio processing of a channel pair (left and right)...
#define HRIRS_IMPULSE_LEN
Definition: hrirs.h:45
static force_inline void ast_slinear_saturated_add(short *input, short *value)
Definition: utils.h:425
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
void free_convolve_channel_pair(struct convolve_channel_pair *cchan_pair)
Frees all data needed for binaural processing by a pair of audio channels (left and right)...
#define HRIRS_CHANNEL_RIGHT
void set_binaural_data_leave(struct convolve_data *data, unsigned int pos, unsigned int default_sample_size)
Removes a channel from the binaural conference bridge. Marks the position in the virtual room as unus...
void free_convolve_data(struct convolve_data *data)
Frees all channels and data needed for binaural audio processing.
Structure that contains information about a bridge.
Definition: bridge.h:357
#define LOG_ERROR
Definition: logger.h:285
struct ast_frame write_frame
Structure which contains per-channel mixing information.
void create_binaural_frame(struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc, int16_t *bin_buf, int16_t *ann_buf, unsigned int softmix_datalen, unsigned int softmix_samples, int16_t *buf)
Creates a frame out of binaural audio data.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct convolve_channel chan_right
int set_binaural_data_join(struct convolve_data *data, unsigned int default_sample_size)
Joins a channel into a virtual enviroment build with the help of binaural sythesis.
#define MAX_DATALEN
void reset_channel_pair(struct convolve_channel_pair *channel_pair, unsigned int default_sample_size)
Deletes left over signals on a channel that it can be reused.
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct convolve_channel_pair ** cchan_pair
Structure that contains information regarding a channel in a bridge.
void add_binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data, unsigned int softmix_samples, struct softmix_mixing_array *mixing_array, struct softmix_channel *sc, const char *channel_name)
Processes audio data with the binaural synthesis and adds the result to the mixing array...
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
struct convolve_data convolve
Definition: search.h:40
unsigned int binaural_pos_change
static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
Definition: utils.h:438
#define HRIRS_CHANNEL_LEFT
void binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data, struct softmix_mixing_array *mixing_array, int16_t *bin_buf, int16_t *ann_buf)
Mixes all binaural audio data contained in the mixing array.
unsigned int binaural_active
Definition: bridge.h:303