com.adrenak.univoice 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/Runtime/ChatroomAgent.cs +86 -40
- package/Runtime/Interfaces/IAudioInput.cs +1 -1
- package/Runtime/Interfaces/IAudioOutput.cs +9 -9
- package/Runtime/Interfaces/IAudioOutputFactory.cs.meta +11 -11
- package/Runtime/Interfaces/IChatroomNetwork.cs +13 -7
- package/Runtime/Types/ChatroomAudioSegment.cs.meta +11 -11
- package/package.json +27 -18
- package/Runtime/Extensions.cs +0 -39
- package/Runtime/Extensions.cs.meta +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [2.0.2](https://github.com/adrenak/univoice/compare/v2.0.1...v2.0.2) (2022-11-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* remove comment about possible PeerID in IAudioOutput ([2246bb2](https://github.com/adrenak/univoice/commit/2246bb2bef234b84bdf6cd55a9faf87e09133953))
|
|
7
|
+
|
|
8
|
+
## [1.2.1](https://github.com/adrenak/univoice/compare/v1.2.0...v1.2.1) (2022-10-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* PeersOutputs gets filled as peers join, not when they start ([42eaeb9](https://github.com/adrenak/univoice/commit/42eaeb95eef4eea7ee559da9fdbcac78ceb941b4))
|
|
14
|
+
|
|
1
15
|
# [1.2.0](https://github.com/adrenak/univoice/compare/v1.1.4...v1.2.0) (2022-09-20)
|
|
2
16
|
|
|
3
17
|
|
package/Runtime/ChatroomAgent.cs
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Linq;
|
|
3
3
|
using System.Collections.Generic;
|
|
4
|
+
using System.Diagnostics;
|
|
5
|
+
|
|
6
|
+
using Debug = UnityEngine.Debug;
|
|
4
7
|
|
|
5
8
|
namespace Adrenak.UniVoice {
|
|
6
9
|
/// <summary>
|
|
7
10
|
/// Provides the means to host or connect to a chatroom.
|
|
8
11
|
/// </summary>
|
|
9
12
|
public class ChatroomAgent : IDisposable {
|
|
13
|
+
const string TAG = "ChatroomAgent";
|
|
14
|
+
|
|
10
15
|
// ====================================================================
|
|
11
16
|
#region PROPERTIES
|
|
12
17
|
// ====================================================================
|
|
@@ -33,14 +38,29 @@ namespace Adrenak.UniVoice {
|
|
|
33
38
|
/// There is a <see cref="IAudioOutput"/> for each peer that gets
|
|
34
39
|
/// created using the provided <see cref="AudioOutputFactory"/>
|
|
35
40
|
/// The <see cref="IAudioOutput"/> instance corresponding to a peer is
|
|
36
|
-
/// responsible for playing the audio that we receive that peer.
|
|
41
|
+
/// responsible for playing the audio that we receive from that peer.
|
|
37
42
|
/// </summary>
|
|
38
43
|
public Dictionary<short, IAudioOutput> PeerOutputs;
|
|
39
44
|
|
|
45
|
+
/// <summary>
|
|
46
|
+
/// Fired when the <see cref="CurrentMode"/> changes.
|
|
47
|
+
/// </summary>
|
|
48
|
+
public Action<ChatroomAgentMode> OnModeChanged;
|
|
49
|
+
|
|
40
50
|
/// <summary>
|
|
41
51
|
/// The current <see cref="ChatroomAgentMode"/> of this agent
|
|
42
52
|
/// </summary>
|
|
43
|
-
public ChatroomAgentMode CurrentMode {
|
|
53
|
+
public ChatroomAgentMode CurrentMode {
|
|
54
|
+
get => _currentMode;
|
|
55
|
+
private set {
|
|
56
|
+
if(_currentMode != value) {
|
|
57
|
+
_currentMode = value;
|
|
58
|
+
OnModeChanged?.Invoke(value);
|
|
59
|
+
Debug.unityLogger.Log(TAG, "Current Mode set to " + value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
ChatroomAgentMode _currentMode = ChatroomAgentMode.Unconnected;
|
|
44
64
|
|
|
45
65
|
/// <summary>
|
|
46
66
|
/// Mutes all the peers. If set to true, no incoming audio from other
|
|
@@ -69,13 +89,14 @@ namespace Adrenak.UniVoice {
|
|
|
69
89
|
#endregion
|
|
70
90
|
|
|
71
91
|
// ====================================================================
|
|
72
|
-
#region CONSTRUCTION
|
|
92
|
+
#region CONSTRUCTION AND DISPOSAL
|
|
73
93
|
// ====================================================================
|
|
74
94
|
/// <summary>
|
|
75
95
|
/// Creates and returns a new agent using the provided dependencies.
|
|
96
|
+
/// The instance then makes the dependencies work together.
|
|
76
97
|
/// </summary>
|
|
77
98
|
///
|
|
78
|
-
/// <param name="chatroomNetwork">The chatroom network implementation
|
|
99
|
+
/// <param name="chatroomNetwork">The chatroom network implementation
|
|
79
100
|
/// for chatroom access and sending data to peers in a chatroom.
|
|
80
101
|
/// </param>
|
|
81
102
|
///
|
|
@@ -105,7 +126,8 @@ namespace Adrenak.UniVoice {
|
|
|
105
126
|
PeerSettings = new Dictionary<short, ChatroomPeerSettings>();
|
|
106
127
|
PeerOutputs = new Dictionary<short, IAudioOutput>();
|
|
107
128
|
|
|
108
|
-
|
|
129
|
+
Debug.unityLogger.Log(TAG, "Created");
|
|
130
|
+
SetupEventListeners();
|
|
109
131
|
}
|
|
110
132
|
|
|
111
133
|
/// <summary>
|
|
@@ -115,6 +137,7 @@ namespace Adrenak.UniVoice {
|
|
|
115
137
|
/// instances and/or using them outside this instance.
|
|
116
138
|
/// </summary>
|
|
117
139
|
public void Dispose() {
|
|
140
|
+
Debug.unityLogger.Log(TAG, "Disposing");
|
|
118
141
|
AudioInput.Dispose();
|
|
119
142
|
|
|
120
143
|
RemoveAllPeers();
|
|
@@ -122,54 +145,62 @@ namespace Adrenak.UniVoice {
|
|
|
122
145
|
PeerOutputs.Clear();
|
|
123
146
|
|
|
124
147
|
Network.Dispose();
|
|
148
|
+
Debug.unityLogger.Log(TAG, "Disposed");
|
|
125
149
|
}
|
|
126
150
|
#endregion
|
|
127
151
|
|
|
128
152
|
// ====================================================================
|
|
129
153
|
#region INTERNAL
|
|
130
154
|
// ====================================================================
|
|
131
|
-
void
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
void SetupEventListeners() {
|
|
156
|
+
Debug.unityLogger.Log(TAG, "Setting up events.");
|
|
157
|
+
|
|
158
|
+
// Network events
|
|
159
|
+
Network.OnCreatedChatroom += () => {
|
|
160
|
+
Debug.unityLogger.Log(TAG, "Chatroom created.");
|
|
134
161
|
CurrentMode = ChatroomAgentMode.Host;
|
|
162
|
+
};
|
|
135
163
|
Network.OnClosedChatroom += () => {
|
|
136
|
-
|
|
164
|
+
Debug.unityLogger.Log(TAG, "Chatroom closed.");
|
|
137
165
|
RemoveAllPeers();
|
|
166
|
+
CurrentMode = ChatroomAgentMode.Unconnected;
|
|
138
167
|
};
|
|
139
|
-
|
|
140
|
-
// Node client events
|
|
141
168
|
Network.OnJoinedChatroom += id => {
|
|
169
|
+
Debug.unityLogger.Log(TAG, "Joined chatroom.");
|
|
142
170
|
CurrentMode = ChatroomAgentMode.Guest;
|
|
143
171
|
};
|
|
144
|
-
Network.OnLeftChatroom += () =>
|
|
172
|
+
Network.OnLeftChatroom += () => {
|
|
173
|
+
Debug.unityLogger.Log(TAG, "Left chatroom.");
|
|
145
174
|
RemoveAllPeers();
|
|
146
|
-
|
|
175
|
+
CurrentMode = ChatroomAgentMode.Unconnected;
|
|
176
|
+
};
|
|
177
|
+
Network.OnPeerJoinedChatroom += id => {
|
|
178
|
+
Debug.unityLogger.Log(TAG, "New peer joined: " + id);
|
|
147
179
|
AddPeer(id);
|
|
148
|
-
|
|
180
|
+
};
|
|
181
|
+
Network.OnPeerLeftChatroom += id => {
|
|
182
|
+
Debug.unityLogger.Log(TAG, "Peer left: " + id);
|
|
149
183
|
RemovePeer(id);
|
|
184
|
+
};
|
|
150
185
|
|
|
151
186
|
// Stream the incoming audio data using the right peer output
|
|
152
187
|
Network.OnAudioReceived += (peerID, data) => {
|
|
153
|
-
// if we're muting all,
|
|
188
|
+
// if we're muting all, do nothing.
|
|
154
189
|
if (MuteOthers) return;
|
|
155
190
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
var channels = data.channelCount;
|
|
159
|
-
var samples = data.samples;
|
|
160
|
-
|
|
161
|
-
if (HasSettingsForPeer(peerID) && !PeerSettings[peerID].muteThem)
|
|
162
|
-
PeerOutputs[peerID].Feed(index, frequency, channels, samples);
|
|
191
|
+
if (AllowIncomingAudioFromPeer(peerID))
|
|
192
|
+
PeerOutputs[peerID].Feed(data);
|
|
163
193
|
};
|
|
164
194
|
|
|
165
195
|
AudioInput.OnSegmentReady += (index, samples) => {
|
|
196
|
+
if (CurrentMode == ChatroomAgentMode.Unconnected) return;
|
|
197
|
+
|
|
198
|
+
// If we're muting ourselves to all, do nothing.
|
|
166
199
|
if (MuteSelf) return;
|
|
167
200
|
|
|
168
201
|
// Get all the recipients we haven't muted ourselves to
|
|
169
202
|
var recipients = Network.PeerIDs
|
|
170
|
-
.Where(
|
|
171
|
-
return HasSettingsForPeer(x) && !PeerSettings[x].muteSelf;
|
|
172
|
-
});
|
|
203
|
+
.Where(id => AllowOutgoingAudioToPeer(id));
|
|
173
204
|
|
|
174
205
|
// Send the audio segment to every deserving recipient
|
|
175
206
|
foreach (var recipient in recipients)
|
|
@@ -180,35 +211,50 @@ namespace Adrenak.UniVoice {
|
|
|
180
211
|
samples = samples
|
|
181
212
|
});
|
|
182
213
|
};
|
|
214
|
+
Debug.unityLogger.Log(TAG, "Event setup completed.");
|
|
183
215
|
}
|
|
184
216
|
|
|
185
217
|
void AddPeer(short id) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
218
|
+
// Ensure no old settings or outputs exist for this ID.
|
|
219
|
+
RemovePeer(id);
|
|
220
|
+
|
|
221
|
+
PeerSettings.Add(id, new ChatroomPeerSettings());
|
|
222
|
+
|
|
223
|
+
var output = AudioOutputFactory.Create(
|
|
224
|
+
AudioInput.Frequency,
|
|
225
|
+
AudioInput.ChannelCount,
|
|
226
|
+
AudioInput.Frequency * AudioInput.ChannelCount / AudioInput.SegmentRate
|
|
227
|
+
);
|
|
228
|
+
output.ID = id.ToString();
|
|
229
|
+
PeerOutputs.Add(id, output);
|
|
230
|
+
Debug.unityLogger.Log(TAG, "Added peer " + id);
|
|
197
231
|
}
|
|
198
232
|
|
|
199
233
|
void RemovePeer(short id) {
|
|
200
|
-
if (PeerSettings.ContainsKey(id))
|
|
234
|
+
if (PeerSettings.ContainsKey(id)) {
|
|
201
235
|
PeerSettings.Remove(id);
|
|
236
|
+
Debug.unityLogger.Log(TAG, "Removed peer settings for ID " + id);
|
|
237
|
+
}
|
|
202
238
|
if (PeerOutputs.ContainsKey(id)) {
|
|
203
239
|
PeerOutputs[id].Dispose();
|
|
204
240
|
PeerOutputs.Remove(id);
|
|
241
|
+
Debug.unityLogger.Log(TAG, "Removed peer output for ID " + id);
|
|
205
242
|
}
|
|
206
243
|
}
|
|
207
244
|
|
|
208
|
-
|
|
209
|
-
PeerSettings.
|
|
245
|
+
bool AllowIncomingAudioFromPeer(short id) {
|
|
246
|
+
return PeerSettings.ContainsKey(id) && !PeerSettings[id].muteThem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
bool AllowOutgoingAudioToPeer(short id) {
|
|
250
|
+
return PeerSettings.ContainsKey(id) && !PeerSettings[id].muteSelf;
|
|
251
|
+
}
|
|
210
252
|
|
|
211
|
-
|
|
253
|
+
void RemoveAllPeers() {
|
|
254
|
+
Debug.unityLogger.Log(TAG, "Removing all peers");
|
|
255
|
+
foreach(var peer in Network.PeerIDs)
|
|
256
|
+
RemovePeer(peer);
|
|
257
|
+
}
|
|
212
258
|
#endregion
|
|
213
259
|
}
|
|
214
260
|
}
|
|
@@ -26,7 +26,7 @@ namespace Adrenak.UniVoice {
|
|
|
26
26
|
/// <summary>
|
|
27
27
|
/// The number of segments (a segment is a sequence of audio samples)
|
|
28
28
|
/// that are emitted from the source every second.
|
|
29
|
-
/// A 16000 Hz source with one channel at a rate of 10
|
|
29
|
+
/// Eg. A 16000 Hz source with one channel at a rate of 10
|
|
30
30
|
/// will output an array of 1600 samples every 100 milliseconds.
|
|
31
31
|
/// A 44000 Hz source with two channels at a rate of 10
|
|
32
32
|
/// will output an array of 8800 samples every 100 milliseconds.
|
|
@@ -5,13 +5,11 @@ namespace Adrenak.UniVoice {
|
|
|
5
5
|
/// Responsible for playing audio that is sent to it.
|
|
6
6
|
/// You'd normally want a <see cref="UnityEngine.AudioSource"/>
|
|
7
7
|
/// based implementation to play the audio in Unity. But this class can
|
|
8
|
-
/// be used in other ways
|
|
8
|
+
/// be used in other ways such as streaming the received audio to a server
|
|
9
9
|
/// or writing it to a local file. It's just an audio output and the
|
|
10
|
-
/// destination
|
|
10
|
+
/// destination depends on your implementation.
|
|
11
11
|
/// </summary>
|
|
12
12
|
public interface IAudioOutput : IDisposable {
|
|
13
|
-
// TODO: Maybe introduce a PeerID property?
|
|
14
|
-
|
|
15
13
|
/// <summary>
|
|
16
14
|
/// An ID associated with this audio output
|
|
17
15
|
/// </summary>
|
|
@@ -36,10 +34,12 @@ namespace Adrenak.UniVoice {
|
|
|
36
34
|
/// <param name="audioSamples">
|
|
37
35
|
/// The audio samples/segment being fed
|
|
38
36
|
/// </param>
|
|
39
|
-
void Feed(int segmentIndex,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
void Feed(int segmentIndex, int frequency, int channelCount, float[] audioSamples);
|
|
38
|
+
|
|
39
|
+
/// <summary>
|
|
40
|
+
/// Feeds a <see cref="ChatroomAudioSegment"/> object to the audio output.
|
|
41
|
+
/// </summary>
|
|
42
|
+
/// <param name="segment">The audio data to be sent.</param>
|
|
43
|
+
void Feed(ChatroomAudioSegment segment);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
fileFormatVersion: 2
|
|
2
|
-
guid: 095ec1523c98b7f4997c105a06856823
|
|
3
|
-
MonoImporter:
|
|
4
|
-
externalObjects: {}
|
|
5
|
-
serializedVersion: 2
|
|
6
|
-
defaultReferences: []
|
|
7
|
-
executionOrder: 0
|
|
8
|
-
icon: {instanceID: 0}
|
|
9
|
-
userData:
|
|
10
|
-
assetBundleName:
|
|
11
|
-
assetBundleVariant:
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: 095ec1523c98b7f4997c105a06856823
|
|
3
|
+
MonoImporter:
|
|
4
|
+
externalObjects: {}
|
|
5
|
+
serializedVersion: 2
|
|
6
|
+
defaultReferences: []
|
|
7
|
+
executionOrder: 0
|
|
8
|
+
icon: {instanceID: 0}
|
|
9
|
+
userData:
|
|
10
|
+
assetBundleName:
|
|
11
|
+
assetBundleVariant:
|
|
@@ -46,8 +46,10 @@ namespace Adrenak.UniVoice {
|
|
|
46
46
|
/// <summary>
|
|
47
47
|
/// Fired when a peer joins the chatroom.
|
|
48
48
|
/// Provides the ID of the peer as event data.
|
|
49
|
-
/// This action also MUST be called for all previously
|
|
50
|
-
/// existing peers when
|
|
49
|
+
/// NOTE: This action also MUST be called for all previously
|
|
50
|
+
/// existing peers when a local user connects to a network.
|
|
51
|
+
/// This allows the local user to know about the users that
|
|
52
|
+
/// were in the chatroom before they joined.
|
|
51
53
|
/// </summary>
|
|
52
54
|
event Action<short> OnPeerJoinedChatroom;
|
|
53
55
|
|
|
@@ -59,11 +61,15 @@ namespace Adrenak.UniVoice {
|
|
|
59
61
|
|
|
60
62
|
/// <summary>
|
|
61
63
|
/// Fired when the network receives audio data from a peer.
|
|
64
|
+
/// The first argument is the ID of the user the audio came from.
|
|
65
|
+
/// The second is the audio segment.
|
|
62
66
|
/// </summary>
|
|
63
67
|
event Action<short, ChatroomAudioSegment> OnAudioReceived;
|
|
64
68
|
|
|
65
69
|
/// <summary>
|
|
66
70
|
/// Fired when the local user sets audio data to a peer.
|
|
71
|
+
/// The first argument is the ID of the user the audio was sent to.
|
|
72
|
+
/// The second is the audio segment.
|
|
67
73
|
/// </summary>
|
|
68
74
|
event Action<short, ChatroomAudioSegment> OnAudioSent;
|
|
69
75
|
#endregion
|
|
@@ -77,7 +83,7 @@ namespace Adrenak.UniVoice {
|
|
|
77
83
|
short OwnID { get; }
|
|
78
84
|
|
|
79
85
|
/// <summary>
|
|
80
|
-
/// IDs of all the peers in the current chatroom
|
|
86
|
+
/// IDs of all the peers in the current chatroom (excluding <see cref="OwnID"/>)
|
|
81
87
|
/// </summary>
|
|
82
88
|
List<short> PeerIDs { get; }
|
|
83
89
|
#endregion
|
|
@@ -88,25 +94,25 @@ namespace Adrenak.UniVoice {
|
|
|
88
94
|
/// <summary>
|
|
89
95
|
/// Creates a chatroom
|
|
90
96
|
/// </summary>
|
|
91
|
-
/// <param name="data">
|
|
97
|
+
/// <param name="data">Any arguments for hosting a chatroom</param>
|
|
92
98
|
void HostChatroom(object data = null);
|
|
93
99
|
|
|
94
100
|
/// <summary>
|
|
95
101
|
/// Closes a chatroom that the local user is hosting
|
|
96
102
|
/// </summary>
|
|
97
|
-
/// <param name="data">Any arguments for closing the
|
|
103
|
+
/// <param name="data">Any arguments used for closing the chatroom</param>
|
|
98
104
|
void CloseChatroom(object data = null);
|
|
99
105
|
|
|
100
106
|
/// <summary>
|
|
101
107
|
/// Joins a chatroom
|
|
102
108
|
/// </summary>
|
|
103
|
-
/// <param name="data">
|
|
109
|
+
/// <param name="data">Any arguments used to join a chatroom</param>
|
|
104
110
|
void JoinChatroom(object data = null);
|
|
105
111
|
|
|
106
112
|
/// <summary>
|
|
107
113
|
/// Leaves the chatroom the local user is currently in, if any
|
|
108
114
|
/// </summary>
|
|
109
|
-
/// <param name="data">Any arguments
|
|
115
|
+
/// <param name="data">Any arguments used to leave a chatroom</param>
|
|
110
116
|
void LeaveChatroom(object data = null);
|
|
111
117
|
|
|
112
118
|
/// <summary>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
fileFormatVersion: 2
|
|
2
|
-
guid: e3c9ef93e574acf4094f05ab7346bfd5
|
|
3
|
-
MonoImporter:
|
|
4
|
-
externalObjects: {}
|
|
5
|
-
serializedVersion: 2
|
|
6
|
-
defaultReferences: []
|
|
7
|
-
executionOrder: 0
|
|
8
|
-
icon: {instanceID: 0}
|
|
9
|
-
userData:
|
|
10
|
-
assetBundleName:
|
|
11
|
-
assetBundleVariant:
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: e3c9ef93e574acf4094f05ab7346bfd5
|
|
3
|
+
MonoImporter:
|
|
4
|
+
externalObjects: {}
|
|
5
|
+
serializedVersion: 2
|
|
6
|
+
defaultReferences: []
|
|
7
|
+
executionOrder: 0
|
|
8
|
+
icon: {instanceID: 0}
|
|
9
|
+
userData:
|
|
10
|
+
assetBundleName:
|
|
11
|
+
assetBundleVariant:
|
package/package.json
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
"name": "com.adrenak.univoice",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"displayName": "Adrenak.UniVoice",
|
|
5
|
+
"description": "Voice chat/VoIP solution for Unity.",
|
|
6
|
+
"unity": "2019.4",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Vatsal Ambastha",
|
|
9
|
+
"email": "ambastha.vatsal@gmail.com",
|
|
10
|
+
"url": "http://www.vatsalambastha.com"
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"Peer To Peer",
|
|
15
|
+
"WebRTC",
|
|
16
|
+
"P2P",
|
|
17
|
+
"Networking",
|
|
18
|
+
"Voice Chat",
|
|
19
|
+
"voip",
|
|
20
|
+
"Unity",
|
|
21
|
+
"Unity3d",
|
|
22
|
+
"VR",
|
|
23
|
+
"AR",
|
|
24
|
+
"Metaverse"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"registry": "https://registry.npmjs.org"
|
|
28
|
+
}
|
|
20
29
|
}
|
package/Runtime/Extensions.cs
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
using System.Collections.Generic;
|
|
2
|
-
|
|
3
|
-
using UnityEngine;
|
|
4
|
-
|
|
5
|
-
namespace Adrenak.UniVoice {
|
|
6
|
-
public static class Extensions {
|
|
7
|
-
/// <summary>
|
|
8
|
-
/// Returns the normalized position of the AudioSource on its AudioClip
|
|
9
|
-
/// </summary>
|
|
10
|
-
public static float Position(this AudioSource source) {
|
|
11
|
-
return (float)source.timeSamples / source.clip.samples;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// <summary>
|
|
15
|
-
/// Adds the given key to the dictionary with a value if the key
|
|
16
|
-
/// is not present before.
|
|
17
|
-
/// </summary>
|
|
18
|
-
/// <param name="t">The key to check and add</param>
|
|
19
|
-
/// <param name="k">The value if the key is added</param>
|
|
20
|
-
public static void EnsureKey<T, K>
|
|
21
|
-
(this Dictionary<T, K> dict, T t, K k) {
|
|
22
|
-
if (!dict.ContainsKey(t))
|
|
23
|
-
dict.Add(t, k);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/// <summary>
|
|
27
|
-
/// Ensures a key and value pair are in the dictionary
|
|
28
|
-
/// </summary>
|
|
29
|
-
/// <param name="t">The key to ensure</param>
|
|
30
|
-
/// <param name="k">The value associated with the key</param>
|
|
31
|
-
public static void EnsurePair<T, K>
|
|
32
|
-
(this Dictionary<T, K> dict, T t, K k) {
|
|
33
|
-
if (dict.ContainsKey(t))
|
|
34
|
-
dict[t] = k;
|
|
35
|
-
else
|
|
36
|
-
dict.Add(t, k);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
fileFormatVersion: 2
|
|
2
|
-
guid: 646602ab062d77543b3742e51d16658f
|
|
3
|
-
timeCreated: 1547895114
|
|
4
|
-
licenseType: Free
|
|
5
|
-
MonoImporter:
|
|
6
|
-
serializedVersion: 2
|
|
7
|
-
defaultReferences: []
|
|
8
|
-
executionOrder: 0
|
|
9
|
-
icon: {instanceID: 0}
|
|
10
|
-
userData:
|
|
11
|
-
assetBundleName:
|
|
12
|
-
assetBundleVariant:
|