Changeset 5792


Ignore:
Timestamp:
05/15/18 03:23:44 (2 months ago)
Author:
ming
Message:

Closed #2113: Implement conference signal level adjustment for a specific connection

Location:
pjproject/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/conference.h

    r3664 r5792  
    7272    unsigned            listener_cnt;       /**< Number of listeners.       */ 
    7373    unsigned           *listener_slots;     /**< Array of listeners.        */ 
     74    unsigned           *listener_adj_level; /**< Array of listeners' level 
     75                                                 adjustment                 */ 
    7476    unsigned            transmitter_cnt;    /**< Number of transmitter.     */ 
    7577    unsigned            clock_rate;         /**< Clock rate of the port.    */ 
     
    296298 
    297299/** 
    298  * Enable unidirectional audio from the specified source slot to the 
    299  * specified sink slot. 
     300 * Enable unidirectional audio from the specified source slot to the specified 
     301 * sink slot. 
     302 * Application may adjust the level to make signal transmitted from the source 
     303 * slot to the sink slot either louder or more quiet. The level adjustment is 
     304 * calculated with this formula: 
     305 * <b><tt>output = input * (adj_level+128) / 128</tt></b>. Using this, zero 
     306 * indicates no adjustment, the value -128 will mute the signal, and the value 
     307 * of +128 will make the signal 100% louder, +256 will make it 200% louder, 
     308 * etc. 
     309 * 
     310 * The level adjustment will apply to a specific connection only (i.e. only 
     311 * for the signal from the source to the sink), as compared to 
     312 * pjmedia_conf_adjust_tx_level()/pjmedia_conf_adjust_rx_level() which 
     313 * applies to all signals from/to that port. The signal adjustment 
     314 * will be cumulative, in this following order: 
     315 * signal from the source will be adjusted with the level specified 
     316 * in pjmedia_conf_adjust_rx_level(), then with the level specified 
     317 * via this API, and finally with the level specified to the sink's 
     318 * pjmedia_conf_adjust_tx_level().  
    300319 * 
    301320 * @param conf          The conference bridge. 
    302321 * @param src_slot      Source slot. 
    303322 * @param sink_slot     Sink slot. 
    304  * @param level         This argument is reserved for future improvements 
    305  *                      where it is possible to adjust the level of signal 
    306  *                      transmitted in a specific connection. For now, 
    307  *                      this argument MUST be zero. 
     323 * @param adj_level     Adjustment level, which must be greater than or equal 
     324 *                      to -128. A value of zero means there is no level 
     325 *                      adjustment to be made, the value -128 will mute the 
     326 *                      signal, and the value of +128 will make the signal 
     327 *                      100% louder, +256 will make it 200% louder, etc. 
     328 *                      See the function description for the formula. 
    308329 * 
    309330 * @return              PJ_SUCCES on success. 
     
    312333                                                unsigned src_slot, 
    313334                                                unsigned sink_slot, 
    314                                                 int level ); 
     335                                                int adj_level ); 
    315336 
    316337 
     
    497518 
    498519 
     520/** 
     521 * Adjust the level of signal to be transmitted from the source slot to the 
     522 * sink slot. 
     523 * Application may adjust the level to make signal transmitted from the source 
     524 * slot to the sink slot either louder or more quiet. The level adjustment is 
     525 * calculated with this formula: 
     526 * <b><tt>output = input * (adj_level+128) / 128</tt></b>. Using this, zero 
     527 * indicates no adjustment, the value -128 will mute the signal, and the value 
     528 * of +128 will make the signal 100% louder, +256 will make it 200% louder, 
     529 * etc. 
     530 * 
     531 * The level adjustment value will stay with the connection until the 
     532 * connection is removed or new adjustment value is set. The current level 
     533 * adjustment value is reported in the media port info when the 
     534 * #pjmedia_conf_get_port_info() function is called. 
     535 * 
     536 * @param conf          The conference bridge. 
     537 * @param src_slot      Source slot. 
     538 * @param sink_slot     Sink slot. 
     539 * @param adj_level     Adjustment level, which must be greater than or equal 
     540 *                      to -128. A value of zero means there is no level 
     541 *                      adjustment to be made, the value -128 will mute the  
     542 *                      signal, and the value of +128 will make the signal  
     543 *                      100% louder, +256 will make it 200% louder, etc.  
     544 *                      See the function description for the formula. 
     545 * 
     546 * @return              PJ_SUCCESS on success. 
     547 */ 
     548PJ_DECL(pj_status_t) pjmedia_conf_adjust_conn_level( pjmedia_conf *conf, 
     549                                                     unsigned src_slot, 
     550                                                     unsigned sink_slot, 
     551                                                     int adj_level ); 
     552 
     553 
    499554 
    500555PJ_END_DECL 
  • pjproject/trunk/pjmedia/src/pjmedia/conference.c

    r5702 r5792  
    118118    unsigned             listener_cnt;  /**< Number of listeners.           */ 
    119119    SLOT_TYPE           *listener_slots;/**< Array of listeners.            */ 
     120    unsigned            *listener_adj_level; 
     121                                        /**< Array of listeners' level 
     122                                             adjustment.                    */ 
    120123    unsigned             transmitter_cnt;/**<Number of transmitters.        */ 
    121124 
     
    134137    unsigned             tx_adj_level;  /**< Adjustment for TX.             */ 
    135138    unsigned             rx_adj_level;  /**< Adjustment for RX.             */ 
     139    pj_int16_t          *adj_level_buf; /**< The adjustment buffer.         */ 
    136140 
    137141    /* Resample, for converting clock rate, if they're different. */ 
     
    282286 
    283287    /* Create transmit flag array */ 
    284     conf_port->listener_slots = (SLOT_TYPE*) 
    285                                 pj_pool_zalloc(pool,  
    286                                           conf->max_ports * sizeof(SLOT_TYPE)); 
     288    conf_port->listener_slots = (SLOT_TYPE*) pj_pool_zalloc(pool,  
     289                                          conf->max_ports * sizeof(SLOT_TYPE)); 
    287290    PJ_ASSERT_RETURN(conf_port->listener_slots, PJ_ENOMEM); 
     291 
     292    /* Create adjustment level array */ 
     293    conf_port->listener_adj_level = (unsigned *) pj_pool_zalloc(pool,  
     294                                       conf->max_ports * sizeof(unsigned)); 
     295    PJ_ASSERT_RETURN(conf_port->listener_adj_level, PJ_ENOMEM); 
    288296 
    289297    /* Save some port's infos, for convenience. */ 
     
    302310        conf_port->channel_count = conf->channel_count; 
    303311    } 
     312 
     313    /* Create adjustment level buffer. */ 
     314    conf_port->adj_level_buf = (pj_int16_t*) pj_pool_zalloc(pool,  
     315                               conf->samples_per_frame * sizeof(pj_int16_t)); 
    304316 
    305317    /* If port's clock rate is different than conference's clock rate, 
     
    949961                                               unsigned src_slot, 
    950962                                               unsigned sink_slot, 
    951                                                int level ) 
     963                                               int adj_level ) 
    952964{ 
    953965    struct conf_port *src_port, *dst_port; 
     
    959971                     sink_slot<conf->max_ports, PJ_EINVAL); 
    960972 
    961     /* For now, level MUST be zero. */ 
    962     PJ_ASSERT_RETURN(level == 0, PJ_EINVAL); 
     973    /* Value must be from -128 to +127 */ 
     974    /* Disabled, you can put more than +127, at your own risk: 
     975     PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 
     976     */ 
     977    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL); 
    963978 
    964979    pj_mutex_lock(conf->mutex); 
     
    980995    if (i == src_port->listener_cnt) { 
    981996        src_port->listener_slots[src_port->listener_cnt] = sink_slot; 
     997        /* Set normalized adjustment level. */ 
     998        src_port->listener_adj_level[src_port->listener_cnt] = adj_level + 
     999                                                               NORMAL_LEVEL; 
    9821000        ++conf->connect_cnt; 
    9831001        ++src_port->listener_cnt; 
     
    13871405    pj_mutex_unlock(conf->mutex); 
    13881406 
     1407    return PJ_SUCCESS; 
     1408} 
     1409 
     1410/* 
     1411 * Adjust level of individual connection. 
     1412 */ 
     1413PJ_DEF(pj_status_t) pjmedia_conf_adjust_conn_level( pjmedia_conf *conf, 
     1414                                                    unsigned src_slot, 
     1415                                                    unsigned sink_slot, 
     1416                                                    int adj_level ) 
     1417{ 
     1418    struct conf_port *src_port, *dst_port; 
     1419    unsigned i; 
     1420 
     1421    /* Check arguments */ 
     1422    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 
     1423                     sink_slot<conf->max_ports, PJ_EINVAL); 
     1424 
     1425    /* Value must be from -128 to +127 */ 
     1426    /* Disabled, you can put more than +127, at your own risk: 
     1427     PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 
     1428     */ 
     1429    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL); 
     1430 
     1431    pj_mutex_lock(conf->mutex); 
     1432 
     1433    /* Ports must be valid. */ 
     1434    src_port = conf->ports[src_slot]; 
     1435    dst_port = conf->ports[sink_slot]; 
     1436    if (!src_port || !dst_port) { 
     1437        pj_mutex_unlock(conf->mutex); 
     1438        return PJ_EINVAL; 
     1439    } 
     1440 
     1441    /* Check if connection has been made */ 
     1442    for (i=0; i<src_port->listener_cnt; ++i) { 
     1443        if (src_port->listener_slots[i] == sink_slot) 
     1444            break; 
     1445    } 
     1446 
     1447    if (i == src_port->listener_cnt) { 
     1448        /* connection hasn't been made */ 
     1449        pj_mutex_unlock(conf->mutex); 
     1450        return PJ_EINVAL; 
     1451    }  
     1452    /* Set normalized adjustment level. */ 
     1453    src_port->listener_adj_level[i] = adj_level + NORMAL_LEVEL; 
     1454 
     1455    pj_mutex_unlock(conf->mutex); 
    13891456    return PJ_SUCCESS; 
    13901457} 
     
    19532020        { 
    19542021            struct conf_port *listener; 
    1955             pj_int32_t *mix_buf; 
     2022            pj_int32_t *mix_buf;             
     2023            pj_int16_t *p_in_conn_leveled; 
    19562024 
    19572025            listener = conf->ports[conf_port->listener_slots[cj]]; 
     
    19622030 
    19632031            mix_buf = listener->mix_buf; 
     2032 
     2033            /* apply connection level, if not normal */ 
     2034            if (conf_port->listener_adj_level[cj] != NORMAL_LEVEL) { 
     2035                unsigned k = 0; 
     2036                for (; k < conf->samples_per_frame; ++k) { 
     2037                    /* For the level adjustment, we need to store the sample to 
     2038                     * a temporary 32bit integer value to avoid overflowing the 
     2039                     * 16bit sample storage. 
     2040                     */ 
     2041                    pj_int32_t itemp; 
     2042 
     2043                    itemp = p_in[k]; 
     2044                    /*itemp = itemp * adj / NORMAL_LEVEL;*/ 
     2045                    /* bad code (signed/unsigned badness): 
     2046                     *  itemp = (itemp * conf_port->listsener_adj_level) >> 7; 
     2047                     */ 
     2048                    itemp *= conf_port->listener_adj_level[cj]; 
     2049                    itemp >>= 7; 
     2050 
     2051                    /* Clip the signal if it's too loud */ 
     2052                    if (itemp > MAX_LEVEL) itemp = MAX_LEVEL; 
     2053                    else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL; 
     2054 
     2055                    conf_port->adj_level_buf[k] = (pj_int16_t)itemp; 
     2056                } 
     2057 
     2058                /* take the leveled frame */ 
     2059                p_in_conn_leveled = conf_port->adj_level_buf; 
     2060            } else { 
     2061                /* take the frame as-is */ 
     2062                p_in_conn_leveled = p_in; 
     2063            } 
    19642064 
    19652065            if (listener->transmitter_cnt > 1) { 
     
    19732073 
    19742074                for (k = 0; k < samples_per_frame; ++k) { 
    1975                     mix_buf[k] += p_in[k]; 
     2075                    mix_buf[k] += p_in_conn_leveled[k]; 
    19762076                    if (mix_buf[k] < mix_buf_min) 
    19772077                        mix_buf_min = mix_buf[k]; 
     
    20002100 
    20012101                for (k = 0; k < samples_per_frame; ++k) { 
    2002                     mix_buf[k] = p_in[k]; 
     2102                    mix_buf[k] = p_in_conn_leveled[k]; 
    20032103                } 
    20042104            } 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5788 r5792  
    66146614 
    66156615/** 
     6616 * This structure specifies the parameters for conference ports connection. 
     6617 * Use pjsua_conf_connect_param_default() to initialize this structure with 
     6618 * default values. 
     6619 */ 
     6620typedef struct pjsua_conf_connect_param 
     6621{ 
     6622    /* 
     6623     * Signal level adjustment from the source to the sink to make it 
     6624     * louder or quieter. Value 1.0 means no level adjustment, 
     6625     * while value 0 means to mute the port. 
     6626     * 
     6627     * Default: 1.0 
     6628     */ 
     6629    float               level; 
     6630 
     6631} pjsua_conf_connect_param; 
     6632 
     6633 
     6634/** 
     6635 * Initialize pjsua_conf_connect_param with default values. 
     6636 * 
     6637 * @param prm           The parameter. 
     6638 */ 
     6639PJ_DECL(void) pjsua_conf_connect_param_default(pjsua_conf_connect_param *prm); 
     6640 
     6641 
     6642/** 
    66166643 * Get maxinum number of conference ports. 
    66176644 * 
     
    67046731PJ_DECL(pj_status_t) pjsua_conf_connect(pjsua_conf_port_id source, 
    67056732                                        pjsua_conf_port_id sink); 
     6733 
     6734/** 
     6735 * Establish unidirectional media flow from source to sink. One source 
     6736 * may transmit to multiple destinations/sink. And if multiple 
     6737 * sources are transmitting to the same sink, the media will be mixed 
     6738 * together. Source and sink may refer to the same ID, effectively 
     6739 * looping the media. 
     6740 * 
     6741 * Signal level from the source to the sink can be adjusted by making 
     6742 * it louder or quieter via the parameter param. The level adjustment 
     6743 * will apply to a specific connection only (i.e. only for the signal 
     6744 * from the source to the sink), as compared to 
     6745 * pjsua_conf_adjust_tx_level()/pjsua_conf_adjust_rx_level() which 
     6746 * applies to all signals from/to that port. The signal adjustment 
     6747 * will be cumulative, in this following order: 
     6748 * signal from the source will be adjusted with the level specified 
     6749 * in pjsua_conf_adjust_rx_level(), then with the level specified 
     6750 * via this API, and finally with the level specified to the sink's 
     6751 * pjsua_conf_adjust_tx_level(). 
     6752 * 
     6753 * If bidirectional media flow is desired, application needs to call 
     6754 * this function twice, with the second one having the arguments 
     6755 * reversed. 
     6756 * 
     6757 * @param source        Port ID of the source media/transmitter. 
     6758 * @param sink          Port ID of the destination media/received. 
     6759 * @param prm           Conference port connection param. If set to 
     6760 *                      NULL, default values will be used. 
     6761 * 
     6762 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     6763 */ 
     6764PJ_DECL(pj_status_t) pjsua_conf_connect2(pjsua_conf_port_id source, 
     6765                                         pjsua_conf_port_id sink, 
     6766                                         const pjsua_conf_connect_param *prm); 
    67066767 
    67076768 
  • pjproject/trunk/pjsip/include/pjsua2/media.hpp

    r5717 r5792  
    193193}; 
    194194 
     195struct AudioMediaTransmitParam 
     196{ 
     197    /** 
     198     * Signal level adjustment. Value 1.0 means no level adjustment, 
     199     * while value 0 means to mute the port. 
     200     * 
     201     * Default: 1.0 
     202     */ 
     203    float               level; 
     204 
     205public: 
     206    /** 
     207     * Default constructor 
     208     */ 
     209    AudioMediaTransmitParam(); 
     210}; 
     211 
    195212/** 
    196213 * Audio Media. 
     
    228245     */ 
    229246    void startTransmit(const AudioMedia &sink) const throw(Error); 
     247 
     248    /** 
     249     * Establish unidirectional media flow to sink. This media port 
     250     * will act as a source, and it may transmit to multiple destinations/sink. 
     251     * And if multiple sources are transmitting to the same sink, the media 
     252     * will be mixed together. Source and sink may refer to the same Media, 
     253     * effectively looping the media. 
     254     * 
     255     * Signal level from this source to the sink can be adjusted by making 
     256     * it louder or quieter via the parameter param. The level adjustment 
     257     * will apply to a specific connection only (i.e. only for signal 
     258     * from this source to the sink), as compared to 
     259     * adjustTxLevel()/adjustRxLevel() which applies to all signals from/to 
     260     * this media port. The signal adjustment 
     261     * will be cumulative, in this following order: 
     262     * signal from this source will be adjusted with the level specified 
     263     * in adjustTxLevel(), then with the level specified via this API, 
     264     * and finally with the level specified to the sink's adjustRxLevel(). 
     265     * 
     266     * If bidirectional media flow is desired, application needs to call 
     267     * this method twice, with the second one called from the opposite source 
     268     * media. 
     269     * 
     270     * @param sink              The destination Media. 
     271     * @param param             The parameter. 
     272     */ 
     273    void startTransmit2(const AudioMedia &sink,  
     274                        const AudioMediaTransmitParam &param) const 
     275         throw(Error); 
    230276 
    231277    /** 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c

    r5748 r5792  
    715715} 
    716716 
     717PJ_DEF(void) pjsua_conf_connect_param_default(pjsua_conf_connect_param *prm) 
     718{ 
     719    pj_bzero(prm, sizeof(*prm)); 
     720    prm->level = 1.0; 
     721} 
     722 
    717723/* 
    718724 * Get maxinum number of conference ports. 
     
    825831PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source, 
    826832                                        pjsua_conf_port_id sink) 
     833{ 
     834    pjsua_conf_connect_param prm; 
     835 
     836    pjsua_conf_connect_param_default(&prm); 
     837    return pjsua_conf_connect2(source, sink, &prm); 
     838} 
     839                                         
     840/* 
     841 * Establish unidirectional media flow from souce to sink, with signal 
     842 * level adjustment. 
     843 */ 
     844PJ_DEF(pj_status_t) pjsua_conf_connect2( pjsua_conf_port_id source, 
     845                                         pjsua_conf_port_id sink, 
     846                                         const pjsua_conf_connect_param *prm) 
    827847{ 
    828848    pj_status_t status = PJ_SUCCESS; 
     
    958978 
    959979    if (status == PJ_SUCCESS) { 
    960         status = pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0); 
     980        pjsua_conf_connect_param cc_param; 
     981         
     982        if (!prm) 
     983            pjsua_conf_connect_param_default(&cc_param); 
     984        else 
     985            pj_memcpy(&cc_param, prm, sizeof(cc_param)); 
     986        status = pjmedia_conf_connect_port(pjsua_var.mconf, source, sink,  
     987                                           (int)((cc_param.level-1) * 128)); 
    961988    } 
    962989 
  • pjproject/trunk/pjsip/src/pjsua2/media.cpp

    r5724 r5792  
    118118 
    119119/////////////////////////////////////////////////////////////////////////////// 
     120AudioMediaTransmitParam::AudioMediaTransmitParam() 
     121: level(1.0) 
     122{ 
     123} 
     124 
    120125AudioMedia::AudioMedia()  
    121126: Media(PJMEDIA_TYPE_AUDIO), id(PJSUA_INVALID_ID), mediaPool(NULL) 
     
    197202{ 
    198203    PJSUA2_CHECK_EXPR( pjsua_conf_connect(id, sink.id) ); 
     204} 
     205 
     206void AudioMedia::startTransmit2(const AudioMedia &sink, 
     207                                const AudioMediaTransmitParam &param) const 
     208     throw(Error) 
     209{ 
     210    pjsua_conf_connect_param pj_param; 
     211     
     212    pjsua_conf_connect_param_default(&pj_param); 
     213    pj_param.level = param.level; 
     214    PJSUA2_CHECK_EXPR( pjsua_conf_connect2(id, sink.id, &pj_param) ); 
    199215} 
    200216 
Note: See TracChangeset for help on using the changeset viewer.