convert/convert_audio.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al. | ||
| 2 | // http://avisynth.nl | ||
| 3 | |||
| 4 | // This program is free software; you can redistribute it and/or modify | ||
| 5 | // it under the terms of the GNU General Public License as published by | ||
| 6 | // the Free Software Foundation; either version 2 of the License, or | ||
| 7 | // (at your option) any later version. | ||
| 8 | // | ||
| 9 | // This program is distributed in the hope that it will be useful, | ||
| 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | // GNU General Public License for more details. | ||
| 13 | // | ||
| 14 | // You should have received a copy of the GNU General Public License | ||
| 15 | // along with this program; if not, write to the Free Software | ||
| 16 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit | ||
| 17 | // http://www.gnu.org/copyleft/gpl.html . | ||
| 18 | // | ||
| 19 | // Linking Avisynth statically or dynamically with other modules is making a | ||
| 20 | // combined work based on Avisynth. Thus, the terms and conditions of the GNU | ||
| 21 | // General Public License cover the whole combination. | ||
| 22 | // | ||
| 23 | // As a special exception, the copyright holders of Avisynth give you | ||
| 24 | // permission to link Avisynth with independent modules that communicate with | ||
| 25 | // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license | ||
| 26 | // terms of these independent modules, and to copy and distribute the | ||
| 27 | // resulting combined work under terms of your choice, provided that | ||
| 28 | // every copy of the combined work is accompanied by a complete copy of | ||
| 29 | // the source code of Avisynth (the version of Avisynth used to produce the | ||
| 30 | // combined work), being distributed under the terms of the GNU General | ||
| 31 | // Public License plus this exception. An independent module is a module | ||
| 32 | // which is not derived from or based on Avisynth, such as 3rd-party filters, | ||
| 33 | // import and export plugins, or graphical user interfaces. | ||
| 34 | |||
| 35 | // ConvertAudio classes | ||
| 36 | // Copyright (c) Klaus Post 2001 - 2004 | ||
| 37 | // Copyright (c) Ian Brabham 2005 | ||
| 38 | // Copyright (c) 2020 Xinyue Lu | ||
| 39 | // Copyright (c) 2021 pinterf | ||
| 40 | |||
| 41 | #include <avisynth.h> | ||
| 42 | #include <avs/alignment.h> | ||
| 43 | #include "convert_audio.h" | ||
| 44 | #if defined(AVS_BSD) || defined(AVS_MACOS) | ||
| 45 | #include <stdlib.h> | ||
| 46 | #else | ||
| 47 | #include <malloc.h> | ||
| 48 | #endif | ||
| 49 | #include <limits> | ||
| 50 | |||
| 51 | // There are two type parameters. Acceptable sample types and a prefered sample type. | ||
| 52 | // If the current clip is already one of the defined types in sampletype, this will be returned. | ||
| 53 | // If not, the current clip will be converted to the prefered type. | ||
| 54 | 24 | PClip ConvertAudio::Create(PClip clip, int sample_type, int prefered_type) { | |
| 55 |
5/6✓ Branch 5 → 6 taken 24 times.
✗ Branch 5 → 10 not taken.
✓ Branch 9 → 10 taken 23 times.
✓ Branch 9 → 11 taken 1 time.
✓ Branch 12 → 13 taken 23 times.
✓ Branch 12 → 14 taken 1 time.
|
24 | if ((!clip->GetVideoInfo().HasAudio()) || clip->GetVideoInfo().SampleType() & (sample_type | prefered_type)) { |
| 56 | // Sample type is already ok! | ||
| 57 | 23 | return clip; | |
| 58 | } else | ||
| 59 |
4/10✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 23 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 23 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 1 time.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
|
1 | return new ConvertAudio(clip, prefered_type); |
| 60 | } | ||
| 61 | |||
| 62 | 1 | int __stdcall ConvertAudio::SetCacheHints(int cachehints, int frame_range) { | |
| 63 | // We do pass cache requests upwards, to the next filter. | ||
| 64 | 1 | return child->SetCacheHints(cachehints, frame_range); | |
| 65 | } | ||
| 66 | |||
| 67 | 3 | ConvertAudio::ConvertAudio(PClip _clip, int _sample_type) | |
| 68 |
2/4✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 50 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 48 not taken.
|
3 | : GenericVideoFilter(_clip) { |
| 69 | 3 | dst_format = _sample_type; | |
| 70 |
1/2✓ Branch 5 → 6 taken 3 times.
✗ Branch 5 → 51 not taken.
|
3 | src_format = vi.SampleType(); |
| 71 | // Set up convertion matrix | ||
| 72 |
1/2✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 51 not taken.
|
3 | src_bps = vi.BytesPerChannelSample(); // Store old size |
| 73 | 3 | vi.sample_type = dst_format; | |
| 74 | 3 | tempbuffer_size = 0; | |
| 75 | |||
| 76 | #define PAIR(src, dst) ((src << 16) | dst) | ||
| 77 |
2/21✗ Branch 7 → 8 not taken.
✗ Branch 7 → 9 not taken.
✗ Branch 7 → 10 not taken.
✗ Branch 7 → 11 not taken.
✗ Branch 7 → 12 not taken.
✗ Branch 7 → 13 not taken.
✗ Branch 7 → 14 not taken.
✗ Branch 7 → 15 not taken.
✗ Branch 7 → 16 not taken.
✗ Branch 7 → 17 not taken.
✗ Branch 7 → 18 not taken.
✗ Branch 7 → 19 not taken.
✗ Branch 7 → 20 not taken.
✗ Branch 7 → 21 not taken.
✗ Branch 7 → 22 not taken.
✗ Branch 7 → 23 not taken.
✓ Branch 7 → 24 taken 1 time.
✓ Branch 7 → 25 taken 2 times.
✗ Branch 7 → 26 not taken.
✗ Branch 7 → 27 not taken.
✗ Branch 7 → 28 not taken.
|
3 | switch(PAIR(src_format, dst_format)) { |
| 78 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT16): convert_c = convert32To16; break; | |
| 79 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT32): convert_c = convert16To32; break; | |
| 80 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT8 ): convert_c = convert32To8; break; | |
| 81 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT32): convert_c = convert8To32; break; | |
| 82 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT8 ): convert_c = convert16To8; break; | |
| 83 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT16): convert_c = convert8To16; break; | |
| 84 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT24): two_stage = true; // no-break; | |
| 85 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT24): convert_c = convert32To24; break; | |
| 86 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_FLOAT): two_stage = true; // no-break; | |
| 87 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT32): convert_c = convert24To32; break; | |
| 88 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT16): convert_c = convert24To16; break; | |
| 89 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT24): convert_c = convert16To24; break; | |
| 90 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT8 ): convert_c = convert24To8; break; | |
| 91 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT24): convert_c = convert8To24; break; | |
| 92 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_FLOAT): convert_c = convert8ToFLT; break; | |
| 93 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT8): convert_c = convertFLTTo8; break; | |
| 94 | 1 | case PAIR(SAMPLE_INT16, SAMPLE_FLOAT): convert_c = convert16ToFLT; break; | |
| 95 | 2 | case PAIR(SAMPLE_FLOAT, SAMPLE_INT16): convert_c = convertFLTTo16; break; | |
| 96 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_FLOAT): convert_c = convert32ToFLT; break; | |
| 97 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT32): convert_c = convertFLTTo32; break; | |
| 98 | } | ||
| 99 | #ifdef INTEL_INTRINSICS | ||
| 100 |
2/19✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
✗ Branch 28 → 31 not taken.
✗ Branch 28 → 32 not taken.
✗ Branch 28 → 33 not taken.
✗ Branch 28 → 34 not taken.
✗ Branch 28 → 35 not taken.
✗ Branch 28 → 36 not taken.
✗ Branch 28 → 37 not taken.
✗ Branch 28 → 38 not taken.
✗ Branch 28 → 39 not taken.
✗ Branch 28 → 40 not taken.
✗ Branch 28 → 41 not taken.
✗ Branch 28 → 42 not taken.
✓ Branch 28 → 43 taken 1 time.
✓ Branch 28 → 44 taken 2 times.
✗ Branch 28 → 45 not taken.
✗ Branch 28 → 46 not taken.
✗ Branch 28 → 47 not taken.
|
3 | switch(PAIR(src_format, dst_format)) { |
| 101 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT16): convert_sse2 = convert32To16_SSE2; convert_avx2 = convert32To16_AVX2; break; | |
| 102 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT32): convert_sse2 = convert16To32_SSE2; convert_avx2 = convert16To32_AVX2; break; | |
| 103 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT8 ): convert_sse2 = convert32To8_SSE2; break; | |
| 104 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT32): convert_sse2 = convert8To32_SSE2; break; | |
| 105 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT8 ): convert_sse2 = convert16To8_SSE2; break; | |
| 106 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT16): convert_sse2 = convert8To16_SSE2; break; | |
| 107 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT24): | |
| 108 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT24): convert_ssse3 = convert32To24_SSSE3; break; | |
| 109 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_FLOAT): | |
| 110 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT32): convert_ssse3 = convert24To32_SSSE3; break; | |
| 111 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT16): convert_ssse3 = convert24To16_SSSE3; break; | |
| 112 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT24): convert_ssse3 = convert16To24_SSSE3; break; | |
| 113 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT8 ): convert_ssse3 = convert24To8_SSSE3; break; | |
| 114 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT24): convert_ssse3 = convert8To24_SSSE3; break; | |
| 115 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_FLOAT): convert_sse41 = convert8ToFLT_SSE41; convert_avx2 = convert8ToFLT_AVX2; break; | |
| 116 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT8) : convert_sse2 = convertFLTTo8_SSE2; convert_avx2 = convertFLTTo8_AVX2; break; | |
| 117 | 1 | case PAIR(SAMPLE_INT16, SAMPLE_FLOAT): convert_sse41 = convert16ToFLT_SSE41; convert_avx2 = convert16ToFLT_AVX2; break; | |
| 118 | 2 | case PAIR(SAMPLE_FLOAT, SAMPLE_INT16): convert_sse2 = convertFLTTo16_SSE2; convert_avx2 = convertFLTTo16_AVX2; break; | |
| 119 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_FLOAT): convert_sse2 = convert32ToFLT_SSE2; convert_avx2 = convert32ToFLT_AVX2; break; | |
| 120 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT32): convert_sse41 = convertFLTTo32_SSE41; convert_avx2 = convertFLTTo32_AVX2; break; | |
| 121 | } | ||
| 122 | #endif | ||
| 123 | #undef PAIR | ||
| 124 | 3 | } | |
| 125 | |||
| 126 | 4 | ConvertAudio::~ConvertAudio() { | |
| 127 |
1/2✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 5 not taken.
|
3 | if (tempbuffer_size) { |
| 128 | 3 | avs_free(tempbuffer); | |
| 129 | 3 | tempbuffer_size = 0; | |
| 130 | } | ||
| 131 | 4 | } | |
| 132 | |||
| 133 | 3 | void __stdcall ConvertAudio::GetAudio(void *buf, int64_t start, int64_t count, IScriptEnvironment *env) { | |
| 134 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 3 times.
|
3 | if (src_format == dst_format) { |
| 135 | // Shouldn't happen, but just in case | ||
| 136 | ✗ | child->GetAudio(buf, start, count, env); | |
| 137 | ✗ | return; | |
| 138 | } | ||
| 139 | |||
| 140 | 3 | int channels = vi.AudioChannels(); | |
| 141 | |||
| 142 |
1/2✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 27 not taken.
|
3 | if (tempbuffer_size < count) { |
| 143 |
3/6✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 11 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 3 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 3 times.
|
3 | if (count < 0 || count > std::numeric_limits<int>::max()) |
| 144 | ✗ | env->ThrowError("ConvertAudio: audio count is too large."); | |
| 145 | |||
| 146 | 3 | const size_t sample_count = static_cast<size_t>(count); | |
| 147 | 3 | const size_t bytes_per_sample = static_cast<size_t>(src_bps) * static_cast<size_t>(channels); | |
| 148 | |||
| 149 |
3/6✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 18 not taken.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 3 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 3 times.
|
3 | if (bytes_per_sample == 0 || sample_count > std::numeric_limits<size_t>::max() / bytes_per_sample) |
| 150 | ✗ | env->ThrowError("ConvertAudio: audio buffer size overflow."); | |
| 151 | |||
| 152 | 3 | const size_t buffer_size = sample_count * bytes_per_sample; | |
| 153 | 3 | char* new_tempbuffer = static_cast<char*>(avs_malloc(buffer_size, 16)); | |
| 154 | |||
| 155 |
1/2✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 3 times.
|
3 | if (!new_tempbuffer) |
| 156 | ✗ | env->ThrowError("ConvertAudio: insufficient memory."); | |
| 157 | |||
| 158 | 3 | avs_free(tempbuffer); | |
| 159 | 3 | tempbuffer = new_tempbuffer; | |
| 160 | 3 | tempbuffer_size = static_cast<int>(count); | |
| 161 | } | ||
| 162 | |||
| 163 | 3 | child->GetAudio(tempbuffer, start, count, env); | |
| 164 | |||
| 165 |
1/2✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 54 not taken.
|
3 | if (convert == nullptr) { |
| 166 | 3 | convert = convert_c; | |
| 167 |
2/2✓ Branch 30 → 31 taken 2 times.
✓ Branch 30 → 32 taken 1 time.
|
3 | convert_float = src_format == SAMPLE_FLOAT ? convertFLTTo32 : convert32ToFLT; // for two-stage |
| 168 | #ifdef INTEL_INTRINSICS | ||
| 169 | 3 | int cpu_flags = env->GetCPUFlags(); | |
| 170 |
1/2✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 39 not taken.
|
3 | if ((cpu_flags & CPUF_SSE2)) { |
| 171 |
2/2✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 1 time.
|
3 | if (convert_sse2) |
| 172 | 2 | convert = convert_sse2; | |
| 173 |
2/2✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 39 taken 2 times.
|
3 | if (src_format != SAMPLE_FLOAT) |
| 174 | 1 | convert_float = convert32ToFLT_SSE2; | |
| 175 | } | ||
| 176 |
1/2✓ Branch 39 → 40 taken 3 times.
✗ Branch 39 → 42 not taken.
|
3 | if ((cpu_flags & CPUF_SSSE3)) { |
| 177 |
1/2✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 3 times.
|
3 | if (convert_ssse3) |
| 178 | ✗ | convert = convert_ssse3; | |
| 179 | } | ||
| 180 |
1/2✓ Branch 42 → 43 taken 3 times.
✗ Branch 42 → 47 not taken.
|
3 | if ((cpu_flags & CPUF_SSE4_1)) { |
| 181 |
2/2✓ Branch 43 → 44 taken 1 time.
✓ Branch 43 → 45 taken 2 times.
|
3 | if (convert_sse41) |
| 182 | 1 | convert = convert_sse41; | |
| 183 |
2/2✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 47 taken 1 time.
|
3 | if (src_format == SAMPLE_FLOAT) |
| 184 | 2 | convert_float = convertFLTTo32_SSE41; | |
| 185 | } | ||
| 186 |
1/2✓ Branch 47 → 48 taken 3 times.
✗ Branch 47 → 54 not taken.
|
3 | if ((cpu_flags & CPUF_AVX2)) { |
| 187 |
1/2✓ Branch 48 → 49 taken 3 times.
✗ Branch 48 → 50 not taken.
|
3 | if (convert_avx2) |
| 188 | 3 | convert = convert_avx2; | |
| 189 |
2/2✓ Branch 50 → 51 taken 2 times.
✓ Branch 50 → 52 taken 1 time.
|
3 | convert_float = src_format == SAMPLE_FLOAT ? convertFLTTo32_AVX2 : convert32ToFLT_AVX2; |
| 190 | } | ||
| 191 | #endif | ||
| 192 | } | ||
| 193 | |||
| 194 | 3 | int sample_count = static_cast<int>(count * channels); | |
| 195 | |||
| 196 | // Direct conversion cases | ||
| 197 |
1/2✓ Branch 54 → 55 taken 3 times.
✗ Branch 54 → 57 not taken.
|
3 | if (!two_stage) { |
| 198 | 3 | convert(tempbuffer, buf, sample_count); | |
| 199 | 3 | return; | |
| 200 | } | ||
| 201 | |||
| 202 | // Floating point cases | ||
| 203 | ✗ | if (src_format == SAMPLE_FLOAT) { | |
| 204 | ✗ | convert_float(tempbuffer, tempbuffer, sample_count); | |
| 205 | ✗ | convert(tempbuffer, buf, sample_count); | |
| 206 | ✗ | return; | |
| 207 | } | ||
| 208 | |||
| 209 | ✗ | if (dst_format == SAMPLE_FLOAT) { | |
| 210 | ✗ | convert(tempbuffer, buf, sample_count); | |
| 211 | ✗ | convert_float(buf, buf, sample_count); | |
| 212 | ✗ | return; | |
| 213 | } | ||
| 214 | } | ||
| 215 |