Skip to content

Commit 9a89aa4

Browse files
authored
Enhance RtcAudioSource (#81)
1 parent 2cb73a2 commit 9a89aa4

File tree

7 files changed

+104
-33
lines changed

7 files changed

+104
-33
lines changed

Runtime/Scripts/AudioStream.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ namespace LiveKit
1010
public class AudioStream
1111
{
1212
internal readonly FfiHandle Handle;
13-
private AudioSource _audioSource;
14-
private AudioFilter _audioFilter;
13+
public RtcAudioSource AudioSource { get; private set; }
1514
private RingBuffer _buffer;
1615
private short[] _tempBuffer;
1716
private uint _numChannels;
1817
private uint _sampleRate;
1918
private AudioResampler _resampler = new AudioResampler();
2019
private object _lock = new object();
2120

22-
public AudioStream(IAudioTrack audioTrack, AudioSource source)
21+
public AudioStream(IAudioTrack audioTrack, AudioSource source) : this(audioTrack, new BasicAudioSource(source)) { }
22+
23+
public AudioStream(IAudioTrack audioTrack, RtcAudioSource source)
2324
{
2425
if (!audioTrack.Room.TryGetTarget(out var room))
2526
throw new InvalidOperationException("audiotrack's room is invalid");
@@ -40,12 +41,10 @@ public AudioStream(IAudioTrack audioTrack, AudioSource source)
4041
UpdateSource(source);
4142
}
4243

43-
private void UpdateSource(AudioSource source)
44+
private void UpdateSource(RtcAudioSource source)
4445
{
45-
_audioSource = source;
46-
_audioFilter = source.gameObject.AddComponent<AudioFilter>();
47-
//_audioFilter.hideFlags = HideFlags.HideInInspector;
48-
_audioFilter.AudioRead += OnAudioRead;
46+
AudioSource = source;
47+
AudioSource.AudioRead += OnAudioRead;
4948
source.Play();
5049
}
5150

Runtime/Scripts/BasicAudioSource.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using UnityEngine;
3+
4+
namespace LiveKit
5+
{
6+
public class BasicAudioSource : RtcAudioSource
7+
{
8+
protected readonly AudioSource Source;
9+
private readonly AudioFilter _audioFilter;
10+
11+
public override event Action<float[], int, int> AudioRead;
12+
13+
public BasicAudioSource(AudioSource source, int channels = 2, RtcAudioSourceType sourceType = RtcAudioSourceType.AudioSourceCustom) : base(channels, sourceType)
14+
{
15+
Source = source;
16+
_audioFilter = Source.gameObject.AddComponent<AudioFilter>();
17+
}
18+
19+
private void OnAudioRead(float[] data, int channels, int sampleRate)
20+
{
21+
AudioRead?.Invoke(data, channels, sampleRate);
22+
}
23+
24+
public override void Play()
25+
{
26+
_audioFilter.AudioRead += OnAudioRead;
27+
Source.Play();
28+
}
29+
30+
public override void Stop()
31+
{
32+
_audioFilter.AudioRead -= OnAudioRead;
33+
Source.Stop();
34+
}
35+
}
36+
}

Runtime/Scripts/BasicAudioSource.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Scripts/MicrophoneSource.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections;
2+
using UnityEngine;
3+
4+
namespace LiveKit
5+
{
6+
public class MicrophoneSource : BasicAudioSource
7+
{
8+
private string _deviceName;
9+
10+
public MicrophoneSource(AudioSource source) : base(source, 2, RtcAudioSourceType.AudioSourceMicrophone)
11+
{
12+
}
13+
14+
public void Configure(string device, bool loop, int lenghtSec, int frequency)
15+
{
16+
_deviceName = device;
17+
Source.clip = Microphone.Start(device, loop, lenghtSec, frequency);
18+
Source.loop = true;
19+
}
20+
21+
public override IEnumerator Prepare(float timeout = 0)
22+
{
23+
return new WaitUntil(() => Microphone.GetPosition(_deviceName) > 0);
24+
}
25+
26+
}
27+
}

Runtime/Scripts/MicrophoneSource.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Scripts/AudioSource.cs renamed to Runtime/Scripts/RtcAudioSource.cs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
using System;
2-
using UnityEngine;
2+
using System.Collections;
33
using LiveKit.Proto;
44
using LiveKit.Internal;
55
using System.Threading;
66
using LiveKit.Internal.FFIClients.Requests;
7-
using System.Collections.Generic;
87

98
namespace LiveKit
109
{
@@ -16,8 +15,12 @@ public enum RtcAudioSourceType
1615
AudioSourceMicrophone = 1,
1716
}
1817

19-
public class RtcAudioSource : IRtcSource
18+
public abstract class RtcAudioSource : IRtcSource
2019
{
20+
public abstract event Action<float[], int, int> AudioRead;
21+
public virtual IEnumerator Prepare(float timeout = 0) { yield break; }
22+
public abstract void Play();
23+
2124
#if UNITY_IOS
2225
// iOS microphone sample rate is 24k,
2326
// please make sure when you using
@@ -35,28 +38,24 @@ public class RtcAudioSource : IRtcSource
3538

3639
public RtcAudioSourceType SourceType => _sourceType;
3740

38-
private AudioSource _audioSource;
39-
private AudioFilter _audioFilter;
40-
4141
internal readonly FfiHandle Handle;
4242
protected AudioSourceInfo _info;
4343

44-
// Used on the AudioThread
44+
// Possibly used on the AudioThread
4545
private Thread _readAudioThread;
4646
private ThreadSafeQueue<AudioFrame> _frameQueue = new ThreadSafeQueue<AudioFrame>();
4747

4848
private bool _muted = false;
49-
5049
public override bool Muted => _muted;
5150

52-
public RtcAudioSource(AudioSource source, RtcAudioSourceType audioSourceType = RtcAudioSourceType.AudioSourceCustom)
51+
protected RtcAudioSource(int channels = 2, RtcAudioSourceType audioSourceType = RtcAudioSourceType.AudioSourceCustom)
5352
{
5453
_sourceType = audioSourceType;
5554

5655
using var request = FFIBridge.Instance.NewRequest<NewAudioSourceRequest>();
5756
var newAudioSource = request.request;
5857
newAudioSource.Type = AudioSourceType.AudioSourceNative;
59-
newAudioSource.NumChannels = DefaultChannels;
58+
newAudioSource.NumChannels = (uint)channels;
6059
if(_sourceType == RtcAudioSourceType.AudioSourceMicrophone)
6160
{
6261
newAudioSource.SampleRate = DefaultMirophoneSampleRate;
@@ -73,7 +72,12 @@ public RtcAudioSource(AudioSource source, RtcAudioSourceType audioSourceType = R
7372
FfiResponse res = response;
7473
_info = res.NewAudioSource.Source.Info;
7574
Handle = FfiHandle.FromOwnedHandle(res.NewAudioSource.Source.Handle);
76-
UpdateSource(source);
75+
}
76+
77+
public IEnumerator PrepareAndStart()
78+
{
79+
yield return Prepare();
80+
Start();
7781
}
7882

7983
public void Start()
@@ -82,16 +86,14 @@ public void Start()
8286
_readAudioThread = new Thread(Update);
8387
_readAudioThread.Start();
8488

85-
_audioFilter.AudioRead += OnAudioRead;
86-
while (!(Microphone.GetPosition(null) > 0)) { }
87-
_audioSource.Play();
89+
AudioRead += OnAudioRead;
90+
Play();
8891
}
8992

90-
public void Stop()
93+
public virtual void Stop()
9194
{
9295
_readAudioThread?.Abort();
93-
if(_audioFilter) _audioFilter.AudioRead -= OnAudioRead;
94-
if(_audioSource && _audioSource.isPlaying) _audioSource.Stop();
96+
AudioRead -= OnAudioRead;
9597
}
9698

9799
private void Update()
@@ -115,7 +117,6 @@ static short FloatToS16(float v)
115117
v = Math.Max(v, -32768f);
116118
return (short)(v + Math.Sign(v) * 0.5f);
117119
}
118-
119120
unsafe
120121
{
121122
var frameData = new Span<short>(frame.Data.ToPointer(), frame.Length / sizeof(short));
@@ -132,7 +133,6 @@ static short FloatToS16(float v)
132133
_frameQueue.Enqueue(frame);
133134
}
134135

135-
136136
private void ReadAudio()
137137
{
138138
while (_frameQueue.Count > 0)
@@ -169,15 +169,10 @@ private void ReadAudio()
169169
}
170170
}
171171

172-
private void UpdateSource(AudioSource source)
173-
{
174-
_audioSource = source;
175-
_audioFilter = source.gameObject.AddComponent<AudioFilter>();
176-
}
177-
178172
public override void SetMute(bool muted)
179173
{
180174
_muted = muted;
181175
}
176+
182177
}
183178
}

0 commit comments

Comments
 (0)