Audio Monitoring

Audio monitoring enables real-time transmission of audio to headphones, allowing users to hear themselves or other relevant sounds in real time.

This feature is commonly used in karaoke applications, where the recorded vocals and background music are sent to the headphones in real time. This allows users to adjust their performance based on the feedback, enhancing their experience.

Prerequisites

How to Develop

The examples in each of the following steps are code snippets. You can click the link at the bottom right of the sample code to obtain the complete sample codes.

Creating an Audio Recording Builder

Use the OH_AudioStreamBuilder function provided by OHAudio to create an audio recording builder, following the builder design pattern. Set OH_AudioStream_Type to AUDIOSTREAM_TYPE_CAPTURER.

OH_AudioStreamBuilder* builder;
OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_CAPTURER);

Creating an Audio Playback Builder

Use the OH_AudioStreamBuilder function provided by OHAudio to create an audio playback builder, following the builder design pattern. Set OH_AudioStream_Type to AUDIOSTREAM_TYPE_RENDERER.

OH_AudioStreamBuilder* builder;
OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);

Setting the Low Latency Mode

To achieve better audio monitoring, it is essential to maintain low latency from recording to playback. When the device supports low-latency channels, you should use the low latency mode for both recording and playback.

When creating the audio recording builder, call OH_AudioStreamBuilder_SetLatencyMode() to set the low latency mode, and apply it to both recording and playback as follows:

OH_AudioStream_LatencyMode latencyMode = AUDIOSTREAM_LATENCY_MODE_FAST;
OH_AudioStreamBuilder_SetLatencyMode(builder, latencyMode);

To implement real-time audio monitoring, create a shared buffer to store the captured data and promptly retrieve data from this buffer to write to the audio playback builder.

Defining the Shared Buffer and Recording/Playback Functions

int32_t MyOnReadData_Legacy(
    OH_AudioCapturer* capturer,
    void* userData,
    void* buffer,
    int32_t length)
{
    // Obtain captured data of the specified length from the buffer.
    return 0;
}
// ...
int32_t MyOnWriteData(
    OH_AudioRenderer* renderer,
    void* userData,
    void* buffer,
    int32_t length)
{
    // Read data from the shared buffer and write the data with the specified length into the buffer.
    return 0;
}

NOTE

Avoid setting the shared buffer too large, as it can increase audio feedback latency and degrade user experience. You should select a proper buffer size that balances latency and jitter tolerance to maintain optimal performance.

Setting Audio Stream Parameters

The following provides an example of setting parameters for the audio recording stream:

// Set the audio sampling rate.
const int SAMPLING_RATE_48K = 48000;
OH_AudioStreamBuilder_SetSamplingRate(builder, SAMPLING_RATE_48K);
// Set the number of audio channels.
const int channelCount = 2;
OH_AudioStreamBuilder_SetChannelCount(builder, channelCount);
// Set the audio sampling format.
OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
// Set the encoding type of the audio stream.
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
// Set the usage scenario of the audio capturer.
OH_AudioStreamBuilder_SetCapturerInfo(builder, AUDIOSTREAM_SOURCE_TYPE_MIC);

For the playback stream, set the same parameters as the recording stream, except for the working scenario.

Set the working scenario parameter as follows:

OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);

Setting Recording Callback Functions

int32_t MyOnReadData_Legacy(
    OH_AudioCapturer* capturer,
    void* userData,
    void* buffer,
    int32_t length)
{
    // Obtain captured data of the specified length from the buffer.
    return 0;
}
int32_t MyOnInterruptEvent_Legacy(
    OH_AudioCapturer* capturer,
    void* userData,
    OH_AudioInterrupt_ForceType type,
    OH_AudioInterrupt_Hint hint)
{
    // Update the capturer status and UI based on the audio interruption information indicated by type and hint.
    return 0;
}

int32_t MyOnStreamEvent_Legacy(
    OH_AudioCapturer* capturer,
    void* userData,
    OH_AudioStream_Event event)
{
    // Update the capturer status and UI based on the audio stream event information indicated by the event.
    return 0;
}

int32_t MyOnError_Legacy(
    OH_AudioCapturer* capturer,
    void* userData,
    OH_AudioStream_Result error)
{
    // Perform operations based on the audio exception information indicated by error.
    return 0;
}
// ...
    OH_AudioCapturer_Callbacks callbacks;
    // Set the callbacks.
    callbacks.OH_AudioCapturer_OnReadData = MyOnReadData_Legacy;
    callbacks.OH_AudioCapturer_OnStreamEvent = MyOnStreamEvent_Legacy;
    callbacks.OH_AudioCapturer_OnInterruptEvent = MyOnInterruptEvent_Legacy;
    callbacks.OH_AudioCapturer_OnError = MyOnError_Legacy;

    OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, nullptr);

Setting Playback Callback Functions

int32_t MyOnWriteData(
    OH_AudioRenderer* renderer,
    void* userData,
    void* buffer,
    int32_t length)
{
    // Read data from the shared buffer and write the data with the specified length into the buffer.
    return 0;
}
int32_t MyOnStreamEvent_Renderer(
    OH_AudioRenderer* renderer,
    void* userData,
    OH_AudioStream_Event event)
{
    // Update the player status and UI based on the audio stream event information indicated by the event.
    return 0;
}

int32_t MyOnInterruptEvent_Renderer(
    OH_AudioRenderer* renderer,
    void* userData,
    OH_AudioInterrupt_ForceType type,
    OH_AudioInterrupt_Hint hint)
{
    // Update the player status and UI based on the audio interruption information indicated by type and hint.
    return 0;
}

int32_t MyOnError_Renderer(
    OH_AudioRenderer* renderer,
    void* userData,
    OH_AudioStream_Result error)
{
    // Perform operations based on the audio exception information indicated by error.
    return 0;
}
// ...
    OH_AudioRenderer_Callbacks callbacks;
    
    // Set the callbacks.
    callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
    callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent_Renderer;
    callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent_Renderer;
    callbacks.OH_AudioRenderer_OnError = MyOnError_Renderer;

    // Set callbacks for the audio renderer.
    OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);

Creating an Audio Capturer

OH_AudioCapturer* audioCapturer;
OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);

Creating an Audio Renderer

OH_AudioRenderer* audioRenderer;
OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);

Using Audio Streams

The following uses recording as an example. You can use the following APIs to control the start, pause, stop, and release of audio streams.

NOTE

When implementing audio monitoring, you need to control both the recording and playback streams to ensure their synchronization.

API Description
OH_AudioStream_Result OH_AudioRenderer_Start(OH_AudioRenderer* renderer) Starts the audio renderer.
OH_AudioStream_Result OH_AudioRenderer_Pause(OH_AudioRenderer* renderer) Pauses the audio renderer.
OH_AudioStream_Result OH_AudioRenderer_Stop(OH_AudioRenderer* renderer) Stops the audio renderer.
OH_AudioStream_Result OH_AudioRenderer_Flush(OH_AudioRenderer* renderer) Flushes obtained audio data.
OH_AudioStream_Result OH_AudioRenderer_Release(OH_AudioRenderer* renderer) Releases the audio renderer.

Releasing the Builder

When the builder is no longer required, release the resources as follows:

OH_AudioStreamBuilder_Destroy(builder);