Fix "no remove aqua speed" bug when player leaves the water
[ryzomcore.git] / nel / src / sound / driver / dsound / buffer_dsound.cpp
blob72423bba7d61eeb4605454704d08b93ca800ed62
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "stddsound.h"
19 #include "buffer_dsound.h"
20 #include "sound_driver_dsound.h"
22 #define NOMINMAX
23 #include <windows.h>
24 #include <mmsystem.h>
26 #ifdef DEBUG_NEW
27 #define new DEBUG_NEW
28 #endif
30 using namespace NLMISC;
31 using namespace std;
33 namespace NLSOUND {
35 static const std::string EmptyString;
37 // Custom mutimedia IO proc.
38 /*LRESULT NelIOProc(LPSTR lpmmioinfo, UINT uMsg, LONG lParam1, LONG lParam2)
40 MMIOINFO *mmioinfo = (MMIOINFO*) lpmmioinfo;
42 switch (uMsg)
44 case MMIOM_OPEN:
46 // do some validity checking.
47 nlassert((mmioinfo->dwFlags & MMIO_CREATE) == 0);
49 char *fileName = (char*)lParam1;
50 std::string fullName = NLMISC::CPath::lookup(fileName, false);
51 if (fullName.empty())
53 mmioinfo->adwInfo[0] = NULL;
54 return MMIOERR_CANNOTOPEN;
57 NLMISC::CIFile *pfile = new NLMISC::CIFile(fullName);
59 mmioinfo->adwInfo[0] = (DWORD)pfile;
60 return MMSYSERR_NOERROR ;
62 break;
63 case MMIOM_CLOSE:
65 NLMISC::CIFile *file = (NLMISC::CIFile *)mmioinfo->adwInfo[0];
66 delete file;
67 return 0;
69 break;
70 case MMIOM_READ:
72 uint8 *pdst = (uint8*) lParam1;
73 uint bytes = (uint) lParam2;
75 nlassert(mmioinfo->adwInfo[0] != NULL);
76 NLMISC::CIFile *file = (NLMISC::CIFile *)mmioinfo->adwInfo[0];
77 bytes = std::min(uint(file->getFileSize() - file->getPos()), bytes);
78 file->serialBufferWithSize(pdst, bytes);
80 mmioinfo->lBufOffset = file->getPos();
82 return bytes;
84 break;
85 case MMIOM_SEEK:
87 uint newPos = (uint) lParam1;
88 uint seekMode = lParam2;
90 nlassert(mmioinfo->adwInfo[0] != NULL);
91 NLMISC::CIFile *file = (NLMISC::CIFile *)mmioinfo->adwInfo[0];
93 switch(seekMode)
95 case SEEK_CUR:
96 file->seek(newPos, NLMISC::IStream::current);
97 break;
98 case SEEK_END:
99 file->seek(newPos, NLMISC::IStream::end);
100 break;
101 case SEEK_SET:
102 file->seek(newPos, NLMISC::IStream::begin);
103 break;
106 mmioinfo->lBufOffset = file->getPos();
108 return mmioinfo->lBufOffset;
110 break;
111 case MMIOM_WRITE:
112 nlassert("Mutimedia IO write is not supported !");
113 break;
114 case MMIOM_WRITEFLUSH:
115 nlassert("Mutimedia IO write is not supported !");
116 break;
122 CBufferDSound::CBufferDSound() : _Data(NULL), _Capacity(0), _Size(0)
124 _Name = CStringMapper::map(EmptyString);
125 _Format = Mono16;
126 _Freq = 0;
129 CBufferDSound::~CBufferDSound()
131 // nldebug("Destroying DirectSound buffer %s (%p)", CSoundDriverDSound::instance()->getStringMapper()->unmap(_Name).c_str(), this);
133 if (_Data)
135 delete[] _Data;
136 _Data = NULL;
140 void CBufferDSound::setName(NLMISC::TStringId bufferName)
142 _Name = bufferName;
145 /// Set the sample format. (channels = 1, 2, ...; bitsPerSample = 8, 16; frequency = samples per second, 44100, ...)
146 void CBufferDSound::setFormat(TBufferFormat format, uint8 channels, uint8 bitsPerSample, uint32 frequency)
148 bufferFormatToSampleFormat(format, channels, bitsPerSample, _Format);
149 _Freq = frequency;
152 /// 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.
153 uint8 *CBufferDSound::lock(uint capacity)
155 if (_Data)
157 if (capacity > _Capacity)
159 delete[] _Data;
160 _Data = NULL;
164 if (!_Data)
166 _Data = new uint8[capacity];
167 _Capacity = capacity;
168 if (_Size > capacity)
169 _Size = capacity;
172 return _Data;
175 /// Notify that you are done writing to this buffer, so it can be copied over to hardware if needed. Returns true if ok.
176 bool CBufferDSound::unlock(uint size)
178 if (size > _Capacity)
180 _Size = _Capacity;
181 return false;
183 else
185 _Size = size;
186 return true;
190 /// Copy the data with specified size into the buffer. A readable local copy is only guaranteed when OptionLocalBufferCopy is set. Returns true if ok.
191 bool CBufferDSound::fill(const uint8 *src, uint size)
193 uint8 *dest = lock(size);
194 if (dest == NULL) return false;
195 CFastMem::memcpy(dest, src, size);
196 return unlock(size);
199 /// Return the sample format information.
200 void CBufferDSound::getFormat(TBufferFormat &format, uint8 &channels, uint8 &bitsPerSample, uint32 &frequency) const
202 sampleFormatToBufferFormat(_Format, format, channels, bitsPerSample);
203 frequency = _Freq;
206 /// Return the size of the buffer, in bytes.
207 uint CBufferDSound::getSize() const
209 return _Size;
212 float CBufferDSound::getDuration() const
214 float frames = (float) _Size;
216 switch (_Format)
218 case Mono8:
219 break;
220 case Mono16ADPCM:
221 frames *= 2.0f;
222 break;
223 case Mono16:
224 frames /= 2.0f;
225 break;
226 case Stereo8:
227 frames /= 2.0f;
228 break;
229 case Stereo16:
230 frames /= 4.0f;
231 break;
234 return 1000.0f * frames / (float) _Freq;
237 bool CBufferDSound::isStereo() const
239 return (_Format == Stereo8) || (_Format == Stereo16);
242 /// Return the name of this buffer
243 NLMISC::TStringId CBufferDSound::getName() const
245 return _Name;
248 /// Return true if the buffer is loaded. Used for async load/unload.
249 bool CBufferDSound::isBufferLoaded() const
251 return _Data != NULL;
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 CBufferDSound::setStorageMode(TStorageMode /* storageMode */)
258 // software buffering, no hardware storage mode available
261 /// Get the storage mode of this buffer.
262 IBuffer::TStorageMode CBufferDSound::getStorageMode()
264 // always uses software buffers
265 return IBuffer::StorageSoftware;
268 } // NLSOUND