Skip to main content

Call quality

Customer satisfaction for your Voice Calling integrated app depends on the quality of audio it provides. The quality of audio communication through your app is affected by the following factors:

  • Bandwidth of network connection: Bandwidth is the volume of information that an Internet connection can handle per unit of time. When the available bandwidth is not sufficient to transmit the amount of data necessary to provide the desired quality, your users hear audio that cuts in and out.

  • Stability of network connection: Network connections are often unstable with the network quality going up and down. Users get temporarily disconnected and come back online after an interruption. These issues lead to a poor audio experience for your users unless your app is configured to respond to these situations and take remedial actions.

  • Hardware quality: The microphone used to capture audio must be of sufficiently good quality. If the user's hardware does not capture the audio information in suitably high definition, it limits the quality of audio that is available to the remote user.

  • Audio settings: The audio quality depends on the sample rate, bitrate, number of channels and other audio parameters. If you do not choose proper settings, the audio transmitted is of poor quality. On the other hand, if the settings are too demanding, the available bandwidth quickly gets choked leading to suboptimal experience for your users.

  • Echo: Echo is produced when your audio signal is played by a remote user through a speakerphone or an external device. This audio is captured by the remote user's microphone and sent back to you. Echo negatively effects audio quality making speech difficult to understand.

  • Multiple users in a channel: When multiple users engage in real-time communication in a channel, the available bandwidth is quickly used up due to several incoming streams. The device performance also deteriorates due to the excessive workload required to decode and play multiple streams.

This page shows you how to use Voice SDK features to account for such factors in your app and ensure optimal audio quality in your Voice Calling app.

Understand the tech

Voice SDK provides the following features to deal with channel quality issues:

  • Network probe test: The network probe test checks the last-mile network quality before you join a channel. The method returns network quality statistics including round-trip latency, packet loss rate, and network bandwidth.

  • Audio profiles: Delivering the best quality audio to your users requires choosing audio settings customized for your particular application. In Voice SDK you can choose from pre-configured audio profiles and audio scenarios to optimize audio settings for a wide range of applications.

    • An audio profile sets the audio sample rate, bitrate, encoding scheme, and the number of channels for your audio. Voice SDK offers several preset audio profiles to choose from. To pick the most suitable audio profile for your application, refer to the List of audio profiles.
    • An audio scenario specifies the audio performance in terms of volume, audio quality, and echo cancellation. Based on the nature of your application, you can pick the most suitable option from the List of audio scenarios.
  • In-call quality statistics: Voice SDK provides several callbacks and methods to monitor channel quality in real-time. These methods and callbacks provide vital statistics to evaluate communication quality and provide the information necessary to take remedial actions. Voice SDK provides you the following statistics :

    • Network quality: The uplink and downlink network quality in terms of the transmission bitrate, packet loss rate, average Round-Trip Time (RTT), and jitter in your network.

    • Call quality: Information on the current user session and the resources being used by the channel in terms of the number of users in a channel, packet loss rate, CPU usage and call duration. Use these statistics to troubleshoot call quality issues.

    • Local audio quality: Local audio measurements such as audio channels, sample rate, sending bitrate, and packet loss rate in the audio stream.

    • Remote audio quality: These statistics provide information such as the number of channels, received bitrate, jitter in the audio stream, audio loss rate, and packet loss rate.

    • Audio states: Agora SD-RTN™ reports the new state, and the reason for change, whenever the state of an audio stream changes.

  • Echo cancellation: Voice SDK offers audio mixing functionality to play media in a channel. You can mix a local or online audio file with the audio captured through the microphone, or completely replace the microphone audio. Audio mixing takes advantage of the echo cancellation features of Voice SDK to reduce echo in a channel. Refer to Audio and voice effects to learn more about audio mixing in Voice SDK.

  • Connection state monitoring: The connection state between an app and Agora SD-RTN™ changes when the app joins or leaves a channel, or goes offline due to network or authentication issues. Voice SDK provides connection state monitoring to detect when and why a network connection is interrupted. When the connection state changes, Agora SD-RTN™ sends a callback to notify the app. Voice SDK then automatically tries to reconnect to the server to restore the connection.

  • Log files: Voice SDK provides configuration options that you use to customize the location, content and size of log files containing key data of Voice SDK operation. When you setup logging, Voice SDK writes information messages, warnings, and errors regarding activities such as initialization, configuration, connection and disconnection to log files. Log files are useful in detecting and resolving channel quality issues.

The following figure shows the workflow you need to implement to ensure channel quality in your app:

Ensure Channel Quality

Prerequisites

In order to follow this procedure you must have:

  • Android Studio 4.1 or higher.
  • Android SDK API Level 24 or higher.
  • A mobile device that runs Android 4.1 or higher.
  • An Agora account and project.

  • A computer with Internet access.

    Ensure that no firewall is blocking your network communication.

Project setup

To create the environment necessary to implement call quality best practice into your app, open the SDK quickstart Voice Calling project you created previously.

Implement best practice to optimize call-quality

This section shows you how to integrate call-quality optimization features of Voice SDK into your app, step-by-step.

Implement the user interface

This section guides you through the necessary UI changes in the SDK quickstart project interface to implement call quality features.

Add a network status indicator to the user interface

In order to enable app users to see the network status, add TextView elements to the user interface. To do this, open /app/res/layout/activity_main.xml and add the following lines before </RelativeLayout>:


_25
<TextView
_25
android:id="@+id/networkStatus"
_25
android:layout_width="20dp"
_25
android:layout_height="20dp"
_25
android:layout_below="@id/joinLeaveButton"
_25
android:layout_alignRight="@id/joinLeaveButton"
_25
/>
_25
_25
<TextView
_25
android:id="@+id/networkLabel"
_25
android:layout_width="wrap_content"
_25
android:layout_height="wrap_content"
_25
android:layout_below="@id/joinLeaveButton"
_25
android:layout_toLeftOf="@id/networkStatus"
_25
android:text="Network Status: "
_25
/>
_25
_25
<Button
_25
android:id="@+id/echoTestButton"
_25
android:layout_width="wrap_content"
_25
android:layout_height="wrap_content"
_25
android:layout_below="@id/joinLeaveButton"
_25
android:layout_alignStart="@id/joinLeaveButton"
_25
android:onClick="echoTest"
_25
android:text="Start Echo Test" />

Handle the system logic

  1. Import the required Android and Agora libraries

    To set the TextView color, and integrate Voice SDK channel quality libraries, add the following statements after the last import statement in /app/java/com.example.<projectname>/MainActivity.


    _4
    import android.graphics.Color;
    _4
    _4
    import io.agora.rtc2.internal.LastmileProbeConfig;
    _4
    import io.agora.rtc2.EchoTestConfiguration;

  2. Define variables to manage test state and workflow

    In /app/java/com.example.<projectname>/MainActivity, add the following declaration to class MainActivity:


    _4
    private TextView networkStatus; // For updating the network status
    _4
    private int counter = 0; // Controls the frequency of messages
    _4
    private boolean isEchoTestRunning = false; // Keeps track of the echo test
    _4
    private Button echoTestButton;

  3. Update the network status indication

    To show the network quality result visually to the user, add the following to the MainActivity class:


    _6
    private void updateNetworkStatus(int quality){
    _6
    if (quality > 0 && quality < 3) networkStatus.setBackgroundColor(Color.GREEN);
    _6
    else if (quality <= 4) networkStatus.setBackgroundColor(Color.YELLOW);
    _6
    else if (quality <= 6) networkStatus.setBackgroundColor(Color.RED);
    _6
    else networkStatus.setBackgroundColor(Color.WHITE);
    _6
    }

    To setup access to the network status indicator UI element, add the following lines to the onCreate method after setupVoiceSDKEngine();


    _2
    networkStatus = findViewById(R.id.networkStatus);
    _2
    echoTestButton = findViewById(R.id.echoTestButton);

Implement features to ensure quality

To implement the call quality features, take the following steps:

  1. Enable the user to test the network

    In the MainActivity class, add the following method:


    _14
    public void startProbeTest() {
    _14
    // Configure a LastmileProbeConfig instance.
    _14
    LastmileProbeConfig config = new LastmileProbeConfig();
    _14
    // Probe the uplink network quality.
    _14
    config.probeUplink = true;
    _14
    // Probe the downlink network quality.
    _14
    config.probeDownlink = true;
    _14
    // The expected uplink bitrate (bps). The value range is [100000,5000000].
    _14
    config.expectedUplinkBitrate = 100000;
    _14
    // The expected downlink bitrate (bps). The value range is [100000,5000000].
    _14
    config.expectedDownlinkBitrate = 100000;
    _14
    agoraEngine.startLastmileProbeTest(config);
    _14
    showMessage("Running the last mile probe test ...");
    _14
    }

  2. Set log file configuration

    When a user starts your app, the Agora Engine is initialized. Before initialization, you set the log file parameters using LogConfig. In setupVoiceSDKEngine, add the following code before agoraEngine = RtcEngine.create(config);.


    _8
    // Setup log configuration
    _8
    RtcEngineConfig.LogConfig logConfig = new RtcEngineConfig.LogConfig();
    _8
    // Set the log filter to ERROR
    _8
    logConfig.level = Constants.LogLevel.getValue(Constants.LogLevel.LOG_LEVEL_ERROR);
    _8
    // Set the log file size to 2 MB
    _8
    logConfig.fileSizeInKB = 2048;
    _8
    // Assign the log configuration object to engine configuration
    _8
    config.mLogConfig = logConfig;

  3. Implement best practice for app initiation

    After Agora Engine initialization, do the following:

    • Set an audio profile and audio scenario: Setting an audio profile is optional and only required if you have special requirements such as streaming music.
    • Start the network probe test: A quick test at startup to gauge network quality.

    To implement these features, add the following code to setupVoiceSDKEngine after agoraEngine = RtcEngine.create(config);;


    _5
    // Set audio profile and audio scenario.
    _5
    agoraEngine.setAudioProfile(Constants.AUDIO_PROFILE_DEFAULT, Constants.AUDIO_SCENARIO_GAME_STREAMING);
    _5
    _5
    // Start the probe test
    _5
    startProbeTest();

  4. Test the user's hardware

    The echo test checks that the user's hardware is working properly. To start and stop the test, add the following method to the MainActivity class:


    _16
    public void echoTest(View view) {
    _16
    if (!isEchoTestRunning) {
    _16
    EchoTestConfiguration echoConfig = new EchoTestConfiguration();
    _16
    echoConfig.enableAudio = true;
    _16
    echoConfig.token = token;
    _16
    echoConfig.channelId = channelName;
    _16
    _16
    agoraEngine.startEchoTest(echoConfig);
    _16
    echoTestButton.setText("Stop Echo Test");
    _16
    isEchoTestRunning = true;
    _16
    } else {
    _16
    agoraEngine.stopEchoTest();
    _16
    echoTestButton.setText("Start Echo Test");
    _16
    isEchoTestRunning = false;
    _16
    }
    _16
    }

  5. Listen to Agora Engine events to receive state change notifications and quality statistics.

    Add the following event handlers to receive state change notifications and quality statistics:

    • onLastmileQuality: Receives the network quality result.
    • onLastmileProbeResult: Receives detailed probe test results.
    • onNetworkQuality: Receives statistics on network quality.
    • onRtcStats: Receives the Agora Engine stats.
    • onRemoteAudioStateChanged: Receives notifications of audio state change from remote users.

    In the MainActivity class, add the following methods after private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {


    _44
    @Override
    _44
    public void onLastmileQuality(int quality) {
    _44
    runOnUiThread(() -> updateNetworkStatus(quality));
    _44
    }
    _44
    _44
    @Override
    _44
    public void onLastmileProbeResult(LastmileProbeResult result) {
    _44
    agoraEngine.stopLastmileProbeTest();
    _44
    // The result object contains the detailed test results that help you
    _44
    // manage call quality. For example, the downlink jitter"
    _44
    showMessage("Downlink jitter: " + result.downlinkReport.jitter);
    _44
    }
    _44
    _44
    @Override
    _44
    public void onNetworkQuality(int uid, int txQuality, int rxQuality) {
    _44
    // Use DownLink NetQuality to update the network status
    _44
    runOnUiThread(() -> updateNetworkStatus(rxQuality));
    _44
    }
    _44
    _44
    @Override
    _44
    public void onRtcStats(RtcStats rtcStats) {
    _44
    counter += 1;
    _44
    String msg = "";
    _44
    _44
    if (counter == 4)
    _44
    msg = rtcStats.users + " user(s)";
    _44
    else if (counter == 8 ) {
    _44
    msg = "Last mile delay: " + rtcStats.lastmileDelay;
    _44
    }
    _44
    else if (counter == 12 ) {
    _44
    msg = "Packet loss rate: " + rtcStats.rxPacketLossRate;
    _44
    counter = 0;
    _44
    }
    _44
    _44
    if (msg.length()>0) showMessage(msg);
    _44
    }
    _44
    _44
    @Override
    _44
    public void onRemoteAudioStateChanged(
    _44
    int uid, int state, int reason, int elapsed) {
    _44
    // Listens for state change of remote audio
    _44
    showMessage("Remote audio state changed\n User: " + uid
    _44
    + "\n State: " + state + "\n Reason: " + reason);
    _44
    }

  6. Configure the Voice SDK log file

    To customize the location, content and size of log files, add the following code to setupVoiceSDKEngine before agoraEngine = RtcEngine.create(config);:


    _6
    // Configure the log file
    _6
    RtcEngineConfig.LogConfig logConfig = new RtcEngineConfig.LogConfig();
    _6
    logConfig.filePath = "/storage/emulated/0/Android/data/<package name>/files/agorasdk1.log.";
    _6
    logConfig.fileSizeInKB = 256; // Range 128-1024 Kb
    _6
    logConfig.level = Constants.LogLevel.getValue(Constants.LogLevel.LOG_LEVEL_WARN);
    _6
    config.mLogConfig = logConfig;

    Make sure you replace the <package name> in filePath with the name of your package.

    If you want to upload the log file automatically to a CDN, use the method setLocalAccessPoint(LocalAccessPointConfiguration config) to specify the local access point and assign the native access module to the SDK.

Test your implementation

To ensure that you have implemented call quality features into your app:

  1. Generate a temporary token in Agora Console .

  2. In your browser, navigate to the Agora web demo and update App ID, Channel, and Token with the values for your temporary token, then click Join.

  1. In Android Studio, open app/java/com.example.<projectname>/MainActivity, and update appId, channelName and token with the values for your temporary token.

  2. Connect a physical Android device to your development device.

  3. In Android Studio, click Run app. A moment later you see the project installed on your device.

    If this is the first time you run the project, grant microphone and camera access to your app.

  4. When the app starts, it does the following:

    • Sets the log file location, size, and logging level according to your preference.

    • Sets the audio profile

    • Starts a network probe test

      You see the result of the network probe test displayed in the network status icon.

  5. Run the echo test.

    1. Press Start Echo Test.

    2. Speak into the device microphone. You hear the recorded audio after a short delay.

      This test confirms that the user's hardware is working properly.

    3. Press Stop Echo Test to end the test before joining a channel.

  6. Press Join to connect to the same channel as your web demo.

  7. After joining a channel, you receive toast messages informing you of some selected call statistics, including:

    • The number of users in the channel
    • Packet loss rate
    • Remote audio state changes
  8. You see the network status indicator updated periodically based on the result of the onNetworkQuality callback.

Reference

This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this product.

List of audio profiles

Voice SDK provides the following audio profile options:

Audio ProfileSample RateBit RateEncoding ModeNumber of Channels
Default32 kHzUp to 18 KbpsAudio encodingMono
Speech Standard32 kHzUp to 18 KbpsAudio encodingMono
Music Standard48 kHzUp to 64 KbpsMusic encodingMono
Music Standard Stereo48 kHzUp to 80 KbpsMusic encodingStereo
Music High-quality48 kHzUp to 96 KbpsMusic encodingMono
Music High-quality Stereo48 kHzUp to 128 KbpsMusic encodingStereo

List of audio scenarios

Voice SDK provides the following audio scenarios to choose from:

Audio ScenarioPurpose
DefaultBasic communication.
Chatroom EntertainmentEntertainment scenario where users need to frequently switch the user role.
EducationEducation scenario where users want smoothness and stability.
Game StreamingHigh-quality audio chatroom scenario where hosts mainly play music.
ShowroomShowroom scenario where a single host wants high-quality audio.
Chatroom GamingGaming scenario for group chat that only contains human voice.
IOTInternet of Things scenario for devices that require low power consumption.
MeetingMeeting scenario that mainly contains human voice.

Profile and scenario parameter settings for some typical applications

ApplicationProfileScenarioFeatures
One-to-one classroomDefaultDefaultPrioritizes the call quality with smooth transmission and high-fidelity audio.
Battle Royale GameSpeech StandardChatroom GamingNoise reduction. Transmits voice only. Reduces the transmission rate. Suitable for multiplayer games.
Murder Mystery GameMusic StandardChatroom EntertainmentHigh-fidelity audio encoding and decoding. No volume or audio quality change when you mute/unmute the microphone.
KTVMusic High-qualityGame StreamingHigh-fidelity audio and effects. Adapts to the high-fidelity audio application.
PodcastMusic High-quality StereoShowRoomHigh-fidelity audio and stereo panning. Support for professional audio hardware.
Music educationMusic Standard StereoGame StreamingPrioritizes audio quality. Suitable for transmitting live external audio effects.
Collaborative teachingMusic Standard StereoChatroom EntertainmentHigh-fidelity audio and effects. No volume or audio quality change when you mute/unmute the microphone.

API reference

Voice Calling