diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 824c8a9c91..0afc61d85d 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -106,15 +106,19 @@ SWITCH_DECLARE(switch_status) switch_core_codec_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag); SWITCH_DECLARE(switch_status) switch_core_codec_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag); SWITCH_DECLARE(switch_status) switch_core_codec_destroy(switch_codec *codec); SWITCH_DECLARE(switch_status) switch_core_session_set_read_codec(switch_core_session *session, switch_codec *codec); diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h index 354bbd0ea5..ee8b78a98e 100644 --- a/src/include/switch_frame.h +++ b/src/include/switch_frame.h @@ -44,6 +44,7 @@ struct switch_frame { size_t datalen; size_t buflen; int samples; + int rate; }; #ifdef __cplusplus diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 6ffa6a1d15..ac4cb3b07c 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -228,15 +228,19 @@ struct switch_codec_implementation { switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag); switch_status (*decode)(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag); switch_status (*destroy)(switch_codec *); const struct switch_codec_implementation *next; diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 65fae82cc1..c37d9f434f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -55,6 +55,7 @@ typedef enum { SWITCH_STATUS_NOTIMPL, SWITCH_STATUS_MEMERR, SWITCH_STATUS_NOOP, + SWITCH_STATUS_RESAMPLE, SWITCH_STATUS_GENERR, SWITCH_STATUS_INUSE } switch_status; diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 12580f367d..f682dd2d0f 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -70,10 +70,10 @@ SWITCH_DECLARE(switch_status) switch_socket_create_pollfd(switch_pollfd_t *poll, SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms); SWITCH_DECLARE(void) switch_swap_linear(int16_t *buf, int len); SWITCH_DECLARE(char *) switch_cut_path(char *in); -SWITCH_DECLARE(int) float_to_short(float *f, short *s, int len); -SWITCH_DECLARE(int) char_to_float(char *c, float *f, int len); -SWITCH_DECLARE(int) float_to_char(float *f, char *c, int len); -SWITCH_DECLARE(int) short_to_float(short *s, float *f, int len); +SWITCH_DECLARE(int) switch_float_to_short(float *f, short *s, int len); +SWITCH_DECLARE(int) switch_char_to_float(char *c, float *f, int len); +SWITCH_DECLARE(int) switch_float_to_char(float *f, char *c, int len); +SWITCH_DECLARE(int) switch_short_to_float(short *s, float *f, int len); #if !defined(switch_strdupa) && defined(__GNUC__) # define switch_strdupa(s) \ diff --git a/src/mod/codec/mod_codec_gsm/mod_codec_gsm.c b/src/mod/codec/mod_codec_gsm/mod_codec_gsm.c index b29a1c547d..62460f450b 100644 --- a/src/mod/codec/mod_codec_gsm/mod_codec_gsm.c +++ b/src/mod/codec/mod_codec_gsm/mod_codec_gsm.c @@ -79,8 +79,10 @@ static switch_status switch_gsm_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { struct gsm_context *context = codec->private; @@ -117,8 +119,10 @@ static switch_status switch_gsm_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { struct gsm_context *context = codec->private; diff --git a/src/mod/mod_codec_g729/mod_codec_g729.c b/src/mod/mod_codec_g729/mod_codec_g729.c index 490e76e498..05c4d3d768 100644 --- a/src/mod/mod_codec_g729/mod_codec_g729.c +++ b/src/mod/mod_codec_g729/mod_codec_g729.c @@ -74,8 +74,10 @@ static switch_status switch_g729_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { struct g729_context *context = codec->private; @@ -112,8 +114,10 @@ static switch_status switch_g729_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { struct g729_context *context = codec->private; diff --git a/src/mod/mod_exosip/mod_exosip.c b/src/mod/mod_exosip/mod_exosip.c index 59bd5529ae..024d544b30 100644 --- a/src/mod/mod_exosip/mod_exosip.c +++ b/src/mod/mod_exosip/mod_exosip.c @@ -911,6 +911,7 @@ static switch_status exosip_create_call(eXosip_event_t *event) return SWITCH_STATUS_FALSE; } else { int ms; + tech_pvt->read_frame.rate = rate; switch_set_flag(tech_pvt, TFLAG_USING_CODEC); ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms); @@ -1075,6 +1076,7 @@ static void handle_answer(eXosip_event_t *event) return; } else { int ms; + tech_pvt->read_frame.rate = rate; switch_set_flag(tech_pvt, TFLAG_USING_CODEC); ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Outbound Codec %s/%d %d ms\n", dname, rate, ms); diff --git a/src/mod/mod_g711codec/mod_g711codec.c b/src/mod/mod_g711codec/mod_g711codec.c index 5ce8d8000a..0bc9c57046 100644 --- a/src/mod/mod_g711codec/mod_g711codec.c +++ b/src/mod/mod_g711codec/mod_g711codec.c @@ -55,8 +55,10 @@ static switch_status switch_g711u_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { short *dbuf; @@ -79,8 +81,10 @@ static switch_status switch_g711u_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { short *dbuf; @@ -129,8 +133,10 @@ static switch_status switch_g711a_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { short *dbuf; @@ -153,8 +159,10 @@ static switch_status switch_g711a_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { short *dbuf; diff --git a/src/mod/mod_iaxchan/mod_iaxchan.c b/src/mod/mod_iaxchan/mod_iaxchan.c index 7ddfbc7a81..ee1a644801 100644 --- a/src/mod/mod_iaxchan/mod_iaxchan.c +++ b/src/mod/mod_iaxchan/mod_iaxchan.c @@ -298,6 +298,7 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s int rate; ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000; rate = tech_pvt->write_codec.implementation->samples_per_second; + tech_pvt->read_frame.rate = rate; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Codec %s/%d %d ms\n", dname, rate, ms); tech_pvt->read_frame.codec = &tech_pvt->read_codec; switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec); diff --git a/src/mod/mod_playback/mod_playback.c b/src/mod/mod_playback/mod_playback.c index aac2922181..b561071a3a 100644 --- a/src/mod/mod_playback/mod_playback.c +++ b/src/mod/mod_playback/mod_playback.c @@ -103,7 +103,7 @@ void playback_function(switch_core_session *session, char *data) switch_channel_hangup(channel); return; } - + write_frame.rate = fh.samplerate; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "setup timer success %d bytes per %d ms!\n", len, interval); /* start a thread to absorb incoming audio */ @@ -136,7 +136,7 @@ void playback_function(switch_core_session *session, char *data) } write_frame.datalen = ilen * 2; - write_frame.samples = ilen; + write_frame.samples = (int)ilen; #ifdef SWAP_LINEAR switch_swap_linear(write_frame.data, (int)write_frame.datalen / 2); #endif diff --git a/src/mod/mod_portaudio/mod_portaudio.c b/src/mod/mod_portaudio/mod_portaudio.c index a784851824..51e7ec29bd 100644 --- a/src/mod/mod_portaudio/mod_portaudio.c +++ b/src/mod/mod_portaudio/mod_portaudio.c @@ -75,6 +75,7 @@ static struct { int call_id; switch_hash *call_hash; switch_mutex_t *device_lock; + int sample_rate; } globals; struct private_object { @@ -559,6 +560,8 @@ static switch_status load_config(void) if (!strcasecmp(cfg.category, "settings")) { if (!strcmp(var, "debug")) { globals.debug = atoi(val); + } else if (!strcmp(var, "sample_rate")) { + globals.sample_rate = atoi(val); } else if (!strcmp(var, "dialplan")) { set_global_dialplan(val); } else if (!strcmp(var, "cid_name")) { @@ -585,6 +588,10 @@ static switch_status load_config(void) set_global_dialplan("default"); } + if (!globals.sample_rate) { + globals.sample_rate = 8000; + } + switch_config_close_file(&cfg); return SWITCH_STATUS_SUCCESS; @@ -692,7 +699,7 @@ error: static switch_status engage_device(struct private_object *tech_pvt) { - int sample_rate = 8000; + int sample_rate = globals.sample_rate; int codec_ms = 20; switch_channel *channel; @@ -723,7 +730,7 @@ static switch_status engage_device(struct private_object *tech_pvt) return SWITCH_STATUS_FALSE; } } - + tech_pvt->read_frame.rate = sample_rate; tech_pvt->read_frame.codec = &tech_pvt->read_codec; switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec); switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec); diff --git a/src/mod/mod_rawaudio/mod_rawaudio.c b/src/mod/mod_rawaudio/mod_rawaudio.c index e81925cd19..57e5615723 100644 --- a/src/mod/mod_rawaudio/mod_rawaudio.c +++ b/src/mod/mod_rawaudio/mod_rawaudio.c @@ -42,21 +42,24 @@ static const char modname[] = "mod_rawaudio"; #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif +#define QUALITY 1 + +struct raw_resampler { + void *resampler; + int from; + int to; + double factor; + float *buf; + int buf_len; + int buf_size; + float *new_buf; + int new_buf_len; + int new_buf_size; +}; + struct raw_context { - void *enc_resampler; - int enc_from; - int enc_to; - double enc_factor; - float *enc_buf; - int enc_buf_len; - int enc_buf_size; - void *dec_resampler; - int dec_from; - int dec_to; - double dec_factor; - float *dec_buf; - int dec_buf_len; - int dec_buf_size; + struct raw_resampler *enc; + struct raw_resampler *dec; }; @@ -67,13 +70,16 @@ static int resample(void *handle, double factor, float *src, int srclen, float * for(;;) { int srcBlock = MIN(srclen-srcpos, srclen); int lastFlag = (last && (srcBlock == srclen-srcpos)); - printf("resampling %d/%d (%d)\n", srcpos, srclen, MIN(dstlen-out, dstlen)); o = resample_process(handle, factor, &src[srcpos], srcBlock, lastFlag, &srcused, &dst[out], dstlen-out); - srcpos += srcused; - if (o >= 0) + //printf("resampling %d/%d (%d) %d %f\n", srcpos, srclen, MIN(dstlen-out, dstlen), srcused, factor); + + srcpos += srcused; + if (o >= 0) { out += o; - if (o < 0 || (o == 0 && srcpos == srclen)) + } + if (o < 0 || (o == 0 && srcpos == srclen)) { break; + } } return out; } @@ -102,8 +108,10 @@ static switch_status switch_raw_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { struct raw_context *context = codec->private; @@ -111,23 +119,49 @@ static switch_status switch_raw_encode(switch_codec *codec, /* NOOP indicates that the audio in is already the same as the audio out, so no conversion was necessary. TBD Support varying number of channels */ + //printf("encode %d->%d (%d)\n", other_codec->implementation->samples_per_second, codec->implementation->samples_per_second, decoded_rate); - if (other_codec && codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) { - if (!context->enc_from) { - printf("Activate Resample %d->%d\n", codec->implementation->samples_per_second, other_codec->implementation->samples_per_second); - context->enc_from = codec->implementation->samples_per_second; - context->enc_to = other_codec->implementation->samples_per_second; - context->enc_factor = ((double) context->enc_from / (double)context->enc_to); - context->enc_resampler = resample_open(1, context->enc_factor, context->enc_factor); - context->enc_buf_size = codec->implementation->bytes_per_frame; - context->enc_buf = (float *) switch_core_alloc(codec->memory_pool, context->enc_buf_size); + if (other_codec && + codec->implementation->samples_per_second != other_codec->implementation->samples_per_second && + decoded_rate != other_codec->implementation->samples_per_second) { + const short *ddp = decoded_data; + short *edp = encoded_data; + size_t ddplen = decoded_data_len / 2; + + if (!context->enc) { + + if (!(context->enc = switch_core_alloc(codec->memory_pool, sizeof(struct raw_resampler)))) { + return SWITCH_STATUS_MEMERR; + } + + context->enc->from = codec->implementation->samples_per_second; + context->enc->to = other_codec->implementation->samples_per_second; + context->enc->factor = ((double)context->enc->from / (double)context->enc->to); + + context->enc->resampler = resample_open(QUALITY, context->enc->factor, context->enc->factor); + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Encode Resample %d->%d %f\n", other_codec->implementation->samples_per_second, codec->implementation->samples_per_second, context->enc->factor); + context->enc->buf_size = codec->implementation->bytes_per_frame * 10; + context->enc->buf = (float *) switch_core_alloc(codec->memory_pool, context->enc->buf_size); + context->enc->new_buf_size = codec->implementation->bytes_per_frame * 10; + context->enc->new_buf = (float *) switch_core_alloc(codec->memory_pool, context->enc->new_buf_size); } - if (context->enc_from) { - + if (context->enc) { + context->enc->buf_len = switch_short_to_float(decoded_data, context->enc->buf, (int)ddplen); + context->enc->new_buf_len = resample(context->enc->resampler, + context->enc->factor, + context->enc->buf, + context->enc->buf_len, + context->enc->new_buf, + context->enc->new_buf_size, + 0); + switch_float_to_short(context->enc->new_buf, edp, decoded_data_len * 2); + *encoded_data_len = context->enc->new_buf_len * 2; + *encoded_rate = context->enc->to; + return SWITCH_STATUS_SUCCESS; } - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_GENERR; } return SWITCH_STATUS_NOOP; @@ -137,13 +171,61 @@ static switch_status switch_raw_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { struct raw_context *context = codec->private; - printf("decode %d %d->%d\n", encoded_data_len, other_codec->implementation->bytes_per_frame, codec->implementation->bytes_per_frame); + //printf("decode %d->%d (%d)\n", other_codec->implementation->samples_per_second, codec->implementation->samples_per_second, encoded_rate); + + + if (other_codec && + codec->implementation->samples_per_second != other_codec->implementation->samples_per_second && + encoded_rate != other_codec->implementation->samples_per_second) { + short *ddp = decoded_data; + const short *edp = encoded_data; + size_t edplen = encoded_data_len / 2; + + if (!context->dec) { + if (!(context->dec = switch_core_alloc(codec->memory_pool, sizeof(struct raw_resampler)))) { + return SWITCH_STATUS_MEMERR; + } + + + context->dec->from = codec->implementation->samples_per_second; + context->dec->to = other_codec->implementation->samples_per_second; + context->dec->factor = ((double)context->dec->from / (double)context->dec->to); + + context->dec->resampler = resample_open(QUALITY, context->dec->factor, context->dec->factor); + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Decode Resample %d->%d %f\n", other_codec->implementation->samples_per_second, codec->implementation->samples_per_second, context->dec->factor); + + context->dec->buf_size = codec->implementation->bytes_per_frame * 10; + context->dec->buf = (float *) switch_core_alloc(codec->memory_pool, context->dec->buf_size); + context->dec->new_buf_size = codec->implementation->bytes_per_frame * 10; + context->dec->new_buf = (float *) switch_core_alloc(codec->memory_pool, context->dec->new_buf_size); + } + + if (context->dec) { + context->dec->buf_len = switch_short_to_float(encoded_data, context->dec->buf, (int)edplen); + context->dec->new_buf_len = resample(context->dec->resampler, + context->dec->factor, + context->dec->buf, + context->dec->buf_len, + context->dec->new_buf, + context->dec->new_buf_size, + 0); + switch_float_to_short(context->dec->new_buf, ddp, (int)edplen); + *decoded_data_len = context->dec->new_buf_len * 2; + *decoded_rate = context->dec->to; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_GENERR; + } + return SWITCH_STATUS_NOOP; } @@ -151,6 +233,16 @@ static switch_status switch_raw_decode(switch_codec *codec, static switch_status switch_raw_destroy(switch_codec *codec) { + struct raw_context *context = codec->private; + + if (context->enc && context->enc->resampler){ + resample_close(context->enc->resampler); + } + + if (context->dec && context->dec->resampler){ + resample_close(context->dec->resampler); + } + return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/mod_speexcodec/mod_speexcodec.c b/src/mod/mod_speexcodec/mod_speexcodec.c index 933883d2e4..d20d646cab 100644 --- a/src/mod/mod_speexcodec/mod_speexcodec.c +++ b/src/mod/mod_speexcodec/mod_speexcodec.c @@ -157,8 +157,10 @@ static switch_status switch_speex_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { struct speex_context *context = codec->private; @@ -211,8 +213,10 @@ static switch_status switch_speex_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { struct speex_context *context = codec->private; diff --git a/src/mod/mod_woomerachan/mod_woomerachan.c b/src/mod/mod_woomerachan/mod_woomerachan.c index ce4679934c..f974cb2eab 100644 --- a/src/mod/mod_woomerachan/mod_woomerachan.c +++ b/src/mod/mod_woomerachan/mod_woomerachan.c @@ -198,6 +198,7 @@ static switch_status woomerachan_on_init(switch_core_session *session) { switch_channel *channel; struct private_object *tech_pvt = NULL; + int rate = 8000; tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); @@ -207,18 +208,18 @@ static switch_status woomerachan_on_init(switch_core_session *session) tech_pvt->frame.data = tech_pvt->databuf; - if (switch_core_codec_init(&tech_pvt->read_codec, "L16", 8000, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + if (switch_core_codec_init(&tech_pvt->read_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel)); switch_channel_hangup(channel); return SWITCH_STATUS_FALSE; } - if (switch_core_codec_init(&tech_pvt->write_codec, "L16", 8000, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + if (switch_core_codec_init(&tech_pvt->write_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel)); switch_channel_hangup(channel); return SWITCH_STATUS_FALSE; } - + tech_pvt->frame.rate = rate; tech_pvt->frame.codec = &tech_pvt->read_codec; switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec); diff --git a/src/switch_core.c b/src/switch_core.c index ccb9c58d64..e5b0fdf0ed 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -253,8 +253,10 @@ SWITCH_DECLARE(switch_status) switch_core_codec_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data, size_t decoded_data_len, + int decoded_rate, void *encoded_data, size_t *encoded_data_len, + int *encoded_rate, unsigned int *flag) { assert(codec != NULL); @@ -271,15 +273,17 @@ SWITCH_DECLARE(switch_status) switch_core_codec_encode(switch_codec *codec, return SWITCH_STATUS_GENERR; } - return codec->implementation->encode(codec, other_codec, decoded_data, decoded_data_len, encoded_data, encoded_data_len, flag); + return codec->implementation->encode(codec, other_codec, decoded_data, decoded_data_len, decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag); } SWITCH_DECLARE(switch_status) switch_core_codec_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data, size_t encoded_data_len, + int encoded_rate, void *decoded_data, size_t *decoded_data_len, + int *decoded_rate, unsigned int *flag) { assert(codec != NULL); @@ -296,7 +300,7 @@ SWITCH_DECLARE(switch_status) switch_core_codec_decode(switch_codec *codec, return SWITCH_STATUS_GENERR; } - return codec->implementation->decode(codec, other_codec, encoded_data, encoded_data_len, decoded_data, decoded_data_len, flag); + return codec->implementation->decode(codec, other_codec, encoded_data, encoded_data_len, encoded_rate, decoded_data, decoded_data_len, decoded_rate, flag); } SWITCH_DECLARE(switch_status) switch_core_codec_destroy(switch_codec *codec) @@ -696,15 +700,19 @@ SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session if (status == SWITCH_STATUS_SUCCESS && need_codec) { switch_frame *enc_frame, *read_frame = *frame; - if (read_frame->codec) { + if (read_frame->codec->codec_interface == session->read_codec->codec_interface) { + status = SWITCH_STATUS_SUCCESS; + } else if (read_frame->codec) { unsigned int flag = 0; session->raw_read_frame.datalen = session->raw_read_frame.buflen; status = switch_core_codec_decode(read_frame->codec, session->read_codec, read_frame->data, read_frame->datalen, + read_frame->rate, session->raw_read_frame.data, &session->raw_read_frame.datalen, + &session->raw_read_frame.rate, &flag); switch (status) { @@ -744,6 +752,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session session->raw_read_frame.datalen = switch_buffer_read(session->raw_read_buffer, session->raw_read_frame.data, session->read_codec->implementation->bytes_per_frame); + session->raw_read_frame.rate = session->read_codec->implementation->samples_per_second; enc_frame = &session->raw_read_frame; } session->enc_read_frame.datalen = session->enc_read_frame.buflen; @@ -751,8 +760,10 @@ SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session (*frame)->codec, session->raw_read_frame.data, session->raw_read_frame.datalen, + session->raw_read_frame.rate, session->enc_read_frame.data, &session->enc_read_frame.datalen, + &session->enc_read_frame.rate, &flag); @@ -801,7 +812,6 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio unsigned int flag = 0, need_codec = 0, perfect = 0; switch_io_flag io_flag = SWITCH_IO_FLAG_NOOP; - /* if you think this code is redundant.... too bad! I like to understand what I'm doing */ if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) { need_codec = TRUE; @@ -816,18 +826,24 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio } if (need_codec) { - if (frame->codec) { + if (frame->codec->codec_interface == session->write_codec->codec_interface) { + write_frame = frame; + status = SWITCH_STATUS_SUCCESS; + } else if (frame->codec) { session->raw_write_frame.datalen = session->raw_write_frame.buflen; status = switch_core_codec_decode(frame->codec, session->write_codec, frame->data, frame->datalen, + frame->rate, session->raw_write_frame.data, &session->raw_write_frame.datalen, + &session->raw_write_frame.rate, &flag); switch (status) { + case SWITCH_STATUS_SUCCESS: write_frame = &session->raw_write_frame; break; @@ -840,7 +856,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio return status; break; } - } + } if (session->write_codec) { if (write_frame->datalen == session->write_codec->implementation->bytes_per_frame) { @@ -866,15 +882,17 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio if (perfect) { enc_frame = write_frame; session->enc_write_frame.datalen = session->enc_write_frame.buflen; + status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, + enc_frame->rate, session->enc_write_frame.data, &session->enc_write_frame.datalen, + &session->enc_write_frame.rate, &flag); - switch (status) { case SWITCH_STATUS_SUCCESS: write_frame = &session->enc_write_frame; @@ -907,13 +925,16 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio bytes))) { enc_frame = &session->raw_write_frame; + session->raw_write_frame.rate = session->write_codec->implementation->samples_per_second; session->enc_write_frame.datalen = session->enc_write_frame.buflen; status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, + enc_frame->rate, session->enc_write_frame.data, &session->enc_write_frame.datalen, + &session->enc_write_frame.rate, &flag); diff --git a/src/switch_utils.c b/src/switch_utils.c index 49cab162bf..bc9fdf4c9f 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -35,92 +35,92 @@ #define MAXSAMPLEC (char)0x7F -SWITCH_DECLARE(int) float_to_short(float *f, short *s, int len) +SWITCH_DECLARE(int) switch_float_to_short(float *f, short *s, int len) { - int i; - float ft; - for(i=0;i= 0) { - s[i] = (short)(ft+0.5); - } else { - s[i] = (short)(ft-0.5); - } - if (s[i] > (short)MAXSAMPLE) s[i] = (short)MAXSAMPLE; - if (s[i] < (short)-MAXSAMPLE) s[i] = (short)-MAXSAMPLE; - } - return len; + int i; + float ft; + for(i=0;i= 0) { + s[i] = (short)(ft+0.5); + } else { + s[i] = (short)(ft-0.5); + } + if (s[i] > (short)MAXSAMPLE) s[i] = (short)MAXSAMPLE; + if (s[i] < (short)-MAXSAMPLE) s[i] = (short)-MAXSAMPLE; + } + return len; } -SWITCH_DECLARE(int) char_to_float(char *c, float *f, int len) +SWITCH_DECLARE(int) switch_char_to_float(char *c, float *f, int len) { - int i; + int i; - if (len % 2) { - return(-1); - } + if (len % 2) { + return(-1); + } - for(i=1;i MAXSAMPLE) f[(int)(i/2)] = MAXSAMPLE; - if (f[(int)(i/2)] < -MAXSAMPLE) f[(int)(i/2)] = -MAXSAMPLE; - } - return len/2; + for(i=1;i MAXSAMPLE) f[(int)(i/2)] = MAXSAMPLE; + if (f[(int)(i/2)] < -MAXSAMPLE) f[(int)(i/2)] = -MAXSAMPLE; + } + return len/2; } -SWITCH_DECLARE(int) float_to_char(float *f, char *c, int len) +SWITCH_DECLARE(int) switch_float_to_char(float *f, char *c, int len) { - int i; - float ft; - long l; - for(i=0;i= 0) { - l = (long)(ft+0.5); - } else { - l = (long)(ft-0.5); - } - c[i*2] = (unsigned char)((l)&0xff); - c[i*2+1] = (unsigned char)(((l)>>8)&0xff); - } - return len*2; + int i; + float ft; + long l; + for(i=0;i= 0) { + l = (long)(ft+0.5); + } else { + l = (long)(ft-0.5); + } + c[i*2] = (unsigned char)((l)&0xff); + c[i*2+1] = (unsigned char)(((l)>>8)&0xff); + } + return len*2; } -SWITCH_DECLARE(int) short_to_float(short *s, float *f, int len) +SWITCH_DECLARE(int) switch_short_to_float(short *s, float *f, int len) { - int i; - int min, max; - min = max = 0; + int i; - for(i=0;i> 8) & 0x00ff) | ((buf[i] << 8) & 0xff00); - } + } }