<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AndrewDDev</title>
    <description>The latest articles on DEV Community by AndrewDDev (@andrewddev).</description>
    <link>https://dev.to/andrewddev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F852981%2F4dfc170c-bedc-4d53-a061-694e6b4bb6e5.jpg</url>
      <title>DEV Community: AndrewDDev</title>
      <link>https://dev.to/andrewddev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andrewddev"/>
    <language>en</language>
    <item>
      <title>How karaoke apps make users fall in love with singing</title>
      <dc:creator>AndrewDDev</dc:creator>
      <pubDate>Fri, 10 Jun 2022 02:21:43 +0000</pubDate>
      <link>https://dev.to/andrewddev/how-karaoke-apps-make-users-fall-in-love-with-singing-4ohk</link>
      <guid>https://dev.to/andrewddev/how-karaoke-apps-make-users-fall-in-love-with-singing-4ohk</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YLioTZn1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/shutterstock1270055839.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YLioTZn1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/shutterstock1270055839.jpg" alt="shutterstock_1270055839" width="880" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The explosion of online karaoke
&lt;/h2&gt;

&lt;p&gt;With the diversification of people's entertainment activities, online entertainment activities are also diversified. This year, online karaoke applications have sprung up, such as WeSing, Smule, Yokee, StarMaker, KaraDoReMi, SingIt (DingaStar), The Voice Karaoke, Many singing applications such as SingPlay have been loved by a large number of users.&lt;/p&gt;

&lt;p&gt;As more and more companies enter, there are more and more ways to play online karaoke, from the initial local recording, to today's Lianmai duet, grabbing wheat, and round wheat singing.&lt;/p&gt;

&lt;p&gt;So how do we make users fall in love with singing?&lt;/p&gt;

&lt;p&gt;If you want users to fall in love with singing, you first need to make users sing well.&lt;/p&gt;

&lt;p&gt;So how do we make our customers sing well?&lt;/p&gt;

&lt;h2&gt;
  
  
  Four secrets to improve sound effects
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Voice change: Through special processing of the sound，By optimizing the sound, the singer can make the voice sound softer while maintaining his own timbre.&lt;/li&gt;
&lt;li&gt;Reverberation: Through special processing of the sound, the reverberation effect of different environments is created, making the sound appear as if it is in a concert hall, a cathedral, etc.&lt;/li&gt;
&lt;li&gt;Reverberation echo: Through special processing of the sound, it can be matched with voice change and reverberation to achieve a variety of custom sound effects, such as ethereal and robot sounds.&lt;/li&gt;
&lt;li&gt;Virtual stereo: Through the deep use of dual-channel technology, each position and angle of the sound source is virtualized to achieve stereo sound, 3D surround sound, and sound discrimination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The function is only effective for the sound collected by the SDK. The developer can dynamically adjust the voice change, reverberation, reverberation echo, and virtual stereo during a call or live broadcast.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before proceeding with voice change/reverb/stereo, please make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in &lt;a href="https://console.zegocloud.com?_source=dev&amp;amp;article=13"&gt;ZEGOCLOUD Admin Console&lt;/a&gt;, and get the AppID of your project.&lt;/li&gt;
&lt;li&gt;The ZEGO Express SDK has been integrated into the project. For details, see &lt;a href="https://docs.zegocloud.com/article/195?_source=dev&amp;amp;article=13"&gt;Integration&lt;/a&gt; and &lt;a href="https://docs.zegocloud.com/article/10836?_source=dev&amp;amp;article=13"&gt;Implementation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Voice Change
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Preset Voice Changer
&lt;/h3&gt;

&lt;p&gt;Call the &lt;code&gt;setVoiceChangerPreset&lt;/code&gt; method to use SDK preset voice changer effect.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ZegoVoiceChangerPreset&lt;/code&gt; preset voice changing effects are as follows, developers can choose according to their needs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GYiYvGs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/16536325394983.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GYiYvGs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/16536325394983.jpg" alt="ZegoVoiceChangerPreset" width="880" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following sample code takes a male voice to a child voice as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setVoiceChangerPreset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoVoiceChangerPreset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MEN_TO_CHILD&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Custom Voice Changer
&lt;/h3&gt;

&lt;p&gt;If the sound changing effect preset by the SDK cannot meet the needs, the developer can call &lt;code&gt;ZegoVoiceChangerParam&lt;/code&gt; Method, through the pitch parameter &lt;code&gt;pitch&lt;/code&gt; to set a custom voice changer, the value range of this parameter is [-8.0, 8.0], the larger the value, the sharper the sound, the default value is 0.0 (ie no voice change).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoVoiceChangerParam&lt;/span&gt; &lt;span class="n"&gt;voiceChangerParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoVoiceChangerParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setVoiceChangerParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reverberation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Preset Reverb
&lt;/h3&gt;

&lt;p&gt;Call &lt;code&gt;setReverbPreset&lt;/code&gt; to set reverberation through preset enumeration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ZegoReverbPreset&lt;/code&gt; preset reverb effects are as follows, developers can choose according to their needs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N0byZ3p3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/16536325703843.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N0byZ3p3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/06/10/16536325703843.jpg" alt="ZegoReverbPreset" width="880" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following sample code takes the large room mode as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbPreset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoReverbPreset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LARGE_ROOM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Custom Reverb
&lt;/h3&gt;

&lt;p&gt;If the SDK preset reverb type cannot meet the needs, developers can call &lt;code&gt;ZegoReverbAdvancedParam&lt;/code&gt; method, to achieve the reverberation effect required by the developer through the configuration of related parameters (for detailed parameter description, please refer to the API documentation).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoReverbAdvancedParam&lt;/span&gt; &lt;span class="n"&gt;reverbParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoReverbAdvancedParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;damping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reverberation damping&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reverberance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reverberation&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;roomSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// room size&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wetOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wetGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dryGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toneLow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toneHigh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preDelay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;20.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stereoWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbAdvancedParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting the custom reverb parameters, the preset reverb effect set when reverb is enabled will be invalid. If you want to use the SDK preset parameters again, you can use &lt;code&gt;setReverbPreset&lt;/code&gt;. Set enumeration method to set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reverberation Echo
&lt;/h2&gt;

&lt;p&gt;Call the &lt;code&gt;setReverbEchoParam&lt;/code&gt; method and set the relevant parameters to realize the developer The required reverberation echo effect (for detailed parameter description, please refer to the API document).&lt;/p&gt;

&lt;p&gt;The following sample code takes the ethereal effect as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoReverbEchoParam&lt;/span&gt; &lt;span class="n"&gt;echoParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoReverbEchoParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;outGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;numDelays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="mi"&gt;230&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;460&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;690&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1150&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1380&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1610&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="mf"&gt;0.41f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.18f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.08f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.03f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.009f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.003f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.001f&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;zegoReverbEchoParamDatas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbEchoParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Virtual Stereo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set the Number of Streaming Audio Channels
&lt;/h3&gt;

&lt;p&gt;If you need to turn on the virtual stereo function, you must first call the &lt;code&gt;setAudioConfig&lt;/code&gt; method to set before pushing the stream The audio encoding channel is Stereo dual channel (default is Mono).&lt;/p&gt;

&lt;p&gt;The example here uses the preset enumeration structure &lt;code&gt;ZegoAudioConfig&lt;/code&gt; to be set to dual-channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoAudioConfig&lt;/span&gt; &lt;span class="n"&gt;audioConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoAudioConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;STANDARD_QUALITY_STEREO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setAudioConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audioConfig&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Virtual Stereo Parameters
&lt;/h3&gt;

&lt;p&gt;After setting the audio encoding channel to dual channel, call the &lt;code&gt;enableVirtualStereo&lt;/code&gt; method, Turn on the virtual stereo through the enable parameter, and set the sound source angle of the virtual stereo through the angle parameter to have the stereo effect. The angle range is 0 to 360, and generally can be set to 90 degrees (that is, straight ahead).&lt;/p&gt;

&lt;p&gt;Starting from the &lt;strong&gt;2.15.0&lt;/strong&gt; version, the SDK supports the all-around virtual stereo. To enable it, set the &lt;code&gt;angle&lt;/code&gt; parameter to &lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following shows how to turn on the virtual stereo and set the angle to 90 degrees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;enableVirtualStereo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following shows how to enable the all-around virtual stereo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;enableVirtualStereo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>android</category>
      <category>mobile</category>
      <category>programming</category>
      <category>audio</category>
    </item>
    <item>
      <title>How to implement sound waves in Android by using ZEGOCLOUD SDK</title>
      <dc:creator>AndrewDDev</dc:creator>
      <pubDate>Tue, 31 May 2022 03:31:28 +0000</pubDate>
      <link>https://dev.to/andrewddev/how-to-implement-sound-waves-in-android-by-using-zegocloud-sdk-2gpi</link>
      <guid>https://dev.to/andrewddev/how-to-implement-sound-waves-in-android-by-using-zegocloud-sdk-2gpi</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YAdhUrzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/30/pexelspixabay257904.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YAdhUrzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/30/pexelspixabay257904.jpg" alt="sound waves" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the karaoke scene, it is often necessary to pull multiple streams and display the user who is speaking. We need to identify whether the user is speaking, the volume of the speech (sound wave), and display it on the UI.&lt;/p&gt;

&lt;p&gt;The SDK provides the following two methods to achieve this function：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sound level&lt;/strong&gt; refers to the volume of a stream. The ZEGO Express SDK provides the ability to capture the sound level of a stream in real time and delivers the captured sound level data to the app client through related callbacks.  A typical use case of this feature is that you can visualize the sound level data on your app UI to indicate the current active speaker and their volume. The following picture shows an example of such use cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio spectrum&lt;/strong&gt; refers to a series of values, each of which represents an audio signal's energy level at a point in a frequency range.  The ZEGO Express SDK provides the ability to capture the audio spectrum data of a stream in real time and delivers the captured audio spectrum data to the app client through related callbacks.  A typical use case of this feature is that you can use it to create and display an audio spectrum visualizer on your app UI, especially for those online karaoke apps. The following picture shows an example of audio spectrum visualizers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YFNL9-5d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/30/16536454174615.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YFNL9-5d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/30/16536454174615.png" alt="Audio spectrum" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin to use sound level and audio spectrum in your project, make sure you complete the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in &lt;a href="https://console.zegocloud.com?_source=medium&amp;amp;article=10001"&gt;ZEGOCLOUD Admin Console&lt;/a&gt;, and get the AppID of your project.&lt;/li&gt;
&lt;li&gt;The ZEGO Express SDK has been integrated into the project. For details, see &lt;a href="https://docs.zegocloud.com/article/195?_source=medium&amp;amp;article=10001"&gt;Integration&lt;/a&gt; and &lt;a href="https://docs.zegocloud.com/article/10836?_source=medium&amp;amp;article=10001"&gt;Implementation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enable the sound level callbacks
&lt;/h2&gt;

&lt;p&gt;To enable sound level callbacks,  call the &lt;code&gt;startSoundLevelMonitor&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mSDKEnging is an instance of ZegoExpressEngine&lt;/span&gt;
&lt;span class="n"&gt;mSDKEnging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startSoundLevelMonitor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the above step is completed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you start previewing the local video by calling the &lt;code&gt;startPreview&lt;/code&gt; method or publishing a local stream by calling the &lt;code&gt;startPublishingStream&lt;/code&gt; method, the SDK will trigger the &lt;code&gt;onCapturedSoundLevelUpdate&lt;/code&gt; callback at an interval of 100ms to deliver the sound level data of the locally captured audio.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
    * The callback to deliver the sound level data of locally captured audio.
    *
    * The callback sends out a notification at an interval of 100 ms.
    * @param soundLevel: The sound level value of the locally captured audio, which is in the range [0.0, 100.0].
    */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCapturedSoundLevelUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;soundLevel&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;When you start playing remote streams by calling the &lt;code&gt;startPlayingStream&lt;/code&gt; method,  the SDK will trigger the  &lt;code&gt;onRemoteSoundLevelUpdate&lt;/code&gt; callback at an interval of 100ms to deliver the sound level data of the remote streams.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
    * The callback to deliver the sound level data of remote streams
    *
    * The callback sends out a notification at an interval of 100 ms.
    * @param soundLevels: The sound level data (key-value pairs) of the remote streams, of which the key is a stream ID, and the value is the sound level value of the corresponding stream. Each sound level value is in the range [0.0, 100.0].
    */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onRemoteSoundLevelUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;soundLevels&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable the audio spectrum callbacks
&lt;/h2&gt;

&lt;p&gt;To enable audio spectrum callbacks, call the  &lt;code&gt;startAudioSpectrumMonitor&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mSDKEnging is an instance of ZegoExpressEngine&lt;/span&gt;
&lt;span class="n"&gt;mSDKEnging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startAudioSpectrumMonitor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the above step is completed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you start previewing the local video by calling the &lt;code&gt;startPreview&lt;/code&gt; method or publishing a local stream by calling the &lt;code&gt;startPublishingStream method, the SDK will trigger the&lt;/code&gt;onCapturedAudioSpectrumUpdate` callback at an interval of 100ms to deliver the audio spectrum data of locally captured audio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
    * The callback to deliver the audio spectrum data of locally captured audio
    *
    * The callback sends out a notification at an interval of 100 ms.
    * @param audioSpectrum: An array of audio spectrum values of the locally captured audio. Each audio spectrum value is in the range [0, 2^30].
    */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCapturedAudioSpectrumUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;audioSpectrum&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you start playing remote streams by calling the &lt;code&gt;startPlayingStream&lt;/code&gt; method,  the SDK will trigger the &lt;code&gt;onRemoteAudioSpectrumUpdate&lt;/code&gt; callback at an interval of 100ms to deliver audio spectrum data of the remote streams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
    * The callback to deliver the audio spectrum data of remote streams
    *
    * The callback sends out a notification at an interval of 100 ms.
    * @param audioSpectrums: The audio spectrum data (key-value pairs) of remote streams, of which the key is a stream ID, and the value is an array of audio spectrum values of the corresponding stream. Each audio spectrum value is in the range [0, 2^30].
    */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onRemoteAudioSpectrumUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;audioSpectrums&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;
&lt;h2&gt;
  
  
  Obtain data from the callbacks
&lt;/h2&gt;

&lt;p&gt;The SDK delivers the sound level data and audio spectrum data of the remote streams as key-value pairs in a &lt;code&gt;HashMap&lt;/code&gt;. In each key-value pair, the key is the stream ID of a remote stream published by another user in the same room, and the value is the sound level value or an array of audio spectrum values that stream.  &lt;/p&gt;

&lt;p&gt;You can first obtain and save the list of remote streams published by the other users in the current room through the &lt;code&gt;onRoomStreamUpdate&lt;/code&gt; callback, and then use each stream ID in the list as an index to get the sound level value or the audio spectrum data of that stream from the &lt;code&gt;HashMap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following examples show how to obtain the sound level and audio spectrum data from the callbacks. For how to render the data onto the UI of the app, refer to the sample code mentioned in Section 2 above.&lt;/p&gt;

&lt;p&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEventHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCapturedSoundLevelUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;soundLevel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Obtain the sound level data of locally captured audio and render it to specific UI controls.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onRemoteSoundLevelUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;soundLevels&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Obtain the sound level data of remote streams and render it to specific UI controls.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCapturedAudioSpectrumUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;audioSpectrum&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Obtain the audio spectrum data of locally captured audio and render it to specific UI controls.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onRemoteAudioSpectrumUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;[]&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;audioSpectrums&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Obtain the audio spectrum data (key-value pairs) of the remote streams and render it to specific UI controls.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;
&lt;h2&gt;
  
  
  Disable the sound level callbacks
&lt;/h2&gt;

&lt;p&gt;To disable the sound level callbacks, call the &lt;code&gt;stopSoundLevelMonitor&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mSDKEnging is an instance of ZegoExpressEngine&lt;/span&gt;
&lt;span class="n"&gt;mSDKEnging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stopSoundLevelMonitor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;After the above step is completed, the SDK will stop triggering the callbacks &lt;code&gt;onCapturedSoundLevelUpdate&lt;/code&gt; and &lt;code&gt;onRemoteSoundLevelUpdate&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Disable the audio spectrum callbacks
&lt;/h2&gt;

&lt;p&gt;To disable audio spectrum callbacks, call the &lt;code&gt;stopAudioSpectrumMonitor&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mSDKEnging is an instance of ZegoExpressEngine&lt;/span&gt;
&lt;span class="n"&gt;mSDKEnging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stopAudioSpectrumMonitor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;After the above step is completed, the SDK will stop triggering the callbacks &lt;code&gt;onCapturedAudioSpectrumUpdate&lt;/code&gt; and &lt;code&gt;onRemoteAudioSpectrumUpdate&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>android</category>
      <category>java</category>
      <category>mobile</category>
      <category>live</category>
    </item>
    <item>
      <title>How to use ZEGOCLOUD SDK to implement Voice change/Reverb/Virtual stereo in Android</title>
      <dc:creator>AndrewDDev</dc:creator>
      <pubDate>Fri, 27 May 2022 06:57:01 +0000</pubDate>
      <link>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-voice-changereverbvirtual-stereo-in-android-8pf</link>
      <guid>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-voice-changereverbvirtual-stereo-in-android-8pf</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2Fpexelsandreapiacquadio3761509.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2Fpexelsandreapiacquadio3761509.jpg" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the live broadcast, chat room, and karaoke room scenes, in order to increase the fun and interactivity, players can change the voice to make things funny, reverberate the atmosphere, and use stereo to make the sound more three-dimensional. ZegoExpress SDK provides a variety of preset voice change, reverberation, reverberation echo, and stereo effects. Developers can flexibly set the sound they want. If you need to listen to it, you can enable ear return for testing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Voice change: By changing the user's pitch, the output sound is sensory different from the original sound, and various effects such as changing male voice to female voice are realized.&lt;/li&gt;
&lt;li&gt;Reverberation: Through special processing of the sound, the reverberation effect of different environments is created, making the sound appear as if it is in a concert hall, a cathedral, etc.&lt;/li&gt;
&lt;li&gt;Reverberation echo: Through special processing of the sound, it can be matched with voice change and reverberation to achieve a variety of custom sound effects, such as ethereal and robot sounds.&lt;/li&gt;
&lt;li&gt;Virtual stereo: Through the deep use of dual-channel technology, each position and angle of the sound source is virtualized to achieve stereo sound, 3D surround sound, and sound discrimination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The function is only effective for the sound collected by the SDK. Developers can dynamically adjust the voice change, reverberation, reverberation echo, and virtual stereo during a call or live broadcast. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before proceeding with voice change/reverb/stereo, please make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in &lt;a href="https://console.zegocloud.com?_source=dev&amp;amp;article=10" rel="noopener noreferrer"&gt;ZEGOCLOUD Admin Console&lt;/a&gt;, and get the AppID of your project.&lt;/li&gt;
&lt;li&gt;The ZEGO Express SDK has been integrated into the project. For details, see &lt;a href="https://docs.zegocloud.com/article/195?_source=dev&amp;amp;article=10" rel="noopener noreferrer"&gt;Integration&lt;/a&gt; and &lt;a href="https://docs.zegocloud.com/article/10836?_source=dev&amp;amp;article=10" rel="noopener noreferrer"&gt;Implementation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Voice Change
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Preset Voice Changer
&lt;/h3&gt;

&lt;p&gt;Call the &lt;code&gt;setVoiceChangerPreset&lt;/code&gt; method to use SDK preset voice changer effect.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ZegoVoiceChangerPreset&lt;/code&gt; preset voice changing effects are as follows, developers can choose according to their needs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536325394983.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536325394983.jpg" alt="ZegoVoiceChangerPreset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following sample code takes a male voice to a child voice as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setVoiceChangerPreset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoVoiceChangerPreset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MEN_TO_CHILD&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Custom Voice Changer
&lt;/h3&gt;

&lt;p&gt;If the sound changing effect preset by the SDK cannot meet the needs, the developer can call &lt;code&gt;ZegoVoiceChangerParam&lt;/code&gt; Method, through the pitch parameter &lt;code&gt;pitch&lt;/code&gt; to set a custom voice changer, the value range of this parameter is [-8.0, 8.0], the larger the value, the sharper the sound, the default value is 0.0 (ie no voice change).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoVoiceChangerParam&lt;/span&gt; &lt;span class="n"&gt;voiceChangerParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoVoiceChangerParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setVoiceChangerParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reverberation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Preset Reverb
&lt;/h3&gt;

&lt;p&gt;Call &lt;code&gt;setReverbPreset&lt;/code&gt; to set reverberation through preset enumeration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ZegoReverbPreset&lt;/code&gt; preset reverb effects are as follows, developers can choose according to their needs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536325703843.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536325703843.jpg" alt="ZegoReverbPreset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following sample code takes the large room mode as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbPreset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoReverbPreset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LARGE_ROOM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Custom Reverb
&lt;/h3&gt;

&lt;p&gt;If the SDK preset reverb type cannot meet the needs, developers can call &lt;code&gt;ZegoReverbAdvancedParam&lt;/code&gt; method, to achieve the reverberation effect required by the developer through the configuration of related parameters (for detailed parameter description, please refer to the API documentation).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoReverbAdvancedParam&lt;/span&gt; &lt;span class="n"&gt;reverbParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoReverbAdvancedParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;damping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reverberation damping&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reverberance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reverberation&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;roomSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// room size&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wetOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wetGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dryGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toneLow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toneHigh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preDelay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;20.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stereoWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbAdvancedParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverbParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting the custom reverb parameters, the preset reverb effect set when reverb is enabled will be invalid. If you want to use the SDK preset parameters again, you can use &lt;code&gt;setReverbPreset&lt;/code&gt;. Set enumeration method to set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reverberation Echo
&lt;/h2&gt;

&lt;p&gt;Call the &lt;code&gt;setReverbEchoParam&lt;/code&gt; method and set the relevant parameters to realize the developer The required reverberation echo effect (for detailed parameter description, please refer to the API document).&lt;/p&gt;

&lt;p&gt;The following sample code takes the ethereal effect as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoReverbEchoParam&lt;/span&gt; &lt;span class="n"&gt;echoParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoReverbEchoParam&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;outGain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;numDelays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="mi"&gt;230&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;460&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;690&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1150&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1380&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1610&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="mf"&gt;0.41f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.18f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.08f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.03f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.009f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.003f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.001f&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;decay&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;zegoReverbEchoParamDatas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setReverbEchoParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echoParam&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Virtual Stereo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set the Number of Streaming Audio Channels
&lt;/h3&gt;

&lt;p&gt;If you need to turn on the virtual stereo function, you must first call the &lt;code&gt;setAudioConfig&lt;/code&gt; method to set before pushing the stream The audio encoding channel is Stereo dual channel (default is Mono).&lt;/p&gt;

&lt;p&gt;The example here uses the preset enumeration structure &lt;code&gt;ZegoAudioConfig&lt;/code&gt; to be set to dual-channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoAudioConfig&lt;/span&gt; &lt;span class="n"&gt;audioConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ZegoAudioConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;STANDARD_QUALITY_STEREO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setAudioConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audioConfig&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Virtual Stereo Parameters
&lt;/h3&gt;

&lt;p&gt;After setting the audio encoding channel to dual channel, call the &lt;code&gt;enableVirtualStereo&lt;/code&gt; method, Turn on the virtual stereo through the enable parameter, and set the sound source angle of the virtual stereo through the angle parameter to have the stereo effect. The angle range is 0 to 360, and generally can be set to 90 degrees (that is, straight ahead).&lt;/p&gt;

&lt;p&gt;Starting from the &lt;strong&gt;2.15.0&lt;/strong&gt; version, the SDK supports the all-around virtual stereo. To enable it, set the &lt;code&gt;angle&lt;/code&gt; parameter to &lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following shows how to turn on the virtual stereo and set the angle to 90 degrees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;enableVirtualStereo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following shows how to enable the all-around virtual stereo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ZegoExpressEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEngine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;enableVirtualStereo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>android</category>
      <category>java</category>
      <category>mobile</category>
      <category>voice</category>
    </item>
    <item>
      <title>How to use ZEGOCLOUD SDK to implement call quality monitoring in Android</title>
      <dc:creator>AndrewDDev</dc:creator>
      <pubDate>Fri, 27 May 2022 06:42:48 +0000</pubDate>
      <link>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-call-quality-monitoring-in-android-4863</link>
      <guid>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-call-quality-monitoring-in-android-4863</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16509779206897.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16509779206897.jpg" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The ZEGOCLOUD Express-Video SDK provides the ability to monitor the streaming quality during stream publishing and stream playing. After stream publishing or stream playing is started, the SDK triggers the corresponding streaming quality callback every 3 seconds, and client applications can obtain real-time streaming quality data by listening for these callbacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you monitor the streaming information, make sure you complete the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in &lt;a href="https://console.zegocloud.com?_source=dev&amp;amp;article=8" rel="noopener noreferrer"&gt;ZEGOCLOUD Admin Console&lt;/a&gt;, and get the AppID of your project.&lt;/li&gt;
&lt;li&gt;The ZEGO Express SDK has been integrated into the project. For details, see &lt;a href="https://docs.zegocloud.com/article/195?_source=dev&amp;amp;article=8" rel="noopener noreferrer"&gt;Integration&lt;/a&gt; and &lt;a href="https://docs.zegocloud.com/article/10836?_source=dev&amp;amp;article=8" rel="noopener noreferrer"&gt;Implementation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitor the quality of stream publishing
&lt;/h2&gt;

&lt;p&gt;To monitor the quality of the stream publishing, listen for the &lt;code&gt;onPublisherQualityUpdate&lt;/code&gt; callback. After stream publishing is started, this callback will be triggered every 3 seconds to provide the stream publishing quality data. &lt;/p&gt;

&lt;p&gt;You can obtain stream publishing quality data through this callback to monitor the health of stream publishing in real time and display the upstreaming network quality on your application's UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherQualityUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ZegoPublishStreamQuality&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// You can focus on specific quality attributes and report them to your business server, or focus on a specific field of an object for giving friendly notes for users.&lt;/span&gt;
    &lt;span class="c1"&gt;// The parameter 'quality' has many attributes. If you do not want to handle every one of them, you can just focus on the 'level' attribute, a comprehensive quality indicator calculated by the SDK based on other quality attributes.&lt;/span&gt;
     &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;v&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"onPublisherQualityUpdate: streamID="&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The stream publishing quality attributes in details
&lt;/h3&gt;

&lt;p&gt;The stream publishing quality includes the audio and video capture frame rate, bitrate, RTT, packet loss rate, and others of capturing and encoding stages of the stream publishing process.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ZegoPublishStreamQuality&lt;/code&gt; object includes quality attributes of different stages of the stream publishing process. You can find the detailed attribute definitions in this section:&lt;/p&gt;

&lt;h4&gt;
  
  
  Quality attributes of audio and video capturing
&lt;/h4&gt;

&lt;p&gt;The following attributes reflect the stream publishing quality of audio and video capturing, which is close to the user's subjective perception of the local preview. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;audioCaptureFPS&lt;/code&gt;: The audio capture frame rate (fps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoCaptureFPS&lt;/code&gt;: The video capture frame rate (fps).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of video encoding
&lt;/h4&gt;

&lt;p&gt;The stream publishing quality attributes of video encoding of the encoding stage is as follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;videoEncodeFPS&lt;/code&gt;: The target output frame rate (fps) of video encoding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of stream transmission
&lt;/h4&gt;

&lt;p&gt;The stream publishing quality attributes below reflect the quality of stream transmission (sending), which is related to the encoding bitrate and the current network quality. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;audioSendFPS&lt;/code&gt;: The actual audio transmission frame rate (fps). &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioKBPS&lt;/code&gt;: The actual audio transmission bitrate (kbps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoSendFPS&lt;/code&gt;: The actual video transmission frame rate (fps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoKBPS&lt;/code&gt;: The actual video transmission bitrate (kbps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rtt&lt;/code&gt;: The rount-trip time (ms) from the client device to the ZEGO server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packetLostRate&lt;/code&gt;: The client-side upstreaming packet loss rate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of the total number of bytes
&lt;/h4&gt;

&lt;p&gt;The stream publishing quality attributes below reflect the total number of bytes sent.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;totalSendBytes&lt;/code&gt;: The total number of bytes sent, including audio, video, SEI.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioSendBytes&lt;/code&gt;: The number of audio bytes sent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoSendBytes&lt;/code&gt;: The number of video bytes sent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of encoding information
&lt;/h4&gt;

&lt;p&gt;The stream publishing quality attributes below reflect the encoding information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;videoCodecID&lt;/code&gt;: The video codec.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isHardwareEncoder&lt;/code&gt;: Whether to enable hardware encoding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of published stream quality level
&lt;/h4&gt;

&lt;p&gt;The parameter &lt;code&gt;quality&lt;/code&gt; has many attributes. If you do not want to handle every one of them, you can just focus on the &lt;code&gt;level&lt;/code&gt; attribute, a comprehensive upstreaming network qualityindicator calculated by the &lt;code&gt;ZegoExpressEngine&lt;/code&gt; based on other quality attributes. &lt;/p&gt;

&lt;p&gt;The following table describes the &lt;code&gt;level&lt;/code&gt; fields: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536221815846.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536221815846.jpg" alt="level"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitor the quality of stream playing
&lt;/h2&gt;

&lt;p&gt;To monitor the quality of the stream playing, listen for the &lt;code&gt;onPlayerQualityUpdate&lt;/code&gt; callback. After stream playing is started, this callback will be triggered every 3 seconds to provide the stream playing quality data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerQualityUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ZegoPlayStreamQuality&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// You can focus on specific quality attributes and report them to your business server, or focus on a specific field of an object for giving friendly notes for users.&lt;/span&gt;
     &lt;span class="c1"&gt;// The parameter 'quality' has many attributes. If you do not want to handle every one of them, you can just focus on the 'level' attribute, a comprehensive quality indicator calculated by the SDK based on other quality attributes.&lt;/span&gt;
     &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;v&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"onPlayerQualityUpdate: streamID="&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The stream playing quality attributes in details
&lt;/h3&gt;

&lt;p&gt;The stream playing quality includes the audio and video frame rate, bitrate, delay, packet loss rate, and others of receiving, decoding, and rendering stages of the stream playing process.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ZegoPlayStreamQuality&lt;/code&gt; object includes quality attributes of different stages of the stream playing process. You can find the detailed attribute definitions in this section:&lt;/p&gt;

&lt;h4&gt;
  
  
  Quality attributes of stream receiving
&lt;/h4&gt;

&lt;p&gt;The stream playing quality attributes below reflect the quality of stream receiving, which is related to the quality of stream transmission (sending) and the current network quality. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;audioRecvFPS&lt;/code&gt;: The actual audio receiving frame rate (fps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioDejitterFPS&lt;/code&gt;: The audio dejitter frame rate (f/s).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioKBPS&lt;/code&gt;: The actual audio receiving bitrate (kbps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioBreakRate&lt;/code&gt;: The actual received audio break rate (number of breaks / every 10 seconds).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoRecvFPS&lt;/code&gt;: The actual video receiving frame rate (fps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoDejitterFPS&lt;/code&gt;: The video dejitter frame rate (f/s).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoKBPS&lt;/code&gt;: The actual video receiving bitrate (kbps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoBreakRate&lt;/code&gt;: The actual received video break rate (number of breaks / every 10 seconds).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packetLostRate&lt;/code&gt;: The client-side downstreaming packet loss rate, in percentage, 0.0 - 1.0. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rtt&lt;/code&gt;: The round-trip time (ms) from the client device to the ZEGO server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;avTimestampDiff&lt;/code&gt;: The difference between the video timestamp and the audio timestamp, used to reflect the synchronization of audio and video, in milliseconds. This value is less than 0 means the number of milliseconds that the video leads the audio, greater than 0 means the number of milliseconds that the video lags the audio, and 0 means no difference. When the absolute value is less than 200, it can basically be regarded as synchronized audio and video, when the absolute value is greater than 200 for 10 consecutive seconds, it can be regarded as abnormal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;peerToPeerDelay&lt;/code&gt;: The delay from peer to peer, in milliseconds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;peerToPeerPacketLostRate&lt;/code&gt;: The packet loss rate from peer to peer, in percentage, 0.0 - 1.0.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of stream rendering
&lt;/h4&gt;

&lt;p&gt;The stream playing attributes below reflect the streaming quality at the stream rendering stage, which is close to the viewer's subjective perception. They are affected by the audio/video codec, and the values may be lower than the actual audio/video receiving frame rates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;audioRenderFPS&lt;/code&gt;|_blank](@audioRenderFPS-ZegoPlayStreamQuality): The audio rendering frame rate (fps). &lt;/li&gt;
&lt;li&gt;[&lt;code&gt;videoRenderFPS&lt;/code&gt;: The video rendering frame rate (fps).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delay&lt;/code&gt;: The delay after the data is received by the local end, in milliseconds. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of the total number of bytes
&lt;/h4&gt;

&lt;p&gt;The stream publishing quality attributes below reflect the total number of bytes received.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;totalRecvBytes&lt;/code&gt;: The total number of bytes received, including audio, video, SEI.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audioRecvBytes&lt;/code&gt;: The number of audio bytes received.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;videoRecvBytes&lt;/code&gt;: The number of video bytes received&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quality attributes of decoding information
&lt;/h4&gt;

&lt;p&gt;The stream playing quality attributes below reflect the decoding information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;videoCodecID&lt;/code&gt;: The video codec.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isHardwareDecode&lt;/code&gt;: Whether to enable hardware decoding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitor the status of stream publishing/playing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Callback for updates on stream publishing status
&lt;/h3&gt;

&lt;p&gt;After stream publishing starts, if the status changes, the SDK sends out the event notification through the &lt;code&gt;onPublisherStateUpdate&lt;/code&gt; callback. To monitor the status of stream publishing, listen for this callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ZegoPublisherState&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;errorCode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;extendedData&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPublisherStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errorCode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extendedData&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// In this callback, when the [state] is [ZegoPublisherState.NO_PUBLISH] and the [errorCode] is not 0, indicates the stream publishing is failed. And the SDK won't retry to publish the stream. At this time, user can set a corresponding UI to indicate the current state.     &lt;/span&gt;
        &lt;span class="c1"&gt;// In this callback, when the [state] is [ZegoPublisherState.PUBLISH_REQUESTING] and the [errorCode] is not 0, indicates the stream publishing retry is ongoing. But if the stream publishing retry still fails after the default reconnection duration, it won't try again and will send out a failure notification.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can determine the user's network status during stream publishing based on the &lt;code&gt;state&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The following table describes the value of the &lt;code&gt;state&lt;/code&gt; property and the corresponding user status:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536222340058.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536222340058.jpg" alt="corresponding user status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The parameter &lt;code&gt;extendedData&lt;/code&gt; provides extended information for status updates. If you are using the ZEGO CDN, the key of this parameter is &lt;code&gt;flv_url_list&lt;/code&gt;, &lt;code&gt;rtmp_url_list&lt;/code&gt;, and &lt;code&gt;hls_url_list&lt;/code&gt;, which correspond to the stream playing URL of &lt;code&gt;FLV&lt;/code&gt;, &lt;code&gt;RTMP&lt;/code&gt;, and &lt;code&gt;HLS&lt;/code&gt; protocols respectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Callback for updates on stream playing status
&lt;/h3&gt;

&lt;p&gt;After stream playing starts, if the status changes, the SDK sends out the event notification through the &lt;a href="https://dev.to@onPlayerStateUpdate"&gt;&lt;code&gt;onPlayerStateUpdate&lt;/code&gt;&lt;/a&gt; callback. To monitor the status of stream playing, listen for this callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ZegoPlayerState&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;errorCode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;extendedData&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPlayerStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errorCode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extendedData&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// In this callback, when the [state] is [ZegoPlayerState.NO_PLAY] and the [errorCode] is not 0, indicates the stream playing is failed. And the SDK won't retry to play the stream. At this time, user can set a corresponding UI to indicate the current state. &lt;/span&gt;
        &lt;span class="c1"&gt;// In this callback, when the [state] is [ZegoPlayerState.PLAY_REQUESTING] and the [errorCode] is not 0, indicates the stream playing retry is ongoing. But if the stream playing retry still fails after the default reconnection duration, it won't try again and will send out a failure notification.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can determine the user's network status during stream playing based on the &lt;code&gt;state&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The following table describes the value of the &lt;code&gt;state&lt;/code&gt; property and the corresponding user status:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536222976219.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536222976219.jpg" alt="user status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitor the first frame of audio and video
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Callback on capturing the first frame of audio
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the first frame of audio is captured, listen for the &lt;a href="https://dev.to@onPublisherCapturedAudioFirstFrame"&gt;&lt;code&gt;onPublisherCapturedAudioFirstFrame&lt;/code&gt;&lt;/a&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream publishing starts, the SDK sends out the event notification through this callback when the first frame of audio is captured.&lt;/p&gt;

&lt;p&gt;When you enable stream publishing or local preview for the first time, the SDK engine starts to capture the audio data of the local device, and the SDK sends out event notification through this callback.&lt;br&gt;
You can tell whether the audio data has been captured successfully according to the returned event notification. If no notifications are received, it means the audio device is being used or the device is abnormal.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherCapturedAudioFirstFrame&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPublisherCapturedAudioFirstFrame&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Callback on capturing the first frame of video
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the first frame of video is captured, listen for the &lt;a href="https://dev.to@onPublisherCapturedVideoFirstFrame"&gt;&lt;code&gt;onPublisherCapturedVideoFirstFrame&lt;/code&gt;&lt;/a&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream publishing starts, the SDK sends out the event notification through this callback when the first frame of video is captured.&lt;/p&gt;

&lt;p&gt;When you enable stream publishing or local preview for the first time, the SDK engine starts to capture the video data of the local device, and the SDK sends out event notification through this callback.&lt;br&gt;
You can tell whether the video data has been captured successfully according to the returned event notification. If no notifications are received, it means the video device is being used or the device is abnormal.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherCapturedVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoPublishChannel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPublisherCapturedVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Callback on receiving the first frame of audio
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the first frame of audio is received, listen for the &lt;a href="https://dev.to@onPlayerRecvAudioFirstFrame"&gt;&lt;code&gt;onPlayerRecvAudioFirstFrame&lt;/code&gt;&lt;/a&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream playing starts, the SDK sends out the event notification through this callback when the first frame of audio is received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerRecvAudioFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPlayerRecvAudioFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;AppLogger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;receiveCallback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"onPlayerRecvAudioFirstFrame streamID:%s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Callback on receiving the first frame of video
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the first frame of video is received, listen for the &lt;code&gt;onPlayerRecvVideoFirstFrame&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream playing starts, the SDK sends out the event notification through this callback when the first frame of video is received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerRecvVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPlayerRecvVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Callback on rendering the first frame of video
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the first frame of video is rendered, listen for the &lt;code&gt;onPlayerRenderVideoFirstFrame&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream playing starts, the SDK sends out the event notification through this callback when the first frame of video is received and has been rendered.&lt;/p&gt;

&lt;p&gt;You can also use this callback to count the time consumed by capturing/receiving/rendering the first frame or use this callback to update the UI components of stream playing.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerRenderVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPlayerRenderVideoFirstFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitor the changes on video resolution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Callback for the changes on the captured video resolution
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the captured video size changes, listen for the &lt;code&gt;onPublisherVideoSizeChanged&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream publishing starts, the SDK sends out the event notification through this callback when the resolution of the captured video changes.&lt;/p&gt;

&lt;p&gt;When you enable stream publishing or local preview for the first time, the SDK engine starts to capture the video data of the local device, and the resolution of the video changes simultaneously.&lt;/p&gt;

&lt;p&gt;You can use this callback to remove the UI elements in the view of the local video preview, or adjust the scale of the view of the local preview dynamically based on the resolution returned by the event callback. &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherVideoSizeChanged&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ZegoPublishChannel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPublisherVideoSizeChanged&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Callback for the changes on the played video resolution
&lt;/h3&gt;

&lt;p&gt;To receive the event notification when the played video resolution changes, listen for the &lt;code&gt;onPlayerVideoSizeChanged&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;After stream playing starts, the SDK sends out the event notification through this callback when the resolution of the played video changes. You can adjust the video display based on the final resolution of the video streams.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You won't receive any notifications when playing audio-only streams. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the stream publisher end triggers the traffic control within the SDK due to network issues, the code distinguishability on the stream publisher side may be dynamically reduced, and SDK sends out notification through this callback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The SDK sends out notification when the UI of the streams you played is being rendered. You can use this callback to update or switch the UI elements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPlayerVideoSizeChanged&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitor the status of the stream forwarding via CDN
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Callback for updates on the status of CDN URL
&lt;/h3&gt;

&lt;p&gt;To receive event notification when the specified CDN URL changes (adds new URL or removes existing URL), listen for the &lt;code&gt;onPublisherRelayCDNStateUpdate&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;After the ZEGO RTC Server forwards the stream to CDN, the SDK sends out event notification when the status of streams forwarded to CDN changes, for example, the stream forwarding stops or the forwarding operation retries. &lt;/p&gt;

&lt;p&gt;You can tell whether the audio and video streams forwarded to CDN are normal according to this callback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the returned result of this callback indicates it is abnormal, locate the cause of the audio and video streams forwarded to CDN and perform a disaster recovery operation accordingly.&lt;/li&gt;
&lt;li&gt;If you do not know the cause of the exception, contact ZEGO technical support for further analysis.&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEventHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IZegoEventHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPublisherRelayCDNStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ZegoStreamRelayCDNInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;infoList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPublisherRelayCDNStateUpdate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;infoList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The stream forwarding attributes in details
&lt;/h3&gt;

&lt;p&gt;The stream forwarding information includes the CDN URL, forwarding status, the cause of stream forwarding status, and when the status changes.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ZegoStreamRelayCDNInfo&lt;/code&gt; object includes stream forwarding attributes. You can find the detailed attribute definitions in this section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536223901465.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536223901465.jpg" alt="ZegoStreamRelayCDNInfo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following table describes the value of the &lt;code&gt;state&lt;/code&gt; property:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536224604942.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536224604942.jpg" alt="state"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following table describes the value of the &lt;code&gt;updateReason&lt;/code&gt; property:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536322903990.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresource.zegocloud.com%2Fcontent_resource%2F2022%2F05%2F27%2F16536322903990.jpg" alt="updateReason"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>zegocloud</category>
      <category>java</category>
      <category>mobile</category>
    </item>
    <item>
      <title>How to use ZEGOCLOUD SDK to implement Acoustic Echo Cancellation、Automatic Gain Control、Active Noise Control in android</title>
      <dc:creator>AndrewDDev</dc:creator>
      <pubDate>Mon, 23 May 2022 12:22:17 +0000</pubDate>
      <link>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-acoustic-echo-cancellation-automatic-gain-control-active-noise-control-in-android-3kj3</link>
      <guid>https://dev.to/andrewddev/how-to-use-zegocloud-sdk-to-implement-acoustic-echo-cancellation-automatic-gain-control-active-noise-control-in-android-3kj3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2pW6RO36--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/23/16510311268680.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2pW6RO36--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resource.zegocloud.com/content_resource/2022/05/23/16510311268680.jpg" alt="cover image" width="880" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;To promote audio quality and user experience, ZEGOCLOUD provides the ability to process audio with 3A technologies, including AEC, AGC, and ANS. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AEC (Acoustic Echo Cancellation): A method of removing the echo from the audio signal captured by the microphone. After this feature is enabled, the SDK will filter the collected audio data to remove the echo.&lt;/li&gt;
&lt;li&gt;AGC (Automatic Gain Control): A feature that automatically adjusts the receiver's audio gain (volume). After this feature is enabled, the sound will be amplified, but the sound quality will be affected to some extent.&lt;/li&gt;
&lt;li&gt;ANS (Active Noise Control): A set of audio technologies that actively cancel the ambient noise. Enabling this feature will make your voice clearer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, make sure you complete the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project in &lt;a href="https://console.zegocloud.com?_source=dev&amp;amp;article=4"&gt;ZEGOCLOUD Admin Console&lt;/a&gt;, and get the AppID of your project.&lt;/li&gt;
&lt;li&gt;The ZEGO Express SDK has been integrated into the project. For details, see &lt;a href="https://docs.zegocloud.com/article/195?_source=dev&amp;amp;article=4"&gt;Integration&lt;/a&gt; and &lt;a href="https://docs.zegocloud.com/article/10836?_source=dev&amp;amp;article=4"&gt;Implementation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up audio 3A processing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set up the AEC (Acoustic Echo Cancellation)
&lt;/h3&gt;

&lt;p&gt;To implement the AEC feature, do the following: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To enable the AEC feature, call the &lt;code&gt;enableAEC&lt;/code&gt; method. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional: To enable the AEC feature for the headphones scenario, call the &lt;code&gt;enableHeadphoneAEC&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To set the AEC mode, call the &lt;code&gt;setAECMode&lt;/code&gt; mode. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following sample code is used for setting the AEC to the medium mode (&lt;code&gt;ZegoAECMode.MEDIUM&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Enable the AEC feature.&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableAEC&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Enable the AEC when using headphones.&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableHeadphoneAEC&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Set the AEC to medium mode (ZegoAECMode.MEDIUM).&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAECMode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoAECMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MEDIUM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up the AGC (Automatic Gain Control)
&lt;/h3&gt;

&lt;p&gt;To enable the AGC, call the &lt;code&gt;enableAGC&lt;/code&gt; method. After this function is turned on, the SDK can automatically adjust the Microphone Volume to adapt to near and far sound pickups and keep the Volume stable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Enable the AGC feature.&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableAGC&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up the ANS (Active Noise Control)
&lt;/h3&gt;

&lt;p&gt;To implement the ANS feature, do the following: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To enable the ANS feature, call the &lt;code&gt;enableANS&lt;/code&gt; method. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional: To control or cancel the transient noise, call the &lt;code&gt;enableTransientANS&lt;/code&gt; method. This feature can be used to suppress the noise of typing keyboard, table, etc. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To set or adjust the ANS mode, call the &lt;code&gt;setANSMode&lt;/code&gt; method. The SDK uses medium mode (&lt;code&gt;ZegoANSMode.MEDIUM&lt;/code&gt;) by default. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following sample code is used for setting the ANS to the soft mode (&lt;code&gt;ZegoANSMode.SOFT&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Enable the ANS feature.&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableANS&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Enable the transient ANS feature to control the transient noise.&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableTransientANS&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Set the ANS to soft mode (ZegoANSMode.SOFT).&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setANSMode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZegoANSMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SOFT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recommended configurations for 3A
&lt;/h3&gt;

&lt;p&gt;The default and recommended configurations for audio 3A processing in the SDK are as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default config&lt;/th&gt;
&lt;th&gt;Recommended config&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableAEC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable/Disable the AEC feature.&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;We recommend you use the default settings for general scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableHeadphoneAEC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable the AEC for the headphone scenario.&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;We recommend you enable this for chatting or playing games in groups.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setAECMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set the AEC mode.&lt;/td&gt;
&lt;td&gt;ZegoAECMode.AGGRESSIVE (Aggressive mode)&lt;/td&gt;
&lt;td&gt;We recommend you use the default settings for general scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableAGC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable/Disable the AGC feature.&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt; In the chatting scenario, use the default settings.&lt;/li&gt;
&lt;li&gt;In the music radio scenario, disable the AGC feature to keep original sound.&lt;/li&gt;
&lt;li&gt; In the educational scenarios, such as large classes, small classes, and 1v1 classes, enable the AGC feature.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableANS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable/Disable the ANS feature.&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;We recommend you use the default settings for general scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setANSMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set the ANS mode.&lt;/td&gt;
&lt;td&gt;ZegoANSMode.MEDIUM (Medium mode)&lt;/td&gt;
&lt;td&gt;We recommend you use the default settings for general scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>noise</category>
      <category>zegocloud</category>
      <category>video</category>
      <category>audio</category>
    </item>
  </channel>
</rss>
