Fix "no remove aqua speed" bug when player leaves the water
[ryzomcore.git] / nel / src / sound / driver / openal / buffer_al.cpp
blob9c200fcf7fdae116fd66b09dfec858cbe33c5979
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010-2012 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdopenal.h"
21 #include "sound_driver_al.h"
22 #include "buffer_al.h"
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 using namespace NLMISC;
30 namespace NLSOUND
33 CBufferAL::CBufferAL(ALuint buffername) :
34 IBuffer(), _BufferName(buffername), _Name(NULL), _SampleFormat(AL_INVALID), _Frequency(0),
35 _DataAligned(NULL), _DataPtr(NULL), _Capacity(0), _Size(0), _StorageMode(IBuffer::StorageAuto), _IsLoaded(false)
40 CBufferAL::~CBufferAL()
42 // delete local copy
43 if (_DataPtr != NULL)
45 delete[] _DataPtr;
46 _DataAligned = NULL;
47 _DataPtr = NULL;
50 // delete OpenAL copy
51 CSoundDriverAL *sdal = CSoundDriverAL::getInstance();
52 //nlinfo("AL: Deleting buffer (name %u)", _BufferName );
53 sdal->removeBuffer( this );
56 /** Preset the name of the buffer. Used for async loading to give a name
57 * before the buffer is effectivly loaded.
58 * If the name after loading of the buffer doesn't match the preset name,
59 * the load will assert.
61 void CBufferAL::setName(NLMISC::TStringId bufferName)
63 _Name = bufferName;
66 /// Set the sample format. (channels = 1, 2, ...; bitsPerSample = 8, 16; frequency = samples per second, 44100, ...)
67 void CBufferAL::setFormat(TBufferFormat format, uint8 channels, uint8 bitsPerSample, uint32 frequency)
69 TSampleFormat sampleFormat;
70 bufferFormatToSampleFormat(format, channels, bitsPerSample, sampleFormat);
71 switch (sampleFormat)
73 case Mono8: _SampleFormat = AL_FORMAT_MONO8; break;
74 case Mono16: _SampleFormat = AL_FORMAT_MONO16; break;
75 case Stereo8: _SampleFormat = AL_FORMAT_STEREO8; break;
76 case Stereo16: _SampleFormat = AL_FORMAT_STEREO16; break;
77 default: nlstop; _SampleFormat = AL_INVALID;
79 _Frequency = frequency;
82 /// Get a writable pointer to the buffer of specified size. Returns NULL in case of failure. It is only guaranteed that the original data is still available when using StorageSoftware and the specified size is not larger than the available data. Call setStorageMode() and setFormat() first.
83 uint8 *CBufferAL::lock(uint capacity)
85 nlassert((_SampleFormat != AL_INVALID) && (_Frequency != 0));
87 _IsLoaded = false;
89 if (_DataPtr)
91 if (capacity > _Capacity)
93 delete[] _DataPtr;
94 _DataAligned = NULL;
95 _DataPtr = NULL;
99 if (!_DataPtr) _DataPtr = new uint8[capacity + 15];
100 _DataAligned = (uint8 *)((size_t)_DataPtr + ((16 - ((size_t)_DataPtr % 16)) % 16));
101 if (_Size > capacity) _Size = capacity;
102 _Capacity = capacity;
104 return _DataAligned;
107 /// Notify that you are done writing to this buffer, so it can be copied over to hardware if needed. Returns true if ok.
108 bool CBufferAL::unlock(uint size)
110 if (size > _Capacity)
112 _Size = _Capacity;
113 return false;
116 // Fill buffer (OpenAL one)
117 _Size = size;
118 alBufferData(_BufferName, _SampleFormat, _DataAligned, _Size, _Frequency);
120 if (_StorageMode != IBuffer::StorageSoftware && !CSoundDriverAL::getInstance()->getOption(ISoundDriver::OptionLocalBufferCopy))
122 delete[] _DataPtr;
123 _DataAligned = NULL;
124 _DataPtr = NULL;
125 _Capacity = 0;
128 // Error handling
129 if (alGetError() == AL_NO_ERROR)
130 _IsLoaded = true; // ->lock() set it to false
132 return _IsLoaded;
135 /// Copy the data with specified size into the buffer. A readable local copy is only guaranteed when OptionLocalBufferCopy is set. Returns true if ok.
136 bool CBufferAL::fill(const uint8 *src, uint size)
138 nlassert((_SampleFormat != AL_INVALID) && (_Frequency != 0));
140 bool localBufferCopy = CSoundDriverAL::getInstance()->getOption(ISoundDriver::OptionLocalBufferCopy);
142 if (_DataPtr)
144 if ((!localBufferCopy) || (size > _Capacity))
146 delete[] _DataPtr;
147 _DataAligned = NULL;
148 _DataPtr = NULL;
149 _Capacity = 0;
153 _Size = size;
155 if (localBufferCopy)
157 // Force a local copy of the buffer
158 if (!_DataPtr)
160 _DataPtr = new uint8[size + 15];
161 _DataAligned = (uint8 *)((size_t)_DataPtr + ((16 - ((size_t)_DataPtr % 16)) % 16));
162 _Capacity = size;
164 CFastMem::memcpy(_DataAligned, src, size);
167 // Fill buffer (OpenAL one)
168 alBufferData(_BufferName, _SampleFormat, src, size, _Frequency);
170 // Error handling
171 _IsLoaded = (alGetError() == AL_NO_ERROR);
173 return _IsLoaded;
176 /// Return the sample format information.
177 void CBufferAL::getFormat(TBufferFormat &format, uint8 &channels, uint8 &bitsPerSample, uint32 &frequency) const
179 TSampleFormat sampleFormat;
180 switch (_SampleFormat)
182 case AL_FORMAT_MONO8: sampleFormat = Mono8; break;
183 case AL_FORMAT_MONO16: sampleFormat = Mono16; break;
184 case AL_FORMAT_STEREO8: sampleFormat = Stereo8; break;
185 case AL_FORMAT_STEREO16: sampleFormat = Stereo16; break;
186 default: sampleFormat = SampleFormatUnknown;
188 sampleFormatToBufferFormat(sampleFormat, format, channels, bitsPerSample);
189 frequency = _Frequency;
194 * Return the size of the buffer, in bytes
196 uint32 CBufferAL::getSize() const
198 return _Size;
199 /*ALint value;
200 alGetBufferi(_BufferName, AL_SIZE, &value);
201 nlassert(alGetError() == AL_NO_ERROR);
202 return value;*/
206 * Return the duration (in ms) of the sample in the buffer
208 float CBufferAL::getDuration() const
210 if ( _Frequency == 0 )
211 return 0;
213 uint32 bytespersample;
214 switch ( _SampleFormat ) {
215 case AL_FORMAT_MONO8:
216 bytespersample = 1;
217 break;
219 case AL_FORMAT_MONO16:
220 case AL_FORMAT_STEREO8:
221 bytespersample = 2;
222 break;
224 case AL_FORMAT_STEREO16:
225 bytespersample = 4;
226 break;
228 default:
229 return 0;
232 return (float)(getSize()) * 1000.0f / (float)_Frequency / (float)bytespersample;
236 * Return true if the buffer is stereo, false if mono
238 bool CBufferAL::isStereo() const
240 return (_SampleFormat==AL_FORMAT_STEREO8) || (_SampleFormat==AL_FORMAT_STEREO16);
243 /// Return the name of this buffer
244 NLMISC::TStringId CBufferAL::getName() const
246 return _Name;
249 bool CBufferAL::isBufferLoaded() const
251 return _IsLoaded;
255 /// Set the storage mode of this buffer, call before filling this buffer. Storage mode is always software if OptionSoftwareBuffer is enabled. Default is auto.
256 void CBufferAL::setStorageMode(TStorageMode storageMode)
258 _StorageMode = storageMode;
261 /// Get the storage mode of this buffer.
262 IBuffer::TStorageMode CBufferAL::getStorageMode()
264 return _StorageMode;
267 } // NLSOUND