目的:改变pcm的采样率,通道数,每一个采样bit数code
public unsafe class AudioResample { private SwrContext* m_swr_ctx = null; private byte** m_dst_data = null; long m_max_dst_nb_samples = 0; int m_dst_linesize = 0; private int m_src_channel_layout = 0; private int m_src_sample_rate = 0; private AVSampleFormat m_src_sample_fmt = 0; private int m_dst_channel_layout = 0; private int m_dst_sample_rate = 0; private AVSampleFormat m_dst_sample_fmt; /// <summary> /// 初始化重采样 /// </summary> public int ARInit(int src_channel_layout, int src_sample_rate, AVSampleFormat src_sample_fmt, int dst_channel_layout, int dst_sample_rate, AVSampleFormat dst_sample_fmt, int data_delay = 20) { if (m_swr_ctx != null) return -1; int ret = 0; int dst_audio_channels; long src_nb_samples = src_sample_rate / data_delay, dst_nb_samples; m_swr_ctx = ffmpeg.swr_alloc(); ffmpeg.av_opt_set_int(m_swr_ctx, "in_channel_layout", (long)src_channel_layout, 0); ffmpeg.av_opt_set_int(m_swr_ctx, "in_sample_rate", src_sample_rate, 0); ffmpeg.av_opt_set_sample_fmt(m_swr_ctx, "in_sample_fmt", src_sample_fmt, 0); ffmpeg.av_opt_set_int(m_swr_ctx, "out_channel_layout", (long)dst_channel_layout, 0); ffmpeg.av_opt_set_int(m_swr_ctx, "out_sample_rate", dst_sample_rate, 0); ffmpeg.av_opt_set_sample_fmt(m_swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); if (ffmpeg.swr_init(m_swr_ctx) < 0) { goto fail; } m_max_dst_nb_samples = dst_nb_samples = ffmpeg.av_rescale_rnd(src_nb_samples, dst_sample_rate, src_sample_rate, AVRounding.AV_ROUND_UP); dst_audio_channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)dst_channel_layout); fixed(byte*** dst_data = &m_dst_data) fixed(int *dst_linesize = &m_dst_linesize) ret = ffmpeg.av_samples_alloc_array_and_samples(dst_data, dst_linesize, dst_audio_channels, (int)dst_nb_samples, dst_sample_fmt, 0); m_src_channel_layout = src_channel_layout; m_dst_channel_layout = dst_channel_layout; m_src_sample_rate = src_sample_rate; m_dst_sample_rate = dst_sample_rate; m_src_sample_fmt = src_sample_fmt; m_dst_sample_fmt = dst_sample_fmt; return 0; fail: ARDeinit(); return -1; } /// <summary> /// 重采样 /// </summary> public byte[] ARConvert(byte* src_data, int src_data_len) { int ret = 0; int dst_data_len = 0; byte* out_data; ret = ARConvert(src_data, src_data_len, &out_data, ref dst_data_len); if (ret < 0) return null; byte[] convert_data = new byte[dst_data_len]; Marshal.Copy((IntPtr)(*m_dst_data), convert_data, 0, convert_data.Length); return convert_data; } public int ARConvert(byte* src_data, int src_data_len, byte** out_data, ref int out_len) { int ret; int dst_data_samples, src_data_sample; int dst_audio_channels; int dst_data_len; int src_audio_channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)m_src_channel_layout); src_data_sample = src_data_len / src_audio_channels; if (m_src_sample_fmt == AVSampleFormat.AV_SAMPLE_FMT_S16) src_data_sample = src_data_sample / 2; fixed (int* dst_linesize = &m_dst_linesize) { dst_data_samples = (int)ffmpeg.av_rescale_rnd(ffmpeg.swr_get_delay(m_swr_ctx, (long)m_src_sample_rate) + (long)src_data_sample, (long)m_dst_sample_rate, (long)m_src_sample_rate, AVRounding.AV_ROUND_UP); dst_audio_channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)m_dst_channel_layout); if (dst_data_samples > m_max_dst_nb_samples) { ffmpeg.av_freep(&m_dst_data[0]); ret = ffmpeg.av_samples_alloc(m_dst_data, dst_linesize, dst_audio_channels, (int)dst_data_samples, m_dst_sample_fmt, 1); if (ret < 0) { m_max_dst_nb_samples = 0; return -1; } m_max_dst_nb_samples = dst_data_samples; } /* convert to destination format */ ret = ffmpeg.swr_convert(m_swr_ctx, m_dst_data, (int)dst_data_samples, (byte**)&src_data, (int)src_data_sample); if (ret < 0) { return -1; } dst_data_len = ffmpeg.av_samples_get_buffer_size(dst_linesize, dst_audio_channels, ret, m_dst_sample_fmt, 1); out_len = dst_data_len; *out_data = *m_dst_data; return 0; } } public void ARDeinit() { if(m_swr_ctx != null) { fixed (SwrContext** swr_ctx = &m_swr_ctx) ffmpeg.swr_free(swr_ctx); m_swr_ctx = null; } if(m_dst_data != null) { ffmpeg.av_freep(&m_dst_data[0]); m_dst_data = null; } } }