1 /*
2     Ming, an SWF output library
3     Copyright (C) 2002  Opaque Industries - http://www.opaque.net/
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <stdlib.h>
21 
22 #include "soundinstance.h"
23 #include "sound.h"
24 #include "block.h"
25 #include "method.h"
26 #include "character.h"
27 #include "libming.h"
28 
29 
30 typedef struct
31 {
32 	unsigned int mark44;
33 	unsigned short level0;
34 	unsigned short level1;
35 } envPoint;
36 
37 struct SWFSoundInstance_s
38 {
39 	struct SWFBlock_s block;
40 
41 	SWFSound sound;
42 	unsigned int inPoint;
43 	unsigned int outPoint;
44 	int numLoops;
45 	byte flags;
46 	byte numEnvPoints;
47 	envPoint *envPoints;
48 };
49 
writeSWFSoundInstanceToMethod(SWFBlock block,SWFByteOutputMethod method,void * data)50 void writeSWFSoundInstanceToMethod(SWFBlock block,
51 																	 SWFByteOutputMethod method, void *data)
52 {
53 	SWFSoundInstance sound;
54 	byte flags;
55 	int i;
56 
57 	// block may be null if we're calling from button.c:
58 
59 	if ( block == NULL )
60 	{
61 		method(0, data);
62 		method(0, data);
63 		method(0, data);
64 		return;
65 	}
66 
67 	sound = (SWFSoundInstance)block;
68 	flags = sound->flags;
69 
70 	if ( sound->sound )
71 		methodWriteUInt16(CHARACTERID(sound->sound), method, data);
72 	else
73 		methodWriteUInt16(0, method, data);	 /* 0 means NULL character */
74 
75 	method(flags, data);
76 
77 	if ( flags & SWF_SOUNDINFO_HASINPOINT )
78 		methodWriteUInt32(sound->inPoint, method, data);
79 
80 	if ( flags & SWF_SOUNDINFO_HASOUTPOINT )
81 		methodWriteUInt32(sound->outPoint, method, data);
82 
83 	if ( flags & SWF_SOUNDINFO_HASLOOPS )
84 		methodWriteUInt16(sound->numLoops, method, data);
85 
86 	if ( flags & SWF_SOUNDINFO_HASENVELOPE )
87 	{
88 		method(sound->numEnvPoints, data);
89 
90 		for ( i=0; i<sound->numEnvPoints; ++i )
91 		{
92 			methodWriteUInt32((sound->envPoints[i]).mark44, method, data);
93 			methodWriteUInt16((sound->envPoints[i]).level0, method, data);
94 			methodWriteUInt16((sound->envPoints[i]).level1, method, data);
95 		}
96 	}
97 }
98 
99 
completeSWFSoundInstance(SWFBlock block)100 int completeSWFSoundInstance(SWFBlock block)
101 {
102 	SWFSoundInstance sound;
103 	byte flags;
104 
105 	// block may be null if we're calling from button.c:
106 
107 	if ( block == NULL )
108 		return 3;
109 
110 	sound = (SWFSoundInstance)block;
111 	flags = sound->flags;
112 
113 	return 3 /* (sound id + flags) */ +
114 		((flags & SWF_SOUNDINFO_HASINPOINT) ? 4 : 0) +
115 		((flags & SWF_SOUNDINFO_HASOUTPOINT) ? 4 : 0) +
116 		((flags & SWF_SOUNDINFO_HASLOOPS) ? 2 : 0) +
117 		((flags & SWF_SOUNDINFO_HASENVELOPE) ? (1 + 8*sound->numEnvPoints) : 0);
118 }
119 
120 /*
121  * adds a SoundEnvelope to event sound
122  */
SWFSoundInstance_addEnvelope(SWFSoundInstance inst,unsigned int mark44,short left,short right)123 void SWFSoundInstance_addEnvelope(SWFSoundInstance inst,
124                                   unsigned int mark44 /* position in 44khz samples */,
125                                   short left /* volume left channel */,
126                                   short right /* volume right channel */)
127 {
128 	inst->flags |= SWF_SOUNDINFO_HASENVELOPE;
129 	inst->envPoints = (envPoint*) realloc(inst->envPoints,
130 		(inst->numEnvPoints + 1) * sizeof(envPoint));
131 	inst->envPoints[inst->numEnvPoints].mark44 = mark44;
132 	inst->envPoints[inst->numEnvPoints].level0 = left;
133 	inst->envPoints[inst->numEnvPoints].level1 = right;
134 	inst->numEnvPoints++;
135 }
136 
137 /*
138  * private constructor
139  * see SWFMove[Clip]_startSound()
140  */
newSWFSoundInstance(SWFSound sound)141 SWFSoundInstance newSWFSoundInstance(SWFSound sound)
142 {
143 	SWFSoundInstance instance = (SWFSoundInstance)malloc(sizeof(struct SWFSoundInstance_s));
144 	SWFBlock block = (SWFBlock)instance;
145 
146 	SWFBlockInit(block);
147 
148 	block->type = SWF_STARTSOUND;
149 
150 	block->writeBlock = writeSWFSoundInstanceToMethod;
151 	block->complete = completeSWFSoundInstance;
152 	/* block->dtor = destroySWFStartSoundBlock; */
153 
154 	instance->sound = sound;
155 	instance->inPoint = 0;
156 	instance->outPoint = 0;
157 	instance->numLoops = 0;
158 	instance->flags = 0;
159 	instance->numEnvPoints = 0;
160 	instance->envPoints = NULL;
161 
162 	return instance;
163 }
164 
165 /*
166  * destroys a SWFSounInstance object
167  */
168 void
destroySWFSoundInstance(SWFSoundInstance soundInstance)169 destroySWFSoundInstance(SWFSoundInstance soundInstance)
170 {
171 	destroySWFBlock((SWFBlock) soundInstance);
172 }
173 
174 
newSWFSoundInstance_stop(SWFSound sound)175 SWFSoundInstance newSWFSoundInstance_stop(SWFSound sound)
176 {
177 	SWFSoundInstance instance = newSWFSoundInstance(sound);
178 	instance->flags = SWF_SOUNDINFO_SYNCSTOPSOUND;
179 	return instance;
180 }
181 
newSWFSoundInstance_startNoMultiple(SWFSound sound)182 SWFSoundInstance newSWFSoundInstance_startNoMultiple(SWFSound sound)
183 {
184 	SWFSoundInstance instance = newSWFSoundInstance(sound);
185 	instance->flags = SWF_SOUNDINFO_SYNCNOMULTIPLE;
186 	return instance;
187 }
188 
189 /*
190  * don't start sound if already playing
191  */
SWFSoundInstance_setNoMultiple(SWFSoundInstance instance)192 void SWFSoundInstance_setNoMultiple(SWFSoundInstance instance)
193 {
194 	instance->flags |= SWF_SOUNDINFO_SYNCNOMULTIPLE;
195 }
196 
197 /*
198  * set loop start point
199  * Sets the loop start point counted in samples
200  */
SWFSoundInstance_setLoopInPoint(SWFSoundInstance instance,unsigned int point)201 void SWFSoundInstance_setLoopInPoint(SWFSoundInstance instance,
202                                      unsigned int point /* number of samples */)
203 {
204 	instance->flags |= SWF_SOUNDINFO_HASINPOINT;
205 	instance->inPoint = point;
206 }
207 
208 /*
209  * set loop stop point
210  * Sets the loop's last sample to play
211  */
SWFSoundInstance_setLoopOutPoint(SWFSoundInstance instance,unsigned int point)212 void SWFSoundInstance_setLoopOutPoint(SWFSoundInstance instance,
213                                       unsigned int point /* number of samples */)
214 {
215 	instance->flags |= SWF_SOUNDINFO_HASOUTPOINT;
216 	instance->outPoint = point;
217 }
218 
219 /*
220  * sets loop count
221  */
SWFSoundInstance_setLoopCount(SWFSoundInstance instance,int count)222 void SWFSoundInstance_setLoopCount(SWFSoundInstance instance, int count /* loop count */)
223 {
224 	instance->flags |= SWF_SOUNDINFO_HASLOOPS;
225 	instance->numLoops = count;
226 }
227 
228 /*
229  * Local variables:
230  * tab-width: 2
231  * c-basic-offset: 2
232  * End:
233  */
234