static void aiLenChanged(void* user_data, const void* buffer, size_t size)
{
   size_t max_frames, remain_frames;
   uint32_t i;
   double ratio;
   struct resampler_data data = {0};
   int16_t *out      = NULL;
   int16_t *raw_data = (int16_t*)buffer;
   size_t frames     = size / 4;
   uint8_t *p        = (uint8_t*)buffer;

   for (i = 0; i < size; i += 4)
   {
      p[i ] ^= p[i + 2];
      p[i + 2] ^= p[i ];
      p[i ] ^= p[i + 2];
      p[i + 1] ^= p[i + 3];
      p[i + 3] ^= p[i + 1];
      p[i + 1] ^= p[i + 3];
   }

audio_batch:
   out               = NULL;
   ratio             = 44100.0 / GameFreq;
   max_frames        = (GameFreq > 44100) ? MAX_AUDIO_FRAMES : (size_t)(MAX_AUDIO_FRAMES / ratio - 1);
   remain_frames     = 0;

   if (frames > max_frames)
   {
      remain_frames = frames - max_frames;
      frames = max_frames;
   }

   data.data_in      = audio_in_buffer_float;
   data.data_out     = audio_out_buffer_float;
   data.input_frames = frames;
   data.ratio        = ratio;

   convert_s16_to_float(audio_in_buffer_float, raw_data, frames * 2, 1.0f);
   resampler->process(resampler_audio_data, &data);
   convert_float_to_s16(audio_out_buffer_s16, audio_out_buffer_float, data.output_frames * 2);

   out                    = audio_out_buffer_s16;

   while (data.output_frames)
   {
      size_t ret          = audio_batch_cb(out, data.output_frames);
      data.output_frames -= ret;
      out                += ret * 2;
   }
   if (remain_frames)
   {
      raw_data = raw_data + frames * 2;
      frames   = remain_frames;
      goto audio_batch;
   }
}
Пример #2
0
static void ffmpeg_audio_resample(ffmpeg_t *handle,
      struct ffemu_audio_data *aud)
{
   if (!handle->audio.use_float && !handle->audio.resampler)
      return;

   if (aud->frames > handle->audio.float_conv_frames)
   {
      handle->audio.float_conv = (float*)av_realloc(handle->audio.float_conv,
            aud->frames * handle->params.channels * sizeof(float));
      if (!handle->audio.float_conv)
         return;

      handle->audio.float_conv_frames = aud->frames;

      /* To make sure we don't accidentially overflow. */
      handle->audio.resample_out_frames = aud->frames * handle->audio.ratio + 16;

      handle->audio.resample_out = (float*)av_realloc(handle->audio.resample_out,
            handle->audio.resample_out_frames *
            handle->params.channels * sizeof(float));
      if (!handle->audio.resample_out)
         return;

      handle->audio.fixed_conv_frames = MAX(handle->audio.resample_out_frames,
            handle->audio.float_conv_frames);
      handle->audio.fixed_conv = (int16_t*)av_realloc(handle->audio.fixed_conv,
            handle->audio.fixed_conv_frames * handle->params.channels * sizeof(int16_t));
      if (!handle->audio.fixed_conv)
         return;
   }

   if (handle->audio.use_float || handle->audio.resampler)
   {
      convert_s16_to_float(handle->audio.float_conv,
            (const int16_t*)aud->data, aud->frames * handle->params.channels, 1.0);
      aud->data = handle->audio.float_conv;
   }

   if (handle->audio.resampler)
   {
      /* It's always two channels ... */
      struct resampler_data info = {0};

      info.data_in      = (const float*)aud->data;
      info.data_out     = handle->audio.resample_out;
      info.input_frames = aud->frames;
      info.ratio        = handle->audio.ratio;

      rarch_resampler_process(handle->audio.resampler,
            handle->audio.resampler_data, &info);
      aud->data   = handle->audio.resample_out;
      aud->frames = info.output_frames;

      if (!handle->audio.use_float)
      {
         convert_float_to_s16(handle->audio.fixed_conv,
               handle->audio.resample_out,
               aud->frames * handle->params.channels);
         aud->data = handle->audio.fixed_conv;
      }
   }
}