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 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
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 "stdsound_lowlevel.h"
22 #include "nel/sound/driver/buffer.h"
23 #include "nel/misc/fast_mem.h"
24 #include "nel/misc/stream.h"
29 void IBuffer::setFormat(TSampleFormat format
, uint freq
)
31 TBufferFormat bufferFormat
;
34 sampleFormatToBufferFormat(format
, bufferFormat
, channels
, bitsPerSample
);
35 setFormat(bufferFormat
, channels
, bitsPerSample
, (uint32
)freq
);
38 // for compatibility, very lazy checks (assume it's set by old setFormat)
39 void IBuffer::getFormat(TSampleFormat
& format
, uint
& freq
) const
41 TBufferFormat bufferFormat
;
45 getFormat(bufferFormat
, channels
, bitsPerSample
, frequency
);
46 freq
= (uint
)frequency
;
47 bufferFormatToSampleFormat(bufferFormat
, channels
, bitsPerSample
, format
);
50 /// Convert old sample format to new buffer format
51 void IBuffer::sampleFormatToBufferFormat(TSampleFormat sampleFormat
, TBufferFormat
&bufferFormat
, uint8
&channels
, uint8
&bitsPerSample
)
56 bufferFormat
= FormatPcm
;
61 bufferFormat
= FormatDviAdpcm
;
66 bufferFormat
= FormatPcm
;
71 bufferFormat
= FormatPcm
;
76 bufferFormat
= FormatPcm
;
81 bufferFormat
= FormatUnknown
;
88 /// Convert new buffer format to old sample format
89 void IBuffer::bufferFormatToSampleFormat(TBufferFormat bufferFormat
, uint8 channels
, uint8 bitsPerSample
, TSampleFormat
&sampleFormat
)
97 switch (bitsPerSample
)
100 sampleFormat
= Mono8
;
103 sampleFormat
= Mono16
;
108 switch (bitsPerSample
)
111 sampleFormat
= Stereo8
;
114 sampleFormat
= Stereo16
;
121 sampleFormat
= Mono16ADPCM
;
125 sampleFormat
= SampleFormatUnknown
;
130 uint
IBuffer::getPCMSizeFromDuration(float duration
, uint8 channels
, uint8 bitsPerSample
, uint32 frequency
)
132 return (uint
)(duration
134 * (((float)bitsPerSample
) / 8.0f
)
135 * ((float)channels
));
138 float IBuffer::getDurationFromPCMSize(uint size
, uint8 channels
, uint8 bitsPerSample
, uint32 frequency
)
142 / (((float)bitsPerSample
) / 8.0f
)
143 / ((float)frequency
);
146 const sint
IBuffer::_IndexTable
[16] =
148 -1, -1, -1, -1, 2, 4, 6, 8,
149 -1, -1, -1, -1, 2, 4, 6, 8,
152 const uint
IBuffer::_StepsizeTable
[89] =
154 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
155 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
156 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
157 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
158 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
159 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
160 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
161 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
162 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
166 void IBuffer::encodeADPCM(const sint16
*indata
, uint8
*outdata
, uint nbSample
, TADPCMState
&state
)
168 const sint16
*inp
= indata
; /* Input buffer pointer */
169 uint8
*outp
= outdata
; /* output buffer pointer */
170 int val
; /* Current input sample value */
171 int sign
; /* Current adpcm sign bit */
172 int delta
; /* Current adpcm output value */
173 int diff
; /* Difference between val and valprev */
174 int valpred
= state
.PreviousSample
; /* Predicted output value */
175 int vpdiff
; /* Current change to valpred */
176 int index
= state
.StepIndex
; /* Current step change index */
177 int step
= _StepsizeTable
[index
]; /* Stepsize */
178 uint8 outputbuffer
= 0; /* place to keep previous 4-bit value */
179 int bufferstep
= 1; /* toggle between outputbuffer/output */
181 for ( ; nbSample
> 0 ; nbSample
-- )
185 /* Step 1 - compute difference with previous value */
186 diff
= val
- valpred
;
187 sign
= (diff
< 0) ? 8 : 0;
188 if ( sign
) diff
= (-diff
);
190 /* Step 2 - Divide and clamp */
192 ** This code *approximately* computes:
193 ** delta = diff*4/step;
194 ** vpdiff = (delta+0.5)*step/4;
195 ** but in shift step bits are dropped. The net result of this is
196 ** that even if you have fast mul/div hardware you cannot put it to
197 ** good use since the fixup would be too expensive.
200 vpdiff
= (step
>> 3);
222 /* Step 3 - Update previous value */
228 /* Step 4 - Clamp previous value to 16 bits */
229 if ( valpred
> 32767 )
231 nlwarning("over+ %d",valpred
);
234 else if ( valpred
< -32768 )
236 nlwarning("over- %d",valpred
);
240 /* Step 5 - Assemble value, update index and step values */
243 index
+= _IndexTable
[delta
];
248 step
= _StepsizeTable
[index
];
250 /* Step 6 - Output value */
253 outputbuffer
= (delta
<< 4) & 0xf0;
257 *outp
++ = (delta
& 0x0f) | outputbuffer
;
259 bufferstep
= !bufferstep
;
262 /* Output last step, if needed */
264 *outp
++ = outputbuffer
;
266 state
.PreviousSample
= sint16(valpred
);
267 state
.StepIndex
= uint8(index
);
270 void IBuffer::decodeADPCM(const uint8
*indata
, sint16
*outdata
, uint nbSample
, TADPCMState
&state
)
272 const uint8
*inp
= indata
; /* Input buffer pointer */
273 sint16
*outp
= outdata
; /* output buffer pointer */
274 int sign
; /* Current adpcm sign bit */
275 int delta
; /* Current adpcm output value */
276 int valpred
= state
.PreviousSample
; /* Predicted value */
277 int vpdiff
; /* Current change to valpred */
278 int index
= state
.StepIndex
; /* Current step change index */
279 int step
= _StepsizeTable
[index
]; /* Stepsize */
280 uint8 inputbuffer
= 0; /* place to keep next 4-bit value */
281 int bufferstep
= 0; /* toggle between inputbuffer/input */
283 for ( ; nbSample
> 0 ; nbSample
-- )
286 /* Step 1 - get the delta value */
289 delta
= inputbuffer
& 0xf;
293 inputbuffer
= *inp
++;
294 delta
= (inputbuffer
>> 4) & 0xf;
296 bufferstep
= !bufferstep
;
298 /* Step 2 - Find new index value (for later) */
299 index
+= _IndexTable
[delta
];
305 /* Step 3 - Separate sign and magnitude */
309 /* Step 4 - Compute difference and new predicted value */
311 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
327 /* Step 5 - clamp output value */
328 if ( valpred
> 32767 )
330 else if ( valpred
< -32768 )
333 /* Step 6 - Update step value */
334 step
= _StepsizeTable
[index
];
336 /* Step 7 - Output value */
337 *outp
++ = sint16(valpred
);
340 state
.PreviousSample
= sint16(valpred
);
341 state
.StepIndex
= uint8(index
);
344 static bool checkFourCC(const uint8
*left
, const char *right
)
346 return (left
[0] == right
[0] && left
[1] == right
[1] && left
[2] == right
[2] && left
[3] == right
[3]);
349 static bool readHeader(const uint8
*header
, const char *fourcc
, uint32
&size
, const uint8
*&data
)
351 memcpy(&size
, header
+ 4, sizeof(uint32
));
353 return (header
[0] == fourcc
[0] && header
[1] == fourcc
[1] && header
[2] == fourcc
[2] && header
[3] == fourcc
[3]);
356 static bool findChunk(const uint8
*src
, uint32 srcSize
, const char *fourcc
, uint32
&size
, const uint8
*&data
)
359 while (offset
+ 8 < srcSize
)
361 bool found
= readHeader(src
+ offset
, fourcc
, size
, data
);
362 if (found
) return true;
368 /// Read a wav file. Data type uint8 is used as unspecified buffer format.
369 bool IBuffer::readWav(const uint8
*wav
, uint size
, std::vector
<uint8
> &result
, TBufferFormat
&bufferFormat
, uint8
&channels
, uint8
&bitsPerSample
, uint32
&frequency
)
374 memset(&mmioinfo
, 0, sizeof(MMIOINFO
));
375 mmioinfo
.fccIOProc
= FOURCC_MEM
;
376 mmioinfo
.pchBuffer
= (HPSTR
)wav
;
377 mmioinfo
.cchBuffer
= size
;
378 HMMIO hmmio
= mmioOpen(NULL
, &mmioinfo
, MMIO_READ
| MMIO_DENYWRITE
);
379 if (!hmmio
) { throw ESoundDriver("Failed to open the file"); }
382 MMCKINFO mmckinforiff
;
383 memset(&mmckinforiff
, 0, sizeof(MMCKINFO
));
384 mmckinforiff
.fccType
= mmioFOURCC('W', 'A', 'V', 'E');
385 if (mmioDescend(hmmio
, &mmckinforiff
, NULL
, MMIO_FINDRIFF
) != MMSYSERR_NOERROR
) { mmioClose(hmmio
, 0); throw ESoundDriver("mmioDescend WAVE failed"); }
388 MMCKINFO mmckinfofmt
;
389 memset(&mmckinfofmt
, 0, sizeof(MMCKINFO
));
390 mmckinfofmt
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
391 if (mmioDescend(hmmio
, &mmckinfofmt
, &mmckinforiff
, MMIO_FINDCHUNK
) != MMSYSERR_NOERROR
) { mmioClose(hmmio
, 0); throw ESoundDriver("mmioDescend fmt failed"); }
392 WAVEFORMATEX
*wavefmt
= (WAVEFORMATEX
*)(&wav
[mmckinfofmt
.dwDataOffset
]);
393 if (mmioAscend(hmmio
, &mmckinfofmt
, 0) != MMSYSERR_NOERROR
) { mmioClose(hmmio
, 0); throw ESoundDriver("mmioAscend fmt failed"); }
396 MMCKINFO mmckinfodata
;
397 memset(&mmckinfodata
, 0, sizeof(MMCKINFO
));
398 mmckinfodata
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
399 if (mmioDescend(hmmio
, &mmckinfodata
, &mmckinforiff
, MMIO_FINDCHUNK
) != MMSYSERR_NOERROR
) { mmioClose(hmmio
, 0); throw ESoundDriver("mmioDescend data failed"); }
400 BYTE
*wavedata
= (BYTE
*)(&wav
[mmckinfodata
.dwDataOffset
]);
401 if (mmioAscend(hmmio
, &mmckinfodata
, 0) != MMSYSERR_NOERROR
) { mmioClose(hmmio
, 0); throw ESoundDriver("mmioAscend data failed"); }
407 bufferFormat
= (TBufferFormat
)wavefmt
->wFormatTag
;
408 channels
= (uint8
)wavefmt
->nChannels
;
409 bitsPerSample
= (uint8
)wavefmt
->wBitsPerSample
;
410 frequency
= wavefmt
->nSamplesPerSec
;
411 result
.resize(mmckinfodata
.cksize
);
412 NLMISC::CFastMem::memcpy(&result
[0], wavedata
, mmckinfodata
.cksize
);
416 // read the RIFF header and check if it contains WAVE data
417 const uint8
*riffHeader
= wav
;
419 const uint8
*riffData
;
420 if (!readHeader(riffHeader
, "RIFF", riffSize
, riffData
))
422 nlwarning("WAV: Cannot find RIFF identifier");
427 nlwarning("WAV: Empty RIFF file");
430 if (!checkFourCC(riffData
, "WAVE"))
432 nlwarning("WAV: RIFF file does not contain WAVE data");
435 uint32 waveSize
= riffSize
- 4;
436 const uint8
*waveData
= riffData
+ 4;
438 // find the 'fmt ' chunk
440 const uint8
*fmtData
;
441 if (!findChunk(waveData
, waveSize
, "fmt ", fmtSize
, fmtData
))
443 nlwarning("WAV: Cannot find 'fmt ' chunk");
448 nlwarning("WAV: The 'fmt ' chunk is incomplete");
452 // find the 'data' chunk
454 const uint8
*dataData
;
455 if (!findChunk(waveData
, waveSize
, "data", dataSize
, dataData
))
457 nlwarning("WAV: Cannot find 'data' chunk");
460 if (dataData
+ dataSize
> wav
+ size
)
462 uint32 cut
= (uint32
)((dataData
+ dataSize
) - (wav
+ size
));
463 nlwarning("WAV: Oversize 'data' chunk with dataSize %u and wav size %u, cutting %u bytes", (uint32
)dataSize
, (uint32
)size
, (uint32
)cut
);
467 // read the 'fmt ' chunk
468 uint16 fmtFormatTag
; // 0-1
469 memcpy(&fmtFormatTag
, fmtData
+ 0, sizeof(uint16
));
470 uint16 fmtChannels
; // 2-3
471 memcpy(&fmtChannels
, fmtData
+ 2, sizeof(uint16
));
472 uint32 fmtSamplesPerSec
; // 4-7
473 memcpy(&fmtSamplesPerSec
, fmtData
+ 4, sizeof(uint32
));
474 //uint32 fmtAvgBytesPerSec; // 8-11
475 //uint16 fmtBlockAlign; // 12-13
476 uint16 fmtBitsPerSample
; // 14-15
477 memcpy(&fmtBitsPerSample
, fmtData
+ 14, sizeof(uint16
));
478 //uint16 fmtExSize; // 16-17 // only if fmtSize > 16
480 bufferFormat
= (TBufferFormat
)fmtFormatTag
;
481 channels
= (uint8
)fmtChannels
;
482 bitsPerSample
= (uint8
)fmtBitsPerSample
;
483 frequency
= fmtSamplesPerSec
;
484 result
.resize(dataSize
);
485 NLMISC::CFastMem::memcpy(&result
[0], dataData
, dataSize
);
492 /// Write a wav file. Data type uint8 does not imply a buffer of any format.
493 bool IBuffer::writeWav(const uint8
*buffer
, uint size
, TBufferFormat bufferFormat
, uint8 channels
, uint8 bitsPerSample
, uint32 frequency
, NLMISC::IStream
&out
)
495 nlassert(!out
.isReading());
497 const uint32 headerSize
= 8; // 32 TAG + 32 SIZE
499 uint32 dataSize
= (uint32
)size
;
501 // create riff header
502 const char *riffFourCC
= "RIFF"; // Chunk FourCC
503 uint32 riffSize
= 4 // Type FourCC
504 + headerSize
+ fmtSize
// fmt Chunk
505 + headerSize
+ dataSize
; // data Chunk
507 const char *waveFourCC
= "WAVE"; // Type FourCC
509 // write riff chunk header
510 out
.serialBuffer(const_cast<uint8
*>(static_cast<const uint8
*>(static_cast<const void *>(riffFourCC
))), 4);
511 out
.serial(riffSize
);
512 // write riff chunk data
513 out
.serialBuffer(const_cast<uint8
*>(static_cast<const uint8
*>(static_cast<const void *>(waveFourCC
))), 4);
516 // create format header
517 const char *fmtFourCC
= "fmt ";
518 // create format data
519 uint16 fmtFormatTag
= (uint16
)bufferFormat
; // 0-1
520 uint16 fmtChannels
= (uint16
)channels
; // 2-3
521 uint32 fmtSamplesPerSec
= (uint32
)frequency
; // 4-7
522 uint16 fmtBitsPerSample
= (uint16
)bitsPerSample
; // 14-15
523 uint16 fmtBlockAlign
= fmtChannels
* fmtBitsPerSample
/ 8; // 12-13
524 uint32 fmtAvgBytesPerSec
= fmtSamplesPerSec
* fmtBlockAlign
; // 8-11
525 // uint16 fmtExSize; // 16-17 // only if fmtSize > 16
527 // write format chunk header
528 out
.serialBuffer(const_cast<uint8
*>(static_cast<const uint8
*>(static_cast<const void *>(fmtFourCC
))), 4);
530 // write format chunk data
531 out
.serial(fmtFormatTag
);
532 out
.serial(fmtChannels
);
533 out
.serial(fmtSamplesPerSec
);
534 out
.serial(fmtAvgBytesPerSec
);
535 out
.serial(fmtBlockAlign
);
536 out
.serial(fmtBitsPerSample
);
538 // create data header
539 const char *dataFourCC
= "data";
541 // write data chunk header
542 out
.serialBuffer(const_cast<uint8
*>(static_cast<const uint8
*>(static_cast<const void *>(dataFourCC
))), 4);
543 out
.serial(dataSize
);
544 // write data chunk data
545 out
.serialBuffer(const_cast<uint8
*>(buffer
), size
);
550 /// Convert buffer data to 16bit Mono PCM.
551 bool IBuffer::convertToMono16PCM(const uint8
*buffer
, uint size
, std::vector
<sint16
> &result
, TBufferFormat bufferFormat
, uint8 channels
, uint8 bitsPerSample
)
553 if (size
== 0 || channels
== 0 || bitsPerSample
== 0) return false;
555 switch (bufferFormat
)
559 result
.resize((std::vector
<sint16
>::size_type
)(((uint64
)size
/ (uint64
)channels
) * 8UL / (uint64
)bitsPerSample
));
560 uint samples
= (uint
)result
.size();
561 switch (bitsPerSample
)
565 const sint8
*src8
= (const sint8
*)(const void *)buffer
;
567 for (uint i
= 0; i
< samples
; ++i
)
570 for (uint k
= 0; k
< channels
; ++k
)
571 sample
+= (sint32
)src8
[j
+ k
];
575 result
[i
] = (sint16
)sample
;
581 const sint16
*src16
= (const sint16
*)(const void *)buffer
;
583 for (uint i
= 0; i
< samples
; ++i
)
586 for (uint k
= 0; k
< channels
; ++k
)
587 sample
+= (sint32
)src16
[j
+ k
];
590 result
[i
] = (sint16
)sample
;
596 const sint32
*src32
= (const sint32
*)(const void *)buffer
;
598 for (uint i
= 0; i
< samples
; ++i
)
601 for (uint k
= 0; k
< channels
; ++k
)
602 sample
+= (sint64
)src32
[j
+ k
];
606 result
[i
] = (sint16
)sample
;
617 uint samples
= size
* 2;
618 result
.resize(samples
);
620 state
.PreviousSample
= 0;
622 decodeADPCM(buffer
, &result
[0], samples
, state
);
631 /// Convert 16bit Mono PCM buffer data to ADPCM.
632 bool IBuffer::convertMono16PCMToMonoADPCM(const sint16
*buffer
, uint samples
, std::vector
<uint8
> &result
)
634 if (samples
== 0) return false;
636 // Allocate ADPCM dest
637 samples
&= 0xfffffffe;
638 result
.resize(samples
/ 2);
642 state
.PreviousSample
= 0;
644 encodeADPCM(buffer
, &result
[0], samples
, state
);