⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_sound.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 2 页
字号:
swfdec_sound_chunk_free (SwfdecSoundChunk *chunk){  g_return_if_fail (chunk != NULL);  g_free (chunk->envelope);  g_free (chunk);}SwfdecSoundChunk *swfdec_sound_parse_chunk (SwfdecSwfDecoder *s, int id){  int has_envelope;  int has_loops;  int has_out_point;  int has_in_point;  guint i, j;  SwfdecSound *sound;  SwfdecSoundChunk *chunk;  SwfdecBits *b = &s->b;  sound = swfdec_swf_decoder_get_character (s, id);  if (!SWFDEC_IS_SOUND (sound)) {    SWFDEC_ERROR ("given id %d does not reference a sound object", id);    return NULL;  }  chunk = g_new0 (SwfdecSoundChunk, 1);  chunk->sound = sound;  SWFDEC_DEBUG ("parsing sound chunk for sound %d", SWFDEC_CHARACTER (sound)->id);  swfdec_bits_getbits (b, 2);  chunk->stop = swfdec_bits_getbits (b, 1);  chunk->no_restart = swfdec_bits_getbits (b, 1);  has_envelope = swfdec_bits_getbits (b, 1);  has_loops = swfdec_bits_getbits (b, 1);  has_out_point = swfdec_bits_getbits (b, 1);  has_in_point = swfdec_bits_getbits (b, 1);  if (has_in_point) {    chunk->start_sample = swfdec_bits_get_u32 (b);  } else {    chunk->start_sample = 0;  }  if (has_out_point) {    chunk->stop_sample = swfdec_bits_get_u32 (b);    if (chunk->stop_sample > sound->n_samples) {      SWFDEC_INFO ("more samples specified (%u) than available (%u)", 	  chunk->stop_sample, sound->n_samples);    }  } else {    chunk->stop_sample = sound->n_samples;  }  if (has_loops) {    chunk->loop_count = swfdec_bits_get_u16 (b);  } else {    chunk->loop_count = 1;  }  if (has_envelope) {    chunk->n_envelopes = swfdec_bits_get_u8 (b);    chunk->envelope = g_new (SwfdecSoundEnvelope, chunk->n_envelopes);  }  SWFDEC_LOG ("  start_sample = %u", chunk->start_sample);  SWFDEC_LOG ("  stop_sample = %u", chunk->stop_sample);  SWFDEC_LOG ("  loop_count = %u", chunk->loop_count);  SWFDEC_LOG ("  n_envelopes = %u", chunk->n_envelopes);  for (i = 0; i < chunk->n_envelopes; i++) {    chunk->envelope[i].offset = swfdec_bits_get_u32 (b);    if (chunk->envelope[i].offset < chunk->start_sample) {      SWFDEC_WARNING ("envelope entry offset too small (%d vs %d)",	  chunk->envelope[i].offset, chunk->start_sample);      chunk->envelope[i].offset = chunk->start_sample;    }    if (i > 0 && chunk->envelope[i].offset <=	chunk->envelope[i-1].offset) {      /* FIXME: figure out how to handle this */      SWFDEC_ERROR ("sound evelope offsets not sorted");    }    for (j = 0; j < 2; j++) {      chunk->envelope[i].volume[j] = swfdec_bits_get_u16 (b);      if (chunk->envelope[i].volume[j] > 32768) {	SWFDEC_ERROR ("envelope volume too big: %u > 32768", 	    chunk->envelope[i].volume[j]);	chunk->envelope[i].volume[j] = 32768;      }    }    SWFDEC_LOG ("    envelope = %u { %u, %u }", chunk->envelope[i].offset,	(guint) chunk->envelope[i].volume[0], (guint) chunk->envelope[i].volume[1]);    /* FIXME: check that mono sound gets averaged and then do this here? */  }  return chunk;}inttag_func_start_sound (SwfdecSwfDecoder * s, guint tag){  SwfdecBits *b = &s->b;  SwfdecSoundChunk *chunk;  int id;  SwfdecSpriteFrame *frame = &s->parse_sprite->frames[s->parse_sprite->parse_frame];  id = swfdec_bits_get_u16 (b);  chunk = swfdec_sound_parse_chunk (s, id);  if (chunk) {    /* append to keep order */    SWFDEC_DEBUG ("appending StartSound event for sound %u to frame %u", id,	s->parse_sprite->parse_frame);    frame->sound = g_slist_append (frame->sound, chunk);  }  return SWFDEC_STATUS_OK;}inttag_func_define_button_sound (SwfdecSwfDecoder * s, guint tag){  guint i;  guint id;  SwfdecButton *button;  id = swfdec_bits_get_u16 (&s->b);  button = (SwfdecButton *) swfdec_swf_decoder_get_character (s, id);  if (!SWFDEC_IS_BUTTON (button)) {    SWFDEC_ERROR ("id %u is not a button", id);    return SWFDEC_STATUS_OK;  }  SWFDEC_LOG ("loading sound events for button %u", id);  for (i = 0; i < 4; i++) {    id = swfdec_bits_get_u16 (&s->b);    if (id) {      SWFDEC_LOG ("loading sound %u for button event %u", id, i);      if (button->sounds[i]) {	SWFDEC_ERROR ("need to delete previous sound for button %u's event %u", 	    SWFDEC_CHARACTER (button)->id, i);	swfdec_sound_chunk_free (button->sounds[i]);      }      button->sounds[i] = swfdec_sound_parse_chunk (s, id);    }  }  return SWFDEC_STATUS_OK;}/** * swfdec_sound_buffer_get_n_samples: * @buffer: data to examine * @format: format the data in @buffer is in * * Determines the number of samples inside @buffer that would be available if * it were to be rendered using the default Flash format, 44100Hz. * * Returns: Number of samples contained in @buffer when rendered **/guintswfdec_sound_buffer_get_n_samples (const SwfdecBuffer *buffer, SwfdecAudioOut format){  g_return_val_if_fail (buffer != NULL, 0);  g_return_val_if_fail (buffer->length % (2 * SWFDEC_AUDIO_OUT_N_CHANNELS (format)) == 0, 0);  return buffer->length / (2 * SWFDEC_AUDIO_OUT_N_CHANNELS (format)) *    SWFDEC_AUDIO_OUT_GRANULARITY (format);}/** * swfdec_sound_render_buffer: * @dest: target buffer to render to * @source: source data to render * @format: format of data in @source and @previous * @previous: previous buffer or NULL for none. This is necessary for *            upsampling at buffer boundaries * @offset: offset in 44100Hz samples into @source * @n_samples: number of samples to render into @dest. If more data would be *	       rendered than is available in @source, 0 samples are used instead. * * Adds data from @source into @dest using the same upsampling algorithm as * Flash player. **//* NB: if you improve the upsampling algorithm, tests might start to break */voidswfdec_sound_buffer_render (gint16 *dest, const SwfdecBuffer *source,     SwfdecAudioOut format, const SwfdecBuffer *previous,     guint offset, guint n_samples){  guint i, j;  guint channels = SWFDEC_AUDIO_OUT_N_CHANNELS (format);  guint rate = SWFDEC_AUDIO_OUT_GRANULARITY (format);  gint16 *src, *end;  g_return_if_fail (dest != NULL);  g_return_if_fail (source != NULL);  g_return_if_fail (swfdec_sound_buffer_get_n_samples (source, format) > 0);  g_return_if_fail (format != 0);  g_return_if_fail (previous == NULL || swfdec_sound_buffer_get_n_samples (previous, format) > 0);  src = (gint16 *) source->data;  end = (gint16 *) (source->data + source->length);  src += channels * (offset / rate);  offset %= rate;  if (offset) {    offset = rate - offset;    /* NB: dest will be pointing to uninitialized memory now */    dest -= offset * 2;    n_samples += offset;  }  /* this is almost the same as the channels == 1 case, so check for bugfixes in both branches */  if (channels == 1) {    int values[rate + 1];    if (src >= end)      n_samples = 0;    else if (src != (gint16 *) source->data)      values[0] = src[-1];    else if (previous)      values[0] = ((gint16 *) previous->data)[previous->length / 2 - 1];    else      values[0] = *src;    while (n_samples > 0) {      if (src > end)	break;      else if (src == end)	values[rate] = 0;      else	values[rate] = *src;      src++;      for (i = rate / 2; i >= 1; i /= 2) {	for (j = i; j < rate; j += 2 * i) {	  values[j] = (values[j + i] + values[j - i]) / 2;	}      }      for (i = offset; i < MIN (rate, n_samples); i++) {	dest[2 * i] += values[i + 1];	dest[2 * i + 1] += values[i + 1];      }      dest += 2 * rate;      values[0] = values[rate];      offset = 0;      n_samples -= MIN (n_samples, rate);    }  } else {    int values[2][rate + 1];    if (src >= end) {      n_samples = 0;    } else if (src != (gint16 *) source->data) {      values[0][0] = src[-2];      values[1][0] = src[-1];    } else if (previous) {      values[0][0] = ((gint16 *) previous->data)[previous->length / 2 - 2];      values[1][0] = ((gint16 *) previous->data)[previous->length / 2 - 1];    } else {      values[0][0] = src[0];      values[1][0] = src[1];    }    while (n_samples > 0) {      if (src > end) {	break;      } else if (src == end) {	values[0][rate] = 0;	values[1][rate] = 0;      } else {	values[0][rate] = src[0];	values[1][rate] = src[1];      }      src += 2;      for (i = rate / 2; i >= 1; i /= 2) {	for (j = i; j < rate; j += 2 * i) {	  values[0][j] = (values[0][j + i] + values[0][j - i]) / 2;	  values[1][j] = (values[1][j + i] + values[1][j - i]) / 2;	}      }      for (i = offset; i < MIN (rate, n_samples); i++) {	dest[2 * i] += values[0][i + 1];	dest[2 * i + 1] += values[1][i + 1];      }      dest += 2 * rate;      values[0][0] = values[0][rate];      values[1][0] = values[1][rate];      offset = 0;      n_samples -= MIN (n_samples, rate);    }  }}/** * swfdec_sound_render: * @sound: a #SwfdecSound * @dest: target to add to * @offset: offset in samples into the data * @n_samples: amount of samples to render * * Renders the given sound onto the existing data in @dest. **/voidswfdec_sound_render (SwfdecSound *sound, gint16 *dest,    guint offset, guint n_samples){  SwfdecBuffer *buffer;  SwfdecAudioOut format;  g_return_if_fail (SWFDEC_IS_SOUND (sound));  /* FIXME: I need a return_if_fail for !created_by_define_sound */  buffer = swfdec_sound_get_decoded (sound, &format);  if (buffer == NULL)    return;  swfdec_sound_buffer_render (dest, buffer, format,       NULL, offset, n_samples);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -