123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #include "precompile.h"
- #include "audiobridge.h"
- #include "audiocontext.h"
- #include "audiolog.h"
- static apr_status_t read_and_write(audiostream_t *src, audiostream_t *dst, audioframe_t *frm)
- {
- apr_status_t status = APR_EGENERAL;
- if (src && (audiostream_get_direction(src) & STREAM_DIR_READ)) {
- status = src->vtbl->read_frame(src, frm);
- if (status == APR_SUCCESS) {
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- status = dst->vtbl->write_frame(dst, frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- } else {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, read frame failed");
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- frm->size = 0; // silence frm
- status = dst->vtbl->write_frame(dst, frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- }
- } else {
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- frm->size = 0; // silence frm
- status = dst->vtbl->write_frame(dst, frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- }
- return status;
- }
- static void mix_frame(audioframe_t *x, audioframe_t *y, audioframe_t *out)
- {
- if (x->size == 0) {
- memcpy(out->buffer, y->buffer, y->size);
- out->size = y->size;
- } else if (y->size == 0) {
- memcpy(out->buffer, x->buffer, x->size);
- out->size = x->size;
- } else {
- int i;
- int frame_samples = x->size >> 1;
- short *xx = (short*)&x->buffer[0];
- short *yy = (short*)&y->buffer[0];
- short *zz = (short*)&out->buffer[0];
- for (i = 0; i < frame_samples; ++i) {
- //int t = (((int)*xx + (int)*yy) * 3) >> 2;
- int t = (*xx + *yy) - (((*xx) * (*yy)) >> 0x10);
- if (t > 32767)
- t = 32767;
- if (t < -32767)
- t = -32767;
- *zz = (short)t;
- xx++;
- yy++;
- zz++;
- }
- out->size = x->size;
- }
- }
- static void process_frame(void *self)
- {
- audiobridge_t *bridge = CONTAINING_RECORD(self, audiobridge_t, base);
- char left_buf[SUGGEST_FRAME_SIZE];
- char right_buf[SUGGEST_FRAME_SIZE];
- audioframe_t left_frm = {&left_buf[0], SUGGEST_FRAME_SIZE, 0};
- audioframe_t right_frm = {&right_buf[0], SUGGEST_FRAME_SIZE, 0};
- apr_status_t left_status, right_status;
- left_status = read_and_write(bridge->leg_stream[AUDIO_BRIDGE_LEG_LEFT], bridge->leg_stream[AUDIO_BRIDGE_LEG_RIGHT], &left_frm);
- right_status = read_and_write(bridge->leg_stream[AUDIO_BRIDGE_LEG_RIGHT], bridge->leg_stream[AUDIO_BRIDGE_LEG_LEFT], &right_frm);
- if (bridge->rec_stream && (audiostream_get_direction(bridge->rec_stream)&STREAM_DIR_WRITE)) {
- apr_status_t status = APR_EGENERAL;
- if (left_status == APR_SUCCESS && right_status != APR_SUCCESS) {
- status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &left_frm);
- } else if (left_status != APR_SUCCESS && right_status == APR_SUCCESS) {
- status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &right_frm);
- } else if (left_status == APR_SUCCESS && right_status == APR_SUCCESS) {
- char rec_buf[SUGGEST_FRAME_SIZE];
- audioframe_t rec_frm = {&rec_buf[0], SUGGEST_FRAME_SIZE, 0};
- mix_frame(&left_frm, &right_frm, &rec_frm);
- status = bridge->rec_stream->vtbl->write_frame(bridge->rec_stream, &rec_frm);
- }
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame to recorder stream failed");
- }
- }
- }
- static void process_frame1(void *self)
- {
- int i;
- audiobridge_t *bridge = CONTAINING_RECORD(self, audiobridge_t, base);
- for (i = 0; i < 2; ++i) {
- char buf[SUGGEST_FRAME_SIZE];
- audiostream_t *src;
- audiostream_t *dst;
- apr_status_t status;
- audioframe_t frm = {&buf[0], SUGGEST_FRAME_SIZE, 0};
- src = bridge->leg_stream[i];
- dst = bridge->leg_stream[1-i];
- if (src && (audiostream_get_direction(src) & STREAM_DIR_READ)) {
- status = src->vtbl->read_frame(src, &frm);
- if (status == APR_SUCCESS) {
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- status = dst->vtbl->write_frame(dst, &frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- } else {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, read frame failed");
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- frm.size = 0; // silence frm
- status = dst->vtbl->write_frame(dst, &frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- }
- } else {
- if (dst && (audiostream_get_direction(dst)&STREAM_DIR_WRITE)) {
- frm.size = 0; // silence frm
- status = dst->vtbl->write_frame(dst, &frm);
- if (status != APR_SUCCESS) {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR,"audio bridge process_frame, write frame failed");
- }
- }
- }
- }
- }
- static audiodriver_vtbl_t g_driver_vtbl = {
- &process_frame,
- };
- apr_status_t audiobridge_create(apr_pool_t *pool, audioengine_t *engine, audiobridge_t **p_bridge)
- {
- audiobridge_t *bridge = apr_palloc(pool, sizeof(audiobridge_t));
- if (NULL == bridge){
- return APR_ENOPOOL;
- }
- memset(bridge, 0, sizeof(audiobridge_t));
- bridge->leg_stream[0] = NULL;
- bridge->leg_stream[1] = NULL;
- bridge->rec_stream = NULL;
- audiodriver_init(engine, &g_driver_vtbl, &bridge->base);
- *p_bridge = bridge;
- return APR_SUCCESS;
- }
- void audiobridge_destroy(audiobridge_t *bridge)
- {
- //...
- }
- void audiobridge_set_leg(audiobridge_t *bridge, int leg, audiostream_t *stream)
- {
- bridge->leg_stream[leg] = stream;
- }
- audiostream_t* audiobridge_get_leg(audiobridge_t *bridge, int leg)
- {
- return bridge->leg_stream[leg];
- }
- void audiobridge_set_recorder(audiobridge_t *bridge, audiostream_t *stream)
- {
- bridge->rec_stream = stream;
- }
- audiostream_t* audiobridge_get_recorder(audiobridge_t *bridge)
- {
- return bridge->rec_stream;
- }
|