Client LuaCsForBarotrauma
VoipSound.cs
2 using Concentus.Structs;
3 using Microsoft.Xna.Framework;
4 using OpenAL;
5 using System;
6 
7 namespace Barotrauma.Sounds
8 {
9  class VoipSound : Sound
10  {
12  {
13  get
14  {
15  return SoundManager.SourcePoolIndex.Voice;
16  }
17  }
18 
19  public new bool IsPlaying
20  {
21  get
22  {
23  return soundChannel != null && soundChannel.IsPlaying;
24  }
25  }
26 
27  private readonly VoipQueue queue;
28  private int bufferID = 0;
29 
30  private SoundChannel soundChannel;
31 
32  private readonly OpusDecoder decoder;
33 
34  public bool UseRadioFilter;
35  public bool UseMuffleFilter;
36 
37  public bool UsingRadio;
38 
39  public float Near { get; private set; }
40  public float Far { get; private set; }
41 
42  private readonly BiQuad[] muffleFilters = new BiQuad[]
43  {
44  new LowpassFilter(VoipConfig.FREQUENCY, 800)
45  };
46  private readonly BiQuad[] radioFilters = new BiQuad[]
47  {
48  new BandpassFilter(VoipConfig.FREQUENCY, 2000)
49  };
50  private const float PostRadioFilterBoost = 1.2f;
51 
52  private float gain;
53  public float Gain
54  {
55  get { return soundChannel == null ? 0.0f : gain; }
56  set
57  {
58  if (soundChannel == null) { return; }
59  gain = value;
60  soundChannel.Gain = value * GameSettings.CurrentConfig.Audio.VoiceChatVolume * client.VoiceVolume;
61  }
62  }
63 
64  public float CurrentAmplitude
65  {
66  get { return soundChannel?.CurrentAmplitude ?? 0.0f; }
67  }
68 
69  private Client client;
70 
71  public VoipSound(Client targetClient, SoundManager owner, VoipQueue q) : base(owner, $"VoIP ({targetClient.Name})", true, true, getFullPath: false)
72  {
73  client = targetClient;
74  decoder = VoipConfig.CreateDecoder();
75 
77  SampleRate = VoipConfig.FREQUENCY;
78 
79  queue = q;
80  bufferID = queue.LatestBufferID;
81 
82  soundChannel = null;
83 
84  SoundChannel chn = new SoundChannel(this, 1.0f, null, 1.0f, 0.4f, 1.0f, "voip", false);
85  soundChannel = chn;
86  Gain = 1.0f;
87  }
88 
89  public override float GetAmplitudeAtPlaybackPos(int playbackPos)
90  {
91  throw new NotImplementedException(); //TODO: implement?
92  }
93 
94  public void SetPosition(Vector3? pos)
95  {
96  soundChannel.Position = pos;
97  }
98 
99  public void SetRange(float near, float far)
100  {
101  soundChannel.Near = Near = near;
102  soundChannel.Far = Far = far;
103  }
104 
105  public void ApplyFilters(short[] buffer, int readSamples)
106  {
107  float finalGain = gain * GameSettings.CurrentConfig.Audio.VoiceChatVolume * client.VoiceVolume;
108  for (int i = 0; i < readSamples; i++)
109  {
110  float fVal = ToolBox.ShortAudioSampleToFloat(buffer[i]);
111 
112  if (finalGain > 1.0f) //TODO: take distance into account?
113  {
114  fVal = Math.Clamp(fVal * finalGain, -1f, 1f);
115  }
116 
117  if (UseMuffleFilter)
118  {
119  foreach (var filter in muffleFilters)
120  {
121  fVal = filter.Process(fVal);
122  }
123  }
124  if (UseRadioFilter)
125  {
126  foreach (var filter in radioFilters)
127  {
128  fVal = Math.Clamp(filter.Process(fVal) * PostRadioFilterBoost, -1f, 1f);
129  }
130  }
131  buffer[i] = ToolBox.FloatToShortAudioSample(fVal);
132  }
133  }
134 
135  public override SoundChannel Play(float gain, float range, Vector2 position, bool muffle = false)
136  {
137  throw new InvalidOperationException();
138  }
139 
140  public override SoundChannel Play(Vector3? position, float gain, float freqMult = 1.0f, bool muffle = false)
141  {
142  throw new InvalidOperationException();
143  }
144 
145  public override SoundChannel Play(float gain)
146  {
147  throw new InvalidOperationException();
148  }
149 
150  public override SoundChannel Play()
151  {
152  throw new InvalidOperationException();
153  }
154 
155  public override int FillStreamBuffer(int samplePos, short[] buffer)
156  {
157  queue.RetrieveBuffer(bufferID, out int compressedSize, out byte[] compressedBuffer);
158  try
159  {
160  if (compressedSize > 0)
161  {
162  decoder.Decode(compressedBuffer, 0, compressedSize, buffer, 0, VoipConfig.BUFFER_SIZE);
163  bufferID++;
164  return VoipConfig.BUFFER_SIZE;
165  }
166  if (bufferID < queue.LatestBufferID - (VoipQueue.BUFFER_COUNT - 1)) bufferID = queue.LatestBufferID - (VoipQueue.BUFFER_COUNT - 1);
167  }
168  catch (Exception e)
169  {
170  DebugConsole.ThrowError($"Failed to decode Opus buffer (buffer size {compressedBuffer.Length}, packet size {compressedSize})", e);
171  bufferID = queue.LatestBufferID - (VoipQueue.BUFFER_COUNT - 1);
172  }
173 
174  return 0;
175  }
176 
177  public override void Dispose()
178  {
179  if (soundChannel != null)
180  {
181  soundChannel.Dispose();
182  soundChannel = null;
183  }
184  base.Dispose();
185  }
186  }
187 }
Represents a biquad-filter.
Definition: SoundFilters.cs:46
Used to apply a lowpass-filter to a signal.
void SetRange(float near, float far)
Definition: VoipSound.cs:99
void ApplyFilters(short[] buffer, int readSamples)
Definition: VoipSound.cs:105
override void Dispose()
Definition: VoipSound.cs:177
override int FillStreamBuffer(int samplePos, short[] buffer)
Definition: VoipSound.cs:155
override float GetAmplitudeAtPlaybackPos(int playbackPos)
Definition: VoipSound.cs:89
void SetPosition(Vector3? pos)
Definition: VoipSound.cs:94
VoipSound(Client targetClient, SoundManager owner, VoipQueue q)
Definition: VoipSound.cs:71
override SoundChannel Play(float gain, float range, Vector2 position, bool muffle=false)
Definition: VoipSound.cs:135
override SoundChannel Play(float gain)
Definition: VoipSound.cs:145
override SoundChannel Play(Vector3? position, float gain, float freqMult=1.0f, bool muffle=false)
Definition: VoipSound.cs:140
override SoundChannel Play()
Definition: VoipSound.cs:150
override SoundManager.SourcePoolIndex SourcePoolIndex
Definition: VoipSound.cs:12
Definition: Al.cs:38
const int FormatMono16
Definition: Al.cs:84
Definition: Al.cs:36