Changeset 2212 for pjproject


Ignore:
Timestamp:
Aug 13, 2008 6:21:03 PM (16 years ago)
Author:
bennylp
Message:

More ticket #590: optimizations in the echo suppressor, gained more than 3x speed. Added entries in mips_test

Location:
pjproject/trunk/pjmedia/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/echo_suppress.c

    r2208 r2212  
    244244    float        best_corr;         /* Best correlation so far.             */ 
    245245 
     246    unsigned     sum_rec_level;     /* Running sum of level in rec_hist     */ 
     247    float        rec_corr;          /* Running corr in rec_hist.            */ 
     248 
     249    unsigned     sum_play_level0;   /* Running sum of level for first pos   */ 
     250    float        play_corr0;        /* Running corr for first pos .         */ 
     251 
    246252    float       *min_factor;        /* Array of minimum scaling factor      */ 
    247253    float       *avg_factor;        /* Array of average scaling factor      */ 
     
    354360    ec->residue = 0; 
    355361    ec->running_cnt = 0; 
     362    ec->sum_rec_level = ec->sum_play_level0 = 0; 
     363    ec->rec_corr = ec->play_corr0 = 0; 
    356364} 
    357365 
     
    376384    ec->residue = 0; 
    377385    ec->running_cnt = 0; 
     386    ec->sum_rec_level = ec->sum_play_level0 = 0; 
     387    ec->rec_corr = ec->play_corr0 = 0; 
    378388 
    379389    PJ_LOG(4,(THIS_FILE, "Echo suppressor soft reset. Re-learning..")); 
     
    404414{ 
    405415    int prev_index; 
    406     unsigned i, frm_level, sum_rec_level; 
    407     float rec_corr; 
     416    unsigned i, j, frm_level, sum_play_level, ulaw; 
     417    pj_uint16_t old_rec_frm_level, old_play_frm_level; 
     418    float play_corr; 
    408419 
    409420    ++ec->update_cnt; 
     
    415426    ++frm_level; /* to avoid division by zero */ 
    416427 
     428    /* Save the oldest frame level for later */ 
     429    old_play_frm_level = ec->play_hist[0]; 
     430 
    417431    /* Push current frame level to the back of the play history */ 
    418432    pj_array_erase(ec->play_hist, sizeof(pj_uint16_t), ec->play_hist_cnt, 0); 
     
    423437    ++frm_level; /* to avoid division by zero */ 
    424438 
     439    /* Save the oldest frame level for later */ 
     440    old_rec_frm_level = ec->rec_hist[0]; 
     441 
    425442    /* Push to the back of the rec history */ 
    426443    pj_array_erase(ec->rec_hist, sizeof(pj_uint16_t), ec->templ_cnt, 0); 
     
    438455 
    439456    /* Calculate rec signal pattern */ 
    440     rec_corr = 0; 
    441     sum_rec_level = 0; 
    442     for (i=0; i < ec->templ_cnt-1; ++i) { 
    443         float corr; 
    444         corr = (float)ec->rec_hist[i+1] / ec->rec_hist[i]; 
    445         rec_corr += corr; 
    446         sum_rec_level += ec->rec_hist[i]; 
    447     } 
    448     sum_rec_level += ec->rec_hist[i]; 
     457    if (ec->sum_rec_level == 0) { 
     458        /* Buffer has just been filled up, do full calculation */ 
     459        ec->rec_corr = 0; 
     460        ec->sum_rec_level = 0; 
     461        for (i=0; i < ec->templ_cnt-1; ++i) { 
     462            float corr; 
     463            corr = (float)ec->rec_hist[i+1] / ec->rec_hist[i]; 
     464            ec->rec_corr += corr; 
     465            ec->sum_rec_level += ec->rec_hist[i]; 
     466        } 
     467        ec->sum_rec_level += ec->rec_hist[i]; 
     468    } else { 
     469        /* Update from previous calculation */ 
     470        ec->sum_rec_level = ec->sum_rec_level - old_rec_frm_level +  
     471                            ec->rec_hist[ec->templ_cnt-1]; 
     472        ec->rec_corr = ec->rec_corr - ((float)ec->rec_hist[0] /  
     473                                              old_rec_frm_level) + 
     474                       ((float)ec->rec_hist[ec->templ_cnt-1] / 
     475                               ec->rec_hist[ec->templ_cnt-2]); 
     476    } 
    449477 
    450478    /* Iterate through the play history and calculate the signal correlation 
     
    453481     * to detect echo. 
    454482     */ 
    455     for (i=0; i < ec->tail_cnt; ++i) { 
    456         unsigned j, end, sum_play_level, ulaw; 
    457         float play_corr = 0, corr_diff; 
    458  
     483    /*  
     484     * First phase: do full calculation for the first position  
     485     */ 
     486    if (ec->sum_play_level0 == 0) { 
     487        /* Buffer has just been filled up, do full calculation */ 
    459488        sum_play_level = 0; 
    460         for (j=i, end=i+ec->templ_cnt-1; j<end; ++j) { 
     489        play_corr = 0; 
     490        for (j=0; j<ec->templ_cnt-1; ++j) { 
    461491            float corr; 
    462492            corr = (float)ec->play_hist[j+1] / ec->play_hist[j]; 
     
    465495        } 
    466496        sum_play_level += ec->play_hist[j]; 
     497        ec->sum_play_level0 = sum_play_level; 
     498        ec->play_corr0 = play_corr; 
     499    } else { 
     500        /* Update from previous calculation */ 
     501        ec->sum_play_level0 = ec->sum_play_level0 - old_play_frm_level +  
     502                              ec->play_hist[ec->templ_cnt-1]; 
     503        ec->play_corr0 = ec->play_corr0 - ((float)ec->play_hist[0] /  
     504                                                  old_play_frm_level) + 
     505                         ((float)ec->play_hist[ec->templ_cnt-1] / 
     506                                 ec->play_hist[ec->templ_cnt-2]); 
     507        sum_play_level = ec->sum_play_level0; 
     508        play_corr = ec->play_corr0; 
     509    } 
     510    ec->tmp_corr[0] = FABS(play_corr - ec->rec_corr); 
     511    ec->tmp_factor[0] = (float)ec->sum_rec_level / sum_play_level; 
     512 
     513    /* Bail out if remote isn't talking */ 
     514    ulaw = pjmedia_linear2ulaw(sum_play_level/ec->templ_cnt) ^ 0xFF; 
     515    if (ulaw < MIN_SIGNAL_ULAW) { 
     516        echo_supp_set_state(ec, ST_REM_SILENT, ulaw); 
     517        return; 
     518    } 
     519    /* Bail out if local user is talking */ 
     520    if (ec->sum_rec_level > sum_play_level) { 
     521        echo_supp_set_state(ec, ST_LOCAL_TALK, ulaw); 
     522        return; 
     523    } 
     524 
     525    /* 
     526     * Second phase: do incremental calculation for the rest of positions 
     527     */ 
     528    for (i=1; i < ec->tail_cnt; ++i) { 
     529        unsigned end; 
     530 
     531        end = i + ec->templ_cnt; 
     532 
     533        sum_play_level = sum_play_level - ec->play_hist[i-1] + 
     534                         ec->play_hist[end-1]; 
     535        play_corr = play_corr - ((float)ec->play_hist[i]/ec->play_hist[i-1]) + 
     536                    ((float)ec->play_hist[end-1]/ec->play_hist[end-2]); 
    467537 
    468538        /* Bail out if remote isn't talking */ 
     
    474544 
    475545        /* Bail out if local user is talking */ 
    476         if (sum_rec_level >= sum_play_level) { 
     546        if (ec->sum_rec_level > sum_play_level) { 
    477547            echo_supp_set_state(ec, ST_LOCAL_TALK, ulaw); 
    478548            return; 
     
    482552        // disabled: not a good idea if mic throws out loud echo 
    483553        /* Also bail out if we suspect there's a doubletalk */ 
    484         ulaw = pjmedia_linear2ulaw(sum_rec_level/ec->templ_cnt) ^ 0xFF; 
     554        ulaw = pjmedia_linear2ulaw(ec->sum_rec_level/ec->templ_cnt) ^ 0xFF; 
    485555        if (ulaw > MIN_SIGNAL_ULAW) { 
    486556            echo_supp_set_state(ec, ST_DOUBLETALK, ulaw); 
     
    490560 
    491561        /* Calculate correlation and save to temporary array */ 
    492         corr_diff = FABS(play_corr - rec_corr); 
    493         ec->tmp_corr[i] = corr_diff; 
     562        ec->tmp_corr[i] = FABS(play_corr - ec->rec_corr); 
    494563 
    495564        /* Also calculate the gain factor between mic and speaker level */ 
    496         ec->tmp_factor[i] = (float)sum_rec_level / sum_play_level; 
     565        ec->tmp_factor[i] = (float)ec->sum_rec_level / sum_play_level; 
    497566        pj_assert(ec->tmp_factor[i] < 1); 
    498567    } 
     
    653722                factor = 1.0; 
    654723                echo_supp_set_state(ec, ST_LOCAL_TALK, rec_level); 
    655             } else if (rec_level >= play_level) { 
     724            } else if (rec_level > play_level) { 
    656725                /* Seems that both are talking. Scale the mic signal 
    657726                 * down a little bit to reduce echo, while allowing both 
     
    689758            factor = (factor + ec->last_factor) / 2; 
    690759        else 
    691             factor = (factor + ec->last_factor*9) / 10; 
     760            factor = (factor + ec->last_factor*19) / 20; 
    692761 
    693762        /* Amplify frame */ 
  • pjproject/trunk/pjmedia/src/test/mips_test.c

    r2192 r2212  
    5252    */ 
    5353 
    54 //#   define CPU_MHZ        (2666) 
    55 //#   define CPU_IPS        (CPU_MHZ * MEGA * 3.039)    /* P4 2.6GHz    */ 
    56  
    57 #   define CPU_MHZ          700 
    58 #   define CPU_IPS          (700 * MEGA * 2.708)        /* P3 700Mhz    */ 
     54#   define CPU_MHZ          (2666) 
     55#   define CPU_IPS          (3.039 * CPU_MHZ * MEGA)    /* P4 2.6GHz    */ 
     56 
     57//#   define CPU_MHZ        700 
     58//#   define CPU_IPS        (700 * MEGA * 2.708)        /* P3 700Mhz    */ 
    5959 
    6060//#   define CPU_MHZ        180 
    6161//#   define CPU_IPS        (CPU_MHZ * MEGA * 1.1)      /* ARM926EJ-S */ 
     62 
     63//#   define CPU_MHZ        312 
     64//#   define CPU_IPS        (CPU_MHZ * MEGA * 1.282)    /* Dell Axim PDA */ 
     65 
    6266#endif 
    6367 
     
    357361 
    358362#define THIS_FILE           "mips_test.c" 
    359 #define DURATION            1000 
     363#define DURATION            5000 
    360364#define PTIME               20  /* MUST be 20! */ 
    361365#define MEGA                1000000 
     
    12641268    pj_status_t status; 
    12651269 
    1266     PJ_UNUSED_ARG(flags); 
    12671270    PJ_UNUSED_ARG(te); 
    12681271 
     
    12731276 
    12741277    status = pjmedia_echo_port_create(pool, gen_port, ec_tail_msec, 0, 
    1275                                       0, &ec_port); 
     1278                                      flags, &ec_port); 
    12761279    if (status != PJ_SUCCESS) 
    12771280        return NULL; 
     
    12881291                                   struct test_entry *te) 
    12891292{ 
     1293    flags = 0; 
    12901294    return ec_create(100, pool, clock_rate, channel_count, samples_per_frame, 
    12911295                     flags, te); 
     
    13001304                                   struct test_entry *te) 
    13011305{ 
     1306    flags = 0; 
    13021307    return ec_create(128, pool, clock_rate, channel_count, samples_per_frame, 
    13031308                     flags, te); 
     
    13121317                                   struct test_entry *te) 
    13131318{ 
     1319    flags = 0; 
    13141320    return ec_create(200, pool, clock_rate, channel_count, samples_per_frame, 
    13151321                     flags, te); 
     
    13241330                                   struct test_entry *te) 
    13251331{ 
     1332    flags = 0; 
    13261333    return ec_create(256, pool, clock_rate, channel_count, samples_per_frame, 
    13271334                     flags, te); 
     
    13371344                                   struct test_entry *te) 
    13381345{ 
     1346    flags = 0; 
    13391347    return ec_create(400, pool, clock_rate, channel_count, samples_per_frame, 
    13401348                     flags, te); 
     
    13491357                                   struct test_entry *te) 
    13501358{ 
     1359    flags = 0; 
    13511360    return ec_create(500, pool, clock_rate, channel_count, samples_per_frame, 
    13521361                     flags, te); 
     
    13611370                                   struct test_entry *te) 
    13621371{ 
     1372    flags = 0; 
    13631373    return ec_create(512, pool, clock_rate, channel_count, samples_per_frame, 
    13641374                     flags, te); 
     
    13731383                                   struct test_entry *te) 
    13741384{ 
     1385    flags = 0; 
    13751386    return ec_create(600, pool, clock_rate, channel_count, samples_per_frame, 
    13761387                     flags, te); 
     
    13851396                                   struct test_entry *te) 
    13861397{ 
     1398    flags = 0; 
     1399    return ec_create(800, pool, clock_rate, channel_count, samples_per_frame, 
     1400                     flags, te); 
     1401} 
     1402 
     1403 
     1404 
     1405/* Echo suppressor with 100ms tail length */ 
     1406static pjmedia_port* es_create_100(pj_pool_t *pool, 
     1407                                   unsigned clock_rate, 
     1408                                   unsigned channel_count, 
     1409                                   unsigned samples_per_frame, 
     1410                                   unsigned flags, 
     1411                                   struct test_entry *te) 
     1412{ 
     1413    flags = PJMEDIA_ECHO_SIMPLE; 
     1414    return ec_create(100, pool, clock_rate, channel_count, samples_per_frame, 
     1415                     flags, te); 
     1416} 
     1417 
     1418/* Echo suppressor with 128ms tail length */ 
     1419static pjmedia_port* es_create_128(pj_pool_t *pool, 
     1420                                   unsigned clock_rate, 
     1421                                   unsigned channel_count, 
     1422                                   unsigned samples_per_frame, 
     1423                                   unsigned flags, 
     1424                                   struct test_entry *te) 
     1425{ 
     1426    flags = PJMEDIA_ECHO_SIMPLE; 
     1427    return ec_create(128, pool, clock_rate, channel_count, samples_per_frame, 
     1428                     flags, te); 
     1429} 
     1430 
     1431/* Echo suppressor with 200ms tail length */ 
     1432static pjmedia_port* es_create_200(pj_pool_t *pool, 
     1433                                   unsigned clock_rate, 
     1434                                   unsigned channel_count, 
     1435                                   unsigned samples_per_frame, 
     1436                                   unsigned flags, 
     1437                                   struct test_entry *te) 
     1438{ 
     1439    flags = PJMEDIA_ECHO_SIMPLE; 
     1440    return ec_create(200, pool, clock_rate, channel_count, samples_per_frame, 
     1441                     flags, te); 
     1442} 
     1443 
     1444/* Echo suppressor with 256ms tail length */ 
     1445static pjmedia_port* es_create_256(pj_pool_t *pool, 
     1446                                   unsigned clock_rate, 
     1447                                   unsigned channel_count, 
     1448                                   unsigned samples_per_frame, 
     1449                                   unsigned flags, 
     1450                                   struct test_entry *te) 
     1451{ 
     1452    flags = PJMEDIA_ECHO_SIMPLE; 
     1453    return ec_create(256, pool, clock_rate, channel_count, samples_per_frame, 
     1454                     flags, te); 
     1455} 
     1456 
     1457 
     1458/* Echo suppressor with 400ms tail length */ 
     1459static pjmedia_port* es_create_400(pj_pool_t *pool, 
     1460                                   unsigned clock_rate, 
     1461                                   unsigned channel_count, 
     1462                                   unsigned samples_per_frame, 
     1463                                   unsigned flags, 
     1464                                   struct test_entry *te) 
     1465{ 
     1466    flags = PJMEDIA_ECHO_SIMPLE; 
     1467    return ec_create(400, pool, clock_rate, channel_count, samples_per_frame, 
     1468                     flags, te); 
     1469} 
     1470 
     1471/* Echo suppressor with 500ms tail length */ 
     1472static pjmedia_port* es_create_500(pj_pool_t *pool, 
     1473                                   unsigned clock_rate, 
     1474                                   unsigned channel_count, 
     1475                                   unsigned samples_per_frame, 
     1476                                   unsigned flags, 
     1477                                   struct test_entry *te) 
     1478{ 
     1479    flags = PJMEDIA_ECHO_SIMPLE; 
     1480    return ec_create(500, pool, clock_rate, channel_count, samples_per_frame, 
     1481                     flags, te); 
     1482} 
     1483 
     1484/* Echo suppressor with 512ms tail length */ 
     1485static pjmedia_port* es_create_512(pj_pool_t *pool, 
     1486                                   unsigned clock_rate, 
     1487                                   unsigned channel_count, 
     1488                                   unsigned samples_per_frame, 
     1489                                   unsigned flags, 
     1490                                   struct test_entry *te) 
     1491{ 
     1492    flags = PJMEDIA_ECHO_SIMPLE; 
     1493    return ec_create(512, pool, clock_rate, channel_count, samples_per_frame, 
     1494                     flags, te); 
     1495} 
     1496 
     1497/* Echo suppressor with 600ms tail length */ 
     1498static pjmedia_port* es_create_600(pj_pool_t *pool, 
     1499                                   unsigned clock_rate, 
     1500                                   unsigned channel_count, 
     1501                                   unsigned samples_per_frame, 
     1502                                   unsigned flags, 
     1503                                   struct test_entry *te) 
     1504{ 
     1505    flags = PJMEDIA_ECHO_SIMPLE; 
     1506    return ec_create(600, pool, clock_rate, channel_count, samples_per_frame, 
     1507                     flags, te); 
     1508} 
     1509 
     1510/* Echo suppressor with 800ms tail length */ 
     1511static pjmedia_port* es_create_800(pj_pool_t *pool, 
     1512                                   unsigned clock_rate, 
     1513                                   unsigned channel_count, 
     1514                                   unsigned samples_per_frame, 
     1515                                   unsigned flags, 
     1516                                   struct test_entry *te) 
     1517{ 
     1518    flags = PJMEDIA_ECHO_SIMPLE; 
    13871519    return ec_create(800, pool, clock_rate, channel_count, samples_per_frame, 
    13881520                     flags, te); 
     
    21292261        { "echo canceller 600ms tail len", OP_GET_PUT, K8|K16, &ec_create_600}, 
    21302262        { "echo canceller 800ms tail len", OP_GET_PUT, K8|K16, &ec_create_800}, 
     2263        { "echo suppressor 100ms tail len", OP_GET_PUT, K8|K16, &es_create_100}, 
     2264        { "echo suppressor 128ms tail len", OP_GET_PUT, K8|K16, &es_create_128}, 
     2265        { "echo suppressor 200ms tail len", OP_GET_PUT, K8|K16, &es_create_200}, 
     2266        { "echo suppressor 256ms tail len", OP_GET_PUT, K8|K16, &es_create_256}, 
     2267        { "echo suppressor 400ms tail len", OP_GET_PUT, K8|K16, &es_create_400}, 
     2268        { "echo suppressor 500ms tail len", OP_GET_PUT, K8|K16, &es_create_500}, 
     2269        { "echo suppressor 512ms tail len", OP_GET_PUT, K8|K16, &es_create_512}, 
     2270        { "echo suppressor 600ms tail len", OP_GET_PUT, K8|K16, &es_create_600}, 
     2271        { "echo suppressor 800ms tail len", OP_GET_PUT, K8|K16, &es_create_800}, 
    21312272        { "tone generator with single freq", OP_GET, K8|K16, &create_tonegen1}, 
    21322273        { "tone generator with dual freq", OP_GET, K8|K16, &create_tonegen2}, 
     
    21962337                    pj_elapsed_usec(&tzero, &times[1])) / 2; 
    21972338 
     2339            usec = usec / (DURATION / 1000); 
     2340 
    21982341            mips = (float)(CPU_IPS * usec / 1000000.0 / 1000000); 
    21992342            cpu_pct = (float)(100.0 * usec / 1000000); 
Note: See TracChangeset for help on using the changeset viewer.