Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add audio processing module #363

Merged
merged 12 commits into from
Mar 4, 2025
Prev Previous commit
Next Next commit
docs
theomonnom committed Feb 20, 2025
commit 99aca00fa707cba3bd3045f442ca079faff82f91
56 changes: 53 additions & 3 deletions livekit-rtc/livekit/rtc/aec.py
Original file line number Diff line number Diff line change
@@ -8,15 +8,34 @@

class Aec:
"""
Acoustic Echo Cancellation (AEC) module for removing echo from audio data.
(It uses the AEC3 implementation from libwebrtc).
Acoustic Echo Cancellation (AEC) module for removing echo from audio data using
the AEC3 implementation from libwebrtc.

Note: Frames must be processed in chunks of exactly 10 ms.
The length of the provided buffers must correspond to 10 ms of audio at the
given sample rate and number of channels.
Only the capture data buffer is modified (in-place). The render data
buffer is used as a reference and is not changed by this process.
"""

def __init__(
self,
sample_rate: int,
num_channels: int,
) -> None:
"""
Initialize a new acoustic echo cancellation (AEC) instance.

Parameters:
- sample_rate (int): The sample rate (in Hz) of the audio to process.
- num_channels (int): The number of channels in the audio stream.

Ensure that each processed chunk represents exactly 10 ms of audio for
reliable echo cancellation.

Example:
aec = Aec(sample_rate=48000, num_channels=2)
"""
self._sample_rate = sample_rate
self._mum_channels = num_channels

@@ -27,7 +46,37 @@ def __init__(
resp = FfiClient.instance.request(req)
self._ffi_handle = FfiHandle(resp.new_aec.aec.handle.id)

def cancel_echo(self, capture_data: bytearray | AudioFrame, render_data: bytearray | AudioFrame) -> None:
def cancel_echo(
self,
capture_data: bytearray | AudioFrame,
render_data: bytearray | AudioFrame
) -> None:
"""
Perform in-place echo cancellation on the capture data based on the render data.

This method processes two separate audio buffers:
1. capture_data (modified in-place)
2. render_data (read-only, not modified)

Parameters:
- capture_data (bytearray | AudioFrame): The capture audio buffer or frame.
This buffer will be edited in-place to remove the echo.
- render_data (bytearray | AudioFrame): The render audio buffer or frame.
This buffer is read-only and provides the reference signal used to
remove echo from capture_data.

Important:
- Each buffer must represent exactly 10 ms of audio (based on the
sample rate and number of channels used to initialize Aec).
- If you pass more or less than 10 ms, the behavior is undefined.

Raises:
- Exception: If the AEC processing fails internally.

Example:
# Assuming capture_data and render_data each hold exactly 10 ms of audio:
aec.cancel_echo(capture_data=capture_data, render_data=render_data)
"""
cap_data = capture_data if isinstance(capture_data, bytearray) else capture_data.data.cast("b")
rend_data = render_data if isinstance(render_data, bytearray) else render_data.data.cast("b")

@@ -42,3 +91,4 @@ def cancel_echo(self, capture_data: bytearray | AudioFrame, render_data: bytearr

if resp.cancel_echo.error:
raise Exception(resp.cancel_echo.error)