audiomixer.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "precompile.h"
  2. #include "audiomixer.h"
  3. #include "audioengine.h"
  4. static apr_status_t read_frame(void *self, audioframe_t *frame)
  5. {
  6. audiomixer_t *mixer = CONTAINING_RECORD(self, audiomixer_t, base);
  7. apr_status_t status;
  8. if (mixer->base.downstream == NULL)
  9. return APR_EGENERAL;
  10. status = mixer->base.downstream->vtbl->read_frame(mixer->base.downstream, frame);
  11. if (status == APR_SUCCESS && frame->size) {
  12. int mixbuf[SUGGEST_FRAME_SIZE];
  13. int mixcnt;
  14. int mixdtmf;
  15. int frame_samples;
  16. int frame_size;
  17. int i;
  18. int kk;
  19. if (mixer->arr_stream->nelts == 0)
  20. return status;
  21. frame_samples = frame->size >> 1;
  22. frame_size = frame->size;
  23. mixcnt = 0;
  24. mixdtmf = 0;
  25. memset(mixbuf, 0, sizeof(mixbuf));
  26. for (i = 0; i < mixer->arr_stream->nelts; ++i) {
  27. audiostream_t *stream = APR_ARRAY_IDX(mixer->arr_stream, i, audiostream_t*);
  28. if (audiostream_get_direction(stream) & STREAM_DIR_READ) {
  29. short frm_buf[SUGGEST_FRAME_SIZE];
  30. audioframe_t frm = {(char*)&frm_buf[0], SUGGEST_FRAME_SIZE};
  31. status = stream->vtbl->read_frame(stream, &frm);
  32. if (status == APR_SUCCESS && frm.size == frame->size) {
  33. for (kk = 0; kk < frame_samples; ++kk)
  34. mixbuf[kk] += frm_buf[kk];
  35. if (mixdtmf == 0 && frm.dtmf)
  36. mixdtmf = frm.dtmf;
  37. mixcnt ++;
  38. }
  39. }
  40. }
  41. if (mixcnt > 0) {
  42. short *dst = (short*)frame->buffer;
  43. for (kk = 0; kk < frame_samples; ++kk) {
  44. int t = mixbuf[kk] + dst[kk];
  45. if (t > 32767)
  46. t = 32767;
  47. if (t < -32767)
  48. t = -32767;
  49. dst[kk] = (short)t;
  50. }
  51. if (frame->dtmf == 0)
  52. frame->dtmf = mixdtmf;
  53. }
  54. } else {
  55. return status;
  56. }
  57. return APR_SUCCESS;
  58. }
  59. static apr_status_t write_frame(void *self, const audioframe_t *frame)
  60. {
  61. audiomixer_t *mixer = CONTAINING_RECORD(self, audiomixer_t, base);
  62. if (mixer->base.downstream) {
  63. return mixer->base.downstream->vtbl->write_frame(mixer->base.downstream, frame);
  64. } else {
  65. return APR_EGENERAL;
  66. }
  67. }
  68. static audiostream_vtbl_t g_stream_vtbl = {
  69. &read_frame,
  70. &write_frame,
  71. };
  72. apr_status_t audiomixer_create(apr_pool_t *pool, audioengine_t *engine, audiomixer_t **p_mixer)
  73. {
  74. audiomixer_t *mixer;
  75. mixer = apr_palloc(pool, sizeof(audiomixer_t));
  76. memset(mixer, 0, sizeof(audiomixer_t));
  77. mixer->arr_stream = apr_array_make(pool, 3, sizeof(audiostream_t*));
  78. audiostream_init(engine, &g_stream_vtbl, &mixer->base);
  79. *p_mixer = mixer;
  80. return APR_SUCCESS;
  81. }
  82. void audiomixer_destroy(audiomixer_t *mixer)
  83. {
  84. }
  85. apr_status_t audiomixer_add_stream(audiomixer_t *mixer, audiostream_t *stream)
  86. {
  87. if (!mixer || !stream)
  88. return APR_EINVAL;
  89. APR_ARRAY_PUSH(mixer->arr_stream, audiostream_t*) = stream;
  90. return APR_SUCCESS;
  91. }
  92. apr_status_t audiomixer_remove_stream(audiomixer_t *mixer, audiostream_t *stream)
  93. {
  94. int i;
  95. if (!mixer || !stream)
  96. return APR_EINVAL;
  97. for (i = 0; i < mixer->arr_stream->nelts; ++i) {
  98. audiostream_t *t = APR_ARRAY_IDX(mixer->arr_stream, i, audiostream_t*);
  99. if (t == stream) {
  100. if (i != mixer->arr_stream->nelts-1)
  101. APR_ARRAY_IDX(mixer->arr_stream, i, audiostream_t*) = APR_ARRAY_IDX(mixer->arr_stream, mixer->arr_stream->nelts-1, audiostream_t*);
  102. apr_array_pop(mixer->arr_stream);
  103. return APR_SUCCESS;
  104. }
  105. }
  106. return APR_NOTFOUND;
  107. }