views:

1548

answers:

9
+4  Q: 

Voice Echo Problem

I'm trying to build a video chat program using Adobe Flex but there is a giant problem with echos. If the participants arn't using headsets, everything they say echos. Worse, they can actually create positive feedback loop of echos that won't end until the mics are muted.

Has anyone found a solution for this on the Flex/Flash platform?

My software is using the Speex codec and I've done my best to eliminate all buffering (i.e. it's a live stream and I set the buffer length to 0). The loop back option is turned off and the "Use Echo Suppression" is turned on. I'm using the Red5 server for the video and audio streaming.

Any help would be appreciated.

+4  A: 

You'll need to implement some filtering to make sure that everything output from the speakers is eliminated from the mic input (or as close as possible). I'm not aware of the specific tools to do this, but the basic idea is that you take parallel time slices of the input and output, and you subtract the wave form of the output from the input. Due to latency, you might have to introduce an offset so things match up.

Dana the Sane
+1  A: 

Also You can pass stream via low-pass filter for some reducing echoing

vitaly.v.ch
Why would the echoes be high frequency?
recursive
low-pass filter will some reduce positive feedback loop and at some conditions will break feedbak loop.
vitaly.v.ch
+1  A: 

I had the same problem in my webconference system and I couldn't find any solution on the web. As far as I understand, "Use Echo Suppression" will cancel only echo made by a loop back. But I've made a simple solution - not perfect, but still better than nothing:

every 50ms check Microphone.activityLevel

if during last 1500ms activityLevel was greater than 20
then Microphone.gain *= 0.8
tst
+1  A: 

Another partial solution is to stop sending when the input level drops below some threshold. This way, echoes will die down once someone stops talking.

Mark Bessey
+1  A: 

You might try a convolution filter, which would attempt to correlate microphone input with recent output that you sent to the speakers. When you detect that the microphone input is similar to the recent output, just mute the microphone until the correlation disappears. (but IANAX, I am not an eXpert)

Qwertie
If you have to explain your acronym, perhaps you just shouldn't use it. Just a thought.
Michael Kohne
A: 

1) You should define the problem - if this happens when no one is talking, right after a sound is heard from the speakers, or only when a lot of people talk at once etc...

2) note that in this field unlike most software problems, there isn't one solution that works 100%, rather the solution is composed of several methods, and only works very good usually but not all the time.

thus you should implement some of the idea's above, to add mine to this respected list:

a) start by adjusting the levels of recording, gain, etc...

b)try to insert a delay from the time the samples are recorded to time it is played. to figure the delay a try and error method is used.

c)Have you any equalizer? adjust it - sometimes the trouble is in a single frequency range, probably the low level ones...

if your efforts doesn't work the problem is more severe, you'll need to either find in Flex, or to implement some sort of 'echo cancellation', This can be done simply or smart, I'm sure that there is open source some where.

Liran Orevi
+7  A: 

This is a known problem in Adobe's software for which there is no fix presently.

For now you can only work around the problem.

You should implement a Push-to-Talk mode in your application and make it easy for users to switch to Push-to-Talk if they are experiencing sound quality problems.

If all users of the application have headsets then they won't have to resort to Push-to-Talk.

If your application is doing many-to-many conferencing it might be an interesting idea to allow users to request a speaker token.

Using an approach based on the suggestion of tst it might be possible to have the application checking which people are talking and then granting the speaker token automatically, rather than have users manually requesting it. Obviously usability testing would have to conducted to ensure this works well in practice.

More info on the bug

You can refer to the following Adobe bug report for more details:

The bug description reads as follows:

Flash player has no AEC support yet. There is no AEC support in Flash player 10 beta also. Developers need built-in AEC to create convenient webservices with live audio/video communication without requirement for user to have a headset. According to Speex project website Speex supports AEC. Please add AEC support for release version of Flash Player 10 to make suitable for communication webservices.

Laurent
Our current workaround is to just recommend headsets...
Jay Stramel
Reworded my answer to make it easier to read.
Laurent
AEC is available from Adobe but it is in their proprietary player (for Connect, if I'm not mistaken). It would be possible to do AEC on the server with Red5 + Xuggle, but from everyone I have spoken with this is quite difficult to get right.
Mondain
A: 

my wife did a masters project on adaptive fir filtering for echo cancelling. it seemed to be able to manage variable delay as long as you knew one source, which you do. this seems like overkill though for your application. check out the wikipedia pages on adaptive filter, fir filter, and the wolfram fir filter code in matlab for a starting point.

John Ellinwood
A: 

Hi, I am Amit from India.

I just tried the below code, and it works fine to reduce the echo. However, I get the volume level reduced too much, being too low to hear the opposite person clearly.

Then i added a condition (see the comment '//code to maintain the gain level' below) to maintain the gain level. But it gives the echo again.

Any immediate help is appreciated.

//echo cancellation rnd public var intCountMilliSec:int = 0; public var intLastActivityLevel:int = 0; private function CancelEcho(e:TimerEvent):void{ intCountMilliSec = intCountMilliSec + 50; if (Red5OutgoingMic.activityLevel > intLastActivityLevel) { intLastActivityLevel = Red5OutgoingMic.activityLevel; }

if (intCountMilliSec >= 1500) { if (intLastActivityLevel> 20) { Red5OutgoingMic.gain *= 0.8;

//code to maintain the gain level

if (Red5OutgoingMic.gain < 40) { Red5OutgoingMic.gain = 40; }

} intCountMilliSec = 0; intLastActivityLevel = 0; }

}

Amit