diff options
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/include/pjmedia/conference.h | 3 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/types.h | 27 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/conference.c | 217 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/dsound.c | 8 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/resample.c | 31 |
5 files changed, 189 insertions, 97 deletions
diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h index 208a8743..7346f7c1 100644 --- a/pjmedia/include/pjmedia/conference.h +++ b/pjmedia/include/pjmedia/conference.h @@ -44,7 +44,8 @@ typedef struct pjmedia_conf_port_info pj_str_t name; /**< Port name. */ pjmedia_port_op tx_setting; /**< Transmit settings. */ pjmedia_port_op rx_setting; /**< Receive settings. */ - pj_bool_t *listener; /**< Array of listeners. */ + unsigned listener_cnt; /**< Number of listeners. */ + unsigned *listener_slots; /**< Array of listeners. */ unsigned clock_rate; /**< Clock rate of the port. */ unsigned channel_count; /**< Number of channels. */ unsigned samples_per_frame; /**< Samples per frame */ diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h index 90f90b50..02edd9ff 100644 --- a/pjmedia/include/pjmedia/types.h +++ b/pjmedia/include/pjmedia/types.h @@ -20,7 +20,9 @@ #define __PJMEDIA_TYPES_H__ #include <pjmedia/config.h> -#include <pj/sock.h> +#include <pj/sock.h> /* pjmedia_sock_info */ +#include <pj/string.h> /* pj_memcpy(), pj_memset() */ + /** * Top most media type. @@ -124,9 +126,16 @@ typedef struct pjmedia_sock_info */ PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) { +#if 1 + pj_memset(samples, 0, count*sizeof(pj_int16_t)); +#elif 0 + unsigned i; + for (i=0; i<count; ++i) samples[i] = 0; +#else unsigned i; - for (i=0; i<count; ++i) - samples[i] = 0; + count >>= 1; + for (i=0; i<count; ++i) ((pj_int32_t*)samples)[i] = (pj_int32_t)0; +#endif } @@ -139,9 +148,17 @@ PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src, unsigned count) { +#if 1 + pj_memcpy(dst, src, count*sizeof(pj_int16_t)); +#elif 0 + unsigned i; + for (i=0; i<count; ++i) dst[i] = src[i]; +#else unsigned i; - for (i=0; i<count; ++i) - dst[i] = src[i]; + count >>= 1; + for (i=0; i<count; ++i) + ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i]; +#endif } diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c index 2a55efd3..abf522b1 100644 --- a/pjmedia/src/pjmedia/conference.c +++ b/pjmedia/src/pjmedia/conference.c @@ -23,6 +23,7 @@ #include <pjmedia/silencedet.h> #include <pjmedia/sound_port.h> #include <pjmedia/stream.h> +#include <pj/array.h> #include <pj/assert.h> #include <pj/log.h> #include <pj/pool.h> @@ -57,6 +58,8 @@ static FILE *fhnd_rec; #define BYTES_PER_SAMPLE 2 #define NORMAL_LEVEL 128 +#define SLOT_TYPE unsigned +#define INVALID_SLOT ((SLOT_TYPE)-1) /* @@ -78,8 +81,9 @@ struct conf_port pjmedia_port *port; /**< get_frame() and put_frame() */ pjmedia_port_op rx_setting; /**< Can we receive from this port */ pjmedia_port_op tx_setting; /**< Can we transmit to this port */ - int listener_cnt; /**< Number of listeners. */ - pj_bool_t *listeners; /**< Array of listeners. */ + unsigned listener_cnt; /**< Number of listeners. */ + SLOT_TYPE *listener_slots;/**< Array of listeners. */ + unsigned transmitter_cnt;/**<Number of transmitters. */ pjmedia_silence_det *vad; /**< VAD for this port. */ /* Shortcut for port info. */ @@ -87,7 +91,6 @@ struct conf_port unsigned samples_per_frame; /**< Port's samples per frame. */ /* Calculated signal levels: */ - pj_bool_t need_tx_level; /**< Need to calculate tx level? */ unsigned tx_level; /**< Last tx level to this port. */ unsigned rx_level; /**< Last rx level from this port. */ @@ -121,7 +124,7 @@ struct conf_port /* Mix buf is a temporary buffer used to calculate the average signal * received by this port from all other ports. Samples from all ports * that are transmitting to this port will be accumulated here, then - * they will be divided by the sources count before the samples are put + * they will be divided by the source level before the samples are put * to the TX buffer of this port. * * This buffer contains samples at bridge's clock rate. @@ -129,7 +132,8 @@ struct conf_port * * Note that the samples here are unsigned 32bit. */ - unsigned sources; /**< Number of sources. */ + unsigned src_level; /**< Sum of input levels */ + unsigned src_cnt; /**< Number of sources. */ pj_uint32_t *mix_buf; /**< Total sum of signal. */ /* Tx buffer is a temporary buffer to be used when there's mismatch @@ -223,10 +227,9 @@ static pj_status_t create_conf_port( pj_pool_t *pool, conf_port->rx_adj_level = NORMAL_LEVEL; /* Create transmit flag array */ - conf_port->listeners = pj_pool_zalloc(pool, - conf->max_ports*sizeof(pj_bool_t)); - PJ_ASSERT_RETURN(conf_port->listeners, PJ_ENOMEM); - + conf_port->listener_slots = pj_pool_zalloc(pool, + conf->max_ports * sizeof(SLOT_TYPE)); + PJ_ASSERT_RETURN(conf_port->listener_slots, PJ_ENOMEM); /* Save some port's infos, for convenience. */ if (port) { @@ -666,6 +669,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, { struct conf_port *src_port, *dst_port; pj_bool_t start_sound = PJ_FALSE; + unsigned i; /* Check arguments */ PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && @@ -683,17 +687,26 @@ PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, src_port = conf->ports[src_slot]; dst_port = conf->ports[sink_slot]; - if (src_port->listeners[sink_slot] == 0) { - src_port->listeners[sink_slot] = 1; + /* Check if connection has been made */ + for (i=0; i<src_port->listener_cnt; ++i) { + if (src_port->listener_slots[i] == sink_slot) + break; + } + + if (i == src_port->listener_cnt) { + src_port->listener_slots[src_port->listener_cnt] = sink_slot; ++conf->connect_cnt; ++src_port->listener_cnt; + ++dst_port->transmitter_cnt; if (conf->connect_cnt == 1) start_sound = 1; - PJ_LOG(4,(THIS_FILE,"Port %.*s transmitting to port %.*s", + PJ_LOG(4,(THIS_FILE,"Port %d (%.*s) transmitting to port %d (%.*s)", + src_slot, (int)src_port->name.slen, src_port->name.ptr, + sink_slot, (int)dst_port->name.slen, dst_port->name.ptr)); } @@ -718,6 +731,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, unsigned sink_slot ) { struct conf_port *src_port, *dst_port; + unsigned i; /* Check arguments */ PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && @@ -732,14 +746,29 @@ PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, src_port = conf->ports[src_slot]; dst_port = conf->ports[sink_slot]; - if (src_port->listeners[sink_slot] != 0) { - src_port->listeners[sink_slot] = 0; + /* Check if connection has been made */ + for (i=0; i<src_port->listener_cnt; ++i) { + if (src_port->listener_slots[i] == sink_slot) + break; + } + + if (i != src_port->listener_cnt) { + pj_assert(src_port->listener_cnt > 0 && + src_port->listener_cnt < conf->max_ports); + pj_assert(dst_port->transmitter_cnt > 0 && + dst_port->transmitter_cnt < conf->max_ports); + pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE), + src_port->listener_cnt, i); --conf->connect_cnt; --src_port->listener_cnt; + --dst_port->transmitter_cnt; - PJ_LOG(4,(THIS_FILE,"Port %.*s stop transmitting to port %.*s", + PJ_LOG(4,(THIS_FILE, + "Port %d (%.*s) stop transmitting to port %d (%.*s)", + src_slot, (int)src_port->name.slen, src_port->name.ptr, + sink_slot, (int)dst_port->name.slen, dst_port->name.ptr)); @@ -784,26 +813,30 @@ PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf, /* Remove this port from transmit array of other ports. */ for (i=0; i<conf->max_ports; ++i) { + unsigned j; + conf_port = conf->ports[i]; if (!conf_port) continue; - if (conf_port->listeners[port] != 0) { - --conf->connect_cnt; - --conf_port->listener_cnt; - conf_port->listeners[port] = 0; + if (conf_port->listener_cnt == 0) + continue; + + for (j=0; j<conf_port->listener_cnt; ++j) { + if (conf_port->listener_slots[j] == port) { + pj_array_erase(conf_port->listener_slots, sizeof(SLOT_TYPE), + conf_port->listener_cnt, j); + --conf->connect_cnt; + --conf_port->listener_cnt; + break; + } } } - /* Remove all ports listening from this port. */ + /* Update conf's connection count. */ conf_port = conf->ports[port]; - for (i=0; i<conf->max_ports; ++i) { - if (conf_port->listeners[i]) { - --conf->connect_cnt; - --conf_port->listener_cnt; - } - } + conf->connect_cnt -= conf_port->listener_cnt; /* Remove the port. */ conf->ports[port] = NULL; @@ -864,7 +897,8 @@ PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf, info->name = conf_port->name; info->tx_setting = conf_port->tx_setting; info->rx_setting = conf_port->rx_setting; - info->listener = conf_port->listeners; + info->listener_cnt = conf_port->listener_cnt; + info->listener_slots = conf_port->listener_slots; info->clock_rate = conf_port->clock_rate; info->channel_count = conf->channel_count; info->samples_per_frame = conf_port->samples_per_frame; @@ -916,7 +950,6 @@ PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf, conf_port = conf->ports[slot]; if (tx_level != NULL) { - conf_port->need_tx_level = 1; *tx_level = conf_port->tx_level; } @@ -1120,10 +1153,10 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, * transmit NULL frame. */ /* note: - * the "cport->sources==0" checking will cause discontinuous + * the "cport->src_level==0" checking will cause discontinuous * transmission for RTP stream. */ - if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->sources==0) { + if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->src_level==0) { pjmedia_frame frame; @@ -1143,6 +1176,39 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, return PJ_SUCCESS; } + buf = (pj_int16_t*)cport->mix_buf; + + /* This is the convention set in get_frame(). For optimization purpose, + * if we only have one transmitter transmitting to this port, then + * the transmitter will directly copy the original 16bit frame to + * mix_buf. + */ + if (cport->transmitter_cnt==1 && cport->src_cnt == 1) { + + /* But still see if we need to adjust the level */ + if (cport->tx_adj_level != NORMAL_LEVEL) { + pj_int16_t *input = buf; + pj_int32_t adj = cport->tx_adj_level; + + for (j=0; j<conf->samples_per_frame; ++j) { + pj_int32_t itemp; + + /* For the level adjustment, we need to store the sample to + * a temporary 32bit integer value to avoid overflowing the + * 16bit sample storage. + */ + itemp = input[j]; + itemp = itemp * adj / NORMAL_LEVEL; + + /* Clip the signal if it's too loud */ + if (itemp > 32767) itemp = 32767; + else if (itemp < -32768) itemp = -32768; + + input[j] = (pj_int16_t) itemp; + } + } + + } /* If there are sources in the mix buffer, convert the mixed samples * to the mixed samples itself. This is possible because mixed sample * is 32bit. @@ -1150,9 +1216,7 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, * In addition to this process, if we need to change the level of * TX signal, we adjust is here too. */ - buf = (pj_int16_t*)cport->mix_buf; - - if (cport->tx_adj_level != NORMAL_LEVEL && cport->sources) { + else if (cport->tx_adj_level != NORMAL_LEVEL && cport->src_level) { unsigned adj_level = cport->tx_adj_level; @@ -1163,7 +1227,7 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, /* Calculate average level, and convert the sample to * 16bit signed integer. */ - itemp = unsigned2pcm(cport->mix_buf[j] / cport->sources); + itemp = unsigned2pcm(cport->mix_buf[j] / cport->src_level); /* Adjust the level */ itemp = itemp * adj_level / NORMAL_LEVEL; @@ -1176,15 +1240,19 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, buf[j] = (pj_int16_t) itemp; } - } else if (cport->sources) { + } else if (cport->src_level) { /* No need to adjust signal level. */ for (j=0; j<conf->samples_per_frame; ++j) { - buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); + buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->src_level); } } else { // Not necessarry. Buffer has been zeroed before. // pjmedia_zero_samples(buf, conf->samples_per_frame); - pj_assert(buf[0] == 0); + //pj_assert(buf[0] == 0); + + // This shouldn't happen. Function should've already bailed out when + // cport->src_level == 0. + pj_assert(0); } /* Calculate TX level if we need to do so. @@ -1196,15 +1264,8 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, * for VU meter display. By doing it here, it should give the acceptable * indication of the signal level of the port. */ - if (cport->need_tx_level && cport->sources) { - pj_uint32_t level; - - /* Get the signal level. */ - level = pjmedia_calc_avg_signal(buf, conf->samples_per_frame); - - /* Convert level to 8bit complement ulaw */ - cport->tx_level = linear2ulaw(level) ^ 0xff; - + if (cport->src_cnt) { + cport->tx_level = cport->src_level / cport->src_cnt; } else { cport->tx_level = 0; } @@ -1310,13 +1371,14 @@ static pj_status_t get_frame(pjmedia_port *this_port, pj_assert(frame->size == conf->samples_per_frame * conf->bits_per_sample / 8); - /* Must lock mutex (must we??) */ + /* Must lock mutex */ pj_mutex_lock(conf->mutex); - /* Zero all port's temporary buffers. */ + /* Reset port source count. We will only reset port's mix + * buffer when we have someone transmitting to it. + */ for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) { struct conf_port *conf_port = conf->ports[i]; - pj_uint32_t *mix_buf; /* Skip empty slot. */ if (!conf_port) @@ -1324,10 +1386,9 @@ static pj_status_t get_frame(pjmedia_port *this_port, ++ci; - conf_port->sources = 0; - mix_buf = conf_port->mix_buf; - - pj_memset(mix_buf, 0, conf->samples_per_frame*sizeof(mix_buf[0])); + /* Reset sources */ + conf_port->src_level = 0; + conf_port->src_cnt = 0; } /* Get frames from all ports, and "mix" the signal @@ -1441,39 +1502,53 @@ static pj_status_t get_frame(pjmedia_port *this_port, /* Put this level to port's last RX level. */ conf_port->rx_level = level; + /* Skip processing frame if level is zero */ + if (level == 0) + continue; + /* Convert the buffer to unsigned 16bit value */ for (j=0; j<conf->samples_per_frame; ++j) conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)frame->buf)[j]); /* Add the signal to all listeners. */ - for (j=0, cj=0; - j<conf->max_ports && cj<(unsigned)conf_port->listener_cnt; - ++j) + for (cj=0; cj < conf_port->listener_cnt; ++cj) { - struct conf_port *listener = conf->ports[j]; + struct conf_port *listener; pj_uint32_t *mix_buf; unsigned k; - if (listener == 0) - continue; - - /* Skip if this is not the listener. */ - if (!conf_port->listeners[j]) - continue; - - /* Var "cj" is the number of listeners we have visited so far */ - ++cj; + listener = conf->ports[conf_port->listener_slots[cj]]; /* Skip if this listener doesn't want to receive audio */ if (listener->tx_setting != PJMEDIA_PORT_ENABLE) continue; - /* Mix the buffer */ + /* Mix the buffer. If this is the first source for target port, + * zero the mix buffer of target port first. + */ mix_buf = listener->mix_buf; - for (k=0; k<conf->samples_per_frame; ++k) - mix_buf[k] += (conf->uns_buf[k] * level); + if (listener->src_level == 0) { + pj_memset(mix_buf, 0, + conf->samples_per_frame*sizeof(mix_buf[0])); + } - listener->sources += level; + /* A little bit of optimization: + * When "conf_port" is the only transmitter to "listener", + * just add copy the frame directly from the original + * 16bit frame (avoiding unsigned2pcm() conversion). + * But write_port() needs to be aware of this trick! + */ + if (listener->transmitter_cnt == 1) { + pjmedia_copy_samples((pj_int16_t*)mix_buf, + frame->buf, conf->samples_per_frame); + listener->src_level = level; + } else { + for (k=0; k<conf->samples_per_frame; ++k) + mix_buf[k] += (conf->uns_buf[k] * level); + + listener->src_level += level; + } + listener->src_cnt++; } } @@ -1510,7 +1585,7 @@ static pj_status_t get_frame(pjmedia_port *this_port, } /* Return sound playback frame. */ - if (conf->ports[0]->sources) { + if (conf->ports[0]->src_level) { TRACE_((THIS_FILE, "write to audio, count=%d", conf->samples_per_frame)); diff --git a/pjmedia/src/pjmedia/dsound.c b/pjmedia/src/pjmedia/dsound.c index 9e1d7a55..81ea2f2c 100644 --- a/pjmedia/src/pjmedia/dsound.c +++ b/pjmedia/src/pjmedia/dsound.c @@ -368,9 +368,9 @@ static BOOL AppReadDataFromBuffer(LPDIRECTSOUNDCAPTUREBUFFER lpDsb, // The buffe if SUCCEEDED(hr) { // Read from pointers. - CopyMemory(lpbSoundData, lpvPtr1, dwBytes1); + pj_memcpy(lpbSoundData, lpvPtr1, dwBytes1); if (lpvPtr2 != NULL) - CopyMemory(lpbSoundData+dwBytes1, lpvPtr2, dwBytes2); + pj_memcpy(lpbSoundData+dwBytes1, lpvPtr2, dwBytes2); // Release the data back to DirectSound. hr = IDirectSoundCaptureBuffer_Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); @@ -407,9 +407,9 @@ static BOOL AppWriteDataToBuffer(LPDIRECTSOUNDBUFFER lpDsb, // The buffer. &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); } if SUCCEEDED(hr) { - CopyMemory(lpvPtr1, lpbSoundData, dwBytes1); + pj_memcpy(lpvPtr1, lpbSoundData, dwBytes1); if (NULL != lpvPtr2) - CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2); + pj_memcpy(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2); hr = IDirectSoundBuffer_Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); if SUCCEEDED(hr) diff --git a/pjmedia/src/pjmedia/resample.c b/pjmedia/src/pjmedia/resample.c index 6ea621c2..a30215fa 100644 --- a/pjmedia/src/pjmedia/resample.c +++ b/pjmedia/src/pjmedia/resample.c @@ -58,9 +58,6 @@ * - move FilterUp() and FilterUD() from filterkit.c * - move stddefs.h and resample.h to this file. * - const correctness. - * - fixed SrcLinear() may write pass output buffer. - * - assume the same for SrcUp() and SrcUD(), so put the same - * protection. */ #include <pjmedia/resample.h> #include <pjmedia/errno.h> @@ -260,7 +257,7 @@ static int Ystart = Y; Yend = Ystart + (unsigned)(nx * pFactor); endTime = time + (1<<Np)*(WORD)nx; - while (time < endTime && Y < Yend) /* bennylp fix: added Y < Yend */ + while (time < endTime) { iconst = (time) & Pmask; xp = &X[(time)>>Np]; /* Ptr to current input sample */ @@ -399,7 +396,7 @@ static int SrcUp(const HWORD X[], HWORD Y[], double pFactor, Ystart = Y; Yend = Ystart + (unsigned)(nx * pFactor); endTime = time + (1<<Np)*(WORD)nx; - while (time < endTime && Y < Yend) /* bennylp fix: protect Y */ + while (time < endTime) { xp = &X[time>>Np]; /* Ptr to current input sample */ /* Perform left-wing inner product */ @@ -443,7 +440,7 @@ static int SrcUD(const HWORD X[], HWORD Y[], double pFactor, Ystart = Y; Yend = Ystart + (unsigned)(nx * pFactor); endTime = time + (1<<Np)*(WORD)nx; - while (time < endTime && Y < Yend) /* bennylp fix: protect Y */ + while (time < endTime) { xp = &X[time>>Np]; /* Ptr to current input sample */ v = FilterUD(pImp, pImpD, pNwing, Interp, xp, (HWORD)(time&Pmask), @@ -495,9 +492,11 @@ PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, /* * If we're downsampling, always use the fast algorithm since it seems - * to yield the same performance. + * to yield the same quality. */ if (rate_out < rate_in) { + //no this is not a good idea. It sounds pretty good with speech, + //but very poor with background noise etc. //high_quality = 0; } @@ -533,7 +532,6 @@ PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, if (high_quality) { unsigned size; - unsigned i; /* This is a bug in xoff calculation, thanks Stephane Lussier * of Macadamian dot com. @@ -551,9 +549,7 @@ PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, resample->buffer = pj_pool_alloc(pool, size); PJ_ASSERT_RETURN(resample->buffer, PJ_ENOMEM); - for (i=0; i<resample->xoff*2; ++i) { - resample->buffer[i] = 0; - } + pjmedia_zero_samples(resample->buffer, resample->xoff*2); } else { @@ -561,6 +557,12 @@ PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, } *p_resample = resample; + + PJ_LOG(5,(THIS_FILE, "resample created: %s qualiy, %s filter, in/out " + "rate=%d/%d", + (high_quality?"high":"low"), + (large_filter?"large":"small"), + rate_in, rate_out)); return PJ_SUCCESS; } @@ -573,7 +575,6 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample, PJ_ASSERT_ON_FAIL(resample, return); if (resample->high_quality) { - unsigned i; pj_int16_t *dst_buf; const pj_int16_t *src_buf; @@ -644,7 +645,7 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample, * */ dst_buf = resample->buffer + resample->xoff*2; - for (i=0; i<resample->frame_size; ++i) dst_buf[i] = input[i]; + pjmedia_copy_samples(dst_buf, input, resample->frame_size); if (resample->factor >= 1) { @@ -688,9 +689,7 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample, dst_buf = resample->buffer; src_buf = input + resample->frame_size - resample->xoff*2; - for (i=0; i<resample->xoff * 2; ++i) { - dst_buf[i] = src_buf[i]; - } + pjmedia_copy_samples(dst_buf, src_buf, resample->xoff * 2); } else { SrcLinear( input, output, resample->factor, resample->frame_size); |