]>
Commit | Line | Data |
---|---|---|
85571bc7 FB |
1 | /* |
2 | * QEMU Mixing engine | |
3 | * | |
4 | * Copyright (c) 2004 Vassili Karpov (malc) | |
5 | * Copyright (c) 1998 Fabrice Bellard | |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | * of this software and associated documentation files (the "Software"), to deal | |
9 | * in the Software without restriction, including without limitation the rights | |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | * copies of the Software, and to permit persons to whom the Software is | |
12 | * furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be included in | |
15 | * all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | * THE SOFTWARE. | |
24 | */ | |
25 | #include "vl.h" | |
26 | //#define DEBUG_FP | |
27 | #include "audio/mixeng.h" | |
28 | ||
29 | #define IN_T int8_t | |
30 | #define IN_MIN CHAR_MIN | |
31 | #define IN_MAX CHAR_MAX | |
32 | #define SIGNED | |
33 | #include "mixeng_template.h" | |
34 | #undef SIGNED | |
35 | #undef IN_MAX | |
36 | #undef IN_MIN | |
37 | #undef IN_T | |
38 | ||
39 | #define IN_T uint8_t | |
40 | #define IN_MIN 0 | |
41 | #define IN_MAX UCHAR_MAX | |
42 | #include "mixeng_template.h" | |
43 | #undef IN_MAX | |
44 | #undef IN_MIN | |
45 | #undef IN_T | |
46 | ||
47 | #define IN_T int16_t | |
48 | #define IN_MIN SHRT_MIN | |
49 | #define IN_MAX SHRT_MAX | |
50 | #define SIGNED | |
51 | #include "mixeng_template.h" | |
52 | #undef SIGNED | |
53 | #undef IN_MAX | |
54 | #undef IN_MIN | |
55 | #undef IN_T | |
56 | ||
57 | #define IN_T uint16_t | |
58 | #define IN_MIN 0 | |
59 | #define IN_MAX USHRT_MAX | |
60 | #include "mixeng_template.h" | |
61 | #undef IN_MAX | |
62 | #undef IN_MIN | |
63 | #undef IN_T | |
64 | ||
65 | t_sample *mixeng_conv[2][2][2] = { | |
66 | { | |
67 | { | |
68 | conv_uint8_t_to_mono, | |
69 | conv_uint16_t_to_mono | |
70 | }, | |
71 | { | |
72 | conv_int8_t_to_mono, | |
73 | conv_int16_t_to_mono | |
74 | } | |
75 | }, | |
76 | { | |
77 | { | |
78 | conv_uint8_t_to_stereo, | |
79 | conv_uint16_t_to_stereo | |
80 | }, | |
81 | { | |
82 | conv_int8_t_to_stereo, | |
83 | conv_int16_t_to_stereo | |
84 | } | |
85 | } | |
86 | }; | |
87 | ||
88 | f_sample *mixeng_clip[2][2][2] = { | |
89 | { | |
90 | { | |
91 | clip_uint8_t_from_mono, | |
92 | clip_uint16_t_from_mono | |
93 | }, | |
94 | { | |
95 | clip_int8_t_from_mono, | |
96 | clip_int16_t_from_mono | |
97 | } | |
98 | }, | |
99 | { | |
100 | { | |
101 | clip_uint8_t_from_stereo, | |
102 | clip_uint16_t_from_stereo | |
103 | }, | |
104 | { | |
105 | clip_int8_t_from_stereo, | |
106 | clip_int16_t_from_stereo | |
107 | } | |
108 | } | |
109 | }; | |
110 | ||
111 | /* | |
112 | * August 21, 1998 | |
113 | * Copyright 1998 Fabrice Bellard. | |
114 | * | |
115 | * [Rewrote completly the code of Lance Norskog And Sundry | |
116 | * Contributors with a more efficient algorithm.] | |
117 | * | |
118 | * This source code is freely redistributable and may be used for | |
119 | * any purpose. This copyright notice must be maintained. | |
120 | * Lance Norskog And Sundry Contributors are not responsible for | |
121 | * the consequences of using this software. | |
122 | */ | |
123 | ||
124 | /* | |
125 | * Sound Tools rate change effect file. | |
126 | */ | |
127 | /* | |
128 | * Linear Interpolation. | |
129 | * | |
130 | * The use of fractional increment allows us to use no buffer. It | |
131 | * avoid the problems at the end of the buffer we had with the old | |
132 | * method which stored a possibly big buffer of size | |
133 | * lcm(in_rate,out_rate). | |
134 | * | |
135 | * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If | |
136 | * the input & output frequencies are equal, a delay of one sample is | |
137 | * introduced. Limited to processing 32-bit count worth of samples. | |
138 | * | |
139 | * 1 << FRAC_BITS evaluating to zero in several places. Changed with | |
140 | * an (unsigned long) cast to make it safe. MarkMLl 2/1/99 | |
141 | */ | |
142 | ||
143 | /* Private data */ | |
144 | typedef struct ratestuff { | |
145 | uint64_t opos; | |
146 | uint64_t opos_inc; | |
147 | uint32_t ipos; /* position in the input stream (integer) */ | |
148 | st_sample_t ilast; /* last sample in the input stream */ | |
149 | } *rate_t; | |
150 | ||
151 | /* | |
152 | * Prepare processing. | |
153 | */ | |
154 | void *st_rate_start (int inrate, int outrate) | |
155 | { | |
156 | rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff)); | |
157 | ||
158 | if (!rate) { | |
159 | exit (EXIT_FAILURE); | |
160 | } | |
161 | ||
162 | if (inrate == outrate) { | |
163 | // exit (EXIT_FAILURE); | |
164 | } | |
165 | ||
166 | if (inrate >= 65535 || outrate >= 65535) { | |
167 | // exit (EXIT_FAILURE); | |
168 | } | |
169 | ||
170 | rate->opos = 0; | |
171 | ||
172 | /* increment */ | |
173 | rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate; | |
174 | ||
175 | rate->ipos = 0; | |
176 | rate->ilast.l = 0; | |
177 | rate->ilast.r = 0; | |
178 | return rate; | |
179 | } | |
180 | ||
181 | /* | |
182 | * Processed signed long samples from ibuf to obuf. | |
183 | * Return number of samples processed. | |
184 | */ | |
185 | void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf, | |
186 | int *isamp, int *osamp) | |
187 | { | |
188 | rate_t rate = (rate_t) opaque; | |
189 | st_sample_t *istart, *iend; | |
190 | st_sample_t *ostart, *oend; | |
191 | st_sample_t ilast, icur, out; | |
192 | int64_t t; | |
193 | ||
194 | ilast = rate->ilast; | |
195 | ||
196 | istart = ibuf; | |
197 | iend = ibuf + *isamp; | |
198 | ||
199 | ostart = obuf; | |
200 | oend = obuf + *osamp; | |
201 | ||
202 | if (rate->opos_inc == 1ULL << 32) { | |
203 | int i, n = *isamp > *osamp ? *osamp : *isamp; | |
204 | for (i = 0; i < n; i++) { | |
205 | obuf[i].l += ibuf[i].r; | |
206 | obuf[i].r += ibuf[i].r; | |
207 | } | |
208 | *isamp = n; | |
209 | *osamp = n; | |
210 | return; | |
211 | } | |
212 | ||
213 | while (obuf < oend) { | |
214 | ||
215 | /* Safety catch to make sure we have input samples. */ | |
216 | if (ibuf >= iend) | |
217 | break; | |
218 | ||
219 | /* read as many input samples so that ipos > opos */ | |
220 | ||
221 | while (rate->ipos <= (rate->opos >> 32)) { | |
222 | ilast = *ibuf++; | |
223 | rate->ipos++; | |
224 | /* See if we finished the input buffer yet */ | |
225 | if (ibuf >= iend) goto the_end; | |
226 | } | |
227 | ||
228 | icur = *ibuf; | |
229 | ||
230 | /* interpolate */ | |
231 | t = rate->opos & 0xffffffff; | |
232 | out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX; | |
233 | out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX; | |
234 | ||
235 | /* output sample & increment position */ | |
236 | #if 0 | |
237 | *obuf++ = out; | |
238 | #else | |
239 | obuf->l += out.l; | |
240 | obuf->r += out.r; | |
241 | obuf += 1; | |
242 | #endif | |
243 | rate->opos += rate->opos_inc; | |
244 | } | |
245 | ||
246 | the_end: | |
247 | *isamp = ibuf - istart; | |
248 | *osamp = obuf - ostart; | |
249 | rate->ilast = ilast; | |
250 | } | |
251 | ||
252 | void st_rate_stop (void *opaque) | |
253 | { | |
254 | qemu_free (opaque); | |
255 | } |