2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2008 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
26 #include "swfdec_sound.h"
27 #include "swfdec_audio_decoder.h"
28 #include "swfdec_audio_event.h"
29 #include "swfdec_audio_internal.h"
30 #include "swfdec_bits.h"
31 #include "swfdec_buffer.h"
32 #include "swfdec_button.h"
33 #include "swfdec_debug.h"
34 #include "swfdec_player_internal.h"
35 #include "swfdec_sound_provider.h"
36 #include "swfdec_sprite.h"
37 #include "swfdec_swf_decoder.h"
39 /*** SWFDEC_SOUND_PROVIDER ***/
42 swfdec_sound_sound_provider_start (SwfdecSoundProvider
*provider
,
43 SwfdecActor
*actor
, gsize samples_offset
, guint loops
)
45 SwfdecSound
*sound
= SWFDEC_SOUND (provider
);
48 audio
= swfdec_audio_event_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
)),
49 sound
, samples_offset
, loops
);
50 swfdec_audio_set_actor (audio
, actor
);
51 g_object_unref (audio
);
60 swfdec_sound_object_should_stop (SwfdecAudio
*audio
, gpointer datap
)
62 RemoveData
*data
= datap
;
63 SwfdecAudioEvent
*event
;
65 if (!SWFDEC_IS_AUDIO_EVENT (audio
))
67 event
= SWFDEC_AUDIO_EVENT (audio
);
68 if (event
->sound
!= data
->sound
)
70 return audio
->actor
== data
->actor
;
74 swfdec_sound_sound_provider_stop (SwfdecSoundProvider
*provider
, SwfdecActor
*actor
)
76 RemoveData data
= { actor
, SWFDEC_SOUND (provider
) };
78 swfdec_player_stop_sounds (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
)),
79 swfdec_sound_object_should_stop
, &data
);
82 static SwfdecSoundMatrix
*
83 swfdec_sound_sound_provider_get_matrix (SwfdecSoundProvider
*provider
)
89 swfdec_sound_sound_provider_init (SwfdecSoundProviderInterface
*iface
)
91 iface
->start
= swfdec_sound_sound_provider_start
;
92 iface
->stop
= swfdec_sound_sound_provider_stop
;
93 iface
->get_matrix
= swfdec_sound_sound_provider_get_matrix
;
96 /*** SWFDEC_SOUND ***/
98 G_DEFINE_TYPE_WITH_CODE (SwfdecSound
, swfdec_sound
, SWFDEC_TYPE_CHARACTER
,
99 G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_SOUND_PROVIDER
, swfdec_sound_sound_provider_init
))
102 swfdec_sound_dispose (GObject
*object
)
104 SwfdecSound
* sound
= SWFDEC_SOUND (object
);
107 swfdec_buffer_unref (sound
->decoded
);
109 swfdec_buffer_unref (sound
->encoded
);
111 G_OBJECT_CLASS (swfdec_sound_parent_class
)->dispose (object
);
115 swfdec_sound_class_init (SwfdecSoundClass
* g_class
)
117 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
119 object_class
->dispose
= swfdec_sound_dispose
;
123 swfdec_sound_init (SwfdecSound
* sound
)
129 tag_func_define_sound (SwfdecSwfDecoder
* s
, guint tag
)
131 SwfdecBits
*b
= &s
->b
;
136 id
= swfdec_bits_get_u16 (b
);
137 sound
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_SOUND
);
139 return SWFDEC_STATUS_OK
;
141 sound
->codec
= swfdec_bits_getbits (b
, 4);
142 SWFDEC_LOG (" codec: %u", sound
->codec
);
143 sound
->format
= swfdec_audio_format_parse (b
);
144 SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (sound
->format
));
145 n_samples
= swfdec_bits_get_u32 (b
);
146 sound
->n_samples
= n_samples
;
148 switch (sound
->codec
) {
150 if (swfdec_audio_format_is_16bit (sound
->format
))
151 SWFDEC_WARNING ("undefined endianness for s16 sound");
152 /* just assume LE and hope it works (FIXME: want a switch for this?) */
153 sound
->codec
= SWFDEC_AUDIO_CODEC_UNCOMPRESSED
;
156 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
159 sound
->skip
= swfdec_bits_get_u16 (b
);
160 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
165 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
168 SWFDEC_WARNING ("unknown codec %d", sound
->codec
);
170 sound
->n_samples
*= swfdec_audio_format_get_granularity (sound
->format
);
172 swfdec_decoder_use_audio_codec (SWFDEC_DECODER (s
), sound
->codec
, sound
->format
);
174 return SWFDEC_STATUS_OK
;
178 swfdec_sound_get_decoded (SwfdecSound
*sound
)
182 SwfdecBufferQueue
*queue
;
187 g_return_val_if_fail (SWFDEC_IS_SOUND (sound
), NULL
);
189 if (sound
->decoded
) {
190 return sound
->decoded
;
192 if (sound
->encoded
== NULL
)
195 decoder
= swfdec_audio_decoder_new (sound
->codec
, sound
->format
);
199 swfdec_audio_decoder_push (decoder
, sound
->encoded
);
200 swfdec_audio_decoder_push (decoder
, NULL
);
201 queue
= swfdec_buffer_queue_new ();
202 while ((tmp
= swfdec_audio_decoder_pull (decoder
))) {
203 swfdec_buffer_queue_push (queue
, tmp
);
205 g_object_unref (decoder
);
206 depth
= swfdec_buffer_queue_get_depth (queue
);
208 SWFDEC_ERROR ("decoding didn't produce any data, bailing");
211 tmp
= swfdec_buffer_queue_pull (queue
, depth
);
212 swfdec_buffer_queue_unref (queue
);
215 n_samples
= sound
->n_samples
;
217 SWFDEC_LOG ("after decoding, got %"G_GSIZE_FORMAT
" samples, should get %u and skip %u",
218 tmp
->length
/ sample_bytes
, n_samples
, sound
->skip
);
220 SwfdecBuffer
*tmp2
= swfdec_buffer_new_subbuffer (tmp
, sound
->skip
* sample_bytes
,
221 tmp
->length
- sound
->skip
* sample_bytes
);
222 swfdec_buffer_unref (tmp
);
225 if (tmp
->length
> n_samples
* sample_bytes
) {
226 SwfdecBuffer
*tmp2
= swfdec_buffer_new_subbuffer (tmp
, 0, n_samples
* sample_bytes
);
227 SWFDEC_DEBUG ("%u samples in %u bytes should be available, but %"G_GSIZE_FORMAT
" bytes are, cutting them off",
228 n_samples
, n_samples
* sample_bytes
, tmp
->length
);
229 swfdec_buffer_unref (tmp
);
231 } else if (tmp
->length
< n_samples
* sample_bytes
) {
232 /* we handle this case in swfdec_sound_render */
233 /* FIXME: this message is important when writing new codecs, so I made it a warning.
234 * It's probably not worth more than INFO for the usual case though */
235 SWFDEC_WARNING ("%u samples in %u bytes should be available, but only %"G_GSIZE_FORMAT
" bytes are",
236 n_samples
, n_samples
* sample_bytes
, tmp
->length
);
238 /* only assign here, the decoding code checks this variable */
239 sound
->decoded
= tmp
;
241 return sound
->decoded
;
245 swfdec_sound_chunk_free (SwfdecSoundChunk
*chunk
)
247 g_return_if_fail (chunk
!= NULL
);
249 g_free (chunk
->envelope
);
254 swfdec_sound_parse_chunk (SwfdecSwfDecoder
*s
, SwfdecBits
*b
, int id
)
262 SwfdecSoundChunk
*chunk
;
264 sound
= swfdec_swf_decoder_get_character (s
, id
);
265 if (!SWFDEC_IS_SOUND (sound
)) {
266 SWFDEC_ERROR ("given id %d does not reference a sound object", id
);
270 chunk
= g_new0 (SwfdecSoundChunk
, 1);
271 chunk
->sound
= sound
;
272 SWFDEC_DEBUG ("parsing sound chunk for sound %d", SWFDEC_CHARACTER (sound
)->id
);
274 swfdec_bits_getbits (b
, 2);
275 chunk
->stop
= swfdec_bits_getbits (b
, 1);
276 chunk
->no_restart
= swfdec_bits_getbits (b
, 1);
277 has_envelope
= swfdec_bits_getbits (b
, 1);
278 has_loops
= swfdec_bits_getbits (b
, 1);
279 has_out_point
= swfdec_bits_getbits (b
, 1);
280 has_in_point
= swfdec_bits_getbits (b
, 1);
282 chunk
->start_sample
= swfdec_bits_get_u32 (b
);
283 SWFDEC_LOG (" start_sample = %u", chunk
->start_sample
);
285 chunk
->start_sample
= 0;
288 chunk
->stop_sample
= swfdec_bits_get_u32 (b
);
289 if (chunk
->stop_sample
== 0) {
290 SWFDEC_FIXME ("stop sample == 0???");
292 SWFDEC_LOG (" stop_sample = %u", chunk
->stop_sample
);
293 if (chunk
->stop_sample
<= chunk
->start_sample
) {
294 SWFDEC_ERROR ("stopping before starting? (start sample %u, stop sample %u)",
295 chunk
->start_sample
, chunk
->stop_sample
);
296 chunk
->stop_sample
= 0;
299 chunk
->stop_sample
= 0;
302 chunk
->loop_count
= swfdec_bits_get_u16 (b
);
303 if (chunk
->loop_count
== 0) {
304 SWFDEC_ERROR ("loop_count 0 not allowed, setting to 1");
305 chunk
->loop_count
= 1;
307 SWFDEC_LOG (" loop_count = %u", chunk
->loop_count
);
309 chunk
->loop_count
= 1;
312 chunk
->n_envelopes
= swfdec_bits_get_u8 (b
);
313 chunk
->envelope
= g_new0 (SwfdecSoundEnvelope
, chunk
->n_envelopes
);
314 SWFDEC_LOG (" n_envelopes = %u", chunk
->n_envelopes
);
317 for (i
= 0; i
< chunk
->n_envelopes
&& swfdec_bits_left (b
); i
++) {
318 chunk
->envelope
[i
].offset
= swfdec_bits_get_u32 (b
);
319 if (i
> 0 && chunk
->envelope
[i
-1].offset
> chunk
->envelope
[i
].offset
) {
320 SWFDEC_ERROR ("unordered sound envelopes");
321 chunk
->envelope
[i
].offset
= chunk
->envelope
[i
-1].offset
;
324 for (j
= 0; j
< 2; j
++) {
325 chunk
->envelope
[i
].volume
[j
] = swfdec_bits_get_u16 (b
);
326 if (chunk
->envelope
[i
].volume
[j
] > 32768) {
327 SWFDEC_FIXME ("too big envelope volumes (%u > 32768) not handled correctly",
328 chunk
->envelope
[i
].volume
[j
]);
329 chunk
->envelope
[i
].volume
[j
] = 32768;
333 SWFDEC_LOG (" envelope = %u { %u, %u }", chunk
->envelope
[i
].offset
,
334 (guint
) chunk
->envelope
[i
].volume
[0], (guint
) chunk
->envelope
[i
].volume
[1]);
337 if (i
< chunk
->n_envelopes
)
338 SWFDEC_ERROR ("out of bits when reading sound envelopes");
344 tag_func_define_button_sound (SwfdecSwfDecoder
* s
, guint tag
)
348 SwfdecButton
*button
;
350 id
= swfdec_bits_get_u16 (&s
->b
);
351 button
= (SwfdecButton
*) swfdec_swf_decoder_get_character (s
, id
);
352 if (!SWFDEC_IS_BUTTON (button
)) {
353 SWFDEC_ERROR ("id %u is not a button", id
);
354 return SWFDEC_STATUS_OK
;
356 SWFDEC_LOG ("loading sound events for button %u", id
);
357 for (i
= 0; i
< 4; i
++) {
358 id
= swfdec_bits_get_u16 (&s
->b
);
360 SWFDEC_LOG ("loading sound %u for button event %u", id
, i
);
361 if (button
->sounds
[i
]) {
362 SWFDEC_ERROR ("need to delete previous sound for button %u's event %u",
363 SWFDEC_CHARACTER (button
)->id
, i
);
364 swfdec_sound_chunk_free (button
->sounds
[i
]);
366 button
->sounds
[i
] = swfdec_sound_parse_chunk (s
, &s
->b
, id
);
370 return SWFDEC_STATUS_OK
;
374 * swfdec_sound_buffer_get_n_samples:
375 * @buffer: data to examine
376 * @format: format the data in @buffer is in
378 * Determines the number of samples inside @buffer that would be available if
379 * it were to be rendered using the default Flash format, 44100Hz.
381 * Returns: Number of samples contained in @buffer when rendered
384 swfdec_sound_buffer_get_n_samples (const SwfdecBuffer
*buffer
, SwfdecAudioFormat format
)
386 g_return_val_if_fail (buffer
!= NULL
, 0);
387 g_return_val_if_fail (buffer
->length
% (2 * swfdec_audio_format_get_channels (format
)) == 0, 0);
389 return buffer
->length
/ (2 * swfdec_audio_format_get_channels (format
)) *
390 swfdec_audio_format_get_granularity (format
);
394 * swfdec_sound_render_buffer:
395 * @dest: target buffer to render to
396 * @source: source data to render
397 * @offset: offset in 44100Hz samples into @source
398 * @n_samples: number of samples to render into @dest. If more data would be
399 * rendered than is available in @source, 0 samples are used instead.
401 * Adds data from @source into @dest
404 swfdec_sound_buffer_render (gint16
*dest
, const SwfdecBuffer
*source
,
405 guint offset
, guint n_samples
)
407 g_return_if_fail (dest
!= NULL
);
408 g_return_if_fail (source
!= NULL
);
409 g_return_if_fail ((offset
+ n_samples
) * 4 <= source
->length
);
411 memcpy (dest
, source
->data
+ 4 * offset
, 4 * n_samples
);