]> git.sesse.net Git - casparcg/blob - modules/ffmpeg/producer/audio/audio_resampler.cpp
e92d3a8b02d51c6ca8aed4f05213e7c8bbf3ed0d
[casparcg] / modules / ffmpeg / producer / audio / audio_resampler.cpp
1 #include "../../StdAfx.h"\r
2 \r
3 #include "audio_resampler.h"\r
4 \r
5 #include <common/exception/exceptions.h>\r
6 \r
7 #if defined(_MSC_VER)\r
8 #pragma warning (push)\r
9 #pragma warning (disable : 4244)\r
10 #endif\r
11 extern "C" \r
12 {\r
13         #include <libavcodec/avcodec.h>\r
14 }\r
15 #if defined(_MSC_VER)\r
16 #pragma warning (pop)\r
17 #endif\r
18 \r
19 namespace caspar { namespace ffmpeg {\r
20 \r
21 struct audio_resampler::implementation\r
22 {       \r
23         std::shared_ptr<ReSampleContext> resampler_;\r
24         \r
25         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> copy_buffer_;\r
26         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer2_;\r
27 \r
28         const size_t                    output_channels_;\r
29         const AVSampleFormat    output_sample_format_;\r
30 \r
31         const size_t                    input_channels_;\r
32         const AVSampleFormat    input_sample_format_;\r
33 \r
34         implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
35                 : output_channels_(output_channels)\r
36                 , output_sample_format_(output_sample_format)\r
37                 , input_channels_(input_channels)\r
38                 , input_sample_format_(input_sample_format)\r
39         {\r
40                 if(input_channels               != output_channels || \r
41                    input_sample_rate    != output_sample_rate ||\r
42                    input_sample_format  != output_sample_format)\r
43                 {       \r
44                         auto resampler = av_audio_resample_init(output_channels,                input_channels,\r
45                                                                                                         output_sample_rate,             input_sample_rate,\r
46                                                                                                         output_sample_format,   input_sample_format,\r
47                                                                                                         16, 10, 0, 0.8);\r
48 \r
49                         buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);\r
50 \r
51                         CASPAR_LOG(warning) << L"Resampling." <<\r
52                                                                         L" sample_rate:" << input_sample_rate  <<\r
53                                                                         L" audio_channels:" << input_channels  <<\r
54                                                                         L" sample_fmt:" << input_sample_format;\r
55 \r
56                         if(resampler)\r
57                                 resampler_.reset(resampler, audio_resample_close);\r
58                         else\r
59                                 BOOST_THROW_EXCEPTION(caspar_exception());\r
60                 }               \r
61         }\r
62 \r
63         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data)\r
64         {\r
65                 if(resampler_ && !data.empty())\r
66                 {\r
67                         buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);\r
68                         auto ret = audio_resample(resampler_.get(),\r
69                                                                           reinterpret_cast<short*>(buffer2_.data()), \r
70                                                                           reinterpret_cast<short*>(data.data()), \r
71                                                                           data.size() / (av_get_bytes_per_sample(input_sample_format_) * input_channels_)); \r
72                         buffer2_.resize(ret * av_get_bytes_per_sample(output_sample_format_) * output_channels_);\r
73                         std::swap(data, buffer2_);\r
74                 }\r
75 \r
76                 return std::move(data);\r
77         }\r
78 };\r
79 \r
80 \r
81 audio_resampler::audio_resampler(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
82                                 : impl_(new implementation(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format)){}\r
83 std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> audio_resampler::resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data){return impl_->resample(std::move(data));}\r
84 \r
85 }}