com.adrenak.univoice 4.0.0 → 4.1.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/README.md +9 -5
- package/Runtime/Adrenak.UniVoice.Runtime.asmdef +2 -1
- package/Runtime/ClientSession.cs +4 -3
- package/Runtime/Impl/Filters/Concentus Opus Filters/ConcentusDecodeFilter.cs +80 -0
- package/Runtime/Impl/Filters/Concentus Opus Filters/ConcentusEncodeFilter.cs +156 -0
- package/Runtime/Impl/Filters/Concentus Opus Filters/ConcentusEncodeFilter.cs.meta +11 -0
- package/Runtime/Impl/Filters/Concentus Opus Filters/ConcentusFrequencies.cs +31 -0
- package/Runtime/Impl/Filters/Concentus Opus Filters/ConcentusFrequencies.cs.meta +11 -0
- package/Runtime/Impl/Filters/Concentus Opus Filters.meta +8 -0
- package/Runtime/Impl/Inputs/UniMicInput.cs +15 -4
- package/Samples~/Group Chat Sample/Scenes/GroupVoiceCallSample-Mirror.unity +48 -6
- package/Samples~/Group Chat Sample/Scripts/GroupVoiceCallMirrorSample.cs +7 -29
- package/package.json +9 -9
- package/Runtime/Impl/Filters/OpusFilter.cs +0 -85
- /package/Runtime/Impl/Filters/{OpusFilter.cs.meta → Concentus Opus Filters/ConcentusDecodeFilter.cs.meta} +0 -0
package/README.md
CHANGED
|
@@ -12,11 +12,13 @@ Some features of UniVoice:
|
|
|
12
12
|
* 🔊 __Configurable Audio Output__: UniVoice is audio output agnostic. Out of the box is supports playing peer audio using Unity AudioSource. You can divert incoming audio to anywhere you want by implementing the `IAudioOutput` interface.
|
|
13
13
|
|
|
14
14
|
* 🌐 __Configurable Network__: UniVoice is network agnostic and supports Mirror out of the box. You can implement the `IAudioClient` and `IAudioServer` interfaces using the networking plugin of your choice to make it compatible with it.
|
|
15
|
+
|
|
16
|
+
* ✏️ __Audio Filters__: Modify outgoing and incoming audio by implementing the `IAudioFilter` interface. Gaussian blurring for denoising and Opus (Concentus) encoding & decoding for lower bandwidth consumption are provided out of the box.
|
|
15
17
|
|
|
16
18
|
## Installation
|
|
17
19
|
⚠️ [OpenUPM](https://openupm.com/packages/com.adrenak.univoice/?subPage=versions) may not have up to date releases. Install using NPM registry instead 👇
|
|
18
20
|
|
|
19
|
-
Ensure you have the NPM registry in the `
|
|
21
|
+
Ensure you have the NPM registry in the `manifest.json` file of your Unity project with the following scopes:
|
|
20
22
|
```
|
|
21
23
|
"scopedRegistries": [
|
|
22
24
|
{
|
|
@@ -27,11 +29,12 @@ Ensure you have the NPM registry in the `packages.json` file of your Unity proje
|
|
|
27
29
|
"com.adrenak.univoice",
|
|
28
30
|
"com.adrenak.brw",
|
|
29
31
|
"com.adrenak.unimic",
|
|
30
|
-
"com.adrenak.
|
|
32
|
+
"com.adrenak.concentus-unity"
|
|
31
33
|
]
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
```
|
|
37
|
+
Then add `com.adrenak.univoice:x.y.z` to the `dependencies` in your `manifest.json` file (where x.y.z is the version you wish to install). The list of versions is available on [the UniVoice NPM page](https://www.npmjs.com/package/com.adrenak.univoice?activeTab=versions).
|
|
35
38
|
|
|
36
39
|
## Docs
|
|
37
40
|
Am API reference is available: http://www.vatsalambastha.com/univoice
|
|
@@ -42,11 +45,11 @@ This repository contains a sample scene for the Mirror network, which is the bes
|
|
|
42
45
|
To try the sample, import Mirror and add the `UNIVOICE_MIRROR_NETWORK` compilation symbol to your project.
|
|
43
46
|
|
|
44
47
|
## Dependencies
|
|
45
|
-
[com.adrenak.brw](https://www.github.com/adrenak/brw)
|
|
48
|
+
[com.adrenak.brw](https://www.github.com/adrenak/brw) for reading and writing messages for communication. See `MirrorServer.cs` and `MirrorClient.cs` where they're used.
|
|
46
49
|
|
|
47
|
-
[com.adrenak.unimic](https://www.github.com/adrenak/unimic)
|
|
50
|
+
[com.adrenak.unimic](https://www.github.com/adrenak/unimic) for easily capturing audio from any connected mic devices. See `UniMicInput.cs` for usage. Also used for streaming audio playback. See `StreamedAudioSourceOutput.cs` for usage.
|
|
48
51
|
|
|
49
|
-
[com.adrenak.
|
|
52
|
+
[com.adrenak.concentus-unity](https://www.github.com/adrenak/concentus-unity) for Opus encoding and decoding. See `ConcentusEncodeFilter.cs` and `ConcentusDecodeFilter.cs` for usage
|
|
50
53
|
|
|
51
54
|
## License and Support
|
|
52
55
|
This project is under the [MIT license](https://github.com/adrenak/univoice/blob/master/LICENSE).
|
|
@@ -60,3 +63,4 @@ The developer can be reached at the following links:
|
|
|
60
63
|
[LinkedIn](https://www.linkedin.com/in/vatsalAmbastha)
|
|
61
64
|
[GitHub](https://www.github.com/adrenak)
|
|
62
65
|
[Twitter](https://www.twitter.com/vatsalAmbastha)
|
|
66
|
+
Discord: `adrenak#1934`
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Adrenak.UniVoice.Runtime",
|
|
3
|
+
"rootNamespace": "",
|
|
3
4
|
"references": [
|
|
4
5
|
"GUID:f87ecb857e752164ab814a3de8eb0262",
|
|
5
6
|
"GUID:1f776cd02c03a7b4280b6b649d7758e2",
|
|
6
7
|
"GUID:30817c1a0e6d646d99c048fc403f5979",
|
|
7
8
|
"GUID:725ee7191c021de4dbf9269590ded755",
|
|
8
|
-
"GUID:
|
|
9
|
+
"GUID:b118fd5a40c85ad4e9b38e8c4a42bbb1"
|
|
9
10
|
],
|
|
10
11
|
"includePlatforms": [],
|
|
11
12
|
"excludePlatforms": [],
|
package/Runtime/ClientSession.cs
CHANGED
|
@@ -77,8 +77,8 @@ namespace Adrenak.UniVoice {
|
|
|
77
77
|
foreach (var filter in OutputFilters)
|
|
78
78
|
audioFrame = filter.Run(audioFrame);
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
if(audioFrame.samples.Length > 0)
|
|
81
|
+
PeerOutputs[id].Feed(audioFrame);
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -99,7 +99,8 @@ namespace Adrenak.UniVoice {
|
|
|
99
99
|
frame = filter.Run(frame);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
if(frame.samples.Length > 0)
|
|
103
|
+
Client.SendAudioFrame(frame);
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
using Concentus;
|
|
2
|
+
using System;
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Opus encoding and decoding are VERY important for any real world use of UniVoice as without
|
|
6
|
+
* encoding the size of audio data is much (over 10x) larger.
|
|
7
|
+
* For more info see https://www.github.com/adrenak/concentus-unity
|
|
8
|
+
*/
|
|
9
|
+
namespace Adrenak.UniVoice.Filters {
|
|
10
|
+
/// <summary>
|
|
11
|
+
/// Decodes Opus encoded audio. Use this as a filter for incoming client audio.
|
|
12
|
+
/// </summary>
|
|
13
|
+
public class ConcentusDecodeFilter : IAudioFilter {
|
|
14
|
+
IOpusDecoder decoder;
|
|
15
|
+
float[] decodeBuffer;
|
|
16
|
+
int inputChannelCount;
|
|
17
|
+
int inputFrequency;
|
|
18
|
+
byte[] floatsToBytes;
|
|
19
|
+
|
|
20
|
+
/// <summary>
|
|
21
|
+
/// Creates a Concentus decode filter.
|
|
22
|
+
/// </summary>
|
|
23
|
+
/// <param name="decodeBufferLength">
|
|
24
|
+
/// The length of the decode buffer. Default is 11520 to fit a large sample
|
|
25
|
+
/// with frequency 48000, duration 120ms and 2 channels. This should be enough
|
|
26
|
+
/// for almost all scenarios. Increase if you need more.
|
|
27
|
+
/// </param>
|
|
28
|
+
public ConcentusDecodeFilter(int decodeBufferLength = 11520) {
|
|
29
|
+
decodeBuffer = new float[decodeBufferLength];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public AudioFrame Run(AudioFrame input) {
|
|
33
|
+
inputChannelCount = input.channelCount;
|
|
34
|
+
inputFrequency = input.frequency;
|
|
35
|
+
|
|
36
|
+
CreateNewDecoderIfNeeded();
|
|
37
|
+
|
|
38
|
+
var decodeResult = Decode(input.samples, out Span<float> decoded);
|
|
39
|
+
if (decodeResult > 0) {
|
|
40
|
+
floatsToBytes = Utils.Bytes.FloatsToBytes(decoded.ToArray());
|
|
41
|
+
return new AudioFrame {
|
|
42
|
+
timestamp = input.timestamp,
|
|
43
|
+
samples = floatsToBytes,
|
|
44
|
+
channelCount = inputChannelCount,
|
|
45
|
+
frequency = inputFrequency
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return new AudioFrame {
|
|
50
|
+
timestamp = input.timestamp,
|
|
51
|
+
samples = new byte[0],
|
|
52
|
+
channelCount = inputChannelCount,
|
|
53
|
+
frequency = inputFrequency
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
int Decode(Span<byte> toDecode, out Span<float> decoded) {
|
|
59
|
+
// Decode the Opus packet into preallocated buffer
|
|
60
|
+
int samplesPerChannel = decoder.Decode(toDecode, decodeBuffer, decodeBuffer.Length);
|
|
61
|
+
|
|
62
|
+
if (samplesPerChannel > 0) {
|
|
63
|
+
int totalSamples = samplesPerChannel * inputChannelCount; // Total samples across all channels
|
|
64
|
+
decoded = decodeBuffer.AsSpan(0, totalSamples); // Trim to valid samples
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
decoded = Span<float>.Empty;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return samplesPerChannel; // Return number of samples per channel or 0 on failure
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void CreateNewDecoderIfNeeded() {
|
|
74
|
+
if (decoder == null || decoder.SampleRate != inputFrequency || decoder.NumChannels != inputChannelCount) {
|
|
75
|
+
decoder?.Dispose();
|
|
76
|
+
decoder = OpusCodecFactory.CreateDecoder(inputFrequency, inputChannelCount);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
using Concentus;
|
|
2
|
+
using Concentus.Enums;
|
|
3
|
+
using System;
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Opus encoding and decoding are VERY important for any real world use of UniVoice as without
|
|
7
|
+
* encoding the size of audio data is much (over 10x) larger.
|
|
8
|
+
* For more info see https://www.github.com/adrenak/concentus-unity
|
|
9
|
+
*/
|
|
10
|
+
namespace Adrenak.UniVoice.Filters {
|
|
11
|
+
/// <summary>
|
|
12
|
+
/// A filter that encodes audio using Opus. Use this as an output filter
|
|
13
|
+
/// to reduce the size of outgoing client audio
|
|
14
|
+
/// </summary>
|
|
15
|
+
public class ConcentusEncodeFilter : IAudioFilter {
|
|
16
|
+
public ConcentusFrequencies SamplingFrequency { get; private set; }
|
|
17
|
+
IOpusEncoder encoder;
|
|
18
|
+
IResampler resampler;
|
|
19
|
+
byte[] encodeBuffer;
|
|
20
|
+
float[] resampleBuffer;
|
|
21
|
+
int inputDuration;
|
|
22
|
+
int inputChannels;
|
|
23
|
+
int inputFrequency;
|
|
24
|
+
int resamplerChannelCount;
|
|
25
|
+
float[] bytesToFloats;
|
|
26
|
+
byte[] floatsToBytes;
|
|
27
|
+
int resamplerQuality;
|
|
28
|
+
int encoderComplexity;
|
|
29
|
+
int encoderBitrate;
|
|
30
|
+
|
|
31
|
+
/// <summary>
|
|
32
|
+
/// Creates a Concentus encode filter
|
|
33
|
+
/// </summary>
|
|
34
|
+
/// <param name="encodeFrequency">
|
|
35
|
+
/// The frequency the encoder runs at.
|
|
36
|
+
/// If the input audio frequency is different from this value, it will be resampled before encode.
|
|
37
|
+
/// </param>
|
|
38
|
+
/// <param name="resamplerQuality">Resampler quality [1, 10]</param>
|
|
39
|
+
/// <param name="encoderComplexity">Encoder complexity [1, 10]</param>
|
|
40
|
+
/// <param name="encoderBitrate">Encoder bitrate [16000, 256000]. Set to -1 to enable variable bitrate.</param>
|
|
41
|
+
/// <param name="encodeBufferLength">
|
|
42
|
+
/// The length of the encode buffer. Default is 46080 to fit a large sample
|
|
43
|
+
/// with frequency 48000, duration 120ms and 2 channels. This should be enough
|
|
44
|
+
/// for almost all scenarios. Increase if you need more.
|
|
45
|
+
/// </param>
|
|
46
|
+
public ConcentusEncodeFilter(
|
|
47
|
+
ConcentusFrequencies encodeFrequency = ConcentusFrequencies.Frequency_16000,
|
|
48
|
+
int resamplerQuality = 2,
|
|
49
|
+
int encoderComplexity = 3,
|
|
50
|
+
int encoderBitrate = 64000,
|
|
51
|
+
int encodeBufferLength = 46080
|
|
52
|
+
) {
|
|
53
|
+
SamplingFrequency = encodeFrequency;
|
|
54
|
+
this.resamplerQuality = Math.Clamp(resamplerQuality, 1, 10);
|
|
55
|
+
this.encoderComplexity = Math.Clamp(encoderComplexity, 1, 10);
|
|
56
|
+
this.encoderBitrate = Math.Clamp(encoderBitrate, 16000, 256000);
|
|
57
|
+
encodeBuffer = new byte[encodeBufferLength];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public AudioFrame Run(AudioFrame input) {
|
|
61
|
+
inputChannels = input.channelCount;
|
|
62
|
+
inputFrequency = input.frequency;
|
|
63
|
+
inputDuration = ((input.samples.Length / 4) * 1000) / (input.frequency * input.channelCount);
|
|
64
|
+
|
|
65
|
+
CreateNewResamplerAndEncoderIfNeeded();
|
|
66
|
+
|
|
67
|
+
Span<float> toEncode;
|
|
68
|
+
bytesToFloats = Utils.Bytes.BytesToFloats(input.samples);
|
|
69
|
+
toEncode = bytesToFloats;
|
|
70
|
+
|
|
71
|
+
if (inputFrequency != (int)SamplingFrequency)
|
|
72
|
+
toEncode = Resample(bytesToFloats);
|
|
73
|
+
|
|
74
|
+
var encodeResult = Encode(toEncode, out Span<byte> encoded);
|
|
75
|
+
if (encodeResult > 0) {
|
|
76
|
+
floatsToBytes = encoded.ToArray();
|
|
77
|
+
return new AudioFrame {
|
|
78
|
+
timestamp = input.timestamp,
|
|
79
|
+
channelCount = inputChannels,
|
|
80
|
+
samples = floatsToBytes,
|
|
81
|
+
frequency = (int)SamplingFrequency
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return new AudioFrame {
|
|
86
|
+
timestamp = input.timestamp,
|
|
87
|
+
channelCount = inputChannels,
|
|
88
|
+
samples = new byte[0],
|
|
89
|
+
frequency = (int)SamplingFrequency
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void CreateNewResamplerAndEncoderIfNeeded() {
|
|
95
|
+
if (resampleBuffer == null || resampleBuffer.Length != (int)SamplingFrequency * inputDuration * inputChannels / 1000)
|
|
96
|
+
resampleBuffer = new float[(int)SamplingFrequency * inputDuration * inputChannels / 1000];
|
|
97
|
+
|
|
98
|
+
if (resampler == null) {
|
|
99
|
+
resamplerChannelCount = inputChannels;
|
|
100
|
+
resampler = ResamplerFactory.CreateResampler(inputChannels, inputFrequency, (int)SamplingFrequency, resamplerQuality);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
resampler.GetRates(out int in_rate, out int out_rate);
|
|
104
|
+
if (in_rate != inputFrequency || out_rate != (int)SamplingFrequency || resamplerChannelCount != inputChannels) {
|
|
105
|
+
resampler.Dispose();
|
|
106
|
+
resamplerChannelCount = inputChannels;
|
|
107
|
+
resampler = ResamplerFactory.CreateResampler(inputChannels, inputFrequency, (int)SamplingFrequency, resamplerQuality);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (encoder == null || encoder.SampleRate != (int)SamplingFrequency || encoder.NumChannels != inputChannels) {
|
|
112
|
+
encoder?.Dispose();
|
|
113
|
+
encoder = OpusCodecFactory.CreateEncoder((int)SamplingFrequency, inputChannels, OpusApplication.OPUS_APPLICATION_VOIP);
|
|
114
|
+
encoder.Complexity = encoderComplexity;
|
|
115
|
+
if(encoderBitrate == -1)
|
|
116
|
+
encoder.UseVBR = true;
|
|
117
|
+
else {
|
|
118
|
+
encoder.UseVBR = false;
|
|
119
|
+
encoder.Bitrate = encoderBitrate;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Span<float> Resample(Span<float> samples) {
|
|
125
|
+
// Calculate input and output lengths
|
|
126
|
+
int in_len = samples.Length / inputChannels; // Input samples per channel
|
|
127
|
+
int out_len = (int)SamplingFrequency * inputDuration / 1000; // Output samples per channel
|
|
128
|
+
|
|
129
|
+
// Perform resampling into preallocated buffer
|
|
130
|
+
resampler.ProcessInterleaved(samples, ref in_len, resampleBuffer, ref out_len);
|
|
131
|
+
|
|
132
|
+
// Return only the valid portion of resampled data
|
|
133
|
+
return resampleBuffer.AsSpan(0, out_len * inputChannels); // Trim to valid samples
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
int Encode(Span<float> toEncode, out Span<byte> encoded) {
|
|
137
|
+
int frameSize = (int)SamplingFrequency * inputDuration / 1000; // Samples per channel
|
|
138
|
+
int totalSamples = frameSize * inputChannels; // Total interleaved samples
|
|
139
|
+
|
|
140
|
+
if (toEncode.Length < totalSamples) {
|
|
141
|
+
encoded = Span<byte>.Empty;
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Use preallocated encodeBuffer
|
|
146
|
+
int result = encoder.Encode(toEncode.Slice(0, totalSamples), frameSize, encodeBuffer, encodeBuffer.Length);
|
|
147
|
+
|
|
148
|
+
if (result > 0)
|
|
149
|
+
encoded = encodeBuffer.AsSpan(0, result); // Trim to actual encoded size
|
|
150
|
+
else
|
|
151
|
+
encoded = Span<byte>.Empty;
|
|
152
|
+
|
|
153
|
+
return result; // Return number of bytes written or 0 on failure
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
namespace Adrenak.UniVoice.Filters {
|
|
2
|
+
/// <summary>
|
|
3
|
+
/// Defines supported sampling frequencies for the Opus codec via Concentus.
|
|
4
|
+
/// </summary>
|
|
5
|
+
public enum ConcentusFrequencies : int {
|
|
6
|
+
/// <summary>
|
|
7
|
+
/// 8 kHz sampling frequency, typically used for narrowband audio.
|
|
8
|
+
/// </summary>
|
|
9
|
+
Frequency_8000 = 8000,
|
|
10
|
+
|
|
11
|
+
/// <summary>
|
|
12
|
+
/// 12 kHz sampling frequency, suitable for medium-band audio.
|
|
13
|
+
/// </summary>
|
|
14
|
+
Frequency_12000 = 12000,
|
|
15
|
+
|
|
16
|
+
/// <summary>
|
|
17
|
+
/// 16 kHz sampling frequency, commonly used for wideband speech.
|
|
18
|
+
/// </summary>
|
|
19
|
+
Frequency_16000 = 16000,
|
|
20
|
+
|
|
21
|
+
/// <summary>
|
|
22
|
+
/// 24 kHz sampling frequency, providing good quality for music and audio.
|
|
23
|
+
/// </summary>
|
|
24
|
+
Frequency_24000 = 24000,
|
|
25
|
+
|
|
26
|
+
/// <summary>
|
|
27
|
+
/// 48 kHz sampling frequency, offering the highest audio quality.
|
|
28
|
+
/// </summary>
|
|
29
|
+
Frequency_48000 = 48000,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -11,14 +11,24 @@ namespace Adrenak.UniVoice.Inputs {
|
|
|
11
11
|
/// </summary>
|
|
12
12
|
public class UniMicInput : IAudioInput {
|
|
13
13
|
const string TAG = "UniMicInput";
|
|
14
|
-
|
|
15
14
|
public event Action<AudioFrame> OnFrameReady;
|
|
16
15
|
|
|
17
|
-
public Mic.Device
|
|
16
|
+
public Mic.Device device;
|
|
17
|
+
public Mic.Device Device {
|
|
18
|
+
get => device;
|
|
19
|
+
set {
|
|
20
|
+
if (device == value)
|
|
21
|
+
return;
|
|
22
|
+
if(device != null)
|
|
23
|
+
device.OnFrameCollected -= OnFrameCollected;
|
|
24
|
+
device = value;
|
|
25
|
+
if(device != null)
|
|
26
|
+
device.OnFrameCollected += OnFrameCollected;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
18
29
|
|
|
19
30
|
public UniMicInput(Mic.Device device) {
|
|
20
31
|
Device = device;
|
|
21
|
-
device.OnFrameCollected += OnFrameCollected;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
private void OnFrameCollected(int frequency, int channels, float[] samples) {
|
|
@@ -32,7 +42,8 @@ namespace Adrenak.UniVoice.Inputs {
|
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
public void Dispose() {
|
|
35
|
-
Device
|
|
45
|
+
if(Device != null)
|
|
46
|
+
Device.OnFrameCollected -= OnFrameCollected;
|
|
36
47
|
Debug.unityLogger.Log(TAG, "Disposed");
|
|
37
48
|
}
|
|
38
49
|
}
|
|
@@ -43,7 +43,7 @@ RenderSettings:
|
|
|
43
43
|
--- !u!157 &3
|
|
44
44
|
LightmapSettings:
|
|
45
45
|
m_ObjectHideFlags: 0
|
|
46
|
-
serializedVersion:
|
|
46
|
+
serializedVersion: 12
|
|
47
47
|
m_GIWorkflowMode: 0
|
|
48
48
|
m_GISettings:
|
|
49
49
|
serializedVersion: 2
|
|
@@ -98,7 +98,8 @@ LightmapSettings:
|
|
|
98
98
|
m_TrainingDataDestination: TrainingData
|
|
99
99
|
m_LightProbeSampleCountMultiplier: 4
|
|
100
100
|
m_LightingDataAsset: {fileID: 0}
|
|
101
|
-
|
|
101
|
+
m_LightingSettings: {fileID: 4890085278179872738, guid: ad4b002903bb1474ca81b5d0f5e89dd8,
|
|
102
|
+
type: 2}
|
|
102
103
|
--- !u!196 &4
|
|
103
104
|
NavMeshSettings:
|
|
104
105
|
serializedVersion: 2
|
|
@@ -118,6 +119,8 @@ NavMeshSettings:
|
|
|
118
119
|
manualTileSize: 0
|
|
119
120
|
tileSize: 256
|
|
120
121
|
accuratePlacement: 0
|
|
122
|
+
maxJobWorkers: 0
|
|
123
|
+
preserveTilesOutsideBounds: 0
|
|
121
124
|
debug:
|
|
122
125
|
m_Flags: 0
|
|
123
126
|
m_NavMeshData: {fileID: 0}
|
|
@@ -149,6 +152,7 @@ RectTransform:
|
|
|
149
152
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
150
153
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
151
154
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
155
|
+
m_ConstrainProportionsScale: 0
|
|
152
156
|
m_Children:
|
|
153
157
|
- {fileID: 1116173713}
|
|
154
158
|
m_Father: {fileID: 1726461497}
|
|
@@ -174,6 +178,7 @@ MonoBehaviour:
|
|
|
174
178
|
m_Material: {fileID: 0}
|
|
175
179
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
176
180
|
m_RaycastTarget: 1
|
|
181
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
177
182
|
m_Maskable: 1
|
|
178
183
|
m_OnCullStateChanged:
|
|
179
184
|
m_PersistentCalls:
|
|
@@ -241,6 +246,7 @@ Transform:
|
|
|
241
246
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
242
247
|
m_LocalPosition: {x: 153, y: 294.1, z: 0}
|
|
243
248
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
249
|
+
m_ConstrainProportionsScale: 0
|
|
244
250
|
m_Children: []
|
|
245
251
|
m_Father: {fileID: 0}
|
|
246
252
|
m_RootOrder: 3
|
|
@@ -273,6 +279,7 @@ RectTransform:
|
|
|
273
279
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
274
280
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
275
281
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
282
|
+
m_ConstrainProportionsScale: 0
|
|
276
283
|
m_Children:
|
|
277
284
|
- {fileID: 983083073}
|
|
278
285
|
m_Father: {fileID: 1726461497}
|
|
@@ -298,6 +305,7 @@ MonoBehaviour:
|
|
|
298
305
|
m_Material: {fileID: 0}
|
|
299
306
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
300
307
|
m_RaycastTarget: 1
|
|
308
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
301
309
|
m_Maskable: 1
|
|
302
310
|
m_OnCullStateChanged:
|
|
303
311
|
m_PersistentCalls:
|
|
@@ -399,6 +407,7 @@ Transform:
|
|
|
399
407
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
400
408
|
m_LocalPosition: {x: 0, y: 1, z: -10}
|
|
401
409
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
410
|
+
m_ConstrainProportionsScale: 0
|
|
402
411
|
m_Children: []
|
|
403
412
|
m_Father: {fileID: 0}
|
|
404
413
|
m_RootOrder: 0
|
|
@@ -566,6 +575,7 @@ RectTransform:
|
|
|
566
575
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
567
576
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
568
577
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
578
|
+
m_ConstrainProportionsScale: 0
|
|
569
579
|
m_Children:
|
|
570
580
|
- {fileID: 1917147245}
|
|
571
581
|
m_Father: {fileID: 965416053}
|
|
@@ -605,6 +615,7 @@ RectTransform:
|
|
|
605
615
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
606
616
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
607
617
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
618
|
+
m_ConstrainProportionsScale: 0
|
|
608
619
|
m_Children:
|
|
609
620
|
- {fileID: 1790122419}
|
|
610
621
|
m_Father: {fileID: 909505741}
|
|
@@ -629,6 +640,7 @@ MonoBehaviour:
|
|
|
629
640
|
m_EditorClassIdentifier:
|
|
630
641
|
m_Navigation:
|
|
631
642
|
m_Mode: 3
|
|
643
|
+
m_WrapAround: 0
|
|
632
644
|
m_SelectOnUp: {fileID: 0}
|
|
633
645
|
m_SelectOnDown: {fileID: 0}
|
|
634
646
|
m_SelectOnLeft: {fileID: 0}
|
|
@@ -678,6 +690,7 @@ MonoBehaviour:
|
|
|
678
690
|
m_Material: {fileID: 0}
|
|
679
691
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
680
692
|
m_RaycastTarget: 1
|
|
693
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
681
694
|
m_Maskable: 1
|
|
682
695
|
m_OnCullStateChanged:
|
|
683
696
|
m_PersistentCalls:
|
|
@@ -758,6 +771,7 @@ MonoBehaviour:
|
|
|
758
771
|
m_FallbackScreenDPI: 96
|
|
759
772
|
m_DefaultSpriteDPI: 96
|
|
760
773
|
m_DynamicPixelsPerUnit: 1
|
|
774
|
+
m_PresetInfoIsWorld: 0
|
|
761
775
|
--- !u!223 &877991846
|
|
762
776
|
Canvas:
|
|
763
777
|
m_ObjectHideFlags: 0
|
|
@@ -789,6 +803,7 @@ RectTransform:
|
|
|
789
803
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
790
804
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
791
805
|
m_LocalScale: {x: 0, y: 0, z: 0}
|
|
806
|
+
m_ConstrainProportionsScale: 0
|
|
792
807
|
m_Children:
|
|
793
808
|
- {fileID: 1796628514}
|
|
794
809
|
- {fileID: 1726461497}
|
|
@@ -829,6 +844,7 @@ RectTransform:
|
|
|
829
844
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
830
845
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
831
846
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
847
|
+
m_ConstrainProportionsScale: 0
|
|
832
848
|
m_Children:
|
|
833
849
|
- {fileID: 1798840738}
|
|
834
850
|
- {fileID: 965416053}
|
|
@@ -886,6 +902,7 @@ MonoBehaviour:
|
|
|
886
902
|
m_Material: {fileID: 0}
|
|
887
903
|
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
|
888
904
|
m_RaycastTarget: 1
|
|
905
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
889
906
|
m_Maskable: 1
|
|
890
907
|
m_OnCullStateChanged:
|
|
891
908
|
m_PersistentCalls:
|
|
@@ -937,6 +954,7 @@ RectTransform:
|
|
|
937
954
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
938
955
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
939
956
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
957
|
+
m_ConstrainProportionsScale: 0
|
|
940
958
|
m_Children:
|
|
941
959
|
- {fileID: 741068687}
|
|
942
960
|
m_Father: {fileID: 909505741}
|
|
@@ -961,6 +979,7 @@ MonoBehaviour:
|
|
|
961
979
|
m_EditorClassIdentifier:
|
|
962
980
|
m_Navigation:
|
|
963
981
|
m_Mode: 3
|
|
982
|
+
m_WrapAround: 0
|
|
964
983
|
m_SelectOnUp: {fileID: 0}
|
|
965
984
|
m_SelectOnDown: {fileID: 0}
|
|
966
985
|
m_SelectOnLeft: {fileID: 0}
|
|
@@ -989,7 +1008,7 @@ MonoBehaviour:
|
|
|
989
1008
|
m_TargetGraphic: {fileID: 1917147246}
|
|
990
1009
|
m_HandleRect: {fileID: 1917147245}
|
|
991
1010
|
m_Direction: 0
|
|
992
|
-
m_Value:
|
|
1011
|
+
m_Value: 0
|
|
993
1012
|
m_Size: 0.99999994
|
|
994
1013
|
m_NumberOfSteps: 0
|
|
995
1014
|
m_OnValueChanged:
|
|
@@ -1010,6 +1029,7 @@ MonoBehaviour:
|
|
|
1010
1029
|
m_Material: {fileID: 0}
|
|
1011
1030
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1012
1031
|
m_RaycastTarget: 1
|
|
1032
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1013
1033
|
m_Maskable: 1
|
|
1014
1034
|
m_OnCullStateChanged:
|
|
1015
1035
|
m_PersistentCalls:
|
|
@@ -1060,6 +1080,7 @@ RectTransform:
|
|
|
1060
1080
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1061
1081
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1062
1082
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1083
|
+
m_ConstrainProportionsScale: 0
|
|
1063
1084
|
m_Children: []
|
|
1064
1085
|
m_Father: {fileID: 667953547}
|
|
1065
1086
|
m_RootOrder: 0
|
|
@@ -1084,6 +1105,7 @@ MonoBehaviour:
|
|
|
1084
1105
|
m_Material: {fileID: 0}
|
|
1085
1106
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1086
1107
|
m_RaycastTarget: 1
|
|
1108
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1087
1109
|
m_Maskable: 1
|
|
1088
1110
|
m_OnCullStateChanged:
|
|
1089
1111
|
m_PersistentCalls:
|
|
@@ -1138,6 +1160,7 @@ RectTransform:
|
|
|
1138
1160
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1139
1161
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1140
1162
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1163
|
+
m_ConstrainProportionsScale: 0
|
|
1141
1164
|
m_Children: []
|
|
1142
1165
|
m_Father: {fileID: 1726461497}
|
|
1143
1166
|
m_RootOrder: 2
|
|
@@ -1162,6 +1185,7 @@ MonoBehaviour:
|
|
|
1162
1185
|
m_Material: {fileID: 0}
|
|
1163
1186
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1164
1187
|
m_RaycastTarget: 1
|
|
1188
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1165
1189
|
m_Maskable: 1
|
|
1166
1190
|
m_OnCullStateChanged:
|
|
1167
1191
|
m_PersistentCalls:
|
|
@@ -1216,6 +1240,7 @@ RectTransform:
|
|
|
1216
1240
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1217
1241
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1218
1242
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1243
|
+
m_ConstrainProportionsScale: 0
|
|
1219
1244
|
m_Children: []
|
|
1220
1245
|
m_Father: {fileID: 159342650}
|
|
1221
1246
|
m_RootOrder: 0
|
|
@@ -1240,6 +1265,7 @@ MonoBehaviour:
|
|
|
1240
1265
|
m_Material: {fileID: 0}
|
|
1241
1266
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1242
1267
|
m_RaycastTarget: 1
|
|
1268
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1243
1269
|
m_Maskable: 1
|
|
1244
1270
|
m_OnCullStateChanged:
|
|
1245
1271
|
m_PersistentCalls:
|
|
@@ -1294,6 +1320,7 @@ RectTransform:
|
|
|
1294
1320
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1295
1321
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1296
1322
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1323
|
+
m_ConstrainProportionsScale: 0
|
|
1297
1324
|
m_Children: []
|
|
1298
1325
|
m_Father: {fileID: 1798840738}
|
|
1299
1326
|
m_RootOrder: 0
|
|
@@ -1342,6 +1369,7 @@ MonoBehaviour:
|
|
|
1342
1369
|
m_ChildControlHeight: 0
|
|
1343
1370
|
m_ChildScaleWidth: 0
|
|
1344
1371
|
m_ChildScaleHeight: 0
|
|
1372
|
+
m_ReverseArrangement: 0
|
|
1345
1373
|
--- !u!1001 &1206482348
|
|
1346
1374
|
PrefabInstance:
|
|
1347
1375
|
m_ObjectHideFlags: 0
|
|
@@ -1507,6 +1535,7 @@ RectTransform:
|
|
|
1507
1535
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1508
1536
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1509
1537
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1538
|
+
m_ConstrainProportionsScale: 0
|
|
1510
1539
|
m_Children: []
|
|
1511
1540
|
m_Father: {fileID: 1790122419}
|
|
1512
1541
|
m_RootOrder: 0
|
|
@@ -1531,6 +1560,7 @@ MonoBehaviour:
|
|
|
1531
1560
|
m_Material: {fileID: 0}
|
|
1532
1561
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1533
1562
|
m_RaycastTarget: 1
|
|
1563
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1534
1564
|
m_Maskable: 1
|
|
1535
1565
|
m_OnCullStateChanged:
|
|
1536
1566
|
m_PersistentCalls:
|
|
@@ -1581,6 +1611,7 @@ RectTransform:
|
|
|
1581
1611
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
1582
1612
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1583
1613
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1614
|
+
m_ConstrainProportionsScale: 0
|
|
1584
1615
|
m_Children: []
|
|
1585
1616
|
m_Father: {fileID: 1726461497}
|
|
1586
1617
|
m_RootOrder: 1
|
|
@@ -1605,6 +1636,7 @@ MonoBehaviour:
|
|
|
1605
1636
|
m_Material: {fileID: 0}
|
|
1606
1637
|
m_Color: {r: 0.8962264, g: 0.8962264, b: 0.8962264, a: 1}
|
|
1607
1638
|
m_RaycastTarget: 1
|
|
1639
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1608
1640
|
m_Maskable: 1
|
|
1609
1641
|
m_OnCullStateChanged:
|
|
1610
1642
|
m_PersistentCalls:
|
|
@@ -1657,6 +1689,7 @@ RectTransform:
|
|
|
1657
1689
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
1658
1690
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1659
1691
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1692
|
+
m_ConstrainProportionsScale: 0
|
|
1660
1693
|
m_Children:
|
|
1661
1694
|
- {fileID: 909505741}
|
|
1662
1695
|
- {fileID: 1480403820}
|
|
@@ -1699,6 +1732,7 @@ RectTransform:
|
|
|
1699
1732
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1700
1733
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1701
1734
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1735
|
+
m_ConstrainProportionsScale: 0
|
|
1702
1736
|
m_Children:
|
|
1703
1737
|
- {fileID: 1423776684}
|
|
1704
1738
|
m_Father: {fileID: 789642335}
|
|
@@ -1737,6 +1771,7 @@ RectTransform:
|
|
|
1737
1771
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
1738
1772
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1739
1773
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1774
|
+
m_ConstrainProportionsScale: 0
|
|
1740
1775
|
m_Children: []
|
|
1741
1776
|
m_Father: {fileID: 877991847}
|
|
1742
1777
|
m_RootOrder: 0
|
|
@@ -1761,6 +1796,7 @@ MonoBehaviour:
|
|
|
1761
1796
|
m_Material: {fileID: 0}
|
|
1762
1797
|
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
|
1763
1798
|
m_RaycastTarget: 1
|
|
1799
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1764
1800
|
m_Maskable: 1
|
|
1765
1801
|
m_OnCullStateChanged:
|
|
1766
1802
|
m_PersistentCalls:
|
|
@@ -1812,6 +1848,7 @@ RectTransform:
|
|
|
1812
1848
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1813
1849
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1814
1850
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1851
|
+
m_ConstrainProportionsScale: 0
|
|
1815
1852
|
m_Children:
|
|
1816
1853
|
- {fileID: 1188574985}
|
|
1817
1854
|
m_Father: {fileID: 909505741}
|
|
@@ -1850,6 +1887,7 @@ MonoBehaviour:
|
|
|
1850
1887
|
m_Material: {fileID: 0}
|
|
1851
1888
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1852
1889
|
m_RaycastTarget: 1
|
|
1890
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1853
1891
|
m_Maskable: 1
|
|
1854
1892
|
m_OnCullStateChanged:
|
|
1855
1893
|
m_PersistentCalls:
|
|
@@ -1900,6 +1938,7 @@ RectTransform:
|
|
|
1900
1938
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
1901
1939
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
1902
1940
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
1941
|
+
m_ConstrainProportionsScale: 0
|
|
1903
1942
|
m_Children: []
|
|
1904
1943
|
m_Father: {fileID: 741068687}
|
|
1905
1944
|
m_RootOrder: 0
|
|
@@ -1924,6 +1963,7 @@ MonoBehaviour:
|
|
|
1924
1963
|
m_Material: {fileID: 0}
|
|
1925
1964
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
1926
1965
|
m_RaycastTarget: 1
|
|
1966
|
+
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
1927
1967
|
m_Maskable: 1
|
|
1928
1968
|
m_OnCullStateChanged:
|
|
1929
1969
|
m_PersistentCalls:
|
|
@@ -2008,6 +2048,7 @@ Transform:
|
|
|
2008
2048
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
2009
2049
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
2010
2050
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
2051
|
+
m_ConstrainProportionsScale: 0
|
|
2011
2052
|
m_Children: []
|
|
2012
2053
|
m_Father: {fileID: 0}
|
|
2013
2054
|
m_RootOrder: 2
|
|
@@ -2039,7 +2080,7 @@ MonoBehaviour:
|
|
|
2039
2080
|
m_PrefabInstance: {fileID: 0}
|
|
2040
2081
|
m_PrefabAsset: {fileID: 0}
|
|
2041
2082
|
m_GameObject: {fileID: 2117923849}
|
|
2042
|
-
m_Enabled:
|
|
2083
|
+
m_Enabled: 1
|
|
2043
2084
|
m_EditorHideFlags: 0
|
|
2044
2085
|
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
|
|
2045
2086
|
m_Name:
|
|
@@ -2095,7 +2136,7 @@ MonoBehaviour:
|
|
|
2095
2136
|
offlineScene:
|
|
2096
2137
|
onlineScene:
|
|
2097
2138
|
offlineSceneLoadDelay: 0
|
|
2098
|
-
transport: {fileID:
|
|
2139
|
+
transport: {fileID: 2117923850}
|
|
2099
2140
|
networkAddress: localhost
|
|
2100
2141
|
maxConnections: 100
|
|
2101
2142
|
disconnectInactiveConnections: 0
|
|
@@ -2130,6 +2171,7 @@ Transform:
|
|
|
2130
2171
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
2131
2172
|
m_LocalPosition: {x: 1489.682, y: 663.6068, z: 178.25}
|
|
2132
2173
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
2174
|
+
m_ConstrainProportionsScale: 0
|
|
2133
2175
|
m_Children: []
|
|
2134
2176
|
m_Father: {fileID: 0}
|
|
2135
2177
|
m_RootOrder: 4
|
|
@@ -2141,7 +2183,7 @@ MonoBehaviour:
|
|
|
2141
2183
|
m_PrefabInstance: {fileID: 0}
|
|
2142
2184
|
m_PrefabAsset: {fileID: 0}
|
|
2143
2185
|
m_GameObject: {fileID: 2117923849}
|
|
2144
|
-
m_Enabled:
|
|
2186
|
+
m_Enabled: 0
|
|
2145
2187
|
m_EditorHideFlags: 0
|
|
2146
2188
|
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
|
|
2147
2189
|
m_Name:
|
|
@@ -7,12 +7,11 @@ using UnityEngine;
|
|
|
7
7
|
using UnityEngine.UI;
|
|
8
8
|
using UnityEngine.Android;
|
|
9
9
|
|
|
10
|
+
using Adrenak.UniMic;
|
|
10
11
|
using Adrenak.UniVoice.Networks;
|
|
11
12
|
using Adrenak.UniVoice.Outputs;
|
|
12
13
|
using Adrenak.UniVoice.Inputs;
|
|
13
14
|
using Adrenak.UniVoice.Filters;
|
|
14
|
-
using Adrenak.UniMic;
|
|
15
|
-
using Adrenak.UnityOpus;
|
|
16
15
|
|
|
17
16
|
namespace Adrenak.UniVoice.Samples {
|
|
18
17
|
public class GroupVoiceCallMirrorSample : MonoBehaviour {
|
|
@@ -83,35 +82,14 @@ namespace Adrenak.UniVoice.Samples {
|
|
|
83
82
|
// We add some filters to the input audio
|
|
84
83
|
// - The first is audio blur, so that the audio that's been captured by this client
|
|
85
84
|
// has lesser noise
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
session.InputFilters.Add(new GaussianAudioBlur());
|
|
88
86
|
// - The next one is the Opus encoder filter. This is VERY important. Without this the
|
|
89
87
|
// outgoing data would be very large, usually by a factor of 10 or more.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
OpusApplication.VoIP
|
|
96
|
-
);
|
|
97
|
-
var outgoingEncode = new OpusEncodeFilter(encoder);
|
|
98
|
-
|
|
99
|
-
// Finally, we add both the input filters to the session. Note that session.InputFilters
|
|
100
|
-
// is a list and the filters are run in the order they are added to it.
|
|
101
|
-
session.InputFilters.Add(outgoingBlur);
|
|
102
|
-
session.InputFilters.Add(outgoingEncode);
|
|
103
|
-
|
|
104
|
-
// Next, for incoming audio we create some filters.
|
|
105
|
-
// - first is the decoder, because the audio that we are expecting would be encoded.
|
|
106
|
-
// So we create a decoder, use that to create a OpusDecodeFilter and add it to the sessions
|
|
107
|
-
// output filters
|
|
108
|
-
var decoder = new Decoder(
|
|
109
|
-
(SamplingFrequency)mic.SamplingFrequency,
|
|
110
|
-
(NumChannels)mic.ChannelCount
|
|
111
|
-
);
|
|
112
|
-
var incomingDecode = new OpusDecodeFilter(decoder);
|
|
113
|
-
|
|
114
|
-
session.OutputFilters.Add(incomingDecode);
|
|
88
|
+
session.InputFilters.Add(new ConcentusEncodeFilter());
|
|
89
|
+
|
|
90
|
+
// Next, for incoming audio we register the Concentus decode filter as the audio we'd
|
|
91
|
+
// receive from other clients would be encoded and not readily playable
|
|
92
|
+
session.OutputFilters.Add(new ConcentusDecodeFilter());
|
|
115
93
|
|
|
116
94
|
// Subscribe to some server events
|
|
117
95
|
server.OnServerStart += () => {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.adrenak.univoice",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"displayName": "Adrenak.UniVoice",
|
|
5
|
-
"description": "
|
|
6
|
-
"unity": "
|
|
5
|
+
"description": "Voice chat/VoIP framework for Unity.",
|
|
6
|
+
"unity": "2021.2",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Vatsal Ambastha",
|
|
9
9
|
"email": "ambastha.vatsal@gmail.com",
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"Unity3d",
|
|
20
20
|
"VR",
|
|
21
21
|
"AR",
|
|
22
|
-
"Metaverse"
|
|
22
|
+
"Metaverse",
|
|
23
|
+
"mic",
|
|
24
|
+
"opus",
|
|
25
|
+
"concentus"
|
|
23
26
|
],
|
|
24
27
|
"samples": [
|
|
25
28
|
{
|
|
@@ -28,12 +31,9 @@
|
|
|
28
31
|
"path": "Samples~"
|
|
29
32
|
}
|
|
30
33
|
],
|
|
31
|
-
"publishConfig": {
|
|
32
|
-
"registry": "https://registry.npmjs.org"
|
|
33
|
-
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"com.adrenak.brw": "1.0.1",
|
|
36
|
-
"com.adrenak.unimic": "3.2.
|
|
37
|
-
"com.adrenak.
|
|
36
|
+
"com.adrenak.unimic": "3.2.2",
|
|
37
|
+
"com.adrenak.concentus-unity": "1.0.1"
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
using Adrenak.UnityOpus;
|
|
2
|
-
|
|
3
|
-
using System;
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
* Opus encoding and decoding are VERY important for any real world use of UniVoice as without
|
|
7
|
-
* encoding the size of audio data is much (over 10x) larger.
|
|
8
|
-
* For more info see https://www.github.com/adrenak/UnityOpus
|
|
9
|
-
*/
|
|
10
|
-
namespace Adrenak.UniVoice.Filters {
|
|
11
|
-
/// <summary>
|
|
12
|
-
/// A filter that encodes audio using Opus. Use this as an output filter
|
|
13
|
-
/// to reduce the size of outgoing client audio
|
|
14
|
-
/// </summary>
|
|
15
|
-
public class OpusEncodeFilter : IAudioFilter {
|
|
16
|
-
Encoder encoder;
|
|
17
|
-
byte[] outputBuffer;
|
|
18
|
-
|
|
19
|
-
public OpusEncodeFilter(Encoder encoder) {
|
|
20
|
-
this.encoder = encoder;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public AudioFrame Run(AudioFrame input) {
|
|
24
|
-
if(outputBuffer == null)
|
|
25
|
-
outputBuffer = new byte[input.samples.Length * 4];
|
|
26
|
-
else if(input.samples.Length != outputBuffer.Length * 4)
|
|
27
|
-
outputBuffer = new byte[input.samples.Length * 4];
|
|
28
|
-
|
|
29
|
-
int encodeResult = encoder.Encode(Utils.Bytes.BytesToFloats(input.samples), outputBuffer);
|
|
30
|
-
if (encodeResult > 0) {
|
|
31
|
-
byte[] encodedBytes = new byte[encodeResult];
|
|
32
|
-
Array.Copy(outputBuffer, encodedBytes, encodedBytes.Length);
|
|
33
|
-
return new AudioFrame {
|
|
34
|
-
timestamp = 0,
|
|
35
|
-
frequency = input.frequency,
|
|
36
|
-
channelCount = input.channelCount,
|
|
37
|
-
samples = encodedBytes
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
return new AudioFrame {
|
|
42
|
-
timestamp = 0,
|
|
43
|
-
frequency = input.frequency,
|
|
44
|
-
channelCount = input.channelCount,
|
|
45
|
-
samples = null
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/// <summary>
|
|
52
|
-
/// Decodes Opus encoded audio. Use this as a filter for incoming client audio.
|
|
53
|
-
/// </summary>
|
|
54
|
-
public class OpusDecodeFilter : IAudioFilter {
|
|
55
|
-
Decoder decoder;
|
|
56
|
-
float[] outputBuffer;
|
|
57
|
-
|
|
58
|
-
public OpusDecodeFilter(Decoder decoder, int outputBufferLength = 48000) {
|
|
59
|
-
this.decoder = decoder;
|
|
60
|
-
outputBuffer = new float[outputBufferLength];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
public AudioFrame Run(AudioFrame input) {
|
|
64
|
-
var decodeResult = decoder.Decode(input.samples, input.samples.Length, outputBuffer);
|
|
65
|
-
if(decodeResult > 0) {
|
|
66
|
-
float[] decoded = new float[decodeResult];
|
|
67
|
-
Array.Copy(outputBuffer, decoded, decoded.Length);
|
|
68
|
-
return new AudioFrame {
|
|
69
|
-
timestamp = 0,
|
|
70
|
-
frequency = input.frequency,
|
|
71
|
-
channelCount = input.channelCount,
|
|
72
|
-
samples = Utils.Bytes.FloatsToBytes(decoded)
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
return new AudioFrame {
|
|
77
|
-
timestamp = 0,
|
|
78
|
-
frequency = input.frequency,
|
|
79
|
-
channelCount = input.channelCount,
|
|
80
|
-
samples = null
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
File without changes
|