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 | |||
| 50 | // There are two type parameters. Acceptable sample types and a prefered sample type. | ||
| 51 | // If the current clip is already one of the defined types in sampletype, this will be returned. | ||
| 52 | // If not, the current clip will be converted to the prefered type. | ||
| 53 | 20 | PClip ConvertAudio::Create(PClip clip, int sample_type, int prefered_type) { | |
| 54 |
5/6✓ Branch 5 → 6 taken 20 times.
✗ Branch 5 → 10 not taken.
✓ Branch 9 → 10 taken 19 times.
✓ Branch 9 → 11 taken 1 time.
✓ Branch 12 → 13 taken 19 times.
✓ Branch 12 → 14 taken 1 time.
|
20 | if ((!clip->GetVideoInfo().HasAudio()) || clip->GetVideoInfo().SampleType() & (sample_type | prefered_type)) { |
| 55 | // Sample type is already ok! | ||
| 56 | 19 | return clip; | |
| 57 | } else | ||
| 58 |
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); |
| 59 | } | ||
| 60 | |||
| 61 | 1 | int __stdcall ConvertAudio::SetCacheHints(int cachehints, int frame_range) { | |
| 62 | // We do pass cache requests upwards, to the next filter. | ||
| 63 | 1 | return child->SetCacheHints(cachehints, frame_range); | |
| 64 | } | ||
| 65 | |||
| 66 | 3 | ConvertAudio::ConvertAudio(PClip _clip, int _sample_type) | |
| 67 |
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) { |
| 68 | 3 | dst_format = _sample_type; | |
| 69 |
1/2✓ Branch 5 → 6 taken 3 times.
✗ Branch 5 → 51 not taken.
|
3 | src_format = vi.SampleType(); |
| 70 | // Set up convertion matrix | ||
| 71 |
1/2✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 51 not taken.
|
3 | src_bps = vi.BytesPerChannelSample(); // Store old size |
| 72 | 3 | vi.sample_type = dst_format; | |
| 73 | 3 | tempbuffer_size = 0; | |
| 74 | |||
| 75 | #define PAIR(src, dst) ((src << 16) | dst) | ||
| 76 |
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)) { |
| 77 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT16): convert_c = convert32To16; break; | |
| 78 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT32): convert_c = convert16To32; break; | |
| 79 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT8 ): convert_c = convert32To8; break; | |
| 80 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT32): convert_c = convert8To32; break; | |
| 81 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT8 ): convert_c = convert16To8; break; | |
| 82 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT16): convert_c = convert8To16; break; | |
| 83 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT24): two_stage = true; // no-break; | |
| 84 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT24): convert_c = convert32To24; break; | |
| 85 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_FLOAT): two_stage = true; // no-break; | |
| 86 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT32): convert_c = convert24To32; break; | |
| 87 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT16): convert_c = convert24To16; break; | |
| 88 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT24): convert_c = convert16To24; break; | |
| 89 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT8 ): convert_c = convert24To8; break; | |
| 90 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT24): convert_c = convert8To24; break; | |
| 91 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_FLOAT): convert_c = convert8ToFLT; break; | |
| 92 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT8): convert_c = convertFLTTo8; break; | |
| 93 | 1 | case PAIR(SAMPLE_INT16, SAMPLE_FLOAT): convert_c = convert16ToFLT; break; | |
| 94 | 2 | case PAIR(SAMPLE_FLOAT, SAMPLE_INT16): convert_c = convertFLTTo16; break; | |
| 95 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_FLOAT): convert_c = convert32ToFLT; break; | |
| 96 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT32): convert_c = convertFLTTo32; break; | |
| 97 | } | ||
| 98 | #ifdef INTEL_INTRINSICS | ||
| 99 |
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)) { |
| 100 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT16): convert_sse2 = convert32To16_SSE2; convert_avx2 = convert32To16_AVX2; break; | |
| 101 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT32): convert_sse2 = convert16To32_SSE2; convert_avx2 = convert16To32_AVX2; break; | |
| 102 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT8 ): convert_sse2 = convert32To8_SSE2; break; | |
| 103 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT32): convert_sse2 = convert8To32_SSE2; break; | |
| 104 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT8 ): convert_sse2 = convert16To8_SSE2; break; | |
| 105 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT16): convert_sse2 = convert8To16_SSE2; break; | |
| 106 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT24): | |
| 107 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_INT24): convert_ssse3 = convert32To24_SSSE3; break; | |
| 108 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_FLOAT): | |
| 109 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT32): convert_ssse3 = convert24To32_SSSE3; break; | |
| 110 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT16): convert_ssse3 = convert24To16_SSSE3; break; | |
| 111 | ✗ | case PAIR(SAMPLE_INT16, SAMPLE_INT24): convert_ssse3 = convert16To24_SSSE3; break; | |
| 112 | ✗ | case PAIR(SAMPLE_INT24, SAMPLE_INT8 ): convert_ssse3 = convert24To8_SSSE3; break; | |
| 113 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_INT24): convert_ssse3 = convert8To24_SSSE3; break; | |
| 114 | ✗ | case PAIR(SAMPLE_INT8 , SAMPLE_FLOAT): convert_sse41 = convert8ToFLT_SSE41; convert_avx2 = convert8ToFLT_AVX2; break; | |
| 115 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT8) : convert_sse2 = convertFLTTo8_SSE2; convert_avx2 = convertFLTTo8_AVX2; break; | |
| 116 | 1 | case PAIR(SAMPLE_INT16, SAMPLE_FLOAT): convert_sse41 = convert16ToFLT_SSE41; convert_avx2 = convert16ToFLT_AVX2; break; | |
| 117 | 2 | case PAIR(SAMPLE_FLOAT, SAMPLE_INT16): convert_sse2 = convertFLTTo16_SSE2; convert_avx2 = convertFLTTo16_AVX2; break; | |
| 118 | ✗ | case PAIR(SAMPLE_INT32, SAMPLE_FLOAT): convert_sse2 = convert32ToFLT_SSE2; convert_avx2 = convert32ToFLT_AVX2; break; | |
| 119 | ✗ | case PAIR(SAMPLE_FLOAT, SAMPLE_INT32): convert_sse41 = convertFLTTo32_SSE41; convert_avx2 = convertFLTTo32_AVX2; break; | |
| 120 | } | ||
| 121 | #endif | ||
| 122 | #undef PAIR | ||
| 123 | 3 | } | |
| 124 | |||
| 125 | 4 | ConvertAudio::~ConvertAudio() { | |
| 126 |
1/2✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 5 not taken.
|
3 | if (tempbuffer_size) { |
| 127 | 3 | avs_free(tempbuffer); | |
| 128 | 3 | tempbuffer_size = 0; | |
| 129 | } | ||
| 130 | 4 | } | |
| 131 | |||
| 132 | 3 | void __stdcall ConvertAudio::GetAudio(void *buf, int64_t start, int64_t count, IScriptEnvironment *env) { | |
| 133 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 3 times.
|
3 | if (src_format == dst_format) { |
| 134 | // Shouldn't happen, but just in case | ||
| 135 | ✗ | child->GetAudio(buf, start, count, env); | |
| 136 | ✗ | return; | |
| 137 | } | ||
| 138 | |||
| 139 | 3 | int channels = vi.AudioChannels(); | |
| 140 | |||
| 141 |
1/2✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 12 not taken.
|
3 | if (tempbuffer_size < count) { |
| 142 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 3 times.
|
3 | if (tempbuffer_size) |
| 143 | ✗ | avs_free(tempbuffer); | |
| 144 | 3 | tempbuffer = (char *)avs_malloc((int)count * src_bps * channels, 16); | |
| 145 | 3 | tempbuffer_size = (int)count; | |
| 146 | } | ||
| 147 | |||
| 148 | 3 | child->GetAudio(tempbuffer, start, count, env); | |
| 149 | |||
| 150 |
1/2✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 39 not taken.
|
3 | if (convert == nullptr) { |
| 151 | 3 | convert = convert_c; | |
| 152 |
2/2✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 17 taken 1 time.
|
3 | convert_float = src_format == SAMPLE_FLOAT ? convertFLTTo32 : convert32ToFLT; // for two-stage |
| 153 | #ifdef INTEL_INTRINSICS | ||
| 154 | 3 | int cpu_flags = env->GetCPUFlags(); | |
| 155 |
1/2✓ Branch 19 → 20 taken 3 times.
✗ Branch 19 → 24 not taken.
|
3 | if ((cpu_flags & CPUF_SSE2)) { |
| 156 |
2/2✓ Branch 20 → 21 taken 2 times.
✓ Branch 20 → 22 taken 1 time.
|
3 | if (convert_sse2) |
| 157 | 2 | convert = convert_sse2; | |
| 158 |
2/2✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 24 taken 2 times.
|
3 | if (src_format != SAMPLE_FLOAT) |
| 159 | 1 | convert_float = convert32ToFLT_SSE2; | |
| 160 | } | ||
| 161 |
1/2✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 27 not taken.
|
3 | if ((cpu_flags & CPUF_SSSE3)) { |
| 162 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 3 times.
|
3 | if (convert_ssse3) |
| 163 | ✗ | convert = convert_ssse3; | |
| 164 | } | ||
| 165 |
1/2✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 32 not taken.
|
3 | if ((cpu_flags & CPUF_SSE4_1)) { |
| 166 |
2/2✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 2 times.
|
3 | if (convert_sse41) |
| 167 | 1 | convert = convert_sse41; | |
| 168 |
2/2✓ Branch 30 → 31 taken 2 times.
✓ Branch 30 → 32 taken 1 time.
|
3 | if (src_format == SAMPLE_FLOAT) |
| 169 | 2 | convert_float = convertFLTTo32_SSE41; | |
| 170 | } | ||
| 171 |
1/2✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 39 not taken.
|
3 | if ((cpu_flags & CPUF_AVX2)) { |
| 172 |
1/2✓ Branch 33 → 34 taken 3 times.
✗ Branch 33 → 35 not taken.
|
3 | if (convert_avx2) |
| 173 | 3 | convert = convert_avx2; | |
| 174 |
2/2✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 1 time.
|
3 | convert_float = src_format == SAMPLE_FLOAT ? convertFLTTo32_AVX2 : convert32ToFLT_AVX2; |
| 175 | } | ||
| 176 | #endif | ||
| 177 | } | ||
| 178 | |||
| 179 | 3 | int sample_count = static_cast<int>(count * channels); | |
| 180 | |||
| 181 | // Direct conversion cases | ||
| 182 |
1/2✓ Branch 39 → 40 taken 3 times.
✗ Branch 39 → 42 not taken.
|
3 | if (!two_stage) { |
| 183 | 3 | convert(tempbuffer, buf, sample_count); | |
| 184 | 3 | return; | |
| 185 | } | ||
| 186 | |||
| 187 | // Floating point cases | ||
| 188 | ✗ | if (src_format == SAMPLE_FLOAT) { | |
| 189 | ✗ | convert_float(tempbuffer, tempbuffer, sample_count); | |
| 190 | ✗ | convert(tempbuffer, buf, sample_count); | |
| 191 | ✗ | return; | |
| 192 | } | ||
| 193 | |||
| 194 | ✗ | if (dst_format == SAMPLE_FLOAT) { | |
| 195 | ✗ | convert(tempbuffer, buf, sample_count); | |
| 196 | ✗ | convert_float(buf, buf, sample_count); | |
| 197 | ✗ | return; | |
| 198 | } | ||
| 199 | } | ||
| 200 |