1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010-2012 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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"
28 using namespace NLMISC
;
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()
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
)
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
);
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));
91 if (capacity
> _Capacity
)
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
;
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
)
116 // Fill buffer (OpenAL one)
118 alBufferData(_BufferName
, _SampleFormat
, _DataAligned
, _Size
, _Frequency
);
120 if (_StorageMode
!= IBuffer::StorageSoftware
&& !CSoundDriverAL::getInstance()->getOption(ISoundDriver::OptionLocalBufferCopy
))
129 if (alGetError() == AL_NO_ERROR
)
130 _IsLoaded
= true; // ->lock() set it to false
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
);
144 if ((!localBufferCopy
) || (size
> _Capacity
))
157 // Force a local copy of the buffer
160 _DataPtr
= new uint8
[size
+ 15];
161 _DataAligned
= (uint8
*)((size_t)_DataPtr
+ ((16 - ((size_t)_DataPtr
% 16)) % 16));
164 CFastMem::memcpy(_DataAligned
, src
, size
);
167 // Fill buffer (OpenAL one)
168 alBufferData(_BufferName
, _SampleFormat
, src
, size
, _Frequency
);
171 _IsLoaded
= (alGetError() == AL_NO_ERROR
);
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
200 alGetBufferi(_BufferName, AL_SIZE, &value);
201 nlassert(alGetError() == AL_NO_ERROR);
206 * Return the duration (in ms) of the sample in the buffer
208 float CBufferAL::getDuration() const
210 if ( _Frequency
== 0 )
213 uint32 bytespersample
;
214 switch ( _SampleFormat
) {
215 case AL_FORMAT_MONO8
:
219 case AL_FORMAT_MONO16
:
220 case AL_FORMAT_STEREO8
:
224 case AL_FORMAT_STEREO16
:
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
249 bool CBufferAL::isBufferLoaded() const
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()