| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 /* | 11 /* |
| 12 * BwEstimator.c | 12 * BwEstimator.c |
| 13 * | 13 * |
| 14 * This file contains the code for the Bandwidth Estimator designed | 14 * This file contains the code for the Bandwidth Estimator designed |
| 15 * for iSAC. | 15 * for iSAC. |
| 16 * | 16 * |
| 17 */ | 17 */ |
| 18 | 18 |
| 19 #include "bandwidth_estimator.h" | 19 #include "bandwidth_estimator.h" |
| 20 #include "settings.h" | 20 #include "settings.h" |
| 21 #include "isac.h" | 21 #include "isac.h" |
| 22 | 22 |
| 23 #include <assert.h> |
| 23 #include <math.h> | 24 #include <math.h> |
| 25 #include <string.h> |
| 24 | 26 |
| 25 /* array of quantization levels for bottle neck info; Matlab code: */ | 27 /* array of quantization levels for bottle neck info; Matlab code: */ |
| 26 /* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */ | 28 /* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */ |
| 27 static const float kQRateTableWb[12] = | 29 static const float kQRateTableWb[12] = |
| 28 { | 30 { |
| 29 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f, | 31 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f, |
| 30 18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f}; | 32 18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f}; |
| 31 | 33 |
| 32 | 34 |
| 33 static const float kQRateTableSwb[24] = | 35 static const float kQRateTableSwb[24] = |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 | 114 |
| 113 bwest_str->in_wait_period = 0; | 115 bwest_str->in_wait_period = 0; |
| 114 | 116 |
| 115 bwest_str->change_to_WB = 0; | 117 bwest_str->change_to_WB = 0; |
| 116 | 118 |
| 117 bwest_str->numConsecLatePkts = 0; | 119 bwest_str->numConsecLatePkts = 0; |
| 118 bwest_str->consecLatency = 0; | 120 bwest_str->consecLatency = 0; |
| 119 bwest_str->inWaitLatePkts = 0; | 121 bwest_str->inWaitLatePkts = 0; |
| 120 bwest_str->senderTimestamp = 0; | 122 bwest_str->senderTimestamp = 0; |
| 121 bwest_str->receiverTimestamp = 0; | 123 bwest_str->receiverTimestamp = 0; |
| 124 |
| 125 bwest_str->external_bw_info.in_use = 0; |
| 126 |
| 122 return 0; | 127 return 0; |
| 123 } | 128 } |
| 124 | 129 |
| 125 /* This function updates both bottle neck rates
*/ | 130 /* This function updates both bottle neck rates
*/ |
| 126 /* Parameters:
*/ | 131 /* Parameters:
*/ |
| 127 /* rtp_number - value from RTP packet, from NetEq
*/ | 132 /* rtp_number - value from RTP packet, from NetEq
*/ |
| 128 /* frame length - length of signal frame in ms, from iSAC decoder
*/ | 133 /* frame length - length of signal frame in ms, from iSAC decoder
*/ |
| 129 /* send_ts - value in RTP header giving send time in samples
*/ | 134 /* send_ts - value in RTP header giving send time in samples
*/ |
| 130 /* arr_ts - value given by timeGetTime() time of arrival in samples of pa
cket from NetEq */ | 135 /* arr_ts - value given by timeGetTime() time of arrival in samples of pa
cket from NetEq */ |
| 131 /* pksize - size of packet in bytes, from NetEq
*/ | 136 /* pksize - size of packet in bytes, from NetEq
*/ |
| (...skipping 15 matching lines...) Expand all Loading... |
| 147 float arr_ts_diff; | 152 float arr_ts_diff; |
| 148 float send_ts_diff; | 153 float send_ts_diff; |
| 149 float arr_time_noise; | 154 float arr_time_noise; |
| 150 float arr_time_noise_abs; | 155 float arr_time_noise_abs; |
| 151 | 156 |
| 152 float delay_correction_factor = 1; | 157 float delay_correction_factor = 1; |
| 153 float late_diff = 0.0f; | 158 float late_diff = 0.0f; |
| 154 int immediate_set = 0; | 159 int immediate_set = 0; |
| 155 int num_pkts_expected; | 160 int num_pkts_expected; |
| 156 | 161 |
| 162 assert(!bwest_str->external_bw_info.in_use); |
| 157 | 163 |
| 158 // We have to adjust the header-rate if the first packet has a | 164 // We have to adjust the header-rate if the first packet has a |
| 159 // frame-size different than the initialized value. | 165 // frame-size different than the initialized value. |
| 160 if ( frame_length != bwest_str->prev_frame_length ) | 166 if ( frame_length != bwest_str->prev_frame_length ) |
| 161 { | 167 { |
| 162 bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f * | 168 bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f * |
| 163 1000.0f / (float)frame_length; /* bits/s */ | 169 1000.0f / (float)frame_length; /* bits/s */ |
| 164 } | 170 } |
| 165 | 171 |
| 166 /* UPDATE ESTIMATES ON THIS SIDE */ | 172 /* UPDATE ESTIMATES ON THIS SIDE */ |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 | 507 |
| 502 | 508 |
| 503 /* This function updates the send bottle neck rate
*/ | 509 /* This function updates the send bottle neck rate
*/ |
| 504 /* Index - integer (range 0...23) indicating bottle neck & jitter as est
imated by other side */ | 510 /* Index - integer (range 0...23) indicating bottle neck & jitter as est
imated by other side */ |
| 505 /* returns 0 if everything went fine, -1 otherwise
*/ | 511 /* returns 0 if everything went fine, -1 otherwise
*/ |
| 506 int16_t WebRtcIsac_UpdateUplinkBwImpl( | 512 int16_t WebRtcIsac_UpdateUplinkBwImpl( |
| 507 BwEstimatorstr* bwest_str, | 513 BwEstimatorstr* bwest_str, |
| 508 int16_t index, | 514 int16_t index, |
| 509 enum IsacSamplingRate encoderSamplingFreq) | 515 enum IsacSamplingRate encoderSamplingFreq) |
| 510 { | 516 { |
| 517 assert(!bwest_str->external_bw_info.in_use); |
| 518 |
| 511 if((index < 0) || (index > 23)) | 519 if((index < 0) || (index > 23)) |
| 512 { | 520 { |
| 513 return -ISAC_RANGE_ERROR_BW_ESTIMATOR; | 521 return -ISAC_RANGE_ERROR_BW_ESTIMATOR; |
| 514 } | 522 } |
| 515 | 523 |
| 516 /* UPDATE ESTIMATES FROM OTHER SIDE */ | 524 /* UPDATE ESTIMATES FROM OTHER SIDE */ |
| 517 if(encoderSamplingFreq == kIsacWideband) | 525 if(encoderSamplingFreq == kIsacWideband) |
| 518 { | 526 { |
| 519 if(index > 11) | 527 if(index > 11) |
| 520 { | 528 { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 } | 565 } |
| 558 return 0; | 566 return 0; |
| 559 } | 567 } |
| 560 | 568 |
| 561 // called when there is upper-band bit-stream to update jitter | 569 // called when there is upper-band bit-stream to update jitter |
| 562 // statistics. | 570 // statistics. |
| 563 int16_t WebRtcIsac_UpdateUplinkJitter( | 571 int16_t WebRtcIsac_UpdateUplinkJitter( |
| 564 BwEstimatorstr* bwest_str, | 572 BwEstimatorstr* bwest_str, |
| 565 int32_t index) | 573 int32_t index) |
| 566 { | 574 { |
| 575 assert(!bwest_str->external_bw_info.in_use); |
| 576 |
| 567 if((index < 0) || (index > 23)) | 577 if((index < 0) || (index > 23)) |
| 568 { | 578 { |
| 569 return -ISAC_RANGE_ERROR_BW_ESTIMATOR; | 579 return -ISAC_RANGE_ERROR_BW_ESTIMATOR; |
| 570 } | 580 } |
| 571 | 581 |
| 572 if(index > 0) | 582 if(index > 0) |
| 573 { | 583 { |
| 574 /* compute the jitter estimate as decoded on the other side */ | 584 /* compute the jitter estimate as decoded on the other side */ |
| 575 bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg + | 585 bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg + |
| 576 0.1f * (float)MAX_ISAC_MD; | 586 0.1f * (float)MAX_ISAC_MD; |
| 577 } | 587 } |
| 578 else | 588 else |
| 579 { | 589 { |
| 580 /* compute the jitter estimate as decoded on the other side */ | 590 /* compute the jitter estimate as decoded on the other side */ |
| 581 bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg + | 591 bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg + |
| 582 0.1f * (float)MIN_ISAC_MD; | 592 0.1f * (float)MIN_ISAC_MD; |
| 583 } | 593 } |
| 584 | 594 |
| 585 return 0; | 595 return 0; |
| 586 } | 596 } |
| 587 | 597 |
| 588 | 598 |
| 589 | 599 |
| 590 // Returns the bandwidth/jitter estimation code (integer 0...23) | 600 // Returns the bandwidth/jitter estimation code (integer 0...23) |
| 591 // to put in the sending iSAC payload | 601 // to put in the sending iSAC payload |
| 592 uint16_t | 602 void |
| 593 WebRtcIsac_GetDownlinkBwJitIndexImpl( | 603 WebRtcIsac_GetDownlinkBwJitIndexImpl( |
| 594 BwEstimatorstr* bwest_str, | 604 BwEstimatorstr* bwest_str, |
| 595 int16_t* bottleneckIndex, | 605 int16_t* bottleneckIndex, |
| 596 int16_t* jitterInfo, | 606 int16_t* jitterInfo, |
| 597 enum IsacSamplingRate decoderSamplingFreq) | 607 enum IsacSamplingRate decoderSamplingFreq) |
| 598 { | 608 { |
| 599 float MaxDelay; | 609 float MaxDelay; |
| 600 //uint16_t MaxDelayBit; | 610 //uint16_t MaxDelayBit; |
| 601 | 611 |
| 602 float rate; | 612 float rate; |
| 603 float r; | 613 float r; |
| 604 float e1, e2; | 614 float e1, e2; |
| 605 const float weight = 0.1f; | 615 const float weight = 0.1f; |
| 606 const float* ptrQuantizationTable; | 616 const float* ptrQuantizationTable; |
| 607 int16_t addJitterInfo; | 617 int16_t addJitterInfo; |
| 608 int16_t minInd; | 618 int16_t minInd; |
| 609 int16_t maxInd; | 619 int16_t maxInd; |
| 610 int16_t midInd; | 620 int16_t midInd; |
| 611 | 621 |
| 622 if (bwest_str->external_bw_info.in_use) { |
| 623 *bottleneckIndex = bwest_str->external_bw_info.bottleneck_idx; |
| 624 *jitterInfo = bwest_str->external_bw_info.jitter_info; |
| 625 return; |
| 626 } |
| 627 |
| 612 /* Get Max Delay Bit */ | 628 /* Get Max Delay Bit */ |
| 613 /* get unquantized max delay */ | 629 /* get unquantized max delay */ |
| 614 MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str); | 630 MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str); |
| 615 | 631 |
| 616 if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight * | 632 if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight * |
| 617 MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) * | 633 MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) * |
| 618 bwest_str->rec_max_delay_avg_Q - weight * MIN
_ISAC_MD) ) | 634 bwest_str->rec_max_delay_avg_Q - weight * MIN
_ISAC_MD) ) |
| 619 { | 635 { |
| 620 jitterInfo[0] = 0; | 636 jitterInfo[0] = 0; |
| 621 /* update quantized average */ | 637 /* update quantized average */ |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 { | 693 { |
| 678 bottleneckIndex[0] = maxInd; | 694 bottleneckIndex[0] = maxInd; |
| 679 } | 695 } |
| 680 | 696 |
| 681 bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q + | 697 bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q + |
| 682 weight * ptrQuantizationTable[bottleneckIndex[0]]; | 698 weight * ptrQuantizationTable[bottleneckIndex[0]]; |
| 683 bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo; | 699 bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo; |
| 684 | 700 |
| 685 bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight * | 701 bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight * |
| 686 (rate + bwest_str->rec_header_rate); | 702 (rate + bwest_str->rec_header_rate); |
| 687 | |
| 688 return 0; | |
| 689 } | 703 } |
| 690 | 704 |
| 691 | 705 |
| 692 | 706 |
| 693 /* get the bottle neck rate from far side to here, as estimated on this side */ | 707 /* get the bottle neck rate from far side to here, as estimated on this side */ |
| 694 int32_t WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str) | 708 int32_t WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str) |
| 695 { | 709 { |
| 696 int32_t rec_bw; | 710 int32_t rec_bw; |
| 697 float jitter_sign; | 711 float jitter_sign; |
| 698 float bw_adjust; | 712 float bw_adjust; |
| 699 | 713 |
| 714 assert(!bwest_str->external_bw_info.in_use); |
| 715 |
| 700 /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */ | 716 /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */ |
| 701 jitter_sign = bwest_str->rec_jitter_short_term / | 717 jitter_sign = bwest_str->rec_jitter_short_term / |
| 702 bwest_str->rec_jitter_short_term_abs; | 718 bwest_str->rec_jitter_short_term_abs; |
| 703 | 719 |
| 704 /* adjust bw proportionally to negative average jitter sign */ | 720 /* adjust bw proportionally to negative average jitter sign */ |
| 705 bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign); | 721 bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign); |
| 706 | 722 |
| 707 /* adjust Rate if jitter sign is mostly constant */ | 723 /* adjust Rate if jitter sign is mostly constant */ |
| 708 rec_bw = (int32_t)(bwest_str->rec_bw * bw_adjust); | 724 rec_bw = (int32_t)(bwest_str->rec_bw * bw_adjust); |
| 709 | 725 |
| 710 /* limit range of bottle neck rate */ | 726 /* limit range of bottle neck rate */ |
| 711 if (rec_bw < MIN_ISAC_BW) | 727 if (rec_bw < MIN_ISAC_BW) |
| 712 { | 728 { |
| 713 rec_bw = MIN_ISAC_BW; | 729 rec_bw = MIN_ISAC_BW; |
| 714 } | 730 } |
| 715 else if (rec_bw > MAX_ISAC_BW) | 731 else if (rec_bw > MAX_ISAC_BW) |
| 716 { | 732 { |
| 717 rec_bw = MAX_ISAC_BW; | 733 rec_bw = MAX_ISAC_BW; |
| 718 } | 734 } |
| 719 return rec_bw; | 735 return rec_bw; |
| 720 } | 736 } |
| 721 | 737 |
| 722 /* Returns the max delay (in ms) */ | 738 /* Returns the max delay (in ms) */ |
| 723 int32_t | 739 int32_t |
| 724 WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str) | 740 WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str) |
| 725 { | 741 { |
| 726 int32_t rec_max_delay; | 742 int32_t rec_max_delay; |
| 727 | 743 |
| 744 assert(!bwest_str->external_bw_info.in_use); |
| 745 |
| 728 rec_max_delay = (int32_t)(bwest_str->rec_max_delay); | 746 rec_max_delay = (int32_t)(bwest_str->rec_max_delay); |
| 729 | 747 |
| 730 /* limit range of jitter estimate */ | 748 /* limit range of jitter estimate */ |
| 731 if (rec_max_delay < MIN_ISAC_MD) | 749 if (rec_max_delay < MIN_ISAC_MD) |
| 732 { | 750 { |
| 733 rec_max_delay = MIN_ISAC_MD; | 751 rec_max_delay = MIN_ISAC_MD; |
| 734 } | 752 } |
| 735 else if (rec_max_delay > MAX_ISAC_MD) | 753 else if (rec_max_delay > MAX_ISAC_MD) |
| 736 { | 754 { |
| 737 rec_max_delay = MAX_ISAC_MD; | 755 rec_max_delay = MAX_ISAC_MD; |
| 738 } | 756 } |
| 739 return rec_max_delay; | 757 return rec_max_delay; |
| 740 } | 758 } |
| 741 | 759 |
| 742 /* get the bottle neck rate from here to far side, as estimated by far side */ | 760 /* Clamp val to the closed interval [min,max]. */ |
| 743 void | 761 static int32_t clamp(int32_t val, int32_t min, int32_t max) { |
| 744 WebRtcIsac_GetUplinkBandwidth( | 762 assert(min <= max); |
| 745 const BwEstimatorstr* bwest_str, | 763 return val < min ? min : (val > max ? max : val); |
| 746 int32_t* bitRate) | |
| 747 { | |
| 748 /* limit range of bottle neck rate */ | |
| 749 if (bwest_str->send_bw_avg < MIN_ISAC_BW) | |
| 750 { | |
| 751 *bitRate = MIN_ISAC_BW; | |
| 752 } | |
| 753 else if (bwest_str->send_bw_avg > MAX_ISAC_BW) | |
| 754 { | |
| 755 *bitRate = MAX_ISAC_BW; | |
| 756 } | |
| 757 else | |
| 758 { | |
| 759 *bitRate = (int32_t)(bwest_str->send_bw_avg); | |
| 760 } | |
| 761 return; | |
| 762 } | 764 } |
| 763 | 765 |
| 764 /* Returns the max delay value from the other side in ms */ | 766 int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str) { |
| 765 int32_t | 767 return bwest_str->external_bw_info.in_use |
| 766 WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr *bwest_str) | 768 ? bwest_str->external_bw_info.send_bw_avg |
| 767 { | 769 : clamp(bwest_str->send_bw_avg, MIN_ISAC_BW, MAX_ISAC_BW); |
| 768 int32_t send_max_delay; | |
| 769 | |
| 770 send_max_delay = (int32_t)(bwest_str->send_max_delay_avg); | |
| 771 | |
| 772 /* limit range of jitter estimate */ | |
| 773 if (send_max_delay < MIN_ISAC_MD) | |
| 774 { | |
| 775 send_max_delay = MIN_ISAC_MD; | |
| 776 } | |
| 777 else if (send_max_delay > MAX_ISAC_MD) | |
| 778 { | |
| 779 send_max_delay = MAX_ISAC_MD; | |
| 780 } | |
| 781 return send_max_delay; | |
| 782 } | 770 } |
| 783 | 771 |
| 772 int32_t WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str) { |
| 773 return bwest_str->external_bw_info.in_use |
| 774 ? bwest_str->external_bw_info.send_max_delay_avg |
| 775 : clamp(bwest_str->send_max_delay_avg, MIN_ISAC_MD, MAX_ISAC_MD); |
| 776 } |
| 777 |
| 778 void WebRtcIsacBw_GetBandwidthInfo(BwEstimatorstr* bwest_str, |
| 779 enum IsacSamplingRate decoder_sample_rate_hz, |
| 780 IsacBandwidthInfo* bwinfo) { |
| 781 assert(!bwest_str->external_bw_info.in_use); |
| 782 bwinfo->in_use = 1; |
| 783 bwinfo->send_bw_avg = WebRtcIsac_GetUplinkBandwidth(bwest_str); |
| 784 bwinfo->send_max_delay_avg = WebRtcIsac_GetUplinkMaxDelay(bwest_str); |
| 785 WebRtcIsac_GetDownlinkBwJitIndexImpl(bwest_str, &bwinfo->bottleneck_idx, |
| 786 &bwinfo->jitter_info, |
| 787 decoder_sample_rate_hz); |
| 788 } |
| 789 |
| 790 void WebRtcIsacBw_SetBandwidthInfo(BwEstimatorstr* bwest_str, |
| 791 const IsacBandwidthInfo* bwinfo) { |
| 792 memcpy(&bwest_str->external_bw_info, bwinfo, |
| 793 sizeof bwest_str->external_bw_info); |
| 794 } |
| 784 | 795 |
| 785 /* | 796 /* |
| 786 * update long-term average bitrate and amount of data in buffer | 797 * update long-term average bitrate and amount of data in buffer |
| 787 * returns minimum payload size (bytes) | 798 * returns minimum payload size (bytes) |
| 788 */ | 799 */ |
| 789 int WebRtcIsac_GetMinBytes( | 800 int WebRtcIsac_GetMinBytes( |
| 790 RateModel* State, | 801 RateModel* State, |
| 791 int StreamSize, /* bytes in bitstream */ | 802 int StreamSize, /* bytes in bitstream */ |
| 792 const int FrameSamples, /* samples per frame */ | 803 const int FrameSamples, /* samples per frame */ |
| 793 const double BottleNeck, /* bottle neck rate; excl headers (bps) */ | 804 const double BottleNeck, /* bottle neck rate; excl headers (bps) */ |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck * | 1022 s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck * |
| 1012 bottle_neck * 0.000001; | 1023 bottle_neck * 0.000001; |
| 1013 break; | 1024 break; |
| 1014 default: | 1025 default: |
| 1015 s2nr = 0; | 1026 s2nr = 0; |
| 1016 } | 1027 } |
| 1017 | 1028 |
| 1018 return s2nr; | 1029 return s2nr; |
| 1019 | 1030 |
| 1020 } | 1031 } |
| OLD | NEW |