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; } }
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; } } }