1 /* libsswf_tag_sound.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */
2 
3 /*
4 
5 Copyright (c) 2002-2008 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 /** \file
35  *
36  * \brief The implementation of all the different sound classes
37  *
38  * This file declares the body of the functions which are not
39  * inline. It is part of the SSWF library.
40  */
41 
42 #include	"sswf/libsswf.h"
43 
44 using namespace sswf;
45 
46 
47 
48 
49 /////////////////////////////////////////// Envelope
50 
51 
52 /** \class sswf::Envelope
53  *
54  * \brief An array of volumes for a sound effect
55  *
56  * This class is used to defined volume changes to be used
57  * against a sound effect or music.
58  *
59  * This is useful if you have several places where you
60  * want to place the same sound at different volume levels.
61  *
62  * \warning
63  * The volume goes from 0 to 32768. Larger values have an
64  * undefined result.
65  *
66  * \sa sswf::SoundInfo
67  * \sa <a href="../SWFalexref.html#swf_envelope">SWF Alexis' Reference&mdash;swf_envelope</a>
68  */
69 
70 
71 /** \brief Initializes an envelope
72  *
73  * The constructor initializes an envelope with a position
74  * and the volume on the left and right sides. If the sound
75  * is not stereo, the volume of both sides should be set to
76  * the same value.
77  *
78  * The left and right volumes go from 0 (mute) to
79  * 32768 (max. power). The effect of using values outside this
80  * range is undefined.
81  *
82  * The position is always defined as if the rate of the sound
83  * was 44,100k. So you need to multiply all positions by some
84  * value to obtain the correct envelope position.
85  *
86  * So, if the rate of the sound is defined a R, the factor you
87  * need to use is:
88  *
89  *	44,100 / rate
90  *
91  * In other words:
92  *
93  * \htmlonly
94  * <blockquote>
95  * <table cellpadding="5" cellspacing="0" border="1">
96  * 	<tr><th>rate</th><th>factor</th></tr>
97  *	<tr><td align="right"> 5,512</td><td align="right">8</td></tr>
98  *	<tr><td align="right">11,025</td><td align="right">4</td></tr>
99  *	<tr><td align="right">22,050</td><td align="right">2</td></tr>
100  *	<tr><td align="right">44,100</td><td align="right">1</td></tr>
101  * </table>
102  * </blockquote>
103  * \endhtmlonly
104  *
105  * Also, positions need to be defined between the start and
106  * stop positions of the corresponding sswf::SoundInfo (see the
107  * sswf::SoundInfo::SetRange(unsigned long start, unsigned long end)
108  * function.)
109  *
110  * Note that the volume is clamped to the range 0 to 32768.
111  *
112  * \bug
113  * The Envelope does not know whether the sound it will affect
114  * is stereo or mono. This may not be a problem with newer
115  * versions of the Macromedia players.
116  *
117  * \param[in] p The position where the new volume applies
118  * \param[in] l The volume on the left side (0 to 32768)
119  * \param[in] r The volume on the left side (0 to 32768)
120  *
121  * \sa sswf::Envelope::Envelope(const Envelope& envelope)
122  * \sa sswf::SoundInfo
123  * \sa sswf::SoundInfo::SetRange(unsigned long start, unsigned long end)
124  * \sa sswf::TagStartSound
125  * \sa sswf::TagSound
126  */
Envelope(unsigned long p,unsigned short l,unsigned short r)127 Envelope::Envelope(unsigned long p, unsigned short l, unsigned short r)
128 {
129 	// since we are in a constructor, we continue so as to avoid
130 	// throwing... (also the OnError() function is not available...)
131 	if(l > 32768) {
132 		l = 32768;
133 	}
134 	if(r > 32768) {
135 		r = 32768;
136 	}
137 
138 	f_position = p;
139 	f_left     = l;
140 	f_right    = r;
141 }
142 
143 
144 /** \brief Copy an envelope in another one
145  *
146  * This function can be used to copy an envelope in another.
147  *
148  * \sa sswf::Envelope::Envelope(unsigned long p, unsigned short l, unsigned short r)
149  */
Envelope(const Envelope & envelope)150 Envelope::Envelope(const Envelope& envelope)
151 {
152 	f_position = envelope.f_position;
153 	f_left     = envelope.f_left;
154 	f_right    = envelope.f_right;
155 }
156 
157 
158 /** \brief Retrieve the position of this envelope
159  *
160  * This function returns the position of the this envelope.
161  *
162  * \return The position of the envelope
163  */
Position(void) const164 unsigned long Envelope::Position(void) const
165 {
166 	return f_position;
167 }
168 
169 
170 /** \brief Retrieve the volume for the left side
171  *
172  * This function returns the volume for the left side.
173  *
174  * \return The left side volume
175  */
Left(void) const176 unsigned short Envelope::Left(void) const
177 {
178 	return f_left;
179 }
180 
181 
182 /** \brief Retrieve the volume for the right side
183  *
184  * This function returns the volume for the right side.
185  *
186  * \return The right side volume
187  */
Right(void) const188 unsigned short Envelope::Right(void) const
189 {
190 	return f_right;
191 }
192 
193 
194 /** \brief Save an envelope in a Data buffer
195  *
196  * This function is used to save an envelope as the SWF
197  * player expects. It saves the position, left and then
198  * right volumes.
199  *
200  * \param[in] data The Data buffer where the envelope is to be saved
201  */
Save(Data & data) const202 void Envelope::Save(Data& data) const
203 {
204 	data.PutLong(f_position);
205 	data.PutShort(f_left);
206 	data.PutShort(f_right);
207 }
208 
209 
210 
211 /////////////////////////////////////////// SoundInfo
212 
213 
214 /** \class sswf::SoundInfo
215  *
216  * \brief Information about out to playback a sound effect
217  *
218  * A SoundInfo object defines how to playback a sound effect.
219  * In general, you play a sound effect from start to finish
220  * once. The sound info lets you have a large sound effect and
221  * only play a portion of it with different volume information
222  * (i.e. envelope)
223  *
224  * A SoundInfo object is set in a TagStartSound object.
225  *
226  * \warning
227  * The volume goes from 0 to 32768. Larger values have an
228  * undefined result.
229  *
230  * \bug
231  * This object does not accept 0 as a sound object identifier.
232  * No object should have its identifier set to zero anyway.
233  *
234  * \sa sswf::Envelope
235  * \sa sswf::TagStartSound
236  * \sa <a href="../SWFalexref.html#swf_soundinfo">SWF Alexis' Reference&mdash;swf_soundinfo</a>
237  */
238 
239 
240 /** \brief Initializes a sound information class.
241  *
242  * This constructor resets the SoundInfo object to defaults:
243  *
244  * Stop the sound, the sound effect cannot be played more
245  * than once, the start and end position are 0 and end of
246  * the sound effect respectively, it loops just once and
247  * there is no envelopes by default.
248  *
249  * \param[in] error_manager A pointer to your TagHeader (i.e. it is the error manager!)
250  *
251  * \sa sswf::Envelope
252  */
SoundInfo(ErrorManager & error_manager)253 SoundInfo::SoundInfo(ErrorManager& error_manager)
254 	: f_error_manager(error_manager)
255 {
256 	f_sound_id = 0;
257 	f_stop = false;
258 	f_no_multiple = false;
259 	f_start_position = 0;
260 	f_end_position = 0;
261 	f_loop = 1;
262 	//f_envelopes = ... -- auto init by constructor
263 }
264 
265 
266 /** \brief Set the reference to the sound to playback.
267  *
268  * This function must be called with a valid identifier (i.e. an
269  * identifier to a sound effect object.)
270  *
271  * The default value (0) is not valid. Thus you have to call
272  * this function at least once.
273  *
274  * \param[in] id The identifier of the corresponding TagSound
275  */
SetSoundID(sswf_id_t id)276 void SoundInfo::SetSoundID(sswf_id_t id)
277 {
278 	if(id == 0) {
279 		f_error_manager.OnError(ErrorManager::ERROR_CODE_INVALID_IDENTIFIER, "A SoundInfo object must be given a valid TagSound object reference.");
280 		return;
281 	}
282 	f_sound_id = id;
283 }
284 
285 
286 /** \brief Whether this SoundInfo is used to stop a sound.
287  *
288  * This function is used to mark a SoundInfo entry as a "Stop Button"
289  * (true) or a "Start Button" (false.)
290  *
291  * When a sound is marked to be stopped (default), then the other
292  * parameters (except the sound identifier) are ignored.
293  *
294  * \param[in] stop If true, stop the sound.
295  */
StopSound(bool stop)296 void SoundInfo::StopSound(bool stop)
297 {
298 	f_stop = stop;
299 }
300 
301 
302 /** \brief Whether the referenced sound can be played multiple times in parallel.
303  *
304  * This flag is used to determine whether the referenced sound can be
305  * played multiple times in parallel. In general, this flag is set to
306  * true but the default is false.
307  *
308  * \param[in] no_multiple Whether multiple instances will play in parallel
309  */
NoMultiple(bool no_multiple)310 void SoundInfo::NoMultiple(bool no_multiple)
311 {
312 	f_no_multiple = no_multiple;
313 }
314 
315 
316 /** \brief The start and end points to playback.
317  *
318  * The SoundInfo can be used to play only a small portion of a sound effect.
319  * This function can be used to define the start and end points in the sound
320  * samples.
321  *
322  * The start parameter must be small than the end parameter unless one or
323  * the other is set to zero. (i.e. zero represents the default; for the start
324  * zero is zero and for the end zero represents the total number of samples
325  * of the referenced sound tag.)
326  *
327  * The position is defined in number of samples. So when set to 1 with stereo
328  * 16 bits sample, the sound starts playing at byte offset 4.
329  *
330  * \param[in] start The start position
331  * \param[in] end The end position
332  */
SetRange(unsigned long start,unsigned long end)333 void SoundInfo::SetRange(unsigned long start, unsigned long end)
334 {
335 	if(start > end && start != 0 && end != 0) {
336 		f_error_manager.OnError(ErrorManager::ERROR_CODE_EMPTY_POSITION_RANGE, "The start position is larger than the end in a SoundInfo object.");
337 		return;
338 	}
339 	f_start_position = start;
340 	f_end_position = end;
341 }
342 
343 
344 /** \brief Set the number of times a sound shall be played.
345  *
346  * This function changes the number of time a sound effect will be
347  * repeated. By default a sound effect is played just once.
348  *
349  * \bug
350  * The loop parameter cannot be set to zero.
351  *
352  * \param[in] loop The number of times the sound effect shall be played
353  */
SetLoop(unsigned short loop)354 void SoundInfo::SetLoop(unsigned short loop)
355 {
356 	if(loop == 0) {
357 		f_error_manager.OnError(ErrorManager::ERROR_CODE_LOOP_ZERO, "The loop parameter cannot be zero in a SoundInfo object.");
358 		return;
359 	}
360 
361 	f_loop = loop;
362 }
363 
364 
365 /** \brief This function adds one Envelope to the SoundInfo object
366  *
367  * This function accepts an envelope to add to the SoundInfo.
368  *
369  * The Envelope can be used to fade a sound in or out.
370  *
371  * Note that a SoundInfo is limited to a maximum of 255 envelopes.
372  *
373  * The input Envelope is duplicated in the SoundInfo.
374  *
375  * Note that the new envelope is placed where it needs to be so as
376  * to be properly ordered by position (since version 1.8.1--in
377  * previous versions, additional envelopes would be appended so
378  * they had to be added in order.)
379  *
380  * \param[in] envelope The envelope to add
381  */
AddEnvelope(const Envelope & envelope)382 void SoundInfo::AddEnvelope(const Envelope& envelope)
383 {
384 	Envelope	*e, *env;
385 	long		r;
386 	int		idx;
387 
388 	if(f_envelopes.Count() >= 255) {
389 		f_error_manager.OnError(ErrorManager::ERROR_CODE_ENVELOPE_OVERFLOW, "Too many envelopes for a SoundInfo object.");
390 		return;
391 	}
392 
393 	e = new Envelope(envelope);
394 	MemAttach(e, sizeof(Envelope), "SoundInfo::AddEnvelope(): duplication of the envelope object");
395 
396 	// Not too sure whether we need to order those, but most certainly!
397 	// Now it's done; also we avoid two envelopes at the same position.
398 	for(idx = f_envelopes.Count() - 1; idx >= 0; --idx) {
399 		env = dynamic_cast<Envelope *>(f_envelopes.Get(idx));
400 		r = env->Position() - e->Position();
401 		if(r < 0) {
402 			f_envelopes.Set(idx + 1, e);
403 			return;
404 		}
405 		if(r == 0) {
406 			f_error_manager.OnError(ErrorManager::ERROR_CODE_ENVELOPE_EXISTS, "Another envelope already exists at that position");
407 			return;
408 		}
409 	}
410 
411 	f_envelopes.Set(-1, e);
412 }
413 
414 
415 /** \brief Makes sure that the sound identifier was defined
416  *
417  * This function ensures that:
418  *
419  * \li The sound identifier was set to a valid sound identifier;
420  * \li The loop counter is not zero;
421  * \li The start position is before the end position.
422  *
423  * \return ErrorManager::ERROR_CODE_NONE or some other ErrorManager::error_code_t
424  */
PreSave(void)425 ErrorManager::error_code_t SoundInfo::PreSave(void)
426 {
427 	ErrorManager::error_code_t	err;
428 
429 	if(f_sound_id == 0) {
430 		f_error_manager.OnError(ErrorManager::ERROR_CODE_INVALID_IDENTIFIER, "A SoundInfo object must be given a valid TagSound object reference.");
431 		return ErrorManager::ERROR_CODE_INVALID_IDENTIFIER;
432 	}
433 
434 	// if stopped, it doesn't matter much that the other info is invalid
435 	if(!f_stop) {
436 		if(f_start_position > f_end_position && f_start_position != 0 && f_end_position != 0) {
437 			err = f_error_manager.OnError(ErrorManager::ERROR_CODE_EMPTY_POSITION_RANGE, "The start position is larger than the end in a SoundInfo object.");
438 			if(err != ErrorManager::ERROR_CODE_NONE) {
439 				return err;
440 			}
441 		}
442 
443 		// this should never happen
444 		if(f_loop == 0) {
445 			err = f_error_manager.OnError(ErrorManager::ERROR_CODE_LOOP_ZERO, "The loop parameter cannot be zero in a SoundInfo object.");
446 			if(err != ErrorManager::ERROR_CODE_NONE) {
447 				return err;
448 			}
449 		}
450 	}
451 
452 	return ErrorManager::ERROR_CODE_NONE;
453 }
454 
455 
456 
457 /** \brief Save the information in the specified Data buffer
458  *
459  * This function saves the SoundInfo parameters in the specified
460  * Data buffer.
461  *
462  * \param[in,out] data The buffer where the tag is saved
463  */
Save(Data & data) const464 void SoundInfo::Save(Data& data) const
465 {
466 	int		idx, max;
467 
468 	data.PutShort(f_sound_id);
469 	data.WriteBits(0, 2);
470 	data.WriteBits(f_stop, 1);
471 	if(f_stop) {
472 		// if the sound is being stopped, we don't need any other info
473 		data.WriteBits(0, 5);
474 	}
475 	else {
476 		max = f_envelopes.Count();
477 
478 		data.WriteBits(f_no_multiple, 1);
479 		data.WriteBits(max > 0, 1);
480 		data.WriteBits(f_loop != 1, 1);
481 		data.WriteBits(f_start_position != 0, 1);
482 		data.WriteBits(f_end_position != 0, 1);
483 
484 		if(f_start_position != 0) {
485 			data.PutLong(f_start_position);
486 		}
487 		if(f_end_position != 0) {
488 			data.PutLong(f_end_position);
489 		}
490 		if(f_loop != 1) {
491 			data.PutShort(f_loop);
492 		}
493 		// when we have envelops, save them all!
494 		if(max > 0) {
495 			data.PutByte(max);
496 			for(idx = 0; idx < max; idx++) {
497 				dynamic_cast<const Envelope *>(f_envelopes.Get(idx))->Save(data);
498 			}
499 		}
500 	}
501 }
502 
503 
504 /////////////////////////////////////////// TagStartSound
505 
506 
507 /** \class sswf::TagStartSound
508  *
509  * \brief Class used to start/stop a sound
510  *
511  * This class is used to start and/or stop a sound in an SWF
512  * animation.
513  *
514  * In order to work properly, you must call
515  * sswf::TagStartSound::SetInfo(SoundInfo *sound_info)
516  * at least once.
517  *
518  * \sa sswf::TagStartSound::SetInfo(SoundInfo *sound_info)
519  * \sa <a href="../SWFalexref.html#tag_startsound">SWF Alexis' Reference&mdash;Start Sound</a>
520  * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
521  */
522 
523 
524 /** \brief Initialize a start sound tag
525  *
526  * This function initializes a start sound tag. This means setting
527  * the pointer to the sound info to NULL.
528  *
529  * \param[in] parent The parent of this TagStartSound
530  *
531  * \sa sswf::TagStartSound::SetInfo(SoundInfo *sound_info)
532  */
TagStartSound(TagBase * parent)533 TagStartSound::TagStartSound(TagBase *parent)
534 	: TagBase("startsound", parent)
535 {
536 	f_sound_info = 0;
537 }
538 
539 
540 
541 /** \brief Returns the type flags of this start sound tag
542  *
543  * The start sound tag is a CONTROL tag.
544  *
545  * The start sound tag has a reference to a sound (actually
546  * defined in the sound info.)
547  *
548  * \return A set of SWF TYPE flags
549  *
550  * \sa sswf::TagStartSound::SetInfo(SoundInfo *sound_info)
551  */
TypeFlags(void) const552 TagBase::swf_type_t TagStartSound::TypeFlags(void) const
553 {
554 	return SWF_TYPE_CONTROL | SWF_TYPE_REFERENCE;
555 }
556 
557 
558 /** \brief Defines the sound info of this start sound tag
559  *
560  * This function saves the specified sound info pointer in
561  * the TagStartSound object.
562  *
563  * \warning
564  * The sound_info structure will be used by the TagStartSound until
565  * replaced by a new pointer or set to NULL.
566  *
567  * \par
568  * You are responsible to ensure that this structure remains valid
569  * until the object does not require it anymore.
570  */
SetInfo(SoundInfo * sound_info)571 void TagStartSound::SetInfo(SoundInfo *sound_info)
572 {
573 	// NOTE: should we copy the user object?
574 	f_sound_info = sound_info;
575 }
576 
577 
578 /** \brief Test the validity of the start sound tag
579  *
580  * This function makes sure that you have set a valid sound info.
581  *
582  * If the sound info pointer is null, this function returns
583  * an error.
584  *
585  * \return sswf::ErrorManager::ERROR_CODE_START_SOUND_NO_INFO
586  * 	if no sound info was defined; no error otherwise
587  */
PreSave(void)588 ErrorManager::error_code_t TagStartSound::PreSave(void)
589 {
590 	if(f_sound_info == 0) {
591 		OnError(ErrorManager::ERROR_CODE_START_SOUND_NO_INFO, "Cannot start a sound without info.");
592 		return ErrorManager::ERROR_CODE_START_SOUND_NO_INFO;
593 	}
594 
595 	return f_sound_info->PreSave();
596 }
597 
598 
599 
600 /** \brief Save the start sound tag in the Data buffer
601  *
602  * This function saves the start sound tag in the specified Data buffer.
603  * This calls the sswf::SoundInfo::Save(Data& data) function.
604  *
605  * \param[in] data The Data buffer where the start sound tag is saved
606  *
607  * \return an error manager code
608  *
609  * \sa sswf::SoundInfo::Save(Data& data)
610  */
Save(Data & data)611 ErrorManager::error_code_t TagStartSound::Save(Data& data)
612 {
613 	Data		sub_data;
614 
615 	// the sound info size varies with envelopes
616 	f_sound_info->Save(sub_data);
617 
618 	SaveTag(data, SWF_TAG_START_SOUND, sub_data.ByteSize());
619 	data.Append(sub_data);
620 
621 	return  ErrorManager::ERROR_CODE_NONE;
622 }
623 
624 
625 
626 
627 
628 
629 
630 
631 /////////////////////////////////////////// TagSound
632 
633 
634 /** \class sswf::TagSound
635  *
636  * \brief Declare a sound
637  *
638  * This class defines a sound rate, samples, mono or stereo, 8 or 16 bits, etc.
639  *
640  * \todo
641  * This sound does not yet support for streaming sound.
642  *
643  * \sa <a href="../SWFalexref.html#tag_definesound">SWF Alexis' Reference&mdash;Define Sound</a>
644  * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
645  */
646 
647 
648 /** \typedef sswf::TagSound::sound_format_t
649  *
650  * \brief Valid formats of sounds in Flash
651  *
652  * This type lists all the formats supported by the Flash players.
653  *
654  * \todo
655  * Note that all of these formats are not yet supported by the
656  * SSWF library. The ADPCM and NELLYMOSER have no support.
657  */
658 
659 
660 /** \var sswf::TagSound::SOUND_FORMAT_UNKNOWN
661  *
662  * \brief An undefined or unknown format
663  *
664  * By default a sound tag is defined as having an unknown format.
665  *
666  * It is not valid to call SetData() with this value.
667  *
668  * \sa sswf::TagSound::SetData()
669  *
670  * <br>
671  * <br>
672  */
673 
674 
675 /** \var sswf::TagSound::SOUND_FORMAT_RAW
676  *
677  * \brief This format is used to save uncompressed sound data
678  *
679  * Most of the time, sound samples will be compressed to save space.
680  * Very small sounds may be saved in an uncompressed format for better
681  * quality.
682  *
683  * This format should not be used with 16 bits data since it is not
684  * possible to know for sure whether the sound effects are in little
685  * or big endian (it is dependent on the machine on which you created
686  * the Flash animation!)
687  *
688  * <br>
689  * <br>
690  */
691 
692 
693 /** \var sswf::TagSound::SOUND_FORMAT_ADPCM
694  *
695  * \brief This format is used to save compressed sound data using the ADPCM format
696  *
697  * This is a simple compression scheme somewhat similar in concept to the
698  * RLE for images. This is better suited for sound samples of effects than
699  * for songs.
700  *
701  * \todo
702  * The libsswf library does not support this compression mode yet.
703  *
704  * <br>
705  * <br>
706  */
707 
708 
709 
710 /** \var sswf::TagSound::SOUND_FORMAT_MP3
711  *
712  * \brief This format is used to save compressed music data using the MP3 format
713  *
714  * This is a complex compression scheme somewhat similar in concept to
715  * JPEG for images. This is better suited for sound samples of musics than
716  * for talk or effects.
717  *
718  * \todo
719  * The libsswf library does not yet support this compression. However, it
720  * can load and use an existing MP3 file.
721  *
722  * <br>
723  * <br>
724  */
725 
726 
727 /** \var sswf::TagSound::SOUND_FORMAT_UNCOMPRESSED
728  *
729  * \brief This format is used to save small uncompressed sound effect with full quality
730  *
731  * This is the uncompressed format to use with uncompressed data. This format
732  * ensures the endianess of the data is known (i.e. little endian.) This can
733  * be created and played on any system with no problem.
734  *
735  * <br>
736  * <br>
737  */
738 
739 
740 /** \var sswf::TagSound::SOUND_FORMAT_NELLYMOSER
741  *
742  * \brief This format is used to save compressed voice with high quality
743  *
744  * This is the compressed format to use with voices (with no music in the
745  * background). Though MP3 can also be used for voices, you general get a
746  * better result with this compression scheme for voices.
747  *
748  * \todo
749  * This compression format is not yet supported by the sswf library.
750  *
751  * <br>
752  * <br>
753  */
754 
755 
756 
757 
758 
759 
760 
761 /** \typedef sswf::TagSound::sound_endian_t
762  *
763  * \brief Valid endians for sound samples
764  *
765  * This type lists all the endians supported by the sswf library.
766  */
767 
768 
769 /** \var sswf::TagSound::SOUND_ENDIAN_LITTLE
770  *
771  * \brief The data is in little endian
772  *
773  * Little endian means that the first byte is the least significant
774  * and the last byte is the most significant.
775  *
776  * Pentium or older MIPS based computers are in little endian.
777  *
778  * \code
779  * 	unsigned short file_samples[10];
780  *	char *ptr = (char *) file_samples;
781  *	unsigned short machine_samples[10];
782  *
783  *	machine_samples[0] = ptr[0] + ptr[1] * 256;
784  *	...
785  * \endcode
786  *
787  * <br>
788  * <br>
789  */
790 
791 
792 /** \var sswf::TagSound::SOUND_ENDIAN_BIG
793  *
794  * \brief The data is in big endian
795  *
796  * Big endian means that the first byte is the most significant
797  * and the last byte is the least significant.
798  *
799  * PowerPC or newer MIPS based computers are in big endian.
800  *
801  * \code
802  * 	unsigned short file_samples[10];
803  *	char *ptr = (char *) file_samples;
804  *	unsigned short machine_samples[10];
805  *
806  *	machine_samples[0] = ptr[0] * 256 + ptr[1];
807  *	...
808  * \endcode
809  *
810  * <br>
811  * <br>
812  */
813 
814 
815 
816 /** \var sswf::TagSound::SOUND_ENDIAN_SAME
817  *
818  * \brief The data is in the same endian
819  *
820  * This is used whenever the data is known to be of the same endian
821  * as of the currently running machine. So if you system is a little
822  * endian machine, this tells the system to use little endian.
823  *
824  * \code
825  * 	unsigned short file_samples[10];
826  *	unsigned short machine_samples[10];
827  *
828  *	machine_samples[0] = file_samples[0];
829  *	...
830  * \endcode
831  *
832  * <br>
833  * <br>
834  */
835 
836 
837 
838 /** \var sswf::TagSound::SOUND_ENDIAN_UNKNOWN
839  *
840  * \brief The data endianess is not known
841  *
842  * At this time this value cannot be used. It is not expected that
843  * it will be possible to use this value since in all cases we must
844  * know the endianess of the samples before to be able to use them.
845  *
846  * <br>
847  * <br>
848  */
849 
850 
851 
852 /** \var sswf::TagSound::SOUND_ENDIAN_DONTUSE
853  *
854  * \brief The data is defined on 8 bits
855  *
856  * For data defined on 8 bits, the endian is not defined and thus
857  * it can be marked as "don't use".
858  *
859  * <br>
860  * <br>
861  */
862 
863 
864 
865 
866 
867 
868 #define	SNDINFMT(width, endian)		((width)|((endian)&7))
869 
870 /** \brief The few valid sound rates supported by Flash
871  *
872  * Sound effects in Flash only support these rates.
873  *
874  * Using an encoding like MP3 can be used to specify different rates
875  * in different packets. This is properly supported by newer Flash
876  * versions (version 7+)
877  *
878  * If possible, you should use one of these rates whenever you call
879  * the SetData() function.
880  *
881  * \sa sswf::TagSound::SetData()
882  */
883 const int TagSound::g_sound_rates[4] = { 5512, 11025, 22050, 44100 };
884 
885 
886 /// used by the MP3 loader
887 const int TagSound::g_bitrates[2][16] =
888 {
889 	{ -1, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 },
890 	{ -1, 8,  16, 24, 32, 40, 48, 56,  64,  80,  96, 112, 128, 144, 160, -1 }
891 };
892 
893 
894 /// used by the MP3 loader
895 const int TagSound::g_frequencies[4][4] =
896 {
897 	{ 11025, -1, -1, -1 },
898 	{    -1, -1, -1, -1 },
899 	{ 22050, -1, -1, -1 },
900 	{ 44100, -1, -1, -1 }
901 };
902 
903 
904 /** \brief Initialize a sound tag.
905  *
906  * This constructor initializes the sound as empty.
907  *
908  * \param[in] parent The TagHeader where this sound is added
909  */
TagSound(TagBase * parent)910 TagSound::TagSound(TagBase *parent)
911 	: TagBaseID("sound", parent)
912 {
913 	// the output compression format
914 	f_format = SOUND_FORMAT_RAW;
915 
916 	// the following are all set at the time the SetData() function
917 	// is called -- it is done that way so the coherency of the
918 	// data is preserved (changing from stereo to mono would require
919 	// changing the data!)
920 	f_stereo = false;
921 	f_rate = 0;
922 	f_width = 0;
923 	f_samples = 0;
924 	f_data_size = 0;
925 	f_data_maxsize = 0;
926 	f_data = 0;
927 	f_latency_seek = 0;
928 }
929 
930 
931 /** \brief Returns the type of this tag: Define with an ID.
932  *
933  * The TagSound is a definition tag with an identifier
934  *
935  * \returns SWF_TYPE_DEFINE | SWF_TYPE_HAS_ID
936  */
TypeFlags(void) const937 TagBase::swf_type_t TagSound::TypeFlags(void) const
938 {
939 	// TODO: with streaming sound effects, the object may have references
940 	//	 though it will be to itself... thus we should be fine.
941 	return SWF_TYPE_DEFINE | SWF_TYPE_HAS_ID;
942 }
943 
944 
945 
946 
947 /** \brief Set the name of a sound file.
948  *
949  * This function takes the name of a file representing a sound
950  * effect. The file is loaded on the spot and its content is
951  * kept in memory.
952  *
953  * This function calls the LoadWaveFile() with a handle to the
954  * file it just opened. If that function fails to read the file,
955  * then this function tries again by calling the LoadMP3File().
956  *
957  * \param[in] filename The name of the file to load
958  *
959  * \return ErrorManager::ERROR_CODE_NONE when no error occured,
960  *	some other ErrorManager::error_code_t on an error
961  *
962  * \sa sswf::TagSound::LoadWaveFile(FILE *f)
963  * \sa sswf::TagSound::LoadMP3File(FILE *f)
964  */
SetFilename(const char * filename)965 ErrorManager::error_code_t TagSound::SetFilename(const char *filename)
966 {
967 	int	ec;
968 	FILE	*f;
969 
970 	f = fopen(filename, "rb");
971 	if(f == NULL) {
972 		return OnError(ErrorManager::ERROR_CODE_IO, "cannot open sound file \"%s\" for reading.", filename);
973 	}
974 
975 	ec = LoadWaveFile(f);
976 	if(ec != 0) {
977 		rewind(f);
978 		ec = LoadMP3File(f);
979 	}
980 
981 	fclose(f);
982 
983 	if(ec != 0) {
984 		return OnError(ErrorManager::ERROR_CODE_IO, "cannot open sound file \"%s\" for reading.", filename);
985 	}
986 
987 	return ErrorManager::ERROR_CODE_NONE;
988 }
989 
990 
991 /** \brief Load a RIFF or WAVE sound file.
992  *
993  * This function is called with a file descriptor to read a file which is
994  * expected to be a RIFF or WAVE file. If the file cannot be read properly,
995  * the function returns with an error (-1).
996  *
997  * \param[in] f The file descriptor
998  *
999  * \return 0 when the function succeeds in reading the entire file; -1 otherwise
1000  */
LoadWaveFile(FILE * f)1001 int TagSound::LoadWaveFile(FILE *f)
1002 {
1003 	unsigned char	header[12];
1004 	sound_wave_t	fmt;
1005 	unsigned long	sz, data_size;
1006 	char		*data;
1007 	int		cnt;
1008 
1009 	if(fread(header, 12, 1, f) != 1) {
1010 		return -1;
1011 	}
1012 
1013 	if(header[0] != 'R' || header[1] != 'I' || header[ 2] != 'F' || header [ 3] != 'F'
1014 	|| header[8] != 'W' || header[9] != 'A' || header[10] != 'V' || header [11] != 'E') {
1015 		return -1;
1016 	}
1017 
1018 	// size is in header[4..7] -- we don't really need it do we?
1019 
1020 	// we go through the list of chunks until we got the fmt
1021 	// and data chunks
1022 	data = 0;
1023 	data_size = 0;	// if data is defined, this is too -- avoid warnings
1024 	cnt = 0;
1025 	while(cnt != 3) {
1026 		// this read will fail if we reach the end of the file
1027 		// before we've got the fmt and data chunks
1028 		if(fread(header, 8, 1, f) != 1) {
1029 			MemFree(data);
1030 			return -1;
1031 		}
1032 		if(header[0] == 'f' && header[1] == 'm' && header[2] == 't' && header[3] == ' ') {
1033 			/* we found the format info, read it! */
1034 			if((cnt & 1) != 0) {
1035 				// Ooooops! more than one fmt chunk?!?
1036 				MemFree(data);
1037 				return -1;
1038 			}
1039 			sz = header[4] + (header[5] << 8)
1040 					+ (header[6] << 16) + (header[7] << 24);
1041 			if(sz != sizeof(fmt)) {
1042 				// incompatible/unknown format chunk size
1043 				MemFree(data);
1044 				return -1;
1045 			}
1046 			if(fread(&fmt, sizeof(fmt), 1, f) != 1) {
1047 				// can't read format info
1048 				MemFree(data);
1049 				return -1;
1050 			}
1051 			// on big endian systems it is necessary to swap values here
1052 #if BYTE_ORDER == BIG_ENDIAN
1053 			fmt.format   = swap_short(fmt.format);
1054 			fmt.channels = swap_short(fmt.channels);
1055 			fmt.rate     = swap_int(fmt.rate);
1056 			fmt.width    = swap_short(fmt.width);
1057 			// what isn't swapped we don't use
1058 			//fmt.align  = swap_short(fmt.align);
1059 			//fmt.average_rate = swap_int(fmt.average_rate);
1060 #endif
1061 			// quickly check to see if we understand this info
1062 			if(fmt.format != 1	// only PCM files understood at this time!
1063 			|| (fmt.channels != 1 && fmt.channels != 2)
1064 			|| (fmt.width != 8 && fmt.width != 16)) {
1065 				MemFree(data);
1066 				return -1;
1067 			}
1068 			cnt |= 1;
1069 		}
1070 		else if(header[0] == 'd' && header[1] == 'a' && header[2] == 't' && header[3] == 'a') {
1071 			if((cnt & 2) != 0) {
1072 				// Ooooops! more than one data chunk?!?
1073 				MemFree(data);
1074 				return -1;
1075 			}
1076 			data_size = header[4] + (header[5] << 8)
1077 					+ (header[6] << 16) + (header[7] << 24);
1078 			data = (char *) MemAlloc(data_size, "TagSound::SetFilename(): temporary data buffer");
1079 			if(fread(data, data_size, 1, f) != 1) {
1080 				// can't read data samples
1081 				MemFree(data);
1082 				return -1;
1083 			}
1084 			cnt |= 2;
1085 		}
1086 	}
1087 
1088 	// got the format info and (uncompressed) data now
1089 	// note that 8 bits data is unsigned whereas 16 bits
1090 	// is signed!!! data is always in little endian which
1091 	// thus need to be swapped on big endian computers
1092 	return SetData(
1093 		data,
1094 		data_size,
1095 		SOUND_ENDIAN_LITTLE,
1096 		fmt.width == 8 ? 8 : -16,
1097 		fmt.rate,
1098 		fmt.channels == 2);
1099 }
1100 
1101 
1102 
1103 /** \brief Load an MP3 sound file.
1104  *
1105  * This function is called with a file descriptor to read a file which is
1106  * expected to be an MP3 file. If the file cannot be read properly,
1107  * the function returns with an error (-1).
1108  *
1109  * \param[in] f The file descriptor
1110  *
1111  * \return 0 when the function succeeds in reading the entire file; -1 otherwise
1112  */
LoadMP3File(FILE * f)1113 int TagSound::LoadMP3File(FILE *f)
1114 {
1115 	unsigned char	header[4];
1116 	int		ec, frame_size;
1117 
1118 	// TODO: we certainly should check whether
1119 	//	 this looks like an MP3 file...
1120 
1121 	// That's an MP3 (hmmm)
1122 	f_format = SOUND_FORMAT_MP3;
1123 
1124 	// Not too sure about this one at this time we kind of ignore
1125 	// this parameter...
1126 	//f_latency_seek = 0;
1127 
1128 	// MP3s are always 16 bits
1129 	f_width = 16;
1130 
1131 	// Restart from the start each time a new file is loaded
1132 	f_data_size = 0;
1133 	f_samples = 0;
1134 
1135 	// save the total size of the buffer at this time
1136 	//for(int cnt = 0; cnt  < 50; cnt++) {
1137 	for(;;) {
1138 		// get the size of frame
1139 		ec = CheckMP3Header(f, header, frame_size);
1140 		if(ec != 0) {
1141 			break;
1142 		}
1143 
1144 		// now that we have the size, make sure the data
1145 		// buffer is large enough
1146 		if(f_data_size + frame_size > f_data_maxsize) {
1147 			// large blocks will speed things up for large MP3 files
1148 			f_data_maxsize = (f_data_size + frame_size + 1024 * 1024 - 1) & -1024 * 1024;
1149 			f_data = (unsigned char *) MemRealloc(f_data, f_data_maxsize, "TagSound::LoadMP3File() -- frame buffer");
1150 		}
1151 
1152 		// copy the header
1153 		f_data[f_data_size + 0] = header[0];
1154 		f_data[f_data_size + 1] = header[1];
1155 		f_data[f_data_size + 2] = header[2];
1156 		f_data[f_data_size + 3] = header[3];
1157 
1158 		// finally read the frame in our buffer
1159 		if(fread(f_data + f_data_size + 4, 1, frame_size - 4, f) != (size_t) (frame_size - 4)) {
1160 			return -1;
1161 		}
1162 
1163 		// move to the next frame
1164 		f_data_size += frame_size;
1165 	}
1166 
1167 	// the value 2 represents EOF
1168 	return ec == 2 ? 0 : ec;
1169 }
1170 
1171 
1172 /** \brief Internal function to test the validity of an MP3 header
1173  *
1174  * This function checks the validity of an MP3 header.
1175  *
1176  * \param[in] f The file descriptor of the MP3 file to check
1177  * \param[in] header A pointer to the header buffer
1178  * \param[out] frame_size Set to the frame size
1179  *
1180  * \return 0 when no error occurs; -1 on errors
1181  */
CheckMP3Header(FILE * f,unsigned char * header,int & frame_size)1182 int TagSound::CheckMP3Header(FILE *f, unsigned char *header, int& frame_size)
1183 {
1184 	int	ec, mode;
1185 	int	bitrate, frequency;
1186 
1187 	// Read the first or next header
1188 	// (we always try to re-sync.)
1189 	ec = ReadMP3Header(f, header);
1190 	if(ec != 0) {
1191 		return ec;
1192 	}
1193 
1194         // Only layer 3 files are valid for the flash player
1195         if(((header[1] >> 1) & 3) != 1) {
1196 		return -1;
1197 	}
1198 
1199 	mode = (header[1] >> 3) & 3;
1200 
1201 	// Get bitrate from bitrates array -- depends on mode as well
1202 	bitrate = g_bitrates[mode == 3 ? 0 : 1][(header[2] >> 4) & 15];
1203 
1204 	// Get frequency -- also depends on mode
1205 	frequency = g_frequencies[mode][(header[2] >> 2) & 3];
1206 
1207 	// make sure these are valid
1208 	if(bitrate == -1 || frequency == -1) {
1209 		return -1;
1210 	}
1211 
1212 	// WARNING: not too sure whether the frequence and stereo
1213 	// information should reflect the first or last MP3 frame
1214 	// at this time it's the last (but I would guess it won't
1215 	// change very much in a single MP3?)
1216 	switch(frequency) {
1217 	//case  5512: f_rate = 0; break; -- this is not supported in MP3
1218 	case 11025: f_rate = 1; break;
1219 	case 22050: f_rate = 2; break;
1220 	case 44100: f_rate = 3; break;
1221 
1222 	// we can't change the MP3 rate without decompressing
1223 	// and recompressing which we don't currently support
1224 	// [also the table only gives us the three valid values
1225 	// anyway...]
1226 	default:
1227 		return -1;
1228 
1229 	}
1230 
1231 	// Channel mode
1232 	f_stereo = ((header[3] >> 6) & 3) != 3;
1233 
1234 	// Increment the samples counter
1235 	f_samples += mode == 3 ? 1152 : 576; // V2 and V1 sample counts
1236 
1237 	// Calculate the frame size (including the pad)
1238 	frame_size = (mode == 3 ? 144 : 72) * bitrate * 1000 / frequency
1239 			+ ((header[2] >> 1) & 1);
1240 
1241 	return 0;
1242 }
1243 
1244 
1245 /** \brief Internal function used to read an MP3 header
1246  *
1247  * This function reads one MP3 header.
1248  *
1249  * \note
1250  * If we can't find the next Sync. then we tell the caller that we found the
1251  * end of the file.
1252  *
1253  * \todo
1254  * These MP3 functions badly need to handle a large buffer instead of reading the
1255  * file byte per byte!
1256  *
1257  * \return 0 when no error occured; 2 when the end of the file is reached
1258  * 	and -1 when an error occurs
1259  */
ReadMP3Header(FILE * f,unsigned char * header)1260 int TagSound::ReadMP3Header(FILE *f, unsigned char *header)
1261 {
1262 	int	r;
1263 
1264 	// TODO: we may want to load the entire file at once
1265 	//	 so it is much faster than this -- imagine that
1266 	//	 we read a 2Mb file 1 byte at a time...
1267 
1268 	// sync to first or next frame
1269 	do {
1270 		r = fread(header, 1, 1, f);
1271 		if(r != 1) {
1272 			goto err;
1273 		}
1274 	} while(header[0] != 255);
1275 
1276 	do {
1277 		r = fread(header + 1, 1, 1, f);
1278 		if(r != 1) {
1279 			goto err;
1280 		}
1281 	} while((header[1] & 0xE0) != 0xE0);
1282 
1283 	r = fread(header + 2, 1, 2, f);
1284 	if(r == 2) {
1285 		return 0;
1286 	}
1287 err:
1288 	return r >= 0 ? 2 : -1;
1289 }
1290 
1291 
1292 /** \brief Change the format of the tag
1293  *
1294  * This function changes the format of the samples.
1295  *
1296  * \note
1297  * If you loaded an MP3 file, then the format cannot be changed.
1298  * This may change in a future version of the library.
1299  *
1300  * \param[in] format The new format.
1301  */
SetFormat(sound_format_t format)1302 void TagSound::SetFormat(sound_format_t format)
1303 {
1304 	// SetFormat() doesn't work when it's already MP3...
1305 	// [this is because we don't support the compression
1306 	// we only support loading an existing MP3 and saving
1307 	// it as is...]
1308 	if(f_format == SOUND_FORMAT_MP3) {
1309 		if(format != SOUND_FORMAT_MP3) {
1310 			OnError(ErrorManager::ERROR_CODE_FORMAT_LOCKED, "cannot change sound format when it is set to MP3.");
1311 		}
1312 		return;
1313 	}
1314 
1315 	f_format = format;
1316 }
1317 
1318 
1319 /** \brief Change the format of the tag
1320  *
1321  * This function reads one sample from a buffer expected to be of format
1322  * in_fmt and adjusts it as required.
1323  *
1324  * The function is used to resample input samples to samples valid
1325  * for the specified mode (rate, format, mono or stereo, etc.)
1326  *
1327  * \param[in] data The buffer to read from
1328  * \param[in] adjust The adjustment to make to the input value unsigned
1329  * \param[in] in_fmt The format of the input data
1330  *
1331  * \return The adjusted sample
1332  */
ReadSample(const unsigned char * data,unsigned short adjust,int in_fmt)1333 short TagSound::ReadSample(const unsigned char *data, unsigned short adjust, int in_fmt)
1334 {
1335 	switch(in_fmt) {
1336 	case SNDINFMT(8, SOUND_ENDIAN_LITTLE):
1337 	case SNDINFMT(8, SOUND_ENDIAN_BIG):
1338 	case SNDINFMT(8, SOUND_ENDIAN_SAME):
1339 	case SNDINFMT(8, SOUND_ENDIAN_DONTUSE):
1340 		// 8 bits are returned on 8 bits.
1341 		return (signed char) (data[0] + adjust);
1342 
1343 	case SNDINFMT(16, SOUND_ENDIAN_LITTLE):
1344 #if BYTE_ORDER == LITTLE_ENDIAN
1345 	case SNDINFMT(16, SOUND_ENDIAN_SAME):
1346 #endif
1347 		return (data[0] + data[1] * 256) + adjust;
1348 
1349 	case SNDINFMT(16, SOUND_ENDIAN_BIG):
1350 #if BYTE_ORDER == BIG_ENDIAN
1351 	case SNDINFMT(16, SOUND_ENDIAN_SAME):
1352 #endif
1353 		return (data[1] + data[0] * 256) + adjust;
1354 
1355 	case SNDINFMT(24, SOUND_ENDIAN_LITTLE):
1356 #if BYTE_ORDER == LITTLE_ENDIAN
1357 	case SNDINFMT(24, SOUND_ENDIAN_SAME):
1358 #endif
1359 		return (data[1] + data[2] * 256) + adjust;
1360 
1361 	case SNDINFMT(24, SOUND_ENDIAN_BIG):
1362 #if BYTE_ORDER == BIG_ENDIAN
1363 	case SNDINFMT(24, SOUND_ENDIAN_SAME):
1364 #endif
1365 		return (data[2] + data[1] * 256) + adjust;
1366 
1367 	case SNDINFMT(32, SOUND_ENDIAN_LITTLE):
1368 #if BYTE_ORDER == LITTLE_ENDIAN
1369 	case SNDINFMT(32, SOUND_ENDIAN_SAME):
1370 #endif
1371 		return (data[2] + data[3] * 256) + adjust;
1372 
1373 	case SNDINFMT(32, SOUND_ENDIAN_BIG):
1374 #if BYTE_ORDER == BIG_ENDIAN
1375 	case SNDINFMT(32, SOUND_ENDIAN_SAME):
1376 #endif
1377 		return (data[1] + data[0] * 256) + adjust;
1378 
1379 	}
1380 
1381 	/* the list of valid formats is checked sooner so we should
1382 	 * never reach this place!
1383 	 */
1384 
1385 	/*NOTREACHED*/
1386 	return 0;	/* avoid warnings */
1387 }
1388 
1389 
1390 
1391 /** \brief Function used to resample a set of samples from some format to another.
1392  *
1393  * This function is used whenever the SetData() or similar function is called with
1394  * data in a format which is not directly supported by Flash. Then it is resampled
1395  * to a way that works in Flash.
1396  *
1397  * This means duplicating or removing some of the input samples. When removing samples,
1398  * an average of a certain number of samples will be computed. This is not always the
1399  * proper method, but in most cases it works well.
1400  *
1401  * \param[in] snd The destination buffer
1402  * \param[in] out_bytes Size of one sample in the destination buffer (snd + out_bytes moves the pointer to the 2nd sample)
1403  * \param[in] src The source buffer
1404  * \param[in] size The size of the source buffer in bytes
1405  * \param[in] in_bytes Size of one sample in the source buffer (src + in_bytes moves the pointer to the 2nd sample)
1406  * \param[in] max The maximum number of samples to work on (i.e. size of the destination buffer)
1407  * \param[in] fix How much the samples need to be fixed to adjust for the rate difference
1408  * \param[in] adjust The adjustment to make the input value unsigned
1409  * \param[in] in_fmt The format of the samples in the input buffer
1410  *
1411  * \sa sswf::TagSound::ReadSample
1412  */
Resample(unsigned char * snd,unsigned int out_bytes,const unsigned char * src,size_t size,unsigned int in_bytes,size_t max,double fix,unsigned short adjust,int in_fmt)1413 void TagSound::Resample(unsigned char *snd, unsigned int out_bytes, const unsigned char *src, size_t size, unsigned int in_bytes, size_t max, double fix, unsigned short adjust, int in_fmt)
1414 {
1415 	size_t			idx;
1416 	double			p1, p2, start, end, s, inv_fix;
1417 	unsigned long		pi1, pi2, cnt;
1418 	short			sample;
1419 	const unsigned char	*in, *end_src;
1420 
1421 	out_bytes -= f_width == 16 ? 2 : 1;
1422 
1423 	inv_fix = 1.0 / fix;
1424 	end_src = src + size;
1425 	for(idx = 0; idx < max; idx++) {
1426 		// start position & end position
1427 		p1 = (double) idx * inv_fix;
1428 		p2 = p1 + inv_fix;
1429 
1430 		// check with integral values
1431 		pi1 = (unsigned long) floor(p1);
1432 		pi2 = (unsigned long) floor(p2);
1433 
1434 		if(pi1 == pi2) {
1435 			// in this case we only use part of one sample
1436 			start = p2 - p1;
1437 			end = 0.0;
1438 			cnt = 0;
1439 		}
1440 		else {
1441 			// in this case we need multiple samples
1442 			// we may also use part of two samples
1443 			// (when cnt == 0)
1444 			start = 1.0 - p1 + (double) pi1;
1445 			end = p2 - (double) pi2;
1446 			cnt = pi2 - pi1 - 1;
1447 		}
1448 
1449 		// skip to the 1st byte we want to read
1450 		in = src + pi1 * in_bytes;
1451 
1452 		// read the first sample (note that start can be 1.0)
1453 		assert(in < end_src, "TagSound::Resample(): source data pointer out of bounds");
1454 		s = (double) ReadSample(in, adjust, in_fmt) * start;
1455 		in += in_bytes;
1456 
1457 		// when multiple samples are required to compute the
1458 		// new sample, then read them all right here
1459 		while(cnt > 0) {
1460 			cnt--;
1461 			assert(in < end_src, "TagSound::Resample(): source data pointer out of bounds");
1462 			s += (double) ReadSample(in, adjust, in_fmt);
1463 			in += in_bytes;
1464 		}
1465 
1466 		// if we have something at the end (end can be 0.0 but never 1.0)
1467 		// and we still have samples in the input, use that bit too
1468 		if(end > 0.0 && in < end_src) {
1469 			s += (double) ReadSample(in, adjust, in_fmt) * end;
1470 		}
1471 
1472 		// note that there can't be an overflow
1473 		// or I'm really bad at math! so the
1474 		// following works without having to test
1475 		// for overflows
1476 		sample = (short) rint(s * fix);
1477 
1478 		*snd++ = (unsigned char) sample;
1479 		if(f_width == 16) {
1480 			*snd++ = (unsigned char) (sample >> 8);
1481 		}
1482 
1483 		// in stereo the following skips the other channel too
1484 		snd += out_bytes;
1485 	}
1486 }
1487 
1488 
1489 /** \brief Returns the number of samples in that TagSound
1490  *
1491  * This function returns the current number of samples defined
1492  * in this TagSound.
1493  *
1494  * \return The number of samples or zero when none
1495  */
GetSamplesCount(void) const1496 size_t TagSound::GetSamplesCount(void) const
1497 {
1498 	return f_samples;
1499 }
1500 
1501 
1502 /** \brief Set sample data in a TagSound object.
1503  *
1504  * This function sets the specified user defined data in the TagSound
1505  * object.
1506  *
1507  * The data is expected to be valid sound samples.
1508  *
1509  * The source samples must be mono or stereo, on 8, 16, 24 or 32 bits,
1510  * at a reasonable rate (1024 to 88000), in little or big endian.
1511  *
1512  * If the input data has samples which are signed (i.e. -128 to +127
1513  * or -32768 to +32767,) then the width must be passed negative (i.e.
1514  * -8, -16, -24 or -32). Positive values indicate that the input samples
1515  * are unsigned (i.e. 0 to 255 or 0 to 65535.)
1516  *
1517  * Flash understands only a very limited set of rates:
1518  *
1519  *	\li 5512
1520  *	\li 11025
1521  *	\li 22050
1522  *	\li 44100
1523  *
1524  * This function understands any other rate, yet the sample data will be
1525  * resampled when another rate is specified.
1526  *
1527  * Note that Flash only understands 8 or 16 bits data. The low bits of 24
1528  * and 32 bits samples are dropped.
1529  *
1530  * Stereo samples are expected to be interleaved with the left side sample
1531  * first.
1532  *
1533  * \param[in] data The source data samples
1534  * \param[in] size The number of bytes in the source buffer (should be a proper multiple)
1535  * \param[in] endian One of the sound endian (little, big, same or unused)
1536  * \param[in] width 8, 16, 24 or 32; or negative to indicate signed data
1537  * \param[in] rate Any rate between 1024 and 88000 inclusive
1538  * \param[in] stereo Whether mono (false) or stereo (true) samples are passed
1539  *
1540  * \return zero when no error occured, -1 when something happens
1541  */
SetData(const void * data,size_t size,sound_endian_t endian,int width,unsigned int rate,bool stereo)1542 int TagSound::SetData(const void *data, size_t size, sound_endian_t endian, int width, unsigned int rate, bool stereo)
1543 {
1544 	unsigned int		in_bytes, out_bytes, good_rate, in_fmt;
1545 	unsigned short		sample, adjust;
1546 	unsigned char		*snd;
1547 	size_t			in_samples, in_count, cnt, out_samples;
1548 	double			fix;
1549 	bool			signed_data;
1550 
1551 	// SetData() doesn't work yet for MP3
1552 	if(f_format == SOUND_FORMAT_MP3) {
1553 		return -1;
1554 	}
1555 
1556 	if((signed_data = width < 0)) {
1557 		width = -width;
1558 	}
1559 
1560 	// in release mode, these are checked below and the
1561 	// function will return 1.
1562 	assert(width == 8 || width == 16 || width == 24 || width == 32, "TagSound::SetData(): the width of a sound must be 8, 16, 24 or 32, the value %d can't be used", width);
1563 	assert(rate >= 1024 && rate <= 88000, "TagSound::SetData(): the samples rate must be between 1024 and 88000, the value %d is being rejected", rate);
1564 	assert(endian >= 0 && endian < SOUND_ENDIAN_UNKNOWN, "TagSound::SetData(): unknown endianess: %d", endian);
1565 
1566 	/* first we compute what we need (i.e. the size of the buffer we will keep) */
1567 	switch(width) {		// bytes per samples
1568 	case  8: in_bytes = 1; out_bytes = 1; f_width =  8; break;
1569 	case 16: in_bytes = 2; out_bytes = 2; f_width = 16; break;
1570 	case 24:
1571 	case 32: in_bytes = 4; out_bytes = 2; f_width = 16; break;
1572 	default: return -1;
1573 	}
1574 
1575 	/* compute the number of samples in the input buffer */
1576 	in_count = in_samples = size / in_bytes;
1577 
1578 	if((f_stereo = stereo)) {
1579 		  in_bytes *= 2;
1580 		 out_bytes *= 2;
1581 		in_samples /= 2;
1582 	}
1583 
1584 	// assert the # of samples, not the size since in_samples could be
1585 	// zero after the division of size by in_bytes
1586 	assert(data != 0 && in_samples > 0, "TagSound::SetData(): a sound data buffer can't be empty or a null pointer");
1587 	if(data == 0 || in_samples == 0) {
1588 		return -1;
1589 	}
1590 
1591 	/* compute a correct rate if not already so */
1592 	switch(rate) {
1593 	case  5512: f_rate = 0; break;
1594 	case 11025: f_rate = 1; break;
1595 	case 22050: f_rate = 2; break;
1596 	case 44100: f_rate = 3; break;
1597 	default:
1598 		if(rate < 1024) {
1599 			return -1;
1600 		}
1601 		if(rate < 6063) {
1602 			f_rate = 0;
1603 		}
1604 		else if(rate < 12127) {
1605 			f_rate = 1;
1606 		}
1607 		else if(rate < 24255) {
1608 			f_rate = 2;
1609 		}
1610 		else if(rate > 88000) {
1611 			return -1;
1612 		}
1613 		else {
1614 			f_rate = 3;
1615 		}
1616 	}
1617 	good_rate = g_sound_rates[f_rate];
1618 
1619 	/* if the rate is the same, then we can compute the output buffer as is */
1620 	if(good_rate == rate) {
1621 		/* use input buffer as is (beside endianess) */
1622 		out_samples = in_samples;
1623 		fix = 0.0;		// unused in this case, avoid warnings
1624 	}
1625 	else {
1626 		/* oops! user had a strange input file? got to fix the samples */
1627 		fix = (double) good_rate / (double) rate;
1628 		out_samples = (size_t) ceil((double) in_samples * fix);
1629 	}
1630 
1631 	in_fmt = SNDINFMT(width, endian);
1632 
1633 	switch(in_fmt) {
1634 	case SNDINFMT(8, SOUND_ENDIAN_LITTLE):
1635 	case SNDINFMT(8, SOUND_ENDIAN_BIG):
1636 	case SNDINFMT(8, SOUND_ENDIAN_SAME):
1637 	case SNDINFMT(8, SOUND_ENDIAN_DONTUSE):
1638 		adjust = signed_data ? 0 : -128;
1639 		break;
1640 
1641 	case SNDINFMT(16, SOUND_ENDIAN_LITTLE):
1642 	case SNDINFMT(16, SOUND_ENDIAN_BIG):
1643 	case SNDINFMT(16, SOUND_ENDIAN_SAME):
1644 	case SNDINFMT(24, SOUND_ENDIAN_LITTLE):
1645 	case SNDINFMT(24, SOUND_ENDIAN_BIG):
1646 	case SNDINFMT(24, SOUND_ENDIAN_SAME):
1647 	case SNDINFMT(32, SOUND_ENDIAN_LITTLE):
1648 	case SNDINFMT(32, SOUND_ENDIAN_BIG):
1649 	case SNDINFMT(32, SOUND_ENDIAN_SAME):
1650 		adjust = signed_data ? 0 : -32768;
1651 		break;
1652 
1653 	default:
1654 		return -1;
1655 
1656 	}
1657 
1658 	/* the f_data buffer size can now be computed */
1659 	MemFree(f_data);
1660 	f_samples = 0;
1661 	f_data = (unsigned char *) MemAlloc(out_samples * out_bytes, "TagSound::SetData() -- array of samples");
1662 
1663 	/* if we have the same rate, do it quick! */
1664 	snd = f_data;
1665 	if(good_rate == rate) {
1666 		cnt = in_count;
1667 		if(stereo) {
1668 			// we do all at once, so we need to have the proper
1669 			// number of bytes not taking the stereo in account
1670 			in_bytes /= 2;
1671 		}
1672 		do {
1673 			// read one sample
1674 			sample = ReadSample((const unsigned char *) data, adjust, in_fmt);
1675 			data = (char *) data + in_bytes;
1676 			// save in our buffer in little endian and increase
1677 			// the snd pointer accordingly
1678 			*snd++ = (unsigned char) sample;
1679 			if(f_width == 16) {
1680 				*snd++ = (unsigned char) (sample >> 8);
1681 			}
1682 			cnt--;
1683 		} while(cnt > 0);
1684 	}
1685 	else if(stereo) {
1686 		// resample stereo sound (resample left then right track)
1687 		Resample(snd, out_bytes, (const unsigned char *) data, size, in_bytes, out_samples, fix, adjust, in_fmt);
1688 		Resample(snd + out_bytes / 2, out_bytes, (const unsigned char *) data + in_bytes / 2, size, in_bytes, out_samples, fix, adjust, in_fmt);
1689 	}
1690 	else {
1691 		// resample non-stereo sound (one call to the loop is enough)
1692 		Resample(snd, out_bytes, (const unsigned char *) data, size, in_bytes, out_samples, fix, adjust, in_fmt);
1693 	}
1694 
1695 	f_samples = out_samples;
1696 
1697 	return 0;
1698 }
1699 
1700 
1701 
1702 /** \brief Change the current samples to mono.
1703  *
1704  * Force the samples to be mono. The average of the left and right samples
1705  * is computed.
1706  *
1707  * \note
1708  * At this time, it is not possible to transform an MP3 set of samples to
1709  * mono. This would require a decompression and recompression which is not
1710  * yet available.
1711  */
SetMono(void)1712 void TagSound::SetMono(void)
1713 {
1714 	unsigned char	*in, *out;
1715 	size_t		idx;
1716 	unsigned short	sample;
1717 
1718 	// SetMone() doesn't work yet for MP3
1719 	if(f_format == SOUND_FORMAT_MP3) {
1720 		OnError(ErrorManager::ERROR_CODE_FORMAT_LOCKED, "cannot change sound format when it is set to MP3.");
1721 		return;
1722 	}
1723 
1724 	if(f_stereo && f_samples > 0) {
1725 		// the user is asking us to remove the L+R and generate a Mono
1726 		// track instead, so what we do is Mono = (L+R)/2
1727 		in = out = f_data;
1728 		if(f_width == 8) {
1729 			for(idx = 0; idx < f_samples; idx++, in += 2, out++) {
1730 				out[0] = (in[0] + in[1]) / 2;
1731 			}
1732 		}
1733 		else {
1734 			for(idx = 0; idx < f_samples; idx++, in += 4, out += 2) {
1735 				sample = (in[0] + in[2] + ((in[1] + in[3]) << 8)) / 2;
1736 				out[0] = (unsigned char) sample;
1737 				out[1] = (unsigned char) (sample >> 8);
1738 			}
1739 		}
1740 		f_stereo = false;
1741 	}
1742 }
1743 
1744 
1745 
1746 /** \brief Force the samples to 8 bits.
1747  *
1748  * This function transforms the current samples from 16 to 8 bits. If
1749  * the samples already are set at 8 bits, then nothing happens.
1750  *
1751  * This function does not try to adjust the sound, it simply drops the
1752  * lower 8 bits of each sample.
1753  *
1754  * \note
1755  * It is not possible to transform an MP3 set of samples to 8 bits.
1756  */
Set8Bits(void)1757 void TagSound::Set8Bits(void)
1758 {
1759 	unsigned char	*in, *out;
1760 	size_t		idx;
1761 
1762 	// Set8Bits() doesn't work yet for MP3
1763 	if(f_format == SOUND_FORMAT_MP3) {
1764 		OnError(ErrorManager::ERROR_CODE_FORMAT_LOCKED, "cannot change sound format when it is set to MP3.");
1765 		return;
1766 	}
1767 
1768 	if(f_width == 16 && f_samples > 0) {
1769 		// the user is asking us to make the data 8 bits instead of 16
1770 		// this is really simple: we only keep the top 8 bits!
1771 		in = out = f_data;
1772 		if(f_stereo) {
1773 			for(idx = 0; idx < f_samples; idx++, in += 4, out += 2) {
1774 				out[0] = in[1];
1775 				out[1] = in[3];
1776 			}
1777 		}
1778 		else {
1779 			for(idx = 0; idx < f_samples; idx++, in += 2, out++) {
1780 				out[0] = in[1];
1781 			}
1782 		}
1783 		f_width = 8;
1784 	}
1785 }
1786 
1787 
1788 /** \brief Check that the sound can be saved the way it is.
1789  *
1790  * This function checks that the sound can properly be saved.
1791  *
1792  * This means that all the parameters such as the width,
1793  * format, stereo, etc. all are acceptable.
1794  *
1795  * \return ErrorManager::ERROR_CODE_NONE when the sound is valid;
1796  * 	some other ErrorManager::error_code_t otherwise
1797  */
PreSave(void)1798 ErrorManager::error_code_t TagSound::PreSave(void)
1799 {
1800 	// no effect with an undefined sound effect
1801 	if(f_samples <= 0) {
1802 		return ErrorManager::ERROR_CODE_NONE;
1803 	}
1804 
1805 	if(f_width == 8 && f_format != SOUND_FORMAT_RAW && f_format != SOUND_FORMAT_UNCOMPRESSED) {
1806 		// any compressed data must be 16 bits,
1807 		// we need a function to transform 8 bits to 16 bits
1808 		// (which may mean a decompression + re-compression...)
1809 		OnError(ErrorManager::ERROR_CODE_COMPRESSED_SOUND_8BITS, "cannot generate compressed data which is not 16 bits.");
1810 		return ErrorManager::ERROR_CODE_COMPRESSED_SOUND_8BITS;
1811 	}
1812 
1813 	switch(f_format) {
1814 	case SOUND_FORMAT_ADPCM:
1815 		// TODO: until this is supported, we return an error;
1816 		//	 the minimum version for ADPCM is 2
1817 		OnError(ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT, "ADPCM is not supported yet.");
1818 		return ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT;
1819 
1820 	case SOUND_FORMAT_RAW:
1821 		MinimumVersion(2);
1822 		break;
1823 
1824 	case SOUND_FORMAT_MP3:
1825 	case SOUND_FORMAT_UNCOMPRESSED:
1826 		MinimumVersion(4);
1827 		break;
1828 
1829 	case SOUND_FORMAT_NELLYMOSER:
1830 		MinimumVersion(6);
1831 		// TODO: until this is supported, we return an error
1832 		OnError(ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT, "NELLYMOSER is not supported yet.");
1833 		return ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT;
1834 
1835 	default:
1836 		OnError(ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT, "Unknown sound format not supported.");
1837 		return ErrorManager::ERROR_CODE_UNSUPPORTED_SOUND_FORMAT;
1838 
1839 	}
1840 
1841 	return ErrorManager::ERROR_CODE_NONE;
1842 }
1843 
1844 
1845 /** \brief Save the TagSound in the specified Data buffer
1846  *
1847  * This function saves the sound samples in the specified Data buffer.
1848  *
1849  * \param[in,out] data The data buffer where the tag is saved
1850  *
1851  * \return ErrorManager::ERROR_CODE_NONE when the save succeeds
1852  * 	and another ErrorManager::error_code_t otherwise
1853  */
Save(Data & data)1854 ErrorManager::error_code_t TagSound::Save(Data& data)
1855 {
1856 	Data		sub_data;
1857 	unsigned int	size;
1858 
1859 	// no effect with an undefined sound effect
1860 	if(f_samples <= 0) {
1861 		return ErrorManager::ERROR_CODE_NONE;
1862 	}
1863 
1864 	// TODO: the following doesn't support streaming sound...
1865 
1866 	SaveID(sub_data);
1867 
1868 	// info
1869 	sub_data.WriteBits(f_format, 4);
1870 	sub_data.WriteBits(f_rate, 2);
1871 	sub_data.WriteBits(f_width == 16 ? 1 : 0, 1);
1872 	sub_data.WriteBits(f_stereo, 1);
1873 
1874 	switch(f_format) {
1875 	case SOUND_FORMAT_RAW:			// though we don't check the processor, we save this in little endian!!!
1876 	case SOUND_FORMAT_UNCOMPRESSED:		// always little endian (V4.x)
1877 		// the size in bytes of the f_data buffer
1878 		size = f_samples;
1879 		if(f_stereo) {
1880 			size *= 2;
1881 		}
1882 		if(f_width == 16) {
1883 			size *= 2;
1884 		}
1885 		sub_data.PutLong(f_samples);
1886 		sub_data.Write(f_data, size);
1887 		break;
1888 
1889 	case SOUND_FORMAT_MP3:
1890 		sub_data.PutLong(f_samples);
1891 		sub_data.PutShort(f_latency_seek);
1892 		sub_data.Write(f_data, f_data_size);
1893 		break;
1894 
1895 	// TODO: add support for ADPCM & NellyMoser
1896 
1897 	default:
1898 		assert(0, "the f_format (%d) is accepted in PreSave() but not in Save()", f_format);
1899 		return OnError(ErrorManager::ERROR_CODE_INTERNAL_ERROR, "the f_format (%d) is accepted in PreSave() but not in Save()", f_format);
1900 
1901 	}
1902 
1903 	SaveTag(data, SWF_TAG_DEFINE_SOUND, sub_data.ByteSize());
1904 	data.Append(sub_data);
1905 
1906 	return ErrorManager::ERROR_CODE_NONE;
1907 }
1908 
1909 
1910 
1911 
1912 
1913 /* The following options fold the documentation; use 'zi' to turn on and off
1914  *
1915  * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
1916  */
1917