コード例 #1
0
        private void EstBufDelay(short msInSndCardBuf)
        {
            short delayNew, nSampFar, nSampSndCard;
            short diff;

            nSampFar     = (short)(farendBuf.get_buffer_size());
            nSampSndCard = (short)(msInSndCardBuf * WebRtcConstants.sampMsNb * aec.mult);

            delayNew = (short)(nSampSndCard - nSampFar);

            // Account for resampling frame delay
            if (skewMode && resample)
            {
                throw new NotImplementedException();
                //delayNew -= kResamplingDelay;
            }

            if (delayNew < aecConfig.SamplesPerFrame)
            {
                farendBuf.Flush(aecConfig.SamplesPerFrame);
                delayNew += (short)aecConfig.SamplesPerFrame;
            }

            filtDelay = WebRtcUtil.WEBRTC_SPL_MAX((short)0, (short)(0.8 * filtDelay + 0.2 * delayNew));

            diff = (short)(filtDelay - knownDelay);
            if (diff > 224)
            {
                if (lastDelayDiff < 96)
                {
                    timeForDelayChange = 0;
                }
                else
                {
                    timeForDelayChange++;
                }
            }
            else if (diff < 96 && knownDelay > 0)
            {
                if (lastDelayDiff > 224)
                {
                    timeForDelayChange = 0;
                }
                else
                {
                    timeForDelayChange++;
                }
            }
            else
            {
                timeForDelayChange = 0;
            }
            lastDelayDiff = diff;

            if (timeForDelayChange > 25)
            {
                knownDelay = WebRtcUtil.WEBRTC_SPL_MAX(filtDelay - 160, 0);
            }
            return;
        }
コード例 #2
0
        public void WebRtcAec_Process(short[] nearend, short streamDelayMs, int skew)
        {
            int   nrOfSamples    = nearend.Length;
            short msInSndCardBuf = streamDelayMs;

            var   farend = new short[aecConfig.SamplesPerFrame];
            short nmbrOfFilledBuffers;

            // number of samples == 160 for SWB input
            if (nrOfSamples != 80 && nrOfSamples != 160)
            {
                throw new ArgumentException();
            }

            // Check for valid pointers based on sampling rate
            if (sampFreq == 32000)
            {
                throw new ArgumentException();
            }

            if (msInSndCardBuf < 0)
            {
                msInSndCardBuf = 0;
                //throw new ArgumentException();//todo:warning
            }
            else if (msInSndCardBuf > 500)
            {
                msInSndCardBuf = 500;
                //todo:warning
            }
            msInSndCardBuf     += 10;
            this.msInSndCardBuf = msInSndCardBuf;

            if (skewMode)
            {
                //if (aecpc->skewFrCtr < 25) {
                //    aecpc->skewFrCtr++;
                //}
                //else {
                //    retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
                //    if (retVal == -1) {
                //        aecpc->skew = 0;
                //        aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
                //    }

                //    aecpc->skew /= aecpc->sampFactor*nrOfSamples;

                //    if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
                //        aecpc->resample = kAecFalse;
                //    }
                //    else {
                //        aecpc->resample = kAecTrue;
                //    }

                //    if (aecpc->skew < minSkewEst) {
                //        aecpc->skew = minSkewEst;
                //    }
                //    else if (aecpc->skew > maxSkewEst) {
                //        aecpc->skew = maxSkewEst;
                //    }

                //}
            }

            var nFrames     = (short)(nrOfSamples / aecConfig.SamplesPerFrame);
            var nBlocks10Ms = (short)(nFrames / aec.mult);

            WebRtcUtil.WriteDebugMessage(String.Format("(C#) AEC 01               ECstartup = {0}", ECstartup));
            if (ECstartup)
            {
                nmbrOfFilledBuffers = (short)(farendBuf.get_buffer_size() / aecConfig.SamplesPerFrame);

                // The AEC is in the start up mode
                // AEC is disabled until the soundcard buffer and farend buffers are OK

                // Mechanism to ensure that the soundcard buffer is reasonably stable.
                if (checkBuffSize)
                {
                    checkBufSizeCtr++;
                    // Before we fill up the far end buffer we require the amount of data on the
                    // sound card to be stable (+/-8 ms) compared to the first value. This
                    // comparison is made during the following 4 consecutive frames. If it seems
                    // to be stable then we start to fill up the far end buffer.

                    if (counter == 0)
                    {
                        firstVal = this.msInSndCardBuf;
                        sum      = 0;
                    }

                    if (Math.Abs(firstVal - this.msInSndCardBuf) <
                        WebRtcUtil.WEBRTC_SPL_MAX((int)(0.2 * this.msInSndCardBuf), WebRtcConstants.sampMsNb))
                    {
                        sum += this.msInSndCardBuf;
                        counter++;
                    }
                    else
                    {
                        counter = 0;
                    }

                    if (counter * nBlocks10Ms >= 6)
                    {
                        // The farend buffer size is determined in blocks of 80 samples
                        // Use 75% of the average value of the soundcard buffer
                        bufSizeStart = (short)WebRtcUtil.WEBRTC_SPL_MIN((int)(0.75 * (sum * aec.mult) / (counter * 10)), WebRtcConstants.BUF_SIZE_FRAMES);
                        // buffersize has now been determined
                        checkBuffSize = false;
                    }

                    if (checkBufSizeCtr * nBlocks10Ms > 50)
                    {
                        // for really bad sound cards, don't disable echocanceller for more than 0.5 sec
                        bufSizeStart  = (short)WebRtcUtil.WEBRTC_SPL_MIN((int)(0.75 * (this.msInSndCardBuf * aec.mult) / 10), WebRtcConstants.BUF_SIZE_FRAMES);
                        checkBuffSize = false;
                    }
                }

                // if checkBuffSize changed in the if-statement above
                if (!checkBuffSize)
                {
                    // soundcard buffer is now reasonably stable
                    // When the far end buffer is filled with approximately the same amount of
                    // data as the amount on the sound card we end the start up phase and start
                    // to cancel echoes.

                    if (nmbrOfFilledBuffers == bufSizeStart)
                    {
                        ECstartup = false;                         // Enable the AEC
                    }
                    else if (nmbrOfFilledBuffers > bufSizeStart)
                    {
                        farendBuf.Flush(farendBuf.get_buffer_size() - bufSizeStart * aecConfig.SamplesPerFrame);
                        ECstartup = false;
                    }
                }
            }
            else
            {
                // AEC is enabled

                // Note only 1 block supported for nb and 2 blocks for wb
                for (int i = 0; i < nFrames; i++)
                {
                    nmbrOfFilledBuffers = (short)(farendBuf.get_buffer_size() / aecConfig.SamplesPerFrame);

                    // Check that there is data in the far end buffer
                    if (nmbrOfFilledBuffers > 0)
                    {
                        // Get the next 80 samples from the farend buffer
                        farendBuf.Read(farend, aecConfig.SamplesPerFrame);

                        // Always store the last frame for use when we run out of data
                        farendOld[i] = farend;
                    }
                    else
                    {
                        // We have no data so we use the last played frame
                        farend = farendOld[i];
                    }

                    // Call buffer delay estimator when all data is extracted,
                    // i.e. i = 0 for NB and i = 1 for WB or SWB
                    if ((i == 0 && splitSampFreq == 8000) ||
                        (i == 1 && (splitSampFreq == 16000)))
                    {
                        EstBufDelay(this.msInSndCardBuf);
                    }

                    // Call the AEC
                    var nearend80 = new short[aecConfig.SamplesPerFrame];
                    Buffer.BlockCopy(nearend, aecConfig.SamplesPerFrame * i * sizeof(short), nearend80, 0, aecConfig.SamplesPerFrame * sizeof(short));
                    aec.ProcessFrame(nearend80, farend, nearend80, knownDelay);
                    Buffer.BlockCopy(nearend80, 0, nearend, aecConfig.SamplesPerFrame * i * sizeof(short), aecConfig.SamplesPerFrame * sizeof(short));
                }
            }
        }