1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: snd_mp3.cpp 4297 2010-06-03 22:49:00Z firebrand_kh $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include <mad.h>
29 
30 #include "gamedefs.h"
31 #include "snd_local.h"
32 
33 // MACROS ------------------------------------------------------------------
34 
35 // TYPES -------------------------------------------------------------------
36 
37 class VMp3AudioCodec : public VAudioCodec
38 {
39 public:
40 	enum { INPUT_BUFFER_SIZE = 5 * 8192 };
41 
42 	VStream*			Strm;
43 	bool				FreeStream;
44 	int					BytesLeft;
45 	bool				Initialised;
46 
47 	mad_stream			Stream;
48 	mad_frame			Frame;
49 	mad_synth			Synth;
50 	byte				InputBuffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
51 	int					FramePos;
52 	bool				HaveFrame;
53 
54 	VMp3AudioCodec(VStream*, bool);
55 	~VMp3AudioCodec();
56 	bool Init();
57 	int Decode(short*, int);
58 	int ReadData();
59 	bool Finished();
60 	void Restart();
61 	static VAudioCodec* Create(VStream*);
62 };
63 
64 class VMp3SampleLoader : public VSampleLoader
65 {
66 public:
67 	void Load(sfxinfo_t&, VStream&);
68 };
69 
70 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
71 
72 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
73 
74 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
75 
76 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
77 
78 // PUBLIC DATA DEFINITIONS -------------------------------------------------
79 
80 // PRIVATE DATA DEFINITIONS ------------------------------------------------
81 
82 IMPLEMENT_AUDIO_CODEC(VMp3AudioCodec, "MP3");
83 
84 VMp3SampleLoader		Mp3SampleLoader;
85 
86 // CODE --------------------------------------------------------------------
87 
88 //==========================================================================
89 //
90 //	VMp3AudioCodec::VMp3AudioCodec
91 //
92 //==========================================================================
93 
VMp3AudioCodec(VStream * AStrm,bool AFreeStream)94 VMp3AudioCodec::VMp3AudioCodec(VStream* AStrm, bool AFreeStream)
95 : Strm(AStrm)
96 , FreeStream(AFreeStream)
97 , Initialised(false)
98 {
99 	guard(VMp3AudioCodec::VMp3AudioCodec);
100 	//	Seek file to the begining
101 	BytesLeft = Strm->TotalSize();
102 	Strm->Seek(0);
103 
104 	//	Initialise structures used by libmad
105 	mad_stream_init(&Stream);
106 	mad_frame_init(&Frame);
107 	mad_synth_init(&Synth);
108 	unguard;
109 }
110 
111 //==========================================================================
112 //
113 //	VMp3AudioCodec::~VMp3AudioCodec
114 //
115 //==========================================================================
116 
~VMp3AudioCodec()117 VMp3AudioCodec::~VMp3AudioCodec()
118 {
119 	guard(VMp3AudioCodec::~VMp3AudioCodec);
120 	if (Initialised)
121 	{
122 		//	Close file only if decoder has been initialised succesfully.
123 		if (FreeStream)
124 		{
125 			Strm->Close();
126 			delete Strm;
127 		}
128 		Strm = NULL;
129 	}
130 	//	Clear structs used by libmad.
131 	mad_synth_finish(&Synth);
132 	mad_frame_finish(&Frame);
133 	mad_stream_finish(&Stream);
134 	unguard;
135 }
136 
137 //==========================================================================
138 //
139 //	VMp3AudioCodec::Init
140 //
141 //==========================================================================
142 
Init()143 bool VMp3AudioCodec::Init()
144 {
145 	guard(VMp3AudioCodec::Init);
146 
147 	//	Check for ID3v2 header.
148 	byte Id3Hdr[10];
149 	int SavedPos = Strm->Tell();
150 	Strm->Serialise(Id3Hdr, 10);
151 	if (Id3Hdr[0] == 'I' && Id3Hdr[1] == 'D' && Id3Hdr[2] == '3')
152 	{
153 		//	It's a ID3v3 header, skip it.
154 		int HdrSize = Id3Hdr[9] + (Id3Hdr[8] << 7) + (Id3Hdr[7] << 14) +
155 			(Id3Hdr[6] << 21);
156 		if (HdrSize + 10 > BytesLeft)
157 			return false;
158 		Strm->Seek(Strm->Tell() + HdrSize);
159 		BytesLeft -= 10 + HdrSize;
160 	}
161 	else
162 	{
163 		//	Not a ID3v3 header, seek back to saved position.
164 		Strm->Seek(SavedPos);
165 	}
166 
167 	//	Read some data.
168 	ReadData();
169 
170 	//	Decode first frame. If this fails we assume it's not a MP3 file.
171 	if (mad_frame_decode(&Frame, &Stream))
172 	{
173 		//	Not a valid stream.
174 		return false;
175 	}
176 
177 	//	We are ready to read data.
178 	mad_synth_frame(&Synth, &Frame);
179 	FramePos = 0;
180 	HaveFrame = true;
181 
182 	//	Everything's OK.
183 	SampleRate = Frame.header.samplerate;
184 	Initialised = true;
185 	return true;
186 	unguard;
187 }
188 
189 //==========================================================================
190 //
191 //	VMp3AudioCodec::Decode
192 //
193 //==========================================================================
194 
Decode(short * Data,int NumSamples)195 int VMp3AudioCodec::Decode(short* Data, int NumSamples)
196 {
197 	guard(VMp3AudioCodec::Decode);
198 	int CurSample = 0;
199 	do
200 	{
201 		if (HaveFrame)
202 		{
203 			//	Convert stream from fixed point to short.
204 			for (; FramePos < Synth.pcm.length; FramePos++)
205 			{
206 				//	Left channel
207 				short Sample;
208 				mad_fixed_t Fixed = Synth.pcm.samples[0][FramePos];
209 				if (Fixed >= MAD_F_ONE)
210 					Sample = 0x7fff;
211 				else if (Fixed <= -MAD_F_ONE)
212 					Sample = -0x7fff;
213 				else
214 					Sample = Fixed >> (MAD_F_FRACBITS - 15);
215 				Data[CurSample * 2] = Sample;
216 
217 				//	Right channel. If the decoded stream is monophonic then
218 				// the right output channel is the same as the left one.
219 				if (MAD_NCHANNELS(&Frame.header) == 2)
220 				{
221 					Fixed = Synth.pcm.samples[1][FramePos];
222 					if (Fixed >= MAD_F_ONE)
223 						Sample = 0x7fff;
224 					else if (Fixed <= -MAD_F_ONE)
225 						Sample = -0x7fff;
226 					else
227 						Sample = Fixed >> (MAD_F_FRACBITS - 15);
228 				}
229 				Data[CurSample * 2 + 1] = Sample;
230 				CurSample++;
231 				//	Check if we already have decoded enough.
232 				if (CurSample >= NumSamples)
233 					return CurSample;
234 			}
235 			//	We are done with the frame.
236 			HaveFrame = false;
237 		}
238 
239 		//	Fill in input buffer if it becomes empty.
240 		if (Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
241 		{
242 			if (!ReadData())
243 				break;
244 		}
245 
246 		//	Decode the next frame.
247 		if (mad_frame_decode(&Frame, &Stream))
248 		{
249 			if (MAD_RECOVERABLE(Stream.error) ||
250 				Stream.error==MAD_ERROR_BUFLEN)
251 			{
252 				continue;
253 			}
254 			else
255 			{
256 				break;
257 			}
258 		}
259 
260 		//	Once decoded the frame is synthesized to PCM samples.
261 		mad_synth_frame(&Synth, &Frame);
262 		FramePos = 0;
263 		HaveFrame = true;
264 	} while(1);
265 	return CurSample;
266 	unguard;
267 }
268 
269 //==========================================================================
270 //
271 //	VMp3AudioCodec::ReadData
272 //
273 //==========================================================================
274 
ReadData()275 int VMp3AudioCodec::ReadData()
276 {
277 	guard(VMp3AudioCodec::ReadData);
278 	int			ReadSize;
279 	int			Remaining;
280 	byte*		ReadStart;
281 
282 	//	If there are some bytes left, move them to the beginning of the
283 	// buffer.
284 	if (Stream.next_frame != NULL)
285 	{
286 		Remaining = Stream.bufend - Stream.next_frame;
287 		memmove(InputBuffer, Stream.next_frame, Remaining);
288 		ReadStart = InputBuffer + Remaining;
289 		ReadSize = INPUT_BUFFER_SIZE - Remaining;
290 	}
291 	else
292 	{
293 		ReadSize = INPUT_BUFFER_SIZE;
294 		ReadStart = InputBuffer;
295 		Remaining = 0;
296 	}
297 	//	Fill-in the buffer.
298 	if (ReadSize > BytesLeft)
299 		ReadSize = BytesLeft;
300 	if (!ReadSize)
301 		return 0;
302 	Strm->Serialise(ReadStart, ReadSize);
303 	BytesLeft -= ReadSize;
304 
305 	//	When decoding the last frame of a file, it must be followed by
306 	// MAD_BUFFER_GUARD zero bytes if one wants to decode that last frame.
307 	if (!BytesLeft)
308 	{
309 		memset(ReadStart + ReadSize + Remaining, 0, MAD_BUFFER_GUARD);
310 		ReadSize += MAD_BUFFER_GUARD;
311 	}
312 
313 	//	Pipe the new buffer content to libmad's stream decoder facility.
314 	mad_stream_buffer(&Stream, InputBuffer, ReadSize + Remaining);
315 	Stream.error = MAD_ERROR_NONE;
316 	return ReadSize + Remaining;
317 	unguard;
318 }
319 
320 //==========================================================================
321 //
322 //	VMp3AudioCodec::Finished
323 //
324 //==========================================================================
325 
Finished()326 bool VMp3AudioCodec::Finished()
327 {
328 	guard(VMp3AudioCodec::Finished);
329 	//	We are done if there's no more data and last frame has been decoded.
330 	return !BytesLeft && !HaveFrame;
331 	unguard;
332 }
333 
334 //==========================================================================
335 //
336 //	VMp3AudioCodec::Restart
337 //
338 //==========================================================================
339 
Restart()340 void VMp3AudioCodec::Restart()
341 {
342 	guard(VMp3AudioCodec::Restart);
343 	//	Seek to the beginning of the file.
344 	Strm->Seek(0);
345 	BytesLeft = Strm->TotalSize();
346 	unguard;
347 }
348 
349 //==========================================================================
350 //
351 //	VMp3AudioCodec::Create
352 //
353 //==========================================================================
354 
Create(VStream * InStrm)355 VAudioCodec* VMp3AudioCodec::Create(VStream* InStrm)
356 {
357 	guard(VMp3AudioCodec::Create);
358 	VMp3AudioCodec* Codec = new VMp3AudioCodec(InStrm, true);
359 	if (!Codec->Init())
360 	{
361 		delete Codec;
362 		Codec = NULL;
363 		return NULL;
364 	}
365 	return Codec;
366 	unguard;
367 }
368 
369 //==========================================================================
370 //
371 //	VMp3SampleLoader::Create
372 //
373 //==========================================================================
374 
Load(sfxinfo_t & Sfx,VStream & Stream)375 void VMp3SampleLoader::Load(sfxinfo_t& Sfx, VStream& Stream)
376 {
377 	guard(VMp3SampleLoader::Load);
378 	VMp3AudioCodec* Codec = new VMp3AudioCodec(&Stream, false);
379 	if (!Codec->Init())
380 	{
381 		delete Codec;
382 		Codec = NULL;
383 		return;
384 	}
385 
386 	TArray<short> Data;
387 	do
388 	{
389 		short Buf[16 * 2048];
390 		int SamplesDecoded = Codec->Decode(Buf, 16 * 1024);
391 		if (SamplesDecoded > 0)
392 		{
393 			int OldPos = Data.Num();
394 			Data.SetNumWithReserve(Data.Num() + SamplesDecoded);
395 			for (int i = 0; i < SamplesDecoded; i++)
396 			{
397 				Data[OldPos + i] = Buf[i * 2];
398 			}
399 		}
400 	}
401 	while (!Codec->Finished());
402 	if (!Data.Num())
403 	{
404 		delete Codec;
405 		Codec = NULL;
406 		return;
407 	}
408 
409 	//	Copy parameters.
410 	Sfx.SampleRate = Codec->SampleRate;
411 	Sfx.SampleBits = Codec->SampleBits;
412 
413 	//	Copy data.
414 	Sfx.DataSize = Data.Num() * 2;
415 	Sfx.Data = Z_Malloc(Data.Num() * 2);
416 	memcpy(Sfx.Data, Data.Ptr(), Data.Num() * 2);
417 
418 	delete Codec;
419 	Codec = NULL;
420 	unguard;
421 }
422