@@ -18,12 +18,12 @@ public enum RtcAudioSourceType
18
18
public abstract class RtcAudioSource : IRtcSource
19
19
{
20
20
public abstract event Action < float [ ] , int , int > AudioRead ;
21
- public virtual IEnumerator Prepare ( float timeout = 0 ) { yield break ; }
21
+ public virtual IEnumerator Prepare ( float timeout = 0 ) { yield break ; }
22
22
public abstract void Play ( ) ;
23
23
24
24
#if UNITY_IOS
25
25
// iOS microphone sample rate is 24k,
26
- // please make sure when you using
26
+ // please make sure when you using
27
27
// sourceType is AudioSourceMicrophone
28
28
public static uint DefaultMirophoneSampleRate = 24000 ;
29
29
@@ -43,7 +43,7 @@ public abstract class RtcAudioSource : IRtcSource
43
43
44
44
// Possibly used on the AudioThread
45
45
private Thread _readAudioThread ;
46
- private ThreadSafeQueue < AudioFrame > _frameQueue = new ThreadSafeQueue < AudioFrame > ( ) ;
46
+ private AudioBuffer _captureBuffer = new AudioBuffer ( ) ;
47
47
48
48
private bool _muted = false ;
49
49
public override bool Muted => _muted ;
@@ -85,7 +85,6 @@ public void Start()
85
85
Stop ( ) ;
86
86
_readAudioThread = new Thread ( Update ) ;
87
87
_readAudioThread . Start ( ) ;
88
-
89
88
AudioRead += OnAudioRead ;
90
89
Play ( ) ;
91
90
}
@@ -101,78 +100,55 @@ private void Update()
101
100
while ( true )
102
101
{
103
102
Thread . Sleep ( Constants . TASK_DELAY ) ;
104
- ReadAudio ( ) ;
103
+ var frame = _captureBuffer . ReadDuration ( 10 ) ; // 10ms
104
+ if ( _muted || frame == null ) continue ;
105
+ Capture ( frame ) ;
105
106
}
106
107
}
107
108
108
109
private void OnAudioRead ( float [ ] data , int channels , int sampleRate )
109
110
{
110
- var samplesPerChannel = data . Length / channels ;
111
- var frame = new AudioFrame ( ( uint ) sampleRate , ( uint ) channels , ( uint ) samplesPerChannel ) ;
112
-
113
- static short FloatToS16 ( float v )
114
- {
115
- v *= 32768f ;
116
- v = Math . Min ( v , 32767f ) ;
117
- v = Math . Max ( v , - 32768f ) ;
118
- return ( short ) ( v + Math . Sign ( v ) * 0.5f ) ;
119
- }
120
- unsafe
111
+ _captureBuffer . Write ( data , ( uint ) channels , ( uint ) sampleRate ) ;
112
+ if ( _sourceType == RtcAudioSourceType . AudioSourceMicrophone )
121
113
{
122
- var frameData = new Span < short > ( frame . Data . ToPointer ( ) , frame . Length / sizeof ( short ) ) ;
123
- for ( int i = 0 ; i < data . Length ; i ++ )
124
- {
125
- frameData [ i ] = FloatToS16 ( data [ i ] ) ;
126
- }
127
- if ( _sourceType == RtcAudioSourceType . AudioSourceMicrophone )
128
- {
129
- // Don't play the audio locally, to avoid echo.
130
- Array . Clear ( data , 0 , data . Length ) ;
131
- }
114
+ // Don't play the audio locally, to avoid echo.
115
+ Array . Clear ( data , 0 , data . Length ) ;
132
116
}
133
- _frameQueue . Enqueue ( frame ) ;
134
117
}
135
118
136
- private void ReadAudio ( )
119
+ private void Capture ( AudioFrame frame )
137
120
{
138
- while ( _frameQueue . Count > 0 )
121
+ using var request = FFIBridge . Instance . NewRequest < CaptureAudioFrameRequest > ( ) ;
122
+ using var audioFrameBufferInfo = request . TempResource < AudioFrameBufferInfo > ( ) ;
123
+
124
+ var pushFrame = request . request ;
125
+ pushFrame . SourceHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
126
+
127
+ pushFrame . Buffer = audioFrameBufferInfo ;
128
+ pushFrame . Buffer . DataPtr = ( ulong ) frame . Data ;
129
+ pushFrame . Buffer . NumChannels = frame . NumChannels ;
130
+ pushFrame . Buffer . SampleRate = frame . SampleRate ;
131
+ pushFrame . Buffer . SamplesPerChannel = frame . SamplesPerChannel ;
132
+
133
+ using var response = request . Send ( ) ;
134
+ FfiResponse res = response ;
135
+
136
+ // Frame needs to stay alive until receiving the async callback.
137
+ var asyncId = res . CaptureAudioFrame . AsyncId ;
138
+ void Callback ( CaptureAudioFrameCallback callback )
139
139
{
140
- try
141
- {
142
- AudioFrame frame = _frameQueue . Dequeue ( ) ;
143
-
144
- if ( _muted )
145
- {
146
- continue ;
147
- }
148
- unsafe
149
- {
150
- using var request = FFIBridge . Instance . NewRequest < CaptureAudioFrameRequest > ( ) ;
151
- using var audioFrameBufferInfo = request . TempResource < AudioFrameBufferInfo > ( ) ;
152
-
153
- var pushFrame = request . request ;
154
- pushFrame . SourceHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
155
-
156
- pushFrame . Buffer = audioFrameBufferInfo ;
157
- pushFrame . Buffer . DataPtr = ( ulong ) frame . Data ;
158
- pushFrame . Buffer . NumChannels = frame . NumChannels ;
159
- pushFrame . Buffer . SampleRate = frame . SampleRate ;
160
- pushFrame . Buffer . SamplesPerChannel = frame . SamplesPerChannel ;
161
-
162
- using var response = request . Send ( ) ;
163
- }
164
- }
165
- catch ( Exception e )
166
- {
167
- Utils . Error ( "Audio Framedata error: " + e . Message ) ;
168
- }
140
+ if ( callback . AsyncId != asyncId ) return ;
141
+ if ( callback . HasError )
142
+ Utils . Error ( $ "Audio capture failed: { callback . Error } ") ;
143
+ frame . Dispose ( ) ;
144
+ FfiClient . Instance . CaptureAudioFrameReceived -= Callback ;
169
145
}
146
+ FfiClient . Instance . CaptureAudioFrameReceived += Callback ;
170
147
}
171
148
172
149
public override void SetMute ( bool muted )
173
150
{
174
151
_muted = muted ;
175
152
}
176
-
177
153
}
178
- }
154
+ }
0 commit comments