Changeset 1691
- Timestamp:
- Jan 14, 2008 4:18:37 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r1637 r1691 72 72 * in the port does not cause misaligned signal (which causes noise). 73 73 */ 74 #if 1 75 # define ATTACK_A 10 76 # define ATTACK_B 2 77 # define DECAY_A 10 78 # define DECAY_B 2 79 #else 80 /* To simulate old behavior */ 81 # define ATTACK_A 0 82 # define ATTACK_B 1 83 # define DECAY_A 0 84 # define DECAY_B 1 85 #endif 86 74 #define ATTACK_A (conf->clock_rate / conf->samples_per_frame) 75 #define ATTACK_B 1 76 #define DECAY_A 0 77 #define DECAY_B 1 78 79 #define SIMPLE_AGC(last, target) \ 80 if (target >= last) \ 81 target = (ATTACK_A*(last+1)+ATTACK_B*target)/(ATTACK_A+ATTACK_B); \ 82 else \ 83 target = (DECAY_A*last+DECAY_B*target)/(DECAY_A+DECAY_B) 84 85 #define MAX_LEVEL (32767) 86 #define MIN_LEVEL (-32768) 87 88 #define IS_OVERFLOW(s) ((s > MAX_LEVEL) || (s < MIN_LEVEL)) 87 89 88 90 … … 114 116 unsigned clock_rate; /**< Port's clock rate. */ 115 117 unsigned samples_per_frame; /**< Port's samples per frame. */ 116 117 /* Last level calculated from this port */118 pj_int32_t last_level;119 118 120 119 /* Calculated signal levels: */ … … 149 148 unsigned rx_buf_count; /**< # of samples in the buf. */ 150 149 151 /* Mix buf is a temporary buffer used to calculate the average signal 152 * received by this port from all other ports. Samples from all ports 153 * that are transmitting to this port will be accumulated here, then 154 * they will be divided by the source level before the samples are put 155 * to the TX buffer of this port. 150 /* Mix buf is a temporary buffer used to mix all signal received 151 * by this port from all other ports. The mixed signal will be 152 * automatically adjusted to the appropriate level whenever 153 * there is possibility of clipping. 156 154 * 157 155 * This buffer contains samples at bridge's clock rate. 158 156 * The size of this buffer is equal to samples per frame of the bridge. 159 * 160 * Note that the samples here are unsigned 32bit. 161 */ 162 unsigned src_level; /**< Sum of input levels */ 163 unsigned src_cnt; /**< Number of sources. */ 164 pj_uint32_t *mix_buf; /**< Total sum of signal. */ 157 */ 158 159 int mix_adj; /**< Adjustment level for mix_buf. */ 160 int last_mix_adj; /**< Last adjustment level. */ 161 pj_int32_t *mix_buf; /**< Total sum of signal. */ 165 162 166 163 /* Tx buffer is a temporary buffer to be used when there's mismatch … … 209 206 pj_mutex_t *mutex; /**< Conference mutex. */ 210 207 struct conf_port **ports; /**< Array of ports. */ 211 pj_uint16_t *uns_buf; /**< Buf for unsigned conversion */212 208 unsigned clock_rate; /**< Sampling rate. */ 213 209 unsigned channel_count;/**< Number of channels (1=mono). */ … … 353 349 354 350 /* Create mix buffer. */ 355 conf_port->mix_buf = (pj_ uint32_t*)351 conf_port->mix_buf = (pj_int32_t*) 356 352 pj_pool_zalloc(pool, conf->samples_per_frame * 357 353 sizeof(conf_port->mix_buf[0])); 358 354 PJ_ASSERT_RETURN(conf_port->mix_buf, PJ_ENOMEM); 355 conf_port->last_mix_adj = NORMAL_LEVEL; 359 356 360 357 … … 527 524 if (status != PJ_SUCCESS) 528 525 return status; 529 530 /* Create temporary buffer. */531 conf->uns_buf = (pj_uint16_t*)532 pj_pool_zalloc(pool, samples_per_frame *533 sizeof(conf->uns_buf[0]));534 526 535 527 /* Create mutex. */ … … 1232 1224 1233 1225 1234 /* Convert signed 16bit pcm sample to unsigned 16bit sample */1235 static pj_uint16_t pcm2unsigned(pj_int32_t pcm)1236 {1237 return (pj_uint16_t)(pcm + 32768);1238 }1239 1240 /* Convert unsigned 16bit sample to signed 16bit pcm sample */1241 static pj_int16_t unsigned2pcm(pj_uint32_t uns)1242 {1243 return (pj_int16_t)(uns - 32768);1244 }1245 1246 1247 1226 /* 1248 1227 * Read from port. … … 1378 1357 unsigned j, ts; 1379 1358 pj_status_t status; 1359 pj_int32_t adj_level; 1360 pj_int32_t tx_level; 1380 1361 1381 1362 *frm_type = PJMEDIA_FRAME_TYPE_AUDIO; … … 1403 1384 return PJ_SUCCESS; 1404 1385 1405 } else if (cport->src_level==0) {1406 1407 pjmedia_frame frame;1408 1409 /* If silence is transmitted to this port, transmit silence1410 * PCM frame (otherwise if we transmit NULL frame, nothing will1411 * be written to WAV port). This would work with stream too1412 * since stream has it's own silence detector.1413 */1414 pjmedia_zero_samples((pj_int16_t*)cport->mix_buf,1415 cport->samples_per_frame);1416 1417 /* Adjust the timestamp */1418 frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /1419 conf->clock_rate;1420 frame.type = PJMEDIA_FRAME_TYPE_NONE;1421 frame.buf = (void*)cport->mix_buf;1422 frame.size = (cport->samples_per_frame << 1);1423 1424 if (cport->port && cport->port->put_frame) {1425 pjmedia_port_put_frame(cport->port, &frame);1426 }1427 1428 cport->tx_level = 0;1429 *frm_type = PJMEDIA_FRAME_TYPE_NONE;1430 return PJ_SUCCESS;1431 1432 1433 1386 } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { 1434 1387 cport->tx_level = 0; … … 1437 1390 } 1438 1391 1439 buf = (pj_int16_t*)cport->mix_buf; 1440 1441 /* This is the convention set in get_frame(). For optimization purpose, 1442 * if we only have one transmitter transmitting to this port, then 1443 * the transmitter will directly copy the original 16bit frame to 1444 * mix_buf. 1445 */ 1446 if (cport->transmitter_cnt==1 && cport->src_cnt == 1) { 1447 1448 /* But still see if we need to adjust the level */ 1449 if (cport->tx_adj_level != NORMAL_LEVEL) { 1450 pj_int16_t *input = buf; 1451 pj_int32_t adj = cport->tx_adj_level; 1452 1453 for (j=0; j<conf->samples_per_frame; ++j) { 1454 pj_int32_t itemp; 1455 1456 /* For the level adjustment, we need to store the sample to 1457 * a temporary 32bit integer value to avoid overflowing the 1458 * 16bit sample storage. 1459 */ 1460 itemp = input[j]; 1461 /*itemp = itemp * adj / NORMAL_LEVEL; */ 1462 itemp = (itemp * adj) >> 7; 1463 1464 /* Clip the signal if it's too loud */ 1465 if (itemp > 32767) itemp = 32767; 1466 else if (itemp < -32768) itemp = -32768; 1467 1468 input[j] = (pj_int16_t) itemp; 1469 } 1470 } 1471 1472 } 1392 buf = (pj_int16_t*) cport->mix_buf; 1393 1473 1394 /* If there are sources in the mix buffer, convert the mixed samples 1474 * to the mixed samples itself. This is possible because mixed sample1475 * is 32bit.1395 * from 32bit to 16bit in the mixed samples itself. This is possible 1396 * because mixed sample is 32bit. 1476 1397 * 1477 1398 * In addition to this process, if we need to change the level of 1478 1399 * TX signal, we adjust is here too. 1479 1400 */ 1480 else if (cport->tx_adj_level != NORMAL_LEVEL && cport->src_level) { 1481 1482 pj_int32_t adj_level = cport->tx_adj_level; 1483 1484 /* We need to adjust signal level. */ 1485 for (j=0; j<conf->samples_per_frame; ++j) { 1486 pj_int32_t itemp; 1487 1488 /* Calculate average level, and convert the sample to 1489 * 16bit signed integer. 1490 */ 1491 itemp = unsigned2pcm(cport->mix_buf[j] / cport->src_level); 1401 1402 /* Calculate signal level and adjust the signal when needed. 1403 * Two adjustments performed at once: 1404 * 1. user setting adjustment (tx_adj_level). 1405 * 2. automatic adjustment of overflowed mixed buffer (mix_adj). 1406 */ 1407 1408 /* Apply simple AGC to the mix_adj, the automatic adjust, to avoid 1409 * dramatic change in the level thus causing noise because the signal 1410 * is now not aligned with the signal from the previous frame. 1411 */ 1412 SIMPLE_AGC(cport->last_mix_adj, cport->mix_adj); 1413 cport->last_mix_adj = cport->mix_adj; 1414 1415 adj_level = cport->tx_adj_level * cport->mix_adj / NORMAL_LEVEL; 1416 tx_level = 0; 1417 1418 for (j=0; j<conf->samples_per_frame; ++j) { 1419 if (adj_level != NORMAL_LEVEL) { 1420 pj_int32_t itemp = cport->mix_buf[j]; 1492 1421 1493 1422 /* Adjust the level */ … … 1496 1425 1497 1426 /* Clip the signal if it's too loud */ 1498 if (itemp > 32767) itemp = 32767;1499 else if (itemp < -32768) itemp = -32768;1427 if (itemp > MAX_LEVEL) itemp = MAX_LEVEL; 1428 else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL; 1500 1429 1501 1430 /* Put back in the buffer. */ 1502 1431 buf[j] = (pj_int16_t) itemp; 1432 } else { 1433 buf[j] = (pj_int16_t) cport->mix_buf[j]; 1503 1434 } 1504 1435 1505 } else if (cport->src_level) { 1506 /* No need to adjust signal level. */ 1507 for (j=0; j<conf->samples_per_frame; ++j) { 1508 buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->src_level); 1509 } 1510 } else { 1511 // Not necessarry. Buffer has been zeroed before. 1512 // pjmedia_zero_samples(buf, conf->samples_per_frame); 1513 //pj_assert(buf[0] == 0); 1514 1515 // This shouldn't happen. Function should've already bailed out when 1516 // cport->src_level == 0. 1517 pj_assert(0); 1518 } 1519 1520 /* Calculate TX level if we need to do so. 1521 * This actually is not the most correct place to calculate TX signal 1522 * level of the port; it should calculate the level of the actual 1523 * frame just before put_frame() is called. 1524 * But doing so would make the code more complicated than it is 1525 * necessary, since the purpose of level calculation mostly is just 1526 * for VU meter display. By doing it here, it should give the acceptable 1527 * indication of the signal level of the port. 1528 */ 1529 if (cport->src_cnt) { 1530 cport->tx_level = cport->src_level / cport->src_cnt; 1531 } else { 1532 cport->tx_level = 0; 1533 } 1436 tx_level += (buf[j]>0? buf[j] : -buf[j]); 1437 } 1438 1439 tx_level /= conf->samples_per_frame; 1440 1441 /* Convert level to 8bit complement ulaw */ 1442 tx_level = pjmedia_linear2ulaw(tx_level) ^ 0xff; 1443 1444 cport->tx_level = tx_level; 1534 1445 1535 1446 /* If port has the same clock_rate and samples_per_frame settings as … … 1543 1454 1544 1455 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 1545 frame.buf = (pj_int16_t*)cport->mix_buf;1456 frame.buf = buf; 1546 1457 frame.size = conf->samples_per_frame * BYTES_PER_SAMPLE; 1547 1458 /* No need to adjust timestamp, port has the same … … 1640 1551 pjmedia_frame_type speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE; 1641 1552 unsigned ci, cj, i, j; 1553 pj_int16_t *p_in; 1642 1554 1643 1555 TRACE_((THIS_FILE, "- clock -")); … … 1662 1574 ++ci; 1663 1575 1664 /* Reset sources */ 1665 conf_port->src_level = 0; 1666 conf_port->src_cnt = 0; 1576 /* Reset buffer & auto adjustment level for mixed signal */ 1577 conf_port->mix_adj = NORMAL_LEVEL; 1578 if (conf_port->transmitter_cnt) { 1579 pj_bzero(conf_port->mix_buf, 1580 conf->samples_per_frame*sizeof(conf_port->mix_buf[0])); 1581 } 1667 1582 } 1668 1583 … … 1672 1587 for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 1673 1588 struct conf_port *conf_port = conf->ports[i]; 1674 pj_int32_t level ;1589 pj_int32_t level = 0; 1675 1590 1676 1591 /* Skip empty port. */ … … 1747 1662 } 1748 1663 1749 /* If we need to adjust the RX level from this port, adjust the level 1664 p_in = (pj_int16_t*) frame->buf; 1665 1666 /* Adjust the RX level from this port 1750 1667 * and calculate the average level at the same time. 1751 * Otherwise just calculate the averate level.1752 1668 */ 1753 if (conf_port->rx_adj_level != NORMAL_LEVEL) { 1754 pj_int16_t *input = (pj_int16_t*) frame->buf; 1755 pj_int32_t adj = conf_port->rx_adj_level; 1756 1757 level = 0; 1758 for (j=0; j<conf->samples_per_frame; ++j) { 1759 pj_int32_t itemp; 1760 1669 for (j=0; j<conf->samples_per_frame; ++j) { 1670 if (conf_port->rx_adj_level != NORMAL_LEVEL) { 1761 1671 /* For the level adjustment, we need to store the sample to 1762 1672 * a temporary 32bit integer value to avoid overflowing the 1763 1673 * 16bit sample storage. 1764 1674 */ 1765 itemp = input[j]; 1675 pj_int32_t itemp; 1676 1677 itemp = p_in[j]; 1766 1678 /*itemp = itemp * adj / NORMAL_LEVEL;*/ 1767 itemp = (itemp * adj) >> 7;1679 itemp = (itemp * conf_port->rx_adj_level) >> 7; 1768 1680 1769 1681 /* Clip the signal if it's too loud */ 1770 if (itemp > 32767) itemp = 32767; 1771 else if (itemp < -32768) itemp = -32768; 1772 1773 input[j] = (pj_int16_t) itemp; 1774 1775 if (itemp >=0 ) level += itemp; 1776 else level -= itemp; 1682 if (itemp > MAX_LEVEL) itemp = MAX_LEVEL; 1683 else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL; 1684 1685 p_in[j] = (pj_int16_t) itemp; 1777 1686 } 1778 1687 1779 level /= conf->samples_per_frame; 1780 1781 } else { 1782 level = pjmedia_calc_avg_signal((pj_int16_t*) frame->buf, 1783 conf->samples_per_frame); 1784 } 1785 1786 /* Apply simple AGC to the level, to avoid dramatic change in the 1787 * level thus causing noise because the signal now is not aligned 1788 * with the signal from the previous frame. 1789 */ 1790 if (level >= conf_port->last_level) { 1791 level = (conf_port->last_level * ATTACK_A + level * ATTACK_B) / 1792 (ATTACK_A + ATTACK_B); 1793 } else { 1794 level = (conf_port->last_level * DECAY_A + level * DECAY_B) / 1795 (DECAY_A + DECAY_B); 1796 } 1797 conf_port->last_level = level; 1798 1688 level += (p_in[j]>0? p_in[j] : -p_in[j]); 1689 } 1690 1691 level /= conf->samples_per_frame; 1799 1692 1800 1693 /* Convert level to 8bit complement ulaw */ … … 1807 1700 if (level == 0) 1808 1701 continue; 1809 1810 /* Convert the buffer to unsigned 16bit value */1811 for (j=0; j<conf->samples_per_frame; ++j)1812 conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)frame->buf)[j]);1813 1702 1814 1703 /* Add the signal to all listeners. */ … … 1816 1705 { 1817 1706 struct conf_port *listener; 1818 pj_ uint32_t *mix_buf;1707 pj_int32_t *mix_buf; 1819 1708 unsigned k; 1820 1709 … … 1825 1714 continue; 1826 1715 1827 /* Mix the buffer. If this is the first source for target port, 1828 * zero the mix buffer of target port first. 1716 mix_buf = listener->mix_buf; 1717 1718 /* Mixing signals, 1719 * and calculate appropriate level adjustment if there is 1720 * any overflowed level in the mixed signal. 1829 1721 */ 1830 mix_buf = listener->mix_buf; 1831 if (listener->src_level == 0) { 1832 pj_bzero( mix_buf, conf->samples_per_frame*sizeof(mix_buf[0])); 1833 } 1834 1835 /* A little bit of optimization: 1836 * When "conf_port" is the only transmitter to "listener", 1837 * just add copy the frame directly from the original 1838 * 16bit frame (avoiding unsigned2pcm() conversion). 1839 * But write_port() needs to be aware of this trick! 1840 */ 1841 if (listener->transmitter_cnt == 1) { 1842 pjmedia_copy_samples((pj_int16_t*)mix_buf, 1843 (const pj_int16_t*)frame->buf, 1844 conf->samples_per_frame); 1845 listener->src_level = level; 1846 } else { 1847 for (k=0; k<conf->samples_per_frame; ++k) 1848 mix_buf[k] += (conf->uns_buf[k] * level); 1849 1850 listener->src_level += level; 1851 } 1852 listener->src_cnt++; 1853 } 1854 } 1722 for (k=0; k<conf->samples_per_frame; ++k) { 1723 mix_buf[k] += p_in[k]; 1724 /* Check if normalization adjustment needed. */ 1725 if (IS_OVERFLOW(mix_buf[k])) { 1726 /* NORMAL_LEVEL * MAX_LEVEL / mix_buf[k]; */ 1727 int tmp_adj = (MAX_LEVEL<<7) / mix_buf[k]; 1728 if (tmp_adj<0) tmp_adj = -tmp_adj; 1729 1730 if (tmp_adj<listener->mix_adj) 1731 listener->mix_adj = tmp_adj; 1732 1733 } /* if any overflow in the mixed signals */ 1734 } /* loop mixing signals */ 1735 } /* loop the listeners of conf port */ 1736 } /* loop of all conf ports */ 1855 1737 1856 1738 /* Time for all ports to transmit whetever they have in their … … 1895 1777 1896 1778 /* Return sound playback frame. */ 1897 if (conf->ports[0]-> src_level) {1779 if (conf->ports[0]->tx_level) { 1898 1780 TRACE_((THIS_FILE, "write to audio, count=%d", 1899 1781 conf->samples_per_frame)); 1900 1901 1782 pjmedia_copy_samples( (pj_int16_t*)frame->buf, 1902 1783 (const pj_int16_t*)conf->ports[0]->mix_buf, 1903 1784 conf->samples_per_frame); 1904 1785 } else { 1905 pjmedia_zero_samples((pj_int16_t*)frame->buf, conf->samples_per_frame); 1786 /* Force frame type NONE */ 1787 speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE; 1906 1788 } 1907 1789
Note: See TracChangeset
for help on using the changeset viewer.