2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 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_audio_internal.h"
27 #include "swfdec_sound.h"
28 #include "swfdec_bits.h"
29 #include "swfdec_buffer.h"
30 #include "swfdec_button.h"
31 #include "swfdec_debug.h"
32 #include "swfdec_sprite.h"
33 #include "swfdec_swf_decoder.h"
35 G_DEFINE_TYPE (SwfdecSound
, swfdec_sound
, SWFDEC_TYPE_CACHED
)
38 swfdec_sound_unload (SwfdecCached
*cached
)
40 SwfdecSound
* sound
= SWFDEC_SOUND (cached
);
43 swfdec_buffer_unref (sound
->decoded
);
44 sound
->decoded
= NULL
;
49 swfdec_sound_dispose (GObject
*object
)
51 SwfdecSound
* sound
= SWFDEC_SOUND (object
);
54 swfdec_buffer_unref (sound
->encoded
);
56 G_OBJECT_CLASS (swfdec_sound_parent_class
)->dispose (object
);
60 swfdec_sound_class_init (SwfdecSoundClass
* g_class
)
62 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
63 SwfdecCachedClass
*cached_class
= SWFDEC_CACHED_CLASS (g_class
);
65 object_class
->dispose
= swfdec_sound_dispose
;
67 cached_class
->unload
= swfdec_sound_unload
;
71 swfdec_sound_init (SwfdecSound
* sound
)
77 tag_func_sound_stream_block (SwfdecSwfDecoder
* s
, guint tag
)
84 sound
= SWFDEC_SOUND (s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
].sound_head
);
87 SWFDEC_WARNING ("no streaming sound block");
88 return SWFDEC_STATUS_OK
;
91 n_samples
= swfdec_bits_get_u16 (&s
->b
);
92 if (sound
->format
== SWFDEC_AUDIO_CODEC_MP3
) {
93 skip
= swfdec_bits_get_s16 (&s
->b
);
97 if (swfdec_bits_left (&s
->b
) == 0) {
98 SWFDEC_DEBUG ("empty sound block n_samples=%d skip=%d", n_samples
,
101 return SWFDEC_STATUS_OK
;
103 chunk
= swfdec_bits_get_buffer (&s
->b
, -1);
105 SWFDEC_ERROR ("empty sound chunk");
106 return SWFDEC_STATUS_OK
;
108 SWFDEC_LOG ("got a buffer with %u samples, %d skip and %u bytes mp3 data", n_samples
, skip
,
110 /* use this to write out the stream data to stdout - nice way to get an mp3 file :) */
111 //write (1, (void *) chunk->data, chunk->length);
114 swfdec_sprite_add_sound_chunk (s
->parse_sprite
, s
->parse_sprite
->parse_frame
, chunk
, skip
, n_samples
);
116 return SWFDEC_STATUS_OK
;
120 tag_func_define_sound (SwfdecSwfDecoder
* s
, guint tag
)
122 SwfdecBits
*b
= &s
->b
;
127 id
= swfdec_bits_get_u16 (b
);
128 sound
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_SOUND
);
130 return SWFDEC_STATUS_OK
;
132 sound
->format
= swfdec_bits_getbits (b
, 4);
133 SWFDEC_LOG (" codec: %u", sound
->format
);
134 sound
->original_format
= swfdec_audio_format_parse (b
);
135 SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (sound
->original_format
));
136 n_samples
= swfdec_bits_get_u32 (b
);
137 sound
->n_samples
= n_samples
;
139 switch (sound
->format
) {
141 if (swfdec_audio_format_is_16bit (sound
->original_format
))
142 SWFDEC_WARNING ("undefined endianness for s16 sound");
143 /* just assume LE and hope it works (FIXME: want a switch for this?) */
144 sound
->format
= SWFDEC_AUDIO_CODEC_UNCOMPRESSED
;
147 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
150 sound
->skip
= swfdec_bits_get_u16 (b
);
151 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
156 sound
->encoded
= swfdec_bits_get_buffer (&s
->b
, -1);
159 SWFDEC_WARNING ("unknown format %d", sound
->format
);
161 sound
->n_samples
*= swfdec_audio_format_get_granularity (sound
->original_format
);
163 return SWFDEC_STATUS_OK
;
166 static SwfdecBuffer
*
167 swfdec_sound_get_decoded (SwfdecSound
*sound
, SwfdecAudioFormat
*format
)
171 SwfdecBufferQueue
*queue
;
174 g_return_val_if_fail (SWFDEC_IS_SOUND (sound
), NULL
);
175 g_return_val_if_fail (format
!= NULL
, NULL
);
177 if (sound
->decoded
) {
178 swfdec_cached_use (SWFDEC_CACHED (sound
));
179 *format
= sound
->decoded_format
;
180 return sound
->decoded
;
182 if (sound
->encoded
== NULL
)
185 decoder
= swfdec_audio_decoder_new (sound
->format
, sound
->original_format
);
188 sound
->decoded_format
= swfdec_audio_decoder_get_format (decoder
);
189 sample_bytes
= 2 * swfdec_audio_format_get_channels (sound
->decoded_format
);
190 /* FIXME: The size is only a guess */
191 swfdec_cached_load (SWFDEC_CACHED (sound
), sound
->n_samples
* sample_bytes
);
193 swfdec_audio_decoder_push (decoder
, sound
->encoded
);
194 swfdec_audio_decoder_push (decoder
, NULL
);
195 queue
= swfdec_buffer_queue_new ();
196 while ((tmp
= swfdec_audio_decoder_pull (decoder
)))
197 swfdec_buffer_queue_push (queue
, tmp
);
198 swfdec_audio_decoder_free (decoder
);
199 tmp
= swfdec_buffer_queue_pull (queue
, swfdec_buffer_queue_get_depth (queue
));
200 swfdec_buffer_queue_unref (queue
);
202 SWFDEC_LOG ("after decoding, got %u samples, should get %u and skip %u",
203 tmp
->length
/ sample_bytes
, sound
->n_samples
, sound
->skip
);
205 SwfdecBuffer
*tmp2
= swfdec_buffer_new_subbuffer (tmp
, sound
->skip
* sample_bytes
,
206 tmp
->length
- sound
->skip
* sample_bytes
);
207 swfdec_buffer_unref (tmp
);
210 /* sound buffer may be bigger due to mp3 not having sample boundaries */
211 if (tmp
->length
* swfdec_audio_format_get_granularity (sound
->decoded_format
)
212 > sound
->n_samples
* sample_bytes
) {
213 SwfdecBuffer
*tmp2
= swfdec_buffer_new_subbuffer (tmp
, 0,
214 sound
->n_samples
* sample_bytes
/ swfdec_audio_format_get_granularity (sound
->decoded_format
));
215 swfdec_buffer_unref (tmp
);
218 if (tmp
->length
* swfdec_audio_format_get_granularity (sound
->decoded_format
)
219 < sound
->n_samples
* sample_bytes
) {
220 /* we handle this case in swfdec_sound_render */
221 /* FIXME: this message is important when writing new codecs, so I made it a warning.
222 * It's probably not worth more than INFO for the usual case though */
223 SWFDEC_WARNING ("%u samples in %u bytes should be available, but only %u bytes are",
224 sound
->n_samples
/ swfdec_audio_format_get_granularity (sound
->decoded_format
),
225 sound
->n_samples
* sample_bytes
/ swfdec_audio_format_get_granularity (sound
->decoded_format
),
228 /* only assign here, the decoding code checks this variable */
229 sound
->decoded
= tmp
;
231 *format
= sound
->decoded_format
;
232 return sound
->decoded
;
236 tag_func_sound_stream_head (SwfdecSwfDecoder
* s
, guint tag
)
238 SwfdecBits
*b
= &s
->b
;
239 SwfdecAudioFormat playback
;
244 /* we don't care about playback suggestions */
245 if (swfdec_bits_getbits (b
, 4)) {
246 SWFDEC_ERROR ("0 bits aren't 0");
248 playback
= swfdec_audio_format_parse (b
);
249 SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback
));
251 sound
= g_object_new (SWFDEC_TYPE_SOUND
, NULL
);
252 sound
->format
= swfdec_bits_getbits (b
, 4);
253 sound
->original_format
= swfdec_audio_format_parse (b
);
254 n_samples
= swfdec_bits_get_u16 (b
);
256 if (s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
].sound_head
)
257 g_object_unref (s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
].sound_head
);
258 s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
].sound_head
= sound
;
260 switch (sound
->format
) {
262 if (swfdec_audio_format_is_16bit (sound
->original_format
)) {
263 SWFDEC_WARNING ("undefined endianness for s16 sound");
264 /* just assume LE and hope it works (FIXME: want a switch for this?) */
265 sound
->format
= SWFDEC_AUDIO_CODEC_UNCOMPRESSED
;
270 latency
= swfdec_bits_get_s16 (b
);
277 SWFDEC_WARNING ("unknown format %d", sound
->format
);
280 return SWFDEC_STATUS_OK
;
284 swfdec_sound_chunk_free (SwfdecSoundChunk
*chunk
)
286 g_return_if_fail (chunk
!= NULL
);
288 g_free (chunk
->envelope
);
293 swfdec_sound_parse_chunk (SwfdecSwfDecoder
*s
, int id
)
301 SwfdecSoundChunk
*chunk
;
302 SwfdecBits
*b
= &s
->b
;
304 sound
= swfdec_swf_decoder_get_character (s
, id
);
305 if (!SWFDEC_IS_SOUND (sound
)) {
306 SWFDEC_ERROR ("given id %d does not reference a sound object", id
);
310 chunk
= g_new0 (SwfdecSoundChunk
, 1);
311 chunk
->sound
= sound
;
312 SWFDEC_DEBUG ("parsing sound chunk for sound %d", SWFDEC_CHARACTER (sound
)->id
);
314 swfdec_bits_getbits (b
, 2);
315 chunk
->stop
= swfdec_bits_getbits (b
, 1);
316 chunk
->no_restart
= swfdec_bits_getbits (b
, 1);
317 has_envelope
= swfdec_bits_getbits (b
, 1);
318 has_loops
= swfdec_bits_getbits (b
, 1);
319 has_out_point
= swfdec_bits_getbits (b
, 1);
320 has_in_point
= swfdec_bits_getbits (b
, 1);
322 chunk
->start_sample
= swfdec_bits_get_u32 (b
);
324 chunk
->start_sample
= 0;
327 chunk
->stop_sample
= swfdec_bits_get_u32 (b
);
328 if (chunk
->stop_sample
> sound
->n_samples
) {
329 SWFDEC_INFO ("more samples specified (%u) than available (%u)",
330 chunk
->stop_sample
, sound
->n_samples
);
333 chunk
->stop_sample
= sound
->n_samples
;
336 chunk
->loop_count
= swfdec_bits_get_u16 (b
);
338 chunk
->loop_count
= 1;
341 chunk
->n_envelopes
= swfdec_bits_get_u8 (b
);
342 chunk
->envelope
= g_new (SwfdecSoundEnvelope
, chunk
->n_envelopes
);
344 SWFDEC_LOG (" start_sample = %u", chunk
->start_sample
);
345 SWFDEC_LOG (" stop_sample = %u", chunk
->stop_sample
);
346 SWFDEC_LOG (" loop_count = %u", chunk
->loop_count
);
347 SWFDEC_LOG (" n_envelopes = %u", chunk
->n_envelopes
);
349 for (i
= 0; i
< chunk
->n_envelopes
; i
++) {
350 chunk
->envelope
[i
].offset
= swfdec_bits_get_u32 (b
);
351 if (chunk
->envelope
[i
].offset
< chunk
->start_sample
) {
352 SWFDEC_WARNING ("envelope entry offset too small (%d vs %d)",
353 chunk
->envelope
[i
].offset
, chunk
->start_sample
);
354 chunk
->envelope
[i
].offset
= chunk
->start_sample
;
356 if (i
> 0 && chunk
->envelope
[i
].offset
<=
357 chunk
->envelope
[i
-1].offset
) {
358 /* FIXME: figure out how to handle this */
359 SWFDEC_ERROR ("sound evelope offsets not sorted");
361 for (j
= 0; j
< 2; j
++) {
362 chunk
->envelope
[i
].volume
[j
] = swfdec_bits_get_u16 (b
);
363 if (chunk
->envelope
[i
].volume
[j
] > 32768) {
364 SWFDEC_ERROR ("envelope volume too big: %u > 32768",
365 chunk
->envelope
[i
].volume
[j
]);
366 chunk
->envelope
[i
].volume
[j
] = 32768;
369 SWFDEC_LOG (" envelope = %u { %u, %u }", chunk
->envelope
[i
].offset
,
370 (guint
) chunk
->envelope
[i
].volume
[0], (guint
) chunk
->envelope
[i
].volume
[1]);
371 /* FIXME: check that mono sound gets averaged and then do this here? */
378 tag_func_start_sound (SwfdecSwfDecoder
* s
, guint tag
)
380 SwfdecBits
*b
= &s
->b
;
381 SwfdecSoundChunk
*chunk
;
383 SwfdecSpriteFrame
*frame
= &s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
];
385 id
= swfdec_bits_get_u16 (b
);
387 chunk
= swfdec_sound_parse_chunk (s
, id
);
389 /* append to keep order */
390 SWFDEC_DEBUG ("appending StartSound event for sound %u to frame %u", id
,
391 s
->parse_sprite
->parse_frame
);
392 frame
->sound
= g_slist_append (frame
->sound
, chunk
);
395 return SWFDEC_STATUS_OK
;
399 tag_func_define_button_sound (SwfdecSwfDecoder
* s
, guint tag
)
403 SwfdecButton
*button
;
405 id
= swfdec_bits_get_u16 (&s
->b
);
406 button
= (SwfdecButton
*) swfdec_swf_decoder_get_character (s
, id
);
407 if (!SWFDEC_IS_BUTTON (button
)) {
408 SWFDEC_ERROR ("id %u is not a button", id
);
409 return SWFDEC_STATUS_OK
;
411 SWFDEC_LOG ("loading sound events for button %u", id
);
412 for (i
= 0; i
< 4; i
++) {
413 id
= swfdec_bits_get_u16 (&s
->b
);
415 SWFDEC_LOG ("loading sound %u for button event %u", id
, i
);
416 if (button
->sounds
[i
]) {
417 SWFDEC_ERROR ("need to delete previous sound for button %u's event %u",
418 SWFDEC_CHARACTER (button
)->id
, i
);
419 swfdec_sound_chunk_free (button
->sounds
[i
]);
421 button
->sounds
[i
] = swfdec_sound_parse_chunk (s
, id
);
425 return SWFDEC_STATUS_OK
;
429 * swfdec_sound_buffer_get_n_samples:
430 * @buffer: data to examine
431 * @format: format the data in @buffer is in
433 * Determines the number of samples inside @buffer that would be available if
434 * it were to be rendered using the default Flash format, 44100Hz.
436 * Returns: Number of samples contained in @buffer when rendered
439 swfdec_sound_buffer_get_n_samples (const SwfdecBuffer
*buffer
, SwfdecAudioFormat format
)
441 g_return_val_if_fail (buffer
!= NULL
, 0);
442 g_return_val_if_fail (buffer
->length
% (2 * swfdec_audio_format_get_channels (format
)) == 0, 0);
444 return buffer
->length
/ (2 * swfdec_audio_format_get_channels (format
)) *
445 swfdec_audio_format_get_granularity (format
);
449 * swfdec_sound_render_buffer:
450 * @dest: target buffer to render to
451 * @source: source data to render
452 * @format: format of data in @source and @previous
453 * @previous: previous buffer or NULL for none. This is necessary for
454 * upsampling at buffer boundaries
455 * @offset: offset in 44100Hz samples into @source
456 * @n_samples: number of samples to render into @dest. If more data would be
457 * rendered than is available in @source, 0 samples are used instead.
459 * Adds data from @source into @dest using the same upsampling algorithm as
462 /* NB: if you improve the upsampling algorithm, tests might start to break */
464 swfdec_sound_buffer_render (gint16
*dest
, const SwfdecBuffer
*source
,
465 SwfdecAudioFormat format
, const SwfdecBuffer
*previous
,
466 guint offset
, guint n_samples
)
469 guint channels
= swfdec_audio_format_get_channels (format
);
470 guint rate
= swfdec_audio_format_get_granularity (format
);
473 g_return_if_fail (dest
!= NULL
);
474 g_return_if_fail (source
!= NULL
);
475 g_return_if_fail (swfdec_sound_buffer_get_n_samples (source
, format
) > 0);
476 g_return_if_fail (format
!= 0);
477 g_return_if_fail (previous
== NULL
|| swfdec_sound_buffer_get_n_samples (previous
, format
) > 0);
479 src
= (gint16
*) source
->data
;
480 end
= (gint16
*) (source
->data
+ source
->length
);
481 src
+= channels
* (offset
/ rate
);
484 offset
= rate
- offset
;
485 /* NB: dest will be pointing to uninitialized memory now */
489 /* this is almost the same as the channels == 1 case, so check for bugfixes in both branches */
491 int values
[rate
+ 1];
494 else if (src
!= (gint16
*) source
->data
)
497 values
[0] = ((gint16
*) previous
->data
)[previous
->length
/ 2 - 1];
500 while (n_samples
> 0) {
508 for (i
= rate
/ 2; i
>= 1; i
/= 2) {
509 for (j
= i
; j
< rate
; j
+= 2 * i
) {
510 values
[j
] = (values
[j
+ i
] + values
[j
- i
]) / 2;
513 for (i
= offset
; i
< MIN (rate
, n_samples
); i
++) {
514 dest
[2 * i
] += values
[i
+ 1];
515 dest
[2 * i
+ 1] += values
[i
+ 1];
518 values
[0] = values
[rate
];
520 n_samples
-= MIN (n_samples
, rate
);
523 int values
[2][rate
+ 1];
526 } else if (src
!= (gint16
*) source
->data
) {
527 values
[0][0] = src
[-2];
528 values
[1][0] = src
[-1];
529 } else if (previous
) {
530 values
[0][0] = ((gint16
*) previous
->data
)[previous
->length
/ 2 - 2];
531 values
[1][0] = ((gint16
*) previous
->data
)[previous
->length
/ 2 - 1];
533 values
[0][0] = src
[0];
534 values
[1][0] = src
[1];
536 while (n_samples
> 0) {
539 } else if (src
== end
) {
543 values
[0][rate
] = src
[0];
544 values
[1][rate
] = src
[1];
547 for (i
= rate
/ 2; i
>= 1; i
/= 2) {
548 for (j
= i
; j
< rate
; j
+= 2 * i
) {
549 values
[0][j
] = (values
[0][j
+ i
] + values
[0][j
- i
]) / 2;
550 values
[1][j
] = (values
[1][j
+ i
] + values
[1][j
- i
]) / 2;
553 for (i
= offset
; i
< MIN (rate
, n_samples
); i
++) {
554 dest
[2 * i
] += values
[0][i
+ 1];
555 dest
[2 * i
+ 1] += values
[1][i
+ 1];
558 values
[0][0] = values
[0][rate
];
559 values
[1][0] = values
[1][rate
];
561 n_samples
-= MIN (n_samples
, rate
);
567 * swfdec_sound_render:
568 * @sound: a #SwfdecSound
569 * @dest: target to add to
570 * @offset: offset in samples into the data
571 * @n_samples: amount of samples to render
573 * Renders the given sound onto the existing data in @dest.
576 swfdec_sound_render (SwfdecSound
*sound
, gint16
*dest
,
577 guint offset
, guint n_samples
)
579 SwfdecBuffer
*buffer
;
580 SwfdecAudioFormat format
;
581 g_return_if_fail (SWFDEC_IS_SOUND (sound
));
582 /* FIXME: I need a return_if_fail for !created_by_define_sound */
584 buffer
= swfdec_sound_get_decoded (sound
, &format
);
587 swfdec_sound_buffer_render (dest
, buffer
, format
,
588 NULL
, offset
, n_samples
);