Client LuaCsForBarotrauma
SoundBuffer.cs
2 using OpenAL;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Text;
7 
8 namespace Barotrauma.Sounds
9 {
10  sealed class SoundBuffers : IDisposable
11  {
12  private static readonly HashSet<uint> bufferPool = new HashSet<uint>();
13 #if OSX
14  public const int MaxBuffers = 400; //TODO: check that this value works for macOS
15 #else
16  public const int MaxBuffers = 32000;
17 #endif
18  public static int BuffersGenerated { get; private set; } = 0;
19  private readonly Sound sound;
20 
21  public uint AlBuffer { get; private set; } = 0;
22  public uint AlMuffledBuffer { get; private set; } = 0;
23 
24  public SoundBuffers(Sound sound) { this.sound = sound; }
25  public void Dispose()
26  {
27  if (AlBuffer != 0)
28  {
29  lock (bufferPool)
30  {
31  bufferPool.Add(AlBuffer);
32  }
33  }
34  if (AlMuffledBuffer != 0)
35  {
36  lock (bufferPool)
37  {
38  bufferPool.Add(AlMuffledBuffer);
39  }
40  }
41  AlBuffer = 0;
42  AlMuffledBuffer = 0;
43  }
44 
45  public static void ClearPool()
46  {
47  lock (bufferPool)
48  {
49  bufferPool.ForEach(b => Al.DeleteBuffer(b));
50  bufferPool.Clear();
51  }
52  BuffersGenerated = 0;
53  }
54 
55  public bool RequestAlBuffers()
56  {
57  if (AlBuffer != 0) { return false; }
58  int alError;
59  lock (bufferPool)
60  {
61  while (bufferPool.Count < 2 && BuffersGenerated < MaxBuffers)
62  {
63  Al.GenBuffer(out uint newBuffer);
64  alError = Al.GetError();
65  if (alError != Al.NoError)
66  {
67  DebugConsole.AddWarning($"Error when generating sound buffer: {Al.GetErrorString(alError)}. {BuffersGenerated} buffer(s) were generated. No more sound buffers will be generated.");
69  }
70  else if (!Al.IsBuffer(newBuffer))
71  {
72  DebugConsole.AddWarning($"Error when generating sound buffer: result is not a valid buffer. {BuffersGenerated} buffer(s) were generated. No more sound buffers will be generated.");
74  }
75  else
76  {
77  bufferPool.Add(newBuffer);
80  {
81  DebugConsole.AddWarning($"{BuffersGenerated} buffer(s) were generated. No more sound buffers will be generated.");
82  }
83  }
84  }
85 
86  if (bufferPool.Count >= 2)
87  {
88  AlBuffer = bufferPool.First();
89  bufferPool.Remove(AlBuffer);
90  AlMuffledBuffer = bufferPool.First();
91  bufferPool.Remove(AlMuffledBuffer);
92  return true;
93  }
94  }
95 
96  //can't generate any more OpenAL buffers! we'll have to steal a buffer from someone...
97  foreach (var otherSound in sound.Owner.LoadedSounds)
98  {
99  if (otherSound == sound) { continue; }
100  if (otherSound.IsPlaying()) { continue; }
101  if (otherSound.Buffers == null) { continue; }
102  if (otherSound.Buffers.AlBuffer == 0) { continue; }
103 
104  // Dispose all channels that are holding
105  // a reference to these buffers, otherwise
106  // an INVALID_OPERATION error will be thrown
107  // when attempting to set the buffer data later.
108  // Having the sources not play is not enough,
109  // as OpenAL assumes that you may want to call
110  // alSourcePlay without reassigning the buffer.
111  otherSound.Owner.KillChannels(otherSound);
112 
113  AlBuffer = otherSound.Buffers.AlBuffer;
114  AlMuffledBuffer = otherSound.Buffers.AlMuffledBuffer;
115  otherSound.Buffers.AlBuffer = 0;
116  otherSound.Buffers.AlMuffledBuffer = 0;
117 
118  // For performance reasons, sift the current sound to
119  // the end of the loadedSounds list, that way it'll
120  // be less likely to have its buffers stolen, which
121  // means less reuploads for frequently played sounds.
122  sound.Owner.MoveSoundToPosition(sound, sound.Owner.LoadedSoundCount-1);
123 
124  if (!Al.IsBuffer(AlBuffer))
125  {
126  throw new Exception(sound.Filename + " has an invalid buffer!");
127  }
129  {
130  throw new Exception(sound.Filename + " has an invalid muffled buffer!");
131  }
132 
133  return true;
134  }
135 
136  return false;
137  }
138  }
139 }
Definition: Al.cs:38
static void DeleteBuffer(uint buffer)
static bool IsBuffer(uint bid)
static void GenBuffer(out uint buffer)
Definition: Al.cs:423
static int GetError()
const int NoError
Definition: Al.cs:98
Definition: Al.cs:36