1+ /*
2+ * Copyright 2022 LiveKit
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
117package org .webrtc ;
218
19+ import java .nio .ByteBuffer ;
20+
21+ import androidx .annotation .Nullable ;
22+ import org .webrtc .AudioProcessingFactory ;
23+
24+
325public class ExternalAudioProcessingFactory implements AudioProcessingFactory {
426
5- private final String libname ;
27+ /**
28+ * Interface for external audio processing.
29+ */
30+ public static interface AudioProcessing {
31+ /**
32+ * Called when the processor should be initialized with a new sample rate and
33+ * number of channels.
34+ */
35+ @ CalledByNative ("AudioProcessing" )
36+ void initialize (int sampleRateHz , int numChannels );
37+ /** Called when the processor should be reset with a new sample rate. */
38+ @ CalledByNative ("AudioProcessing" )
39+ void reset (int newRate );
40+ /**
41+ * Processes the given capture or render signal. NOTE: `buffer.data` will be
42+ * freed once this function returns so callers who want to use the data
43+ * asynchronously must make sure to copy it first.
44+ */
45+ @ CalledByNative ("AudioProcessing" )
46+ void process (int numBands , int numFrames , ByteBuffer buffer );
47+ }
648
7- public ExternalAudioProcessingFactory ( String libname ) {
8- if ( libname == null ) {
9- throw new NullPointerException ( "libname must not be null." ) ;
10- }
11- if ( libname . isEmpty () ) {
12- throw new IllegalArgumentException ( "libname must not be empty." );
13- }
14- this . libname = libname ;
49+ private long apmPtr ;
50+ private long capturePostProcessingPtr ;
51+ private long renderPreProcessingPtr ;
52+
53+ public ExternalAudioProcessingFactory ( ) {
54+ apmPtr = nativeGetDefaultApm ( );
55+ capturePostProcessingPtr = 0 ;
56+ renderPreProcessingPtr = 0 ;
1557 }
1658
1759 @ Override
1860 public long createNative () {
19- return nativeCreateAudioProcessingModule (libname );
61+ if (apmPtr == 0 ) {
62+ apmPtr = nativeGetDefaultApm ();
63+ }
64+ return apmPtr ;
2065 }
2166
22- public void destroyNative () {
23- nativeDestroyAudioProcessingModule ();
67+ /**
68+ * Sets the capture post processing module.
69+ * This module is applied to the audio signal after capture and before sending
70+ * to the audio encoder.
71+ */
72+ public void setCapturePostProcessing (@ Nullable AudioProcessing processing ) {
73+ checkExternalAudioProcessorExists ();
74+ long newPtr = nativeSetCapturePostProcessing (processing );
75+ if (capturePostProcessingPtr != 0 ) {
76+ JniCommon .nativeReleaseRef (capturePostProcessingPtr );
77+ capturePostProcessingPtr = 0 ;
78+ }
79+ capturePostProcessingPtr = newPtr ;
2480 }
2581
26- private static native long nativeCreateAudioProcessingModule (String libname );
82+ /**
83+ * Sets the render pre processing module.
84+ * This module is applied to the audio signal after receiving from the audio
85+ * decoder and before rendering.
86+ */
87+ public void setRenderPreProcessing (@ Nullable AudioProcessing processing ) {
88+ checkExternalAudioProcessorExists ();
89+ long newPtr = nativeSetRenderPreProcessing (processing );
90+ if (renderPreProcessingPtr != 0 ) {
91+ JniCommon .nativeReleaseRef (renderPreProcessingPtr );
92+ renderPreProcessingPtr = 0 ;
93+ }
94+ renderPreProcessingPtr = newPtr ;
95+ }
96+
97+ /**
98+ * Sets the bypass flag for the capture post processing module.
99+ * If true, the registered audio processing will be bypassed.
100+ */
101+ public void setBypassFlagForCapturePost ( boolean bypass ) {
102+ checkExternalAudioProcessorExists ();
103+ nativeSetBypassFlagForCapturePost (bypass );
104+ }
105+
106+ /**
107+ * Sets the bypass flag for the render pre processing module.
108+ * If true, the registered audio processing will be bypassed.
109+ */
110+ public void setBypassFlagForRenderPre ( boolean bypass ) {
111+ checkExternalAudioProcessorExists ();
112+ nativeSetBypassFlagForRenderPre (bypass );
113+ }
27114
115+ /**
116+ * Destroys the ExternalAudioProcessor.
117+ */
118+ public void destroy () {
119+ checkExternalAudioProcessorExists ();
120+ if (renderPreProcessingPtr != 0 ) {
121+ JniCommon .nativeReleaseRef (renderPreProcessingPtr );
122+ renderPreProcessingPtr = 0 ;
123+ }
124+ if (capturePostProcessingPtr != 0 ) {
125+ JniCommon .nativeReleaseRef (capturePostProcessingPtr );
126+ capturePostProcessingPtr = 0 ;
127+ }
128+ nativeDestroy ();
129+ apmPtr = 0 ;
130+ }
28131
29- private static native void nativeDestroyAudioProcessingModule ();
132+ private void checkExternalAudioProcessorExists () {
133+ if (apmPtr == 0 ) {
134+ throw new IllegalStateException ("ExternalAudioProcessor has been disposed." );
135+ }
136+ }
30137
138+ private static native long nativeGetDefaultApm ();
139+ private static native long nativeSetCapturePostProcessing (AudioProcessing processing );
140+ private static native long nativeSetRenderPreProcessing (AudioProcessing processing );
141+ private static native void nativeSetBypassFlagForCapturePost (boolean bypass );
142+ private static native void nativeSetBypassFlagForRenderPre (boolean bypass );
143+ private static native void nativeDestroy ();
31144}
0 commit comments