audiobridge.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "precompile.h"
  2. #include "audiobridge.h"
  3. #include "audiocontext.h"
  4. #include "audiolog.h"
  5. static apr_status_t read_and_write(audiostream_t *src, audiostream_t *dst, audioframe_t *frm)
  6. {
  7. apr_status_t status = APR_EGENERAL;
  8. if (src && (audiostream_get_direction(src) & STREAM_DIR_READ)) {
  9. status = src->vtbl->read_frame(src, frm);
  10. if (status == APR_SUCCESS) {
  11. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  12. status = dst->vtbl->write_frame(dst, frm);
  13. if (status != APR_SUCCESS) {
  14. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  15. }
  16. }
  17. } else {
  18. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, read frame failed");
  19. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  20. frm->size = 0; // silence frm
  21. status = dst->vtbl->write_frame(dst, frm);
  22. if (status != APR_SUCCESS) {
  23. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  24. }
  25. }
  26. }
  27. } else {
  28. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  29. frm->size = 0; // silence frm
  30. status = dst->vtbl->write_frame(dst, frm);
  31. if (status != APR_SUCCESS) {
  32. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  33. }
  34. }
  35. }
  36. return status;
  37. }
  38. static void mix_frame(audioframe_t *x, audioframe_t *y, audioframe_t *out)
  39. {
  40. if (x->size == 0) {
  41. memcpy(out->buffer, y->buffer, y->size);
  42. out->size = y->size;
  43. } else if (y->size == 0) {
  44. memcpy(out->buffer, x->buffer, x->size);
  45. out->size = x->size;
  46. } else {
  47. int i;
  48. int frame_samples = x->size >> 1;
  49. short *xx = (short*)&x->buffer[0];
  50. short *yy = (short*)&y->buffer[0];
  51. short *zz = (short*)&out->buffer[0];
  52. for (i = 0; i < frame_samples; ++i) {
  53. //int t = (((int)*xx + (int)*yy) * 3) >> 2;
  54. int t = (*xx + *yy) - (((*xx) * (*yy)) >> 0x10);
  55. if (t > 32767)
  56. t = 32767;
  57. if (t < -32767)
  58. t = -32767;
  59. *zz = (short)t;
  60. xx++;
  61. yy++;
  62. zz++;
  63. }
  64. out->size = x->size;
  65. }
  66. }
  67. static void process_frame(void *self)
  68. {
  69. audiobridge_t *bridge = CONTAINING_RECORD(self, audiobridge_t, base);
  70. char left_buf[SUGGEST_FRAME_SIZE];
  71. char right_buf[SUGGEST_FRAME_SIZE];
  72. audioframe_t left_frm = {&left_buf[0], SUGGEST_FRAME_SIZE, 0};
  73. audioframe_t right_frm = {&right_buf[0], SUGGEST_FRAME_SIZE, 0};
  74. apr_status_t left_status, right_status;
  75. left_status = read_and_write(bridge->leg_stream[AUDIO_BRIDGE_LEG_LEFT], bridge->leg_stream[AUDIO_BRIDGE_LEG_RIGHT], &left_frm);
  76. right_status = read_and_write(bridge->leg_stream[AUDIO_BRIDGE_LEG_RIGHT], bridge->leg_stream[AUDIO_BRIDGE_LEG_LEFT], &right_frm);
  77. if (bridge->rec_stream && (audiostream_get_direction(bridge->rec_stream)&STREAM_DIR_WRITE)) {
  78. apr_status_t status = APR_EGENERAL;
  79. if (left_status == APR_SUCCESS && right_status != APR_SUCCESS) {
  80. status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &left_frm);
  81. } else if (left_status != APR_SUCCESS && right_status == APR_SUCCESS) {
  82. status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &right_frm);
  83. } else if (left_status == APR_SUCCESS && right_status == APR_SUCCESS) {
  84. char rec_buf[SUGGEST_FRAME_SIZE];
  85. audioframe_t rec_frm = {&rec_buf[0], SUGGEST_FRAME_SIZE, 0};
  86. mix_frame(&left_frm, &right_frm, &rec_frm);
  87. status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &rec_frm);
  88. }
  89. if (status != APR_SUCCESS) {
  90. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame to recorder stream failed");
  91. }
  92. }
  93. }
  94. static void process_frame1(void *self)
  95. {
  96. int i;
  97. audiobridge_t *bridge = CONTAINING_RECORD(self, audiobridge_t, base);
  98. for (i = 0; i < 2; ++i) {
  99. char buf[SUGGEST_FRAME_SIZE];
  100. audiostream_t *src;
  101. audiostream_t *dst;
  102. apr_status_t status;
  103. audioframe_t frm = {&buf[0], SUGGEST_FRAME_SIZE, 0};
  104. src = bridge->leg_stream[i];
  105. dst = bridge->leg_stream[1-i];
  106. if (src && (audiostream_get_direction(src) & STREAM_DIR_READ)) {
  107. status = src->vtbl->read_frame(src, &frm);
  108. if (status == APR_SUCCESS) {
  109. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  110. status = dst->vtbl->write_frame(dst, &frm);
  111. if (status != APR_SUCCESS) {
  112. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  113. }
  114. }
  115. } else {
  116. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, read frame failed");
  117. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  118. frm.size = 0; // silence frm
  119. status = dst->vtbl->write_frame(dst, &frm);
  120. if (status != APR_SUCCESS) {
  121. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  122. }
  123. }
  124. }
  125. } else {
  126. if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
  127. frm.size = 0; // silence frm
  128. status = dst->vtbl->write_frame(dst, &frm);
  129. if (status != APR_SUCCESS) {
  130. audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
  131. }
  132. }
  133. }
  134. }
  135. }
  136. static audiodriver_vtbl_t g_driver_vtbl = {
  137. &process_frame,
  138. };
  139. apr_status_t audiobridge_create(apr_pool_t *pool, audioengine_t *engine, audiobridge_t **p_bridge)
  140. {
  141. audiobridge_t *bridge = apr_palloc(pool, sizeof(audiobridge_t));
  142. if (NULL == bridge){
  143. return APR_ENOPOOL;
  144. }
  145. memset(bridge, 0, sizeof(audiobridge_t));
  146. bridge->leg_stream[0] = NULL;
  147. bridge->leg_stream[1] = NULL;
  148. bridge->rec_stream = NULL;
  149. audiodriver_init(engine, &g_driver_vtbl, &bridge->base);
  150. *p_bridge = bridge;
  151. return APR_SUCCESS;
  152. }
  153. void audiobridge_destroy(audiobridge_t *bridge)
  154. {
  155. //...
  156. }
  157. void audiobridge_set_leg(audiobridge_t *bridge, int leg, audiostream_t *stream)
  158. {
  159. bridge->leg_stream[leg] = stream;
  160. }
  161. audiostream_t* audiobridge_get_leg(audiobridge_t *bridge, int leg)
  162. {
  163. return bridge->leg_stream[leg];
  164. }
  165. void audiobridge_set_recorder(audiobridge_t *bridge, audiostream_t *stream)
  166. {
  167. bridge->rec_stream = stream;
  168. }
  169. audiostream_t* audiobridge_get_recorder(audiobridge_t *bridge)
  170. {
  171. return bridge->rec_stream;
  172. }