1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| #include <libswresample/swresample.h> #include <libavutil/opt.h> #include <libavutil/channel_layout.h> #include <libavutil/samplefmt.h>
typedef struct AudioResampler { SwrContext *swr_ctx; AVFrame *input_frame; AVFrame *output_frame; int input_sample_rate; enum AVSampleFormat input_sample_fmt; uint64_t input_channel_layout; int input_channels; int output_sample_rate; enum AVSampleFormat output_sample_fmt; uint64_t output_channel_layout; int output_channels; uint8_t **input_data; uint8_t **output_data; int input_linesize; int output_linesize; int max_input_samples; int max_output_samples; } AudioResampler;
int init_audio_resampler(AudioResampler *resampler, int input_sample_rate, enum AVSampleFormat input_sample_fmt, int input_channels, int output_sample_rate, enum AVSampleFormat output_sample_fmt, int output_channels) { int ret; memset(resampler, 0, sizeof(*resampler)); resampler->input_sample_rate = input_sample_rate; resampler->input_sample_fmt = input_sample_fmt; resampler->input_channels = input_channels; resampler->input_channel_layout = av_get_default_channel_layout(input_channels); resampler->output_sample_rate = output_sample_rate; resampler->output_sample_fmt = output_sample_fmt; resampler->output_channels = output_channels; resampler->output_channel_layout = av_get_default_channel_layout(output_channels); resampler->swr_ctx = swr_alloc(); if (!resampler->swr_ctx) { fprintf(stderr, "无法分配重采样上下文\n"); return AVERROR(ENOMEM); } av_opt_set_int(resampler->swr_ctx, "in_channel_layout", resampler->input_channel_layout, 0); av_opt_set_int(resampler->swr_ctx, "in_sample_rate", resampler->input_sample_rate, 0); av_opt_set_sample_fmt(resampler->swr_ctx, "in_sample_fmt", resampler->input_sample_fmt, 0); av_opt_set_int(resampler->swr_ctx, "out_channel_layout", resampler->output_channel_layout, 0); av_opt_set_int(resampler->swr_ctx, "out_sample_rate", resampler->output_sample_rate, 0); av_opt_set_sample_fmt(resampler->swr_ctx, "out_sample_fmt", resampler->output_sample_fmt, 0); ret = swr_init(resampler->swr_ctx); if (ret < 0) { fprintf(stderr, "无法初始化重采样上下文: %s\n", av_err2str(ret)); return ret; } resampler->max_input_samples = 1024; resampler->max_output_samples = av_rescale_rnd(resampler->max_input_samples, resampler->output_sample_rate, resampler->input_sample_rate, AV_ROUND_UP); ret = av_samples_alloc_array_and_samples(&resampler->input_data, &resampler->input_linesize, resampler->input_channels, resampler->max_input_samples, resampler->input_sample_fmt, 0); if (ret < 0) { fprintf(stderr, "无法分配输入缓冲区: %s\n", av_err2str(ret)); return ret; } ret = av_samples_alloc_array_and_samples(&resampler->output_data, &resampler->output_linesize, resampler->output_channels, resampler->max_output_samples, resampler->output_sample_fmt, 0); if (ret < 0) { fprintf(stderr, "无法分配输出缓冲区: %s\n", av_err2str(ret)); return ret; } return 0; }
int resample_audio(AudioResampler *resampler, const uint8_t **input_data, int input_samples, uint8_t **output_data, int *output_samples) { int ret; int max_output_samples = av_rescale_rnd(swr_get_delay(resampler->swr_ctx, resampler->input_sample_rate) + input_samples, resampler->output_sample_rate, resampler->input_sample_rate, AV_ROUND_UP); if (max_output_samples > resampler->max_output_samples) { av_freep(&resampler->output_data[0]); av_freep(&resampler->output_data); ret = av_samples_alloc_array_and_samples(&resampler->output_data, &resampler->output_linesize, resampler->output_channels, max_output_samples, resampler->output_sample_fmt, 0); if (ret < 0) { fprintf(stderr, "无法重新分配输出缓冲区: %s\n", av_err2str(ret)); return ret; } resampler->max_output_samples = max_output_samples; } ret = swr_convert(resampler->swr_ctx, resampler->output_data, max_output_samples, input_data, input_samples); if (ret < 0) { fprintf(stderr, "重采样失败: %s\n", av_err2str(ret)); return ret; } *output_samples = ret; *output_data = resampler->output_data[0]; return 0; }
void cleanup_audio_resampler(AudioResampler *resampler) { if (resampler->input_data) { av_freep(&resampler->input_data[0]); av_freep(&resampler->input_data); } if (resampler->output_data) { av_freep(&resampler->output_data[0]); av_freep(&resampler->output_data); } swr_free(&resampler->swr_ctx); }
int main() { AudioResampler resampler; int ret; ret = init_audio_resampler(&resampler, 44100, AV_SAMPLE_FMT_S16, 2, 48000, AV_SAMPLE_FMT_S16, 1); if (ret < 0) { return 1; } int input_samples = 1024; int16_t *input_buffer = (int16_t*)resampler.input_data[0]; for (int i = 0; i < input_samples * 2; i += 2) { double t = (double)i / (44100.0 * 2); int16_t sample = (int16_t)(sin(2 * M_PI * 440 * t) * 16384); input_buffer[i] = sample; input_buffer[i + 1] = sample; } uint8_t *output_data; int output_samples; ret = resample_audio(&resampler, (const uint8_t**)resampler.input_data, input_samples, &output_data, &output_samples); if (ret < 0) { cleanup_audio_resampler(&resampler); return 1; } printf("重采样完成: %d 输入样本 -> %d 输出样本\n", input_samples, output_samples); cleanup_audio_resampler(&resampler); return 0; }
|