1
+ using LiveKit . Proto ;
2
+ using LiveKit . Internal . FFIClients . Requests ;
3
+ using LiveKit . Internal ;
4
+ using System ;
5
+ using System . Runtime . CompilerServices ;
6
+ [ assembly: InternalsVisibleTo ( "Tests" ) ]
7
+
8
+ namespace LiveKit
9
+ {
10
+ /// <summary>
11
+ /// Provides WebRTC audio processing capabilities including echo cancellation, noise suppression,
12
+ /// high-pass filtering, and gain control.
13
+ /// </summary>
14
+ public sealed class AudioProcessingModule
15
+ {
16
+ internal readonly FfiHandle Handle ;
17
+
18
+ /// <summary>
19
+ /// Initializes an <see cref="AudioProcessingModule" /> instance with the specified audio processing features.
20
+ /// </summary>
21
+ /// <param name="echoCancellationEnabled">Whether to enable echo cancellation.</param>
22
+ /// <param name="noiseSuppressionEnabled">Whether to enable noise suppression.</param>
23
+ /// <param name="highPassFilterEnabled">Whether to enable high-pass filtering.</param>
24
+ /// <param name="gainControllerEnabled">Whether to enable gain control.</param>
25
+ public AudioProcessingModule (
26
+ bool echoCancellationEnabled ,
27
+ bool noiseSuppressionEnabled ,
28
+ bool highPassFilterEnabled ,
29
+ bool gainControllerEnabled )
30
+ {
31
+ using var request = FFIBridge . Instance . NewRequest < NewApmRequest > ( ) ;
32
+ var newApm = request . request ;
33
+ newApm . EchoCancellerEnabled = echoCancellationEnabled ;
34
+ newApm . NoiseSuppressionEnabled = noiseSuppressionEnabled ;
35
+ newApm . HighPassFilterEnabled = highPassFilterEnabled ;
36
+ newApm . GainControllerEnabled = gainControllerEnabled ;
37
+
38
+ using var response = request . Send ( ) ;
39
+ FfiResponse res = response ;
40
+ Handle = FfiHandle . FromOwnedHandle ( res . NewApm . Apm . Handle ) ;
41
+ }
42
+
43
+ /// <summary>
44
+ /// Process the provided audio frame using the configured audio processing features.
45
+ /// </summary>
46
+ /// <param name="data">The audio frame to process.</param>
47
+ /// <remarks>
48
+ /// Important: Audio frames must be exactly 10 ms in duration.
49
+ ///
50
+ /// The input audio frame is modified in-place (if applicable) by the underlying audio
51
+ /// processing module (e.g., echo cancellation, noise suppression, etc.).
52
+ /// </remarks>
53
+ public void ProcessStream ( AudioFrame data )
54
+ {
55
+ using var request = FFIBridge . Instance . NewRequest < ApmProcessStreamRequest > ( ) ;
56
+ var processStream = request . request ;
57
+ processStream . ApmHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
58
+ processStream . DataPtr = ( ulong ) data . Data ;
59
+ processStream . Size = ( uint ) data . Length ;
60
+ processStream . SampleRate = data . SampleRate ;
61
+ processStream . NumChannels = data . NumChannels ;
62
+
63
+ using var response = request . Send ( ) ;
64
+ FfiResponse res = response ;
65
+ if ( res . ApmProcessStream . HasError )
66
+ {
67
+ throw new Exception ( res . ApmProcessStream . Error ) ;
68
+ }
69
+ }
70
+
71
+ /// <summary>
72
+ /// Process the reverse audio frame (typically used for echo cancellation in a full-duplex setup).
73
+ /// </summary>
74
+ /// <param name="data">The audio frame to process.</param>
75
+ /// <remarks>
76
+ /// Important: Audio frames must be exactly 10 ms in duration.
77
+ ///
78
+ /// In an echo cancellation scenario, this method is used to process the "far-end" audio
79
+ /// prior to mixing or feeding it into the echo canceller. Like <see cref="ProcessStream"/>, the
80
+ /// input audio frame is modified in-place by the underlying processing module.
81
+ /// </remarks>
82
+ public void ProcessReverseStream ( AudioFrame data )
83
+ {
84
+ using var request = FFIBridge . Instance . NewRequest < ApmProcessReverseStreamRequest > ( ) ;
85
+ var processReverseStream = request . request ;
86
+ processReverseStream . ApmHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
87
+ processReverseStream . DataPtr = ( ulong ) data . Data ;
88
+ processReverseStream . Size = ( uint ) data . Length ;
89
+ processReverseStream . SampleRate = data . SampleRate ;
90
+ processReverseStream . NumChannels = data . NumChannels ;
91
+
92
+ using var response = request . Send ( ) ;
93
+ FfiResponse res = response ;
94
+ if ( res . ApmProcessReverseStream . HasError )
95
+ {
96
+ throw new Exception ( res . ApmProcessReverseStream . Error ) ;
97
+ }
98
+ }
99
+ }
100
+ }
0 commit comments