Changeset 904


Ignore:
Timestamp:
Jan 24, 2007 2:02:09 AM (13 years ago)
Author:
bennylp
Message:

Implement ticket #62: option to play tones continuously, and added --play-tone option in pjsua

Location:
pjproject/trunk
Files:
3 edited

Legend:

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

    r875 r904  
    9999 
    100100 
     101/** 
     102 * Tone generator options. 
     103 */ 
     104enum 
     105{ 
     106    /** 
     107     * Play the tones in loop, restarting playing the first tone after 
     108     * the last tone has been played. 
     109     */ 
     110    PJMEDIA_TONEGEN_LOOP    = 1 
     111}; 
     112 
    101113 
    102114/** 
     
    112124 * @param bits_per_sample   Number of bits per sample. This version of PJMEDIA 
    113125 *                          only supports 16bit per sample. 
    114  * @param options           Option flags, must be zero for now. 
     126 * @param options           Option flags. Application may specify  
     127 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop. 
    115128 * @param p_port            Pointer to receive the port instance. 
    116129 * 
     
    128141 
    129142/** 
     143 * Create an instance of tone generator with the specified parameters. 
     144 * When the tone generator is first created, it will be loaded with the 
     145 * default digit map. 
     146 * 
     147 * @param pool              Pool to allocate memory for the port structure. 
     148 * @param name              Optional name for the tone generator. 
     149 * @param clock_rate        Sampling rate. 
     150 * @param channel_count     Number of channels. Currently only mono and stereo 
     151 *                          are supported. 
     152 * @param samples_per_frame Number of samples per frame. 
     153 * @param bits_per_sample   Number of bits per sample. This version of PJMEDIA 
     154 *                          only supports 16bit per sample. 
     155 * @param options           Option flags. Application may specify  
     156 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop. 
     157 * @param p_port            Pointer to receive the port instance. 
     158 * 
     159 * @return                  PJ_SUCCESS on success, or the appropriate 
     160 *                          error code. 
     161 */ 
     162PJ_DECL(pj_status_t) pjmedia_tonegen_create2(pj_pool_t *pool, 
     163                                             const pj_str_t *name, 
     164                                             unsigned clock_rate, 
     165                                             unsigned channel_count, 
     166                                             unsigned samples_per_frame, 
     167                                             unsigned bits_per_sample, 
     168                                             unsigned options, 
     169                                             pjmedia_port **p_port); 
     170 
     171 
     172/** 
    130173 * Check if the tone generator is still busy producing some tones. 
    131174 * 
     
    157200 * @param count             The number of tones in the array. 
    158201 * @param tones             Array of tones to be played. 
    159  * @param options           Playback options, must be zero for now. 
     202 * @param options           Option flags. Application may specify  
     203 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop. 
    160204 * 
    161205 * @return                  PJ_SUCCESS on success, or PJ_ETOOMANY if 
     
    179223 * @param count             Number of digits in the array. 
    180224 * @param digits            Array of MF digits. 
    181  * @param options           Playback options, must be zero for now. 
     225 * @param options           Option flags. Application may specify  
     226 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop. 
    182227 * 
    183228 * @return                  PJ_SUCCESS on success, or PJ_ETOOMANY if 
  • pjproject/trunk/pjmedia/src/pjmedia/tonegen.c

    r747 r904  
    2828 
    2929/* amplitude */ 
    30 #define AMP     16383 
     30#define AMP     8192 
    3131 
    3232 
     
    234234    pjmedia_port        base; 
    235235 
     236    /* options */ 
     237    unsigned            options; 
     238    unsigned            playback_options; 
     239 
    236240    /* Digit map */ 
    237241    pjmedia_tone_digit_map  *digit_map; 
     
    281285 * default digit map. 
    282286 */ 
     287PJ_DEF(pj_status_t) pjmedia_tonegen_create2(pj_pool_t *pool, 
     288                                            const pj_str_t *name, 
     289                                            unsigned clock_rate, 
     290                                            unsigned channel_count, 
     291                                            unsigned samples_per_frame, 
     292                                            unsigned bits_per_sample, 
     293                                            unsigned options, 
     294                                            pjmedia_port **p_port) 
     295{ 
     296    const pj_str_t STR_TONE_GEN = pj_str("tone-gen"); 
     297    struct tonegen  *tonegen; 
     298    pj_status_t status; 
     299 
     300    PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&  
     301                     samples_per_frame && bits_per_sample == 16 &&  
     302                     p_port != NULL, PJ_EINVAL); 
     303 
     304    /* Only support mono and stereo */ 
     305    PJ_ASSERT_RETURN(channel_count==1 || channel_count==2, PJ_EINVAL); 
     306 
     307    /* Create and initialize port */ 
     308    tonegen = pj_pool_zalloc(pool, sizeof(struct tonegen)); 
     309    if (name == NULL || name->slen == 0) name = &STR_TONE_GEN; 
     310    status = pjmedia_port_info_init(&tonegen->base.info, name,  
     311                                    SIGNATURE, clock_rate, channel_count,  
     312                                    bits_per_sample, samples_per_frame); 
     313    if (status != PJ_SUCCESS) 
     314        return status; 
     315 
     316    tonegen->options = options; 
     317    tonegen->base.get_frame = &tonegen_get_frame; 
     318    tonegen->digit_map = &digit_map; 
     319 
     320    /* Done */ 
     321    *p_port = &tonegen->base; 
     322    return PJ_SUCCESS; 
     323} 
     324 
     325 
    283326PJ_DEF(pj_status_t) pjmedia_tonegen_create( pj_pool_t *pool, 
    284327                                            unsigned clock_rate, 
     
    289332                                            pjmedia_port **p_port) 
    290333{ 
    291     const pj_str_t STR_TONE_GEN = pj_str("tone-gen"); 
    292     struct tonegen  *tonegen; 
    293     pj_status_t status; 
    294  
    295     PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&  
    296                      samples_per_frame && bits_per_sample == 16 &&  
    297                      options == 0 && p_port != NULL, PJ_EINVAL); 
    298  
    299     /* Only support mono and stereo */ 
    300     PJ_ASSERT_RETURN(channel_count==1 || channel_count==2, PJ_EINVAL); 
    301  
    302     /* Create and initialize port */ 
    303     tonegen = pj_pool_zalloc(pool, sizeof(struct tonegen)); 
    304     status = pjmedia_port_info_init(&tonegen->base.info, &STR_TONE_GEN,  
    305                                     SIGNATURE, clock_rate, channel_count,  
    306                                     bits_per_sample, samples_per_frame); 
    307     if (status != PJ_SUCCESS) 
    308         return status; 
    309  
    310     tonegen->base.get_frame = &tonegen_get_frame; 
    311     tonegen->digit_map = &digit_map; 
    312  
    313     /* Done */ 
    314     *p_port = &tonegen->base; 
    315     return PJ_SUCCESS; 
     334    return pjmedia_tonegen_create2(pool, NULL, clock_rate, channel_count, 
     335                                   samples_per_frame, bits_per_sample,  
     336                                   options, p_port); 
    316337} 
    317338 
     
    359380    if (tonegen->cur_digit > tonegen->count) { 
    360381        /* We have played all the digits */ 
    361         tonegen->count = 0; 
    362         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    363         return PJ_SUCCESS; 
     382        if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP) 
     383        { 
     384            /* Reset back to the first tone */ 
     385            tonegen->cur_digit = 0; 
     386            tonegen->dig_samples = 0; 
     387 
     388        } else { 
     389            tonegen->count = 0; 
     390            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     391            return PJ_SUCCESS; 
     392        } 
    364393    } 
    365394 
     
    377406         * the digits  
    378407         */ 
    379         tonegen->count = 0; 
    380         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    381         return PJ_SUCCESS; 
     408        if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP) 
     409        { 
     410            /* Reset back to the first tone */ 
     411            tonegen->cur_digit = 0; 
     412            tonegen->dig_samples = 0; 
     413 
     414        } else { 
     415            tonegen->count = 0; 
     416            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     417            return PJ_SUCCESS; 
     418        } 
    382419    } 
    383420     
     
    385422    end = dst + port->info.samples_per_frame; 
    386423 
    387     while (dst < end && tonegen->cur_digit < tonegen->count) { 
     424    while (dst < end) { 
    388425        const pjmedia_tone_desc *dig = &tonegen->digits[tonegen->cur_digit]; 
    389426        unsigned required, cnt, on_samp, off_samp; 
     
    426463            tonegen->cur_digit++; 
    427464            tonegen->dig_samples = 0; 
     465 
     466            if (tonegen->cur_digit >= tonegen->count) { 
     467                /* All digits have been played */ 
     468                if ((tonegen->options & PJMEDIA_TONEGEN_LOOP) || 
     469                    (tonegen->playback_options & PJMEDIA_TONEGEN_LOOP)) 
     470                { 
     471                    tonegen->cur_digit = 0; 
     472                } else { 
     473                    break; 
     474                } 
     475            } 
    428476        } 
    429477    } 
     
    435483    frame->size = port->info.bytes_per_frame; 
    436484 
    437     if (tonegen->cur_digit >= tonegen->count) 
    438         tonegen->count = 0; 
     485    if (tonegen->cur_digit >= tonegen->count) { 
     486        if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP) 
     487        { 
     488            /* Reset back to the first tone */ 
     489            tonegen->cur_digit = 0; 
     490            tonegen->dig_samples = 0; 
     491 
     492        } else { 
     493            tonegen->count = 0; 
     494        } 
     495    } 
    439496 
    440497    return PJ_SUCCESS; 
     
    454511 
    455512    PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE && 
    456                      count && tones && options==0, PJ_EINVAL); 
     513                     count && tones, PJ_EINVAL); 
    457514 
    458515    /* Don't put more than available buffer */ 
     
    460517                     PJ_ETOOMANY); 
    461518 
     519    /* Set playback options */ 
     520    tonegen->playback_options = options; 
     521     
    462522    /* Copy digits */ 
    463523    pj_memcpy(tonegen->digits + tonegen->count, 
     
    493553 
    494554    PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE && 
    495                      count && digits && options==0, PJ_EINVAL); 
     555                     count && digits, PJ_EINVAL); 
    496556    PJ_ASSERT_RETURN(count < PJMEDIA_TONEGEN_MAX_DIGITS, PJ_ETOOMANY); 
    497557 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r903 r904  
    6161    unsigned                wav_count; 
    6262    pj_str_t                wav_files[32]; 
     63    unsigned                tone_count; 
     64    pjmedia_tone_desc       tones[32]; 
     65    pjsua_conf_port_id      tone_slots[32]; 
    6366    pjsua_player_id         wav_id; 
    6467    pjsua_conf_port_id      wav_port; 
     
    159162    puts  ("  --clock-rate=N      Override sound device clock rate"); 
    160163    puts  ("  --null-audio        Use NULL audio device"); 
    161     puts  ("  --play-file=file    Register WAV file in conference bridge"); 
     164    puts  ("  --play-file=file    Register WAV file in conference bridge."); 
     165    puts  ("                      This can be specified multiple times."); 
     166    puts  ("  --play-tone=F1,F2,ON,OFF    Register tone to the conference bridge."); 
     167    puts  ("                      f1,f2=frequency, on,off=on/off duration in msec."); 
     168    puts  ("                      This can be specified multiple times."); 
    162169    puts  ("  --auto-play         Automatically play the file (to incoming calls only)"); 
    163170    puts  ("  --auto-loop         Automatically loop incoming RTP to outgoing RTP"); 
     
    310317           OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP, 
    311318           OPT_AUTO_CONF, OPT_CLOCK_RATE, 
    312            OPT_PLAY_FILE, OPT_RTP_PORT, OPT_ADD_CODEC, OPT_ILBC_MODE, 
    313            OPT_REC_FILE, OPT_AUTO_REC, 
     319           OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC,  
     320           OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC, 
    314321           OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, OPT_NO_VAD, 
    315322           OPT_RX_DROP_PCT, OPT_TX_DROP_PCT, OPT_EC_TAIL, 
     
    358365        { "auto-conf",  0, 0, OPT_AUTO_CONF}, 
    359366        { "play-file",  1, 0, OPT_PLAY_FILE}, 
     367        { "play-tone",  1, 0, OPT_PLAY_TONE}, 
    360368        { "rec-file",   1, 0, OPT_REC_FILE}, 
    361369        { "rtp-port",   1, 0, OPT_RTP_PORT}, 
     
    682690            break; 
    683691 
     692        case OPT_PLAY_TONE: 
     693            { 
     694                int f1, f2, on, off; 
     695                int n; 
     696 
     697                n = sscanf(pj_optarg, "%d,%d,%d,%d", &f1, &f2, &on, &off); 
     698                if (n != 4) { 
     699                    puts("Expecting f1,f2,on,off in --play-tone"); 
     700                    return -1; 
     701                } 
     702 
     703                cfg->tones[cfg->tone_count].freq1 = (short)f1; 
     704                cfg->tones[cfg->tone_count].freq2 = (short)f2; 
     705                cfg->tones[cfg->tone_count].on_msec = (short)on; 
     706                cfg->tones[cfg->tone_count].off_msec = (short)off; 
     707                ++cfg->tone_count; 
     708            } 
     709            break; 
     710 
    684711        case OPT_REC_FILE: 
    685712            cfg->rec_file = pj_str(pj_optarg); 
     
    11351162        pj_ansi_sprintf(line, "--play-file %s\n", 
    11361163                        config->wav_files[i].ptr); 
     1164        pj_strcat2(&cfg, line); 
     1165    } 
     1166    for (i=0; i<config->tone_count; ++i) { 
     1167        pj_ansi_sprintf(line, "--play-tone %d,%d,%d,%d\n", 
     1168                        config->tones[i].freq1, config->tones[i].freq2,  
     1169                        config->tones[i].on_msec, config->tones[i].off_msec); 
    11371170        pj_strcat2(&cfg, line); 
    11381171    } 
     
    29262959    } 
    29272960 
     2961    /* Optionally registers tone players */ 
     2962    for (i=0; i<app_config.tone_count; ++i) { 
     2963        pjmedia_port *tport; 
     2964        char name[80]; 
     2965        pj_str_t label; 
     2966        pj_status_t status; 
     2967 
     2968        pj_ansi_snprintf(name, sizeof(name), "tone-%d,%d", 
     2969                         app_config.tones[i].freq1,  
     2970                         app_config.tones[i].freq2); 
     2971        label = pj_str(name); 
     2972        status = pjmedia_tonegen_create2(app_config.pool, &label, 
     2973                                         8000, 1, 160, 16,  
     2974                                         PJMEDIA_TONEGEN_LOOP,  &tport); 
     2975        if (status != PJ_SUCCESS) { 
     2976            pjsua_perror(THIS_FILE, "Unable to create tone generator", status); 
     2977            goto on_error; 
     2978        } 
     2979 
     2980        status = pjsua_conf_add_port(app_config.pool, tport,  
     2981                                     &app_config.tone_slots[i]); 
     2982        pj_assert(status == PJ_SUCCESS); 
     2983 
     2984        status = pjmedia_tonegen_play(tport, 1, &app_config.tones[i], 0); 
     2985        pj_assert(status == PJ_SUCCESS); 
     2986    } 
     2987 
    29282988    /* Optionally create recorder file, if any. */ 
    29292989    if (app_config.rec_file.slen) { 
     
    30573117{ 
    30583118    pj_status_t status; 
     3119    unsigned i; 
    30593120 
    30603121#ifdef STEREO_DEMO 
     
    30643125    } 
    30653126#endif 
     3127 
     3128    /* Close tone generators */ 
     3129    for (i=0; i<app_config.tone_count; ++i) { 
     3130        pjsua_conf_remove_port(app_config.tone_slots[i]); 
     3131    } 
    30663132 
    30673133    if (app_config.pool) { 
Note: See TracChangeset for help on using the changeset viewer.