google / oboe

Oboe is a C++ library that makes it easy to build high-performance audio apps on Android.
Apache License 2.0
3.71k stars 569 forks source link

how to do live recording and playing. #1457

Open jet-yangqs opened 2 years ago

jet-yangqs commented 2 years ago

I want to make a APP which can record the speaking of someone through mic phone and playing it through speaker of android device by modifying the liveEffect APP.

What I expected: recording the speaking of some body through mic phone and playing it through speaker Simultaneously. What I got: it can not record human voice correctly. if I make a beep near the phone, the output audio of speaker is beep with feedback loop.(same Phenomenon with liveEffect APP)

my modifications include:

  1. In liveEffectEngine, I ceate two streams, one for recording and another for playing.
  2. I write two classes inherited from oboe::AudioStreamCallback with overrided onAudioReady function. I set these two onAudioReady functions as callback function of record and play stream respectively.
  3. I set the callback peroid length to 20 ms by calling setFramesPerDataCallback() function. So these two streams will call their callback function each 20 ms(MilliSeconds);
  4. I use a global char array buffer with size of 640 bytes to store the data(enough for 20 ms length in my case). The reading and writing operations of the buffer from recording and playing thread are protected by std::mutex;
  5. each 20 ms, the record stream will call the callback function and write to the global buffer and the play stream will read from the global buffer.

why I can not get what I want from the design above? can you give me some advices?

philburk commented 2 years ago

The feedback loop is a natural consequence os recording and playing simultaneously. You can reduce the feedback by lowering your phone volume.

The LiveEffect app was designed to use a single output callback that reads data from the input. It was designed that way for a reason. Using two callbacks makes it difficult to synchronize the two streams.

I would recommend keeping the FullStreamDuplex class from the LiveEffect app.

Also, it may be better to use the VoicePerformance input preset. It may use echo cancellation to reduce feedback. In this code add:

->setInputPreset(oboe::InputPreset::VoicePerformance)
jet-yangqs commented 2 years ago

Thank you for your reply and advice. The feedback loop reduce( not completely eliminated) after I setted InputPreset and lowered the phone volume, but there are also some gitchs left. The output is not that pleasant to listen to. And my question become these:

  1. When I add: ->setInputPreset(oboe::InputPreset::VoicePerformance) what effects are applied to the input audio? does it include AcousticEchoCanceler?

  2. I saw from #951 that if I want to enable AcousticEchoCanceler effect, I need to pass audioSessionId from java to native c++. So what the relation among oboe::Usage::VoiceCommunication, oboe::InputPreset::VoicePerformance, AcousticEchoCanceler effect and audioSessionId? For exmaple, if I set oboe::InputPreset::VoicePerformance, but do not create a session ID in java, would the input stream has AcousticEchoCanceler effect? What if I set oboe::Usage::VoiceCommunication together with oboe::InputPreset::VoiceCommunication(note: it is not oboe::InputPreset::VoicePerformance)?

  3. what is the best practice to capture iuput audio with AcousticEchoCanceler effect and lower latency? Thank you!

balazsbanto commented 1 year ago

@jet-yangqs did you found the answers to your questions? I would be glad to hear the answers from the oboe team (@philburk ?) since I run into the same confusions, since there is no obvious guideline on how to enable AEC on Android. Any help would be appreciated !