1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #define OV_EXCLUDE_STATIC_CALLBACKS
30 #include <vorbis/codec.h>
31 #include <vorbis/vorbisfile.h>
32 
33 #include "sys/platform.h"
34 #include "framework/FileSystem.h"
35 
36 #include "sound/snd_local.h"
37 
38 /*
39 ===================================================================================
40 
41   Thread safe decoder memory allocator.
42 
43   Each OggVorbis decoder consumes about 150kB of memory.
44 
45 ===================================================================================
46 */
47 
48 idDynamicBlockAlloc<byte, 1<<20, 128>		decoderMemoryAllocator;
49 
50 const int MIN_OGGVORBIS_MEMORY				= 768 * 1024;
51 
52 extern "C" {
53 	void *_decoder_malloc( size_t size );
54 	void *_decoder_calloc( size_t num, size_t size );
55 	void *_decoder_realloc( void *memblock, size_t size );
56 	void _decoder_free( void *memblock );
57 }
58 
_decoder_malloc(size_t size)59 void *_decoder_malloc( size_t size ) {
60 	void *ptr = decoderMemoryAllocator.Alloc( size );
61 	assert( size == 0 || ptr != NULL );
62 	return ptr;
63 }
64 
_decoder_calloc(size_t num,size_t size)65 void *_decoder_calloc( size_t num, size_t size ) {
66 	void *ptr = decoderMemoryAllocator.Alloc( num * size );
67 	assert( ( num * size ) == 0 || ptr != NULL );
68 	memset( ptr, 0, num * size );
69 	return ptr;
70 }
71 
_decoder_realloc(void * memblock,size_t size)72 void *_decoder_realloc( void *memblock, size_t size ) {
73 	void *ptr = decoderMemoryAllocator.Resize( (byte *)memblock, size );
74 	assert( size == 0 || ptr != NULL );
75 	return ptr;
76 }
77 
_decoder_free(void * memblock)78 void _decoder_free( void *memblock ) {
79 	decoderMemoryAllocator.Free( (byte *)memblock );
80 }
81 
82 
83 /*
84 ===================================================================================
85 
86   OggVorbis file loading/decoding.
87 
88 ===================================================================================
89 */
90 
91 /*
92 ====================
93 FS_ReadOGG
94 ====================
95 */
FS_ReadOGG(void * dest,size_t size1,size_t size2,void * fh)96 size_t FS_ReadOGG( void *dest, size_t size1, size_t size2, void *fh ) {
97 	idFile *f = reinterpret_cast<idFile *>(fh);
98 	return f->Read( dest, size1 * size2 );
99 }
100 
101 /*
102 ====================
103 FS_SeekOGG
104 ====================
105 */
FS_SeekOGG(void * fh,ogg_int64_t to,int type)106 int FS_SeekOGG( void *fh, ogg_int64_t to, int type ) {
107 	fsOrigin_t retype = FS_SEEK_SET;
108 
109 	if ( type == SEEK_CUR ) {
110 		retype = FS_SEEK_CUR;
111 	} else if ( type == SEEK_END ) {
112 		retype = FS_SEEK_END;
113 	} else if ( type == SEEK_SET ) {
114 		retype = FS_SEEK_SET;
115 	} else {
116 		common->FatalError( "fs_seekOGG: seek without type\n" );
117 	}
118 	idFile *f = reinterpret_cast<idFile *>(fh);
119 	return f->Seek( to, retype );
120 }
121 
122 /*
123 ====================
124 FS_CloseOGG
125 ====================
126 */
FS_CloseOGG(void * fh)127 int FS_CloseOGG( void *fh ) {
128 	return 0;
129 }
130 
131 /*
132 ====================
133 FS_TellOGG
134 ====================
135 */
FS_TellOGG(void * fh)136 long FS_TellOGG( void *fh ) {
137 	idFile *f = reinterpret_cast<idFile *>(fh);
138 	return f->Tell();
139 }
140 
141 /*
142 ====================
143 ov_openFile
144 ====================
145 */
ov_openFile(idFile * f,OggVorbis_File * vf)146 int ov_openFile( idFile *f, OggVorbis_File *vf ) {
147 	ov_callbacks callbacks;
148 
149 	memset( vf, 0, sizeof( OggVorbis_File ) );
150 
151 	callbacks.read_func = FS_ReadOGG;
152 	callbacks.seek_func = FS_SeekOGG;
153 	callbacks.close_func = FS_CloseOGG;
154 	callbacks.tell_func = FS_TellOGG;
155 	return ov_open_callbacks((void *)f, vf, NULL, -1, callbacks);
156 }
157 
158 /*
159 ====================
160 idWaveFile::OpenOGG
161 ====================
162 */
OpenOGG(const char * strFileName,waveformatex_t * pwfx)163 int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
164 	OggVorbis_File *ov;
165 
166 	memset( pwfx, 0, sizeof( waveformatex_t ) );
167 
168 	mhmmio = fileSystem->OpenFileRead( strFileName );
169 	if ( !mhmmio ) {
170 		return -1;
171 	}
172 
173 	Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
174 
175 	ov = new OggVorbis_File;
176 
177 	if( ov_openFile( mhmmio, ov ) < 0 ) {
178 		delete ov;
179 		Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
180 		fileSystem->CloseFile( mhmmio );
181 		mhmmio = NULL;
182 		return -1;
183 	}
184 
185 	mfileTime = mhmmio->Timestamp();
186 
187 	vorbis_info *vi = ov_info( ov, -1 );
188 
189 	mpwfx.Format.nSamplesPerSec = vi->rate;
190 	mpwfx.Format.nChannels = vi->channels;
191 	mpwfx.Format.wBitsPerSample = sizeof(short) * 8;
192 	mdwSize = ov_pcm_total( ov, -1 ) * vi->channels;	// pcm samples * num channels
193 	mbIsReadingFromMemory = false;
194 
195 	if ( idSoundSystemLocal::s_realTimeDecoding.GetBool() ) {
196 
197 		ov_clear( ov );
198 		fileSystem->CloseFile( mhmmio );
199 		mhmmio = NULL;
200 		delete ov;
201 
202 		mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_OGG;
203 		mhmmio = fileSystem->OpenFileRead( strFileName );
204 		mMemSize = mhmmio->Length();
205 
206 	} else {
207 
208 		ogg = ov;
209 
210 		mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_PCM;
211 		mMemSize = mdwSize * sizeof( short );
212 	}
213 
214 	memcpy( pwfx, &mpwfx, sizeof( waveformatex_t ) );
215 
216 	Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
217 
218 	isOgg = true;
219 
220 	return 0;
221 }
222 
223 /*
224 ====================
225 idWaveFile::ReadOGG
226 ====================
227 */
ReadOGG(byte * pBuffer,int dwSizeToRead,int * pdwSizeRead)228 int idWaveFile::ReadOGG( byte* pBuffer, int dwSizeToRead, int *pdwSizeRead ) {
229 	int total = dwSizeToRead;
230 	char *bufferPtr = (char *)pBuffer;
231 	OggVorbis_File *ov = (OggVorbis_File *) ogg;
232 
233 	do {
234 		int ret = ov_read( ov, bufferPtr, total >= 4096 ? 4096 : total, Swap_IsBigEndian(), 2, 1, NULL );
235 		if ( ret == 0 ) {
236 			break;
237 		}
238 		if ( ret < 0 ) {
239 			return -1;
240 		}
241 		bufferPtr += ret;
242 		total -= ret;
243 	} while( total > 0 );
244 
245 	dwSizeToRead = (byte *)bufferPtr - pBuffer;
246 
247 	if ( pdwSizeRead != NULL ) {
248 		*pdwSizeRead = dwSizeToRead;
249 	}
250 
251 	return dwSizeToRead;
252 }
253 
254 /*
255 ====================
256 idWaveFile::CloseOGG
257 ====================
258 */
CloseOGG(void)259 int idWaveFile::CloseOGG( void ) {
260 	OggVorbis_File *ov = (OggVorbis_File *) ogg;
261 	if ( ov != NULL ) {
262 		Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
263 		ov_clear( ov );
264 		delete ov;
265 		Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
266 		fileSystem->CloseFile( mhmmio );
267 		mhmmio = NULL;
268 		ogg = NULL;
269 		return 0;
270 	}
271 	return -1;
272 }
273 
274 
275 /*
276 ===================================================================================
277 
278   idSampleDecoderLocal
279 
280 ===================================================================================
281 */
282 
283 class idSampleDecoderLocal : public idSampleDecoder {
284 public:
285 	virtual void			Decode( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest );
286 	virtual void			ClearDecoder( void );
287 	virtual idSoundSample *	GetSample( void ) const;
288 	virtual int				GetLastDecodeTime( void ) const;
289 
290 	void					Clear( void );
291 	int						DecodePCM( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest );
292 	int						DecodeOGG( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest );
293 
294 private:
295 	bool					failed;				// set if decoding failed
296 	int						lastFormat;			// last format being decoded
297 	idSoundSample *			lastSample;			// last sample being decoded
298 	int						lastSampleOffset;	// last offset into the decoded sample
299 	int						lastDecodeTime;		// last time decoding sound
300 	idFile_Memory			file;				// encoded file in memory
301 
302 	OggVorbis_File			ogg;				// OggVorbis file
303 };
304 
305 idBlockAlloc<idSampleDecoderLocal, 64>		sampleDecoderAllocator;
306 
307 /*
308 ====================
309 idSampleDecoder::Init
310 ====================
311 */
Init(void)312 void idSampleDecoder::Init( void ) {
313 	decoderMemoryAllocator.Init();
314 	decoderMemoryAllocator.SetLockMemory( true );
315 	decoderMemoryAllocator.SetFixedBlocks( idSoundSystemLocal::s_realTimeDecoding.GetBool() ? 10 : 1 );
316 }
317 
318 /*
319 ====================
320 idSampleDecoder::Shutdown
321 ====================
322 */
Shutdown(void)323 void idSampleDecoder::Shutdown( void ) {
324 	decoderMemoryAllocator.Shutdown();
325 	sampleDecoderAllocator.Shutdown();
326 }
327 
328 /*
329 ====================
330 idSampleDecoder::Alloc
331 ====================
332 */
Alloc(void)333 idSampleDecoder *idSampleDecoder::Alloc( void ) {
334 	idSampleDecoderLocal *decoder = sampleDecoderAllocator.Alloc();
335 	decoder->Clear();
336 	return decoder;
337 }
338 
339 /*
340 ====================
341 idSampleDecoder::Free
342 ====================
343 */
Free(idSampleDecoder * decoder)344 void idSampleDecoder::Free( idSampleDecoder *decoder ) {
345 	idSampleDecoderLocal *localDecoder = static_cast<idSampleDecoderLocal *>( decoder );
346 	localDecoder->ClearDecoder();
347 	sampleDecoderAllocator.Free( localDecoder );
348 }
349 
350 /*
351 ====================
352 idSampleDecoder::GetNumUsedBlocks
353 ====================
354 */
GetNumUsedBlocks(void)355 int idSampleDecoder::GetNumUsedBlocks( void ) {
356 	return decoderMemoryAllocator.GetNumUsedBlocks();
357 }
358 
359 /*
360 ====================
361 idSampleDecoder::GetUsedBlockMemory
362 ====================
363 */
GetUsedBlockMemory(void)364 int idSampleDecoder::GetUsedBlockMemory( void ) {
365 	return decoderMemoryAllocator.GetUsedBlockMemory();
366 }
367 
368 /*
369 ====================
370 idSampleDecoderLocal::Clear
371 ====================
372 */
Clear(void)373 void idSampleDecoderLocal::Clear( void ) {
374 	failed = false;
375 	lastFormat = WAVE_FORMAT_TAG_PCM;
376 	lastSample = NULL;
377 	lastSampleOffset = 0;
378 	lastDecodeTime = 0;
379 }
380 
381 /*
382 ====================
383 idSampleDecoderLocal::ClearDecoder
384 ====================
385 */
ClearDecoder(void)386 void idSampleDecoderLocal::ClearDecoder( void ) {
387 	Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
388 
389 	switch( lastFormat ) {
390 		case WAVE_FORMAT_TAG_PCM: {
391 			break;
392 		}
393 		case WAVE_FORMAT_TAG_OGG: {
394 			ov_clear( &ogg );
395 			memset( &ogg, 0, sizeof( ogg ) );
396 			break;
397 		}
398 	}
399 
400 	Clear();
401 
402 	Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
403 }
404 
405 /*
406 ====================
407 idSampleDecoderLocal::GetSample
408 ====================
409 */
GetSample(void) const410 idSoundSample *idSampleDecoderLocal::GetSample( void ) const {
411 	return lastSample;
412 }
413 
414 /*
415 ====================
416 idSampleDecoderLocal::GetLastDecodeTime
417 ====================
418 */
GetLastDecodeTime(void) const419 int idSampleDecoderLocal::GetLastDecodeTime( void ) const {
420 	return lastDecodeTime;
421 }
422 
423 /*
424 ====================
425 idSampleDecoderLocal::Decode
426 ====================
427 */
Decode(idSoundSample * sample,int sampleOffset44k,int sampleCount44k,float * dest)428 void idSampleDecoderLocal::Decode( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest ) {
429 	int readSamples44k;
430 
431 	if ( sample->objectInfo.wFormatTag != lastFormat || sample != lastSample ) {
432 		ClearDecoder();
433 	}
434 
435 	lastDecodeTime = soundSystemLocal.CurrentSoundTime;
436 
437 	if ( failed ) {
438 		memset( dest, 0, sampleCount44k * sizeof( dest[0] ) );
439 		return;
440 	}
441 
442 	// samples can be decoded both from the sound thread and the main thread for shakes
443 	Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
444 
445 	switch( sample->objectInfo.wFormatTag ) {
446 		case WAVE_FORMAT_TAG_PCM: {
447 			readSamples44k = DecodePCM( sample, sampleOffset44k, sampleCount44k, dest );
448 			break;
449 		}
450 		case WAVE_FORMAT_TAG_OGG: {
451 			readSamples44k = DecodeOGG( sample, sampleOffset44k, sampleCount44k, dest );
452 			break;
453 		}
454 		default: {
455 			readSamples44k = 0;
456 			break;
457 		}
458 	}
459 
460 	Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
461 
462 	if ( readSamples44k < sampleCount44k ) {
463 		memset( dest + readSamples44k, 0, ( sampleCount44k - readSamples44k ) * sizeof( dest[0] ) );
464 	}
465 }
466 
467 /*
468 ====================
469 idSampleDecoderLocal::DecodePCM
470 ====================
471 */
DecodePCM(idSoundSample * sample,int sampleOffset44k,int sampleCount44k,float * dest)472 int idSampleDecoderLocal::DecodePCM( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest ) {
473 	const byte *first;
474 	int pos, size, readSamples;
475 
476 	lastFormat = WAVE_FORMAT_TAG_PCM;
477 	lastSample = sample;
478 
479 	int shift = 22050 / sample->objectInfo.nSamplesPerSec;
480 	int sampleOffset = sampleOffset44k >> shift;
481 	int sampleCount = sampleCount44k >> shift;
482 
483 	if ( sample->nonCacheData == NULL ) {
484 		assert( false );	// this should never happen ( note: I've seen that happen with the main thread down in idGameLocal::MapClear clearing entities - TTimo )
485 		failed = true;
486 		return 0;
487 	}
488 
489 	if ( !sample->FetchFromCache( sampleOffset * sizeof( short ), &first, &pos, &size, false ) ) {
490 		failed = true;
491 		return 0;
492 	}
493 
494 	if ( size - pos < sampleCount * sizeof( short ) ) {
495 		readSamples = ( size - pos ) / sizeof( short );
496 	} else {
497 		readSamples = sampleCount;
498 	}
499 
500 	// duplicate samples for 44kHz output
501 	SIMDProcessor->UpSamplePCMTo44kHz( dest, (const short *)(first+pos), readSamples, sample->objectInfo.nSamplesPerSec, sample->objectInfo.nChannels );
502 
503 	return ( readSamples << shift );
504 }
505 
506 /*
507 ====================
508 idSampleDecoderLocal::DecodeOGG
509 ====================
510 */
DecodeOGG(idSoundSample * sample,int sampleOffset44k,int sampleCount44k,float * dest)511 int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest ) {
512 	int readSamples, totalSamples;
513 
514 	int shift = 22050 / sample->objectInfo.nSamplesPerSec;
515 	int sampleOffset = sampleOffset44k >> shift;
516 	int sampleCount = sampleCount44k >> shift;
517 
518 	// open OGG file if not yet opened
519 	if ( lastSample == NULL ) {
520 		// make sure there is enough space for another decoder
521 		if ( decoderMemoryAllocator.GetFreeBlockMemory() < MIN_OGGVORBIS_MEMORY ) {
522 			return 0;
523 		}
524 		if ( sample->nonCacheData == NULL ) {
525 			assert( false );	// this should never happen
526 			failed = true;
527 			return 0;
528 		}
529 		file.SetData( (const char *)sample->nonCacheData, sample->objectMemSize );
530 		if ( ov_openFile( &file, &ogg ) < 0 ) {
531 			failed = true;
532 			return 0;
533 		}
534 		lastFormat = WAVE_FORMAT_TAG_OGG;
535 		lastSample = sample;
536 	}
537 
538 	// seek to the right offset if necessary
539 	if ( sampleOffset != lastSampleOffset ) {
540 		if ( ov_pcm_seek( &ogg, sampleOffset / sample->objectInfo.nChannels ) != 0 ) {
541 			failed = true;
542 			return 0;
543 		}
544 	}
545 
546 	lastSampleOffset = sampleOffset;
547 
548 	// decode OGG samples
549 	totalSamples = sampleCount;
550 	readSamples = 0;
551 	do {
552 		float **samples;
553 		int ret = ov_read_float( &ogg, &samples, totalSamples / sample->objectInfo.nChannels, NULL );
554 		if ( ret == 0 ) {
555 			failed = true;
556 			break;
557 		}
558 		if ( ret < 0 ) {
559 			failed = true;
560 			return 0;
561 		}
562 		ret *= sample->objectInfo.nChannels;
563 
564 		SIMDProcessor->UpSampleOGGTo44kHz( dest + ( readSamples << shift ), samples, ret, sample->objectInfo.nSamplesPerSec, sample->objectInfo.nChannels );
565 
566 		readSamples += ret;
567 		totalSamples -= ret;
568 	} while( totalSamples > 0 );
569 
570 	lastSampleOffset += readSamples;
571 
572 	return ( readSamples << shift );
573 }
574