yading@10: /* yading@10: * Copyright (c) 2012 Stefano Sabatini yading@10: * yading@10: * Permission is hereby granted, free of charge, to any person obtaining a copy yading@10: * of this software and associated documentation files (the "Software"), to deal yading@10: * in the Software without restriction, including without limitation the rights yading@10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell yading@10: * copies of the Software, and to permit persons to whom the Software is yading@10: * furnished to do so, subject to the following conditions: yading@10: * yading@10: * The above copyright notice and this permission notice shall be included in yading@10: * all copies or substantial portions of the Software. yading@10: * yading@10: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR yading@10: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, yading@10: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL yading@10: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER yading@10: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, yading@10: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN yading@10: * THE SOFTWARE. yading@10: */ yading@10: yading@10: /** yading@10: * @example doc/examples/resampling_audio.c yading@10: * libswresample API use example. yading@10: */ yading@10: yading@10: #include yading@10: #include yading@10: #include yading@10: #include yading@10: yading@10: static int get_format_from_sample_fmt(const char **fmt, yading@10: enum AVSampleFormat sample_fmt) yading@10: { yading@10: int i; yading@10: struct sample_fmt_entry { yading@10: enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le; yading@10: } sample_fmt_entries[] = { yading@10: { AV_SAMPLE_FMT_U8, "u8", "u8" }, yading@10: { AV_SAMPLE_FMT_S16, "s16be", "s16le" }, yading@10: { AV_SAMPLE_FMT_S32, "s32be", "s32le" }, yading@10: { AV_SAMPLE_FMT_FLT, "f32be", "f32le" }, yading@10: { AV_SAMPLE_FMT_DBL, "f64be", "f64le" }, yading@10: }; yading@10: *fmt = NULL; yading@10: yading@10: for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) { yading@10: struct sample_fmt_entry *entry = &sample_fmt_entries[i]; yading@10: if (sample_fmt == entry->sample_fmt) { yading@10: *fmt = AV_NE(entry->fmt_be, entry->fmt_le); yading@10: return 0; yading@10: } yading@10: } yading@10: yading@10: fprintf(stderr, yading@10: "Sample format %s not supported as output format\n", yading@10: av_get_sample_fmt_name(sample_fmt)); yading@10: return AVERROR(EINVAL); yading@10: } yading@10: yading@10: /** yading@10: * Fill dst buffer with nb_samples, generated starting from t. yading@10: */ yading@10: void fill_samples(double *dst, int nb_samples, int nb_channels, int sample_rate, double *t) yading@10: { yading@10: int i, j; yading@10: double tincr = 1.0 / sample_rate, *dstp = dst; yading@10: const double c = 2 * M_PI * 440.0; yading@10: yading@10: /* generate sin tone with 440Hz frequency and duplicated channels */ yading@10: for (i = 0; i < nb_samples; i++) { yading@10: *dstp = sin(c * *t); yading@10: for (j = 1; j < nb_channels; j++) yading@10: dstp[j] = dstp[0]; yading@10: dstp += nb_channels; yading@10: *t += tincr; yading@10: } yading@10: } yading@10: yading@10: int main(int argc, char **argv) yading@10: { yading@10: int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND; yading@10: int src_rate = 48000, dst_rate = 44100; yading@10: uint8_t **src_data = NULL, **dst_data = NULL; yading@10: int src_nb_channels = 0, dst_nb_channels = 0; yading@10: int src_linesize, dst_linesize; yading@10: int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples; yading@10: enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16; yading@10: const char *dst_filename = NULL; yading@10: FILE *dst_file; yading@10: int dst_bufsize; yading@10: const char *fmt; yading@10: struct SwrContext *swr_ctx; yading@10: double t; yading@10: int ret; yading@10: yading@10: if (argc != 2) { yading@10: fprintf(stderr, "Usage: %s output_file\n" yading@10: "API example program to show how to resample an audio stream with libswresample.\n" yading@10: "This program generates a series of audio frames, resamples them to a specified " yading@10: "output format and rate and saves them to an output file named output_file.\n", yading@10: argv[0]); yading@10: exit(1); yading@10: } yading@10: dst_filename = argv[1]; yading@10: yading@10: dst_file = fopen(dst_filename, "wb"); yading@10: if (!dst_file) { yading@10: fprintf(stderr, "Could not open destination file %s\n", dst_filename); yading@10: exit(1); yading@10: } yading@10: yading@10: /* create resampler context */ yading@10: swr_ctx = swr_alloc(); yading@10: if (!swr_ctx) { yading@10: fprintf(stderr, "Could not allocate resampler context\n"); yading@10: ret = AVERROR(ENOMEM); yading@10: goto end; yading@10: } yading@10: yading@10: /* set options */ yading@10: av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0); yading@10: av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0); yading@10: av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0); yading@10: yading@10: av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0); yading@10: av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0); yading@10: av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); yading@10: yading@10: /* initialize the resampling context */ yading@10: if ((ret = swr_init(swr_ctx)) < 0) { yading@10: fprintf(stderr, "Failed to initialize the resampling context\n"); yading@10: goto end; yading@10: } yading@10: yading@10: /* allocate source and destination samples buffers */ yading@10: yading@10: src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout); yading@10: ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, yading@10: src_nb_samples, src_sample_fmt, 0); yading@10: if (ret < 0) { yading@10: fprintf(stderr, "Could not allocate source samples\n"); yading@10: goto end; yading@10: } yading@10: yading@10: /* compute the number of converted samples: buffering is avoided yading@10: * ensuring that the output buffer will contain at least all the yading@10: * converted input samples */ yading@10: max_dst_nb_samples = dst_nb_samples = yading@10: av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); yading@10: yading@10: /* buffer is going to be directly written to a rawaudio file, no alignment */ yading@10: dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout); yading@10: ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, yading@10: dst_nb_samples, dst_sample_fmt, 0); yading@10: if (ret < 0) { yading@10: fprintf(stderr, "Could not allocate destination samples\n"); yading@10: goto end; yading@10: } yading@10: yading@10: t = 0; yading@10: do { yading@10: /* generate synthetic audio */ yading@10: fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t); yading@10: yading@10: /* compute destination number of samples */ yading@10: dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + yading@10: src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); yading@10: if (dst_nb_samples > max_dst_nb_samples) { yading@10: av_free(dst_data[0]); yading@10: ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, yading@10: dst_nb_samples, dst_sample_fmt, 1); yading@10: if (ret < 0) yading@10: break; yading@10: max_dst_nb_samples = dst_nb_samples; yading@10: } yading@10: yading@10: /* convert to destination format */ yading@10: ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples); yading@10: if (ret < 0) { yading@10: fprintf(stderr, "Error while converting\n"); yading@10: goto end; yading@10: } yading@10: dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, yading@10: ret, dst_sample_fmt, 1); yading@10: printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret); yading@10: fwrite(dst_data[0], 1, dst_bufsize, dst_file); yading@10: } while (t < 10); yading@10: yading@10: if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0) yading@10: goto end; yading@10: fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n" yading@10: "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n", yading@10: fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename); yading@10: yading@10: end: yading@10: if (dst_file) yading@10: fclose(dst_file); yading@10: yading@10: if (src_data) yading@10: av_freep(&src_data[0]); yading@10: av_freep(&src_data); yading@10: yading@10: if (dst_data) yading@10: av_freep(&dst_data[0]); yading@10: av_freep(&dst_data); yading@10: yading@10: swr_free(&swr_ctx); yading@10: return ret < 0; yading@10: }