Commit | Line | Data |
---|---|---|
3719602c PC |
1 | /* Copyright (C) 2010-2020 The RetroArch team |
2 | * | |
3 | * --------------------------------------------------------------------------------------- | |
4 | * The following license statement only applies to this file (audio_resampler.c). | |
5 | * --------------------------------------------------------------------------------------- | |
6 | * | |
7 | * Permission is hereby granted, free of charge, | |
8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), | |
9 | * to deal in the Software without restriction, including without limitation the rights to | |
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |
11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |
16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
21 | */ | |
22 | ||
23 | #include <string.h> | |
24 | ||
25 | #include <string/stdstring.h> | |
26 | #include <features/features_cpu.h> | |
27 | #include <file/config_file_userdata.h> | |
28 | ||
29 | #include <audio/audio_resampler.h> | |
30 | ||
31 | static void resampler_null_process(void *a, struct resampler_data *b) { } | |
32 | static void resampler_null_free(void *a) { } | |
33 | static void *resampler_null_init(const struct resampler_config *a, double b, | |
34 | enum resampler_quality c, resampler_simd_mask_t d) { return (void*)0; } | |
35 | ||
36 | retro_resampler_t null_resampler = { | |
37 | resampler_null_init, | |
38 | resampler_null_process, | |
39 | resampler_null_free, | |
40 | RESAMPLER_API_VERSION, | |
41 | "null", | |
42 | "null" | |
43 | }; | |
44 | ||
45 | static const retro_resampler_t *resampler_drivers[] = { | |
46 | &sinc_resampler, | |
47 | #ifdef HAVE_CC_RESAMPLER | |
48 | &CC_resampler, | |
49 | #endif | |
50 | #ifdef HAVE_NEAREST_RESAMPLER | |
51 | &nearest_resampler, | |
52 | #endif | |
53 | &null_resampler, | |
54 | NULL, | |
55 | }; | |
56 | ||
57 | static const struct resampler_config resampler_config = { | |
58 | config_userdata_get_float, | |
59 | config_userdata_get_int, | |
60 | config_userdata_get_float_array, | |
61 | config_userdata_get_int_array, | |
62 | config_userdata_get_string, | |
63 | config_userdata_free, | |
64 | }; | |
65 | ||
66 | /** | |
67 | * find_resampler_driver_index: | |
68 | * @ident : Identifier of resampler driver to find. | |
69 | * | |
70 | * Finds resampler driver index by @ident name. | |
71 | * | |
72 | * Returns: resampler driver index if resampler driver was found, otherwise | |
73 | * -1. | |
74 | **/ | |
75 | static int find_resampler_driver_index(const char *ident) | |
76 | { | |
77 | unsigned i; | |
78 | ||
79 | for (i = 0; resampler_drivers[i]; i++) | |
80 | if (string_is_equal_noncase(ident, resampler_drivers[i]->ident)) | |
81 | return i; | |
82 | return -1; | |
83 | } | |
84 | ||
85 | /** | |
86 | * find_resampler_driver: | |
87 | * @ident : Identifier of resampler driver to find. | |
88 | * | |
89 | * Finds resampler by @ident name. | |
90 | * | |
91 | * Returns: resampler driver if resampler driver was found, otherwise | |
92 | * NULL. | |
93 | **/ | |
94 | static const retro_resampler_t *find_resampler_driver(const char *ident) | |
95 | { | |
96 | int i = find_resampler_driver_index(ident); | |
97 | ||
98 | if (i >= 0) | |
99 | return resampler_drivers[i]; | |
100 | ||
101 | return resampler_drivers[0]; | |
102 | } | |
103 | ||
104 | /** | |
105 | * resampler_append_plugs: | |
106 | * @re : Resampler handle | |
107 | * @backend : Resampler backend that is about to be set. | |
108 | * @bw_ratio : Bandwidth ratio. | |
109 | * | |
110 | * Initializes resampler driver based on queried CPU features. | |
111 | * | |
112 | * Returns: true (1) if successfully initialized, otherwise false (0). | |
113 | **/ | |
114 | static bool resampler_append_plugs(void **re, | |
115 | const retro_resampler_t **backend, | |
116 | enum resampler_quality quality, | |
117 | double bw_ratio) | |
118 | { | |
119 | resampler_simd_mask_t mask = (resampler_simd_mask_t)cpu_features_get(); | |
120 | ||
121 | if (*backend) | |
122 | *re = (*backend)->init(&resampler_config, bw_ratio, quality, mask); | |
123 | ||
124 | if (!*re) | |
125 | return false; | |
126 | return true; | |
127 | } | |
128 | ||
129 | ||
130 | /** | |
131 | * audio_resampler_driver_find_handle: | |
132 | * @idx : index of driver to get handle to. | |
133 | * | |
134 | * Returns: handle to audio resampler driver at index. Can be NULL | |
135 | * if nothing found. | |
136 | **/ | |
137 | const void *audio_resampler_driver_find_handle(int idx) | |
138 | { | |
139 | const void *drv = resampler_drivers[idx]; | |
140 | if (!drv) | |
141 | return NULL; | |
142 | return drv; | |
143 | } | |
144 | ||
145 | /** | |
146 | * audio_resampler_driver_find_ident: | |
147 | * @idx : index of driver to get handle to. | |
148 | * | |
149 | * Returns: Human-readable identifier of audio resampler driver at index. | |
150 | * Can be NULL if nothing found. | |
151 | **/ | |
152 | const char *audio_resampler_driver_find_ident(int idx) | |
153 | { | |
154 | const retro_resampler_t *drv = resampler_drivers[idx]; | |
155 | if (!drv) | |
156 | return NULL; | |
157 | return drv->ident; | |
158 | } | |
159 | ||
160 | /** | |
161 | * retro_resampler_realloc: | |
162 | * @re : Resampler handle | |
163 | * @backend : Resampler backend that is about to be set. | |
164 | * @ident : Identifier name for resampler we want. | |
165 | * @bw_ratio : Bandwidth ratio. | |
166 | * | |
167 | * Reallocates resampler. Will free previous handle before | |
168 | * allocating a new one. If ident is NULL, first resampler will be used. | |
169 | * | |
170 | * Returns: true (1) if successful, otherwise false (0). | |
171 | **/ | |
172 | bool retro_resampler_realloc(void **re, const retro_resampler_t **backend, | |
173 | const char *ident, enum resampler_quality quality, double bw_ratio) | |
174 | { | |
175 | if (*re && *backend) | |
176 | (*backend)->free(*re); | |
177 | ||
178 | *re = NULL; | |
179 | *backend = find_resampler_driver(ident); | |
180 | ||
181 | if (!resampler_append_plugs(re, backend, quality, bw_ratio)) | |
182 | { | |
183 | if (!*re) | |
184 | *backend = NULL; | |
185 | return false; | |
186 | } | |
187 | ||
188 | return true; | |
189 | } |