2 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
3 * Copyright (c) 2003 Orion Hodson <orion@FreeBSD.org>
4 * Copyright (c) 2005 Ariff Abdullah <ariff@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Major cleanup and overhaul to remove much redundant codes.
33 * 1) Support for signed / unsigned 16, 24 and 32 bit,
34 * big / little endian,
35 * 2) Unlimited channels.
40 * *New* and rewritten soft sample rate converter supporting arbitrary sample
41 * rates, fine grained scaling/coefficients and a unified up/down stereo
42 * converter. Most of the disclaimers from orion's notes also applies
43 * here, regarding linear interpolation deficiencies and pre/post
44 * anti-aliasing filtering issues. This version comes with a much simpler and
45 * tighter interface, although it works almost exactly like the older one.
47 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
49 * This new implementation is fully dedicated in memory of Cameron Grant, *
50 * the creator of the magnificent, highly addictive feeder infrastructure. *
52 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
57 * This rate conversion code uses linear interpolation without any
58 * pre- or post- interpolation filtering to combat aliasing. This
59 * greatly limits the sound quality and should be addressed at some
60 * stage in the future.
62 * Since this accuracy of interpolation is sensitive and examination
63 * of the algorithm output is harder from the kernel, the code is
64 * designed to be compiled in the kernel and in a userland test
65 * harness. This is done by selectively including and excluding code
66 * with several portions based on whether _KERNEL is defined. It's a
67 * little ugly, but exceedingly useful. The testsuite and its
68 * revisions can be found at:
69 * http://people.freebsd.org/~orion/files/feedrate/
71 * Special thanks to Ken Marx for exposing flaws in the code and for
75 #include <dev/sound/pcm/sound.h>
76 #include "feeder_if.h"
78 SND_DECLARE_FILE("$FreeBSD$");
80 #define RATE_ASSERT(x, y) /* KASSERT(x,y) */
81 #define RATE_TEST(x, y) /* if (!(x)) printf y */
82 #define RATE_TRACE(x...) /* printf(x) */
84 MALLOC_DEFINE(M_RATEFEEDER, "ratefeed", "pcm rate feeder");
87 * Don't overflow 32bit integer, since everything is done
88 * within 32bit arithmetic.
90 #define RATE_FACTOR_MIN 1
91 #define RATE_FACTOR_MAX PCM_S24_MAX
92 #define RATE_FACTOR_SAFE(val) (!((val) < RATE_FACTOR_MIN || \
93 (val) > RATE_FACTOR_MAX))
95 struct feed_rate_info;
97 typedef uint32_t (*feed_rate_converter)(struct feed_rate_info *,
100 struct feed_rate_info {
101 uint32_t src, dst; /* rounded source / destination rates */
102 uint32_t rsrc, rdst; /* original source / destination rates */
103 uint32_t gx, gy; /* interpolation / decimation ratio */
104 uint32_t alpha; /* interpolation distance */
105 uint32_t pos, bpos; /* current sample / buffer positions */
106 uint32_t bufsz; /* total buffer size limit */
107 uint32_t bufsz_init; /* allocated buffer size */
108 uint32_t channels; /* total channels */
109 uint32_t bps; /* bytes-per-sample */
110 #ifdef FEEDRATE_STRAY
111 uint32_t stray; /* stray bytes */
114 feed_rate_converter convert;
117 int feeder_rate_min = FEEDRATE_RATEMIN;
118 int feeder_rate_max = FEEDRATE_RATEMAX;
119 int feeder_rate_round = FEEDRATE_ROUNDHZ;
121 TUNABLE_INT("hw.snd.feeder_rate_min", &feeder_rate_min);
122 TUNABLE_INT("hw.snd.feeder_rate_max", &feeder_rate_max);
123 TUNABLE_INT("hw.snd.feeder_rate_round", &feeder_rate_round);
126 sysctl_hw_snd_feeder_rate_min(SYSCTL_HANDLER_ARGS)
130 val = feeder_rate_min;
131 err = sysctl_handle_int(oidp, &val, sizeof(val), req);
132 if (err != 0 || req->newptr == NULL)
134 if (RATE_FACTOR_SAFE(val) && val < feeder_rate_max)
135 feeder_rate_min = val;
140 SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_min, CTLTYPE_INT | CTLFLAG_RW,
141 0, sizeof(int), sysctl_hw_snd_feeder_rate_min, "I",
142 "minimum allowable rate");
145 sysctl_hw_snd_feeder_rate_max(SYSCTL_HANDLER_ARGS)
149 val = feeder_rate_max;
150 err = sysctl_handle_int(oidp, &val, sizeof(val), req);
151 if (err != 0 || req->newptr == NULL)
153 if (RATE_FACTOR_SAFE(val) && val > feeder_rate_min)
154 feeder_rate_max = val;
159 SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_max, CTLTYPE_INT | CTLFLAG_RW,
160 0, sizeof(int), sysctl_hw_snd_feeder_rate_max, "I",
161 "maximum allowable rate");
164 sysctl_hw_snd_feeder_rate_round(SYSCTL_HANDLER_ARGS)
168 val = feeder_rate_round;
169 err = sysctl_handle_int(oidp, &val, sizeof(val), req);
170 if (err != 0 || req->newptr == NULL)
172 if (val < FEEDRATE_ROUNDHZ_MIN || val > FEEDRATE_ROUNDHZ_MAX)
175 feeder_rate_round = val - (val % FEEDRATE_ROUNDHZ);
178 SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_round, CTLTYPE_INT | CTLFLAG_RW,
179 0, sizeof(int), sysctl_hw_snd_feeder_rate_round, "I",
180 "sample rate converter rounding threshold");
182 #define FEEDER_RATE_CONVERT(FMTBIT, RATE_INTCAST, SIGN, SIGNS, ENDIAN, ENDIANS) \
184 feed_convert_##SIGNS##FMTBIT##ENDIANS(struct feed_rate_info *info, \
185 uint8_t *dst, uint32_t max) \
187 uint32_t ret, smpsz, ch, pos, bpos, gx, gy, alpha, d1, d2; \
190 uint8_t *src, *sx, *sy; \
193 alpha = info->alpha; \
198 src = info->buffer + pos; \
199 ch = info->channels; \
200 smpsz = PCM_##FMTBIT##_BPS * ch; \
210 d1 = (alpha << PCM_FXSHIFT) / gy; \
211 d2 = (1U << PCM_FXSHIFT) - d1; \
216 x = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sx); \
217 y = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sy); \
218 x = (((RATE_INTCAST)x * d1) + \
219 ((RATE_INTCAST)y * d2)) >> PCM_FXSHIFT; \
220 PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(dst, x); \
221 dst += PCM_##FMTBIT##_BPS; \
222 sx += PCM_##FMTBIT##_BPS; \
223 sy += PCM_##FMTBIT##_BPS; \
224 ret += PCM_##FMTBIT##_BPS; \
225 } while (--i != 0); \
230 info->alpha = alpha; \
235 FEEDER_RATE_CONVERT(8, int32_t, S, s, NE, ne)
236 FEEDER_RATE_CONVERT(16, int32_t, S, s, LE, le)
237 FEEDER_RATE_CONVERT(24, int32_t, S, s, LE, le)
238 FEEDER_RATE_CONVERT(32, intpcm_t, S, s, LE, le)
239 FEEDER_RATE_CONVERT(16, int32_t, S, s, BE, be)
240 FEEDER_RATE_CONVERT(24, int32_t, S, s, BE, be)
241 FEEDER_RATE_CONVERT(32, intpcm_t, S, s, BE, be)
242 FEEDER_RATE_CONVERT(8, int32_t, U, u, NE, ne)
243 FEEDER_RATE_CONVERT(16, int32_t, U, u, LE, le)
244 FEEDER_RATE_CONVERT(24, int32_t, U, u, LE, le)
245 FEEDER_RATE_CONVERT(32, intpcm_t, U, u, LE, le)
246 FEEDER_RATE_CONVERT(16, int32_t, U, u, BE, be)
247 FEEDER_RATE_CONVERT(24, int32_t, U, u, BE, be)
248 FEEDER_RATE_CONVERT(32, intpcm_t, U, u, BE, be)
251 feed_speed_ratio(uint32_t src, uint32_t dst, uint32_t *gx, uint32_t *gy)
253 uint32_t w, x = src, y = dst;
265 feed_rate_reset(struct feed_rate_info *info)
267 info->src = info->rsrc - (info->rsrc %
268 ((feeder_rate_round > 0) ? feeder_rate_round : 1));
269 info->dst = info->rdst - (info->rdst %
270 ((feeder_rate_round > 0) ? feeder_rate_round : 1));
275 info->bps = PCM_8_BPS;
276 info->convert = NULL;
277 info->bufsz = info->bufsz_init;
280 #ifdef FEEDRATE_STRAY
286 feed_rate_setup(struct pcm_feeder *f)
288 struct feed_rate_info *info = f->data;
289 static const struct {
290 uint32_t format; /* pcm / audio format */
291 uint32_t bps; /* bytes-per-sample, regardless of
293 feed_rate_converter convert;
295 { AFMT_S8, PCM_8_BPS, feed_convert_s8ne },
296 { AFMT_S16_LE, PCM_16_BPS, feed_convert_s16le },
297 { AFMT_S24_LE, PCM_24_BPS, feed_convert_s24le },
298 { AFMT_S32_LE, PCM_32_BPS, feed_convert_s32le },
299 { AFMT_S16_BE, PCM_16_BPS, feed_convert_s16be },
300 { AFMT_S24_BE, PCM_24_BPS, feed_convert_s24be },
301 { AFMT_S32_BE, PCM_32_BPS, feed_convert_s32be },
302 { AFMT_U8, PCM_8_BPS, feed_convert_u8ne },
303 { AFMT_U16_LE, PCM_16_BPS, feed_convert_u16le },
304 { AFMT_U24_LE, PCM_24_BPS, feed_convert_u24le },
305 { AFMT_U32_LE, PCM_32_BPS, feed_convert_u32le },
306 { AFMT_U16_BE, PCM_16_BPS, feed_convert_u16be },
307 { AFMT_U24_BE, PCM_24_BPS, feed_convert_u24be },
308 { AFMT_U32_BE, PCM_32_BPS, feed_convert_u32be },
313 feed_rate_reset(info);
315 if (info->src != info->dst)
316 feed_speed_ratio(info->src, info->dst, &info->gx, &info->gy);
318 if (!(RATE_FACTOR_SAFE(info->gx) && RATE_FACTOR_SAFE(info->gy)))
321 for (i = 0; i < sizeof(convtbl) / sizeof(*convtbl); i++) {
322 if (convtbl[i].format == 0)
324 if ((f->desc->out & ~AFMT_STEREO) == convtbl[i].format) {
325 info->bps = convtbl[i].bps;
326 info->convert = convtbl[i].convert;
332 * No need to interpolate/decimate, just do plain copy.
334 if (info->gx == info->gy)
335 info->convert = NULL;
337 info->channels = (f->desc->out & AFMT_STEREO) ? 2 : 1;
338 info->pos = info->bps * info->channels;
339 info->bpos = info->pos << 1;
340 info->bufsz -= info->bufsz % info->pos;
342 memset(info->buffer, sndbuf_zerodata(f->desc->out), info->bpos);
344 RATE_TRACE("%s: %u (%u) -> %u (%u) [%u/%u] , "
345 "format=0x%08x, channels=%u, bufsz=%u\n",
346 __func__, info->src, info->rsrc, info->dst, info->rdst,
347 info->gx, info->gy, f->desc->out, info->channels,
348 info->bufsz - info->pos);
354 feed_rate_set(struct pcm_feeder *f, int what, int32_t value)
356 struct feed_rate_info *info = f->data;
358 if (value < feeder_rate_min || value > feeder_rate_max)
371 return (feed_rate_setup(f));
375 feed_rate_get(struct pcm_feeder *f, int what)
377 struct feed_rate_info *info = f->data;
391 feed_rate_init(struct pcm_feeder *f)
393 struct feed_rate_info *info;
395 if (f->desc->out != f->desc->in)
398 info = malloc(sizeof(*info), M_RATEFEEDER, M_NOWAIT | M_ZERO);
402 * bufsz = sample from last cycle + conversion space
404 info->bufsz_init = 8 + feeder_buffersize;
405 info->buffer = malloc(sizeof(*info->buffer) * info->bufsz_init,
406 M_RATEFEEDER, M_NOWAIT | M_ZERO);
407 if (info->buffer == NULL) {
408 free(info, M_RATEFEEDER);
411 info->rsrc = DSP_DEFAULT_SPEED;
412 info->rdst = DSP_DEFAULT_SPEED;
414 return (feed_rate_setup(f));
418 feed_rate_free(struct pcm_feeder *f)
420 struct feed_rate_info *info = f->data;
423 if (info->buffer != NULL)
424 free(info->buffer, M_RATEFEEDER);
425 free(info, M_RATEFEEDER);
432 feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
433 uint32_t count, void *source)
435 struct feed_rate_info *info = f->data;
439 if (info->convert == NULL)
440 return (FEEDER_FEED(f->source, c, b, count, source));
443 * This loop has been optimized to generalize both up / down
444 * sampling without causing missing samples or excessive buffer
445 * feeding. The tricky part is to calculate *precise* (slot) value
446 * needed for the entire conversion space since we are bound to
447 * return and fill up the buffer according to the requested 'count'.
448 * Too much feeding will cause the extra buffer stay within temporary
449 * circular buffer forever and always manifest itself as a truncated
450 * sound during end of playback / recording. Too few, and we end up
451 * with possible underruns and waste of cpu cycles.
453 * 'Stray' management exist to combat with possible unaligned
454 * buffering by the caller.
456 smpsz = info->bps * info->channels;
457 RATE_TEST(count >= smpsz && (count % smpsz) == 0,
458 ("%s: Count size not sample integral (%d)\n", __func__, count));
461 count -= count % smpsz;
463 * This slot count formula will stay here for the next million years
464 * to come. This is the key of our circular buffering precision.
466 slot = (((info->gx * (count / smpsz)) + info->gy - info->alpha - 1) /
468 RATE_TEST((slot % smpsz) == 0,
469 ("%s: Slot count not sample integral (%d)\n", __func__, slot));
470 #ifdef FEEDRATE_STRAY
471 RATE_TEST(info->stray == 0, ("%s: [1] Stray bytes: %u\n", __func__,
474 if (info->pos != smpsz && info->bpos - info->pos == smpsz &&
475 info->bpos + slot > info->bufsz) {
477 * Copy last unit sample and its previous to
478 * beginning of buffer.
480 bcopy(info->buffer + info->pos - smpsz, info->buffer,
481 sizeof(*info->buffer) * (smpsz << 1));
483 info->bpos = smpsz << 1;
485 RATE_ASSERT(slot >= 0, ("%s: Negative Slot: %d\n", __func__, slot));
489 fetch = info->bufsz - info->bpos;
490 #ifdef FEEDRATE_STRAY
491 fetch -= info->stray;
493 RATE_ASSERT(fetch >= 0,
494 ("%s: [1] Buffer overrun: %d > %d\n", __func__,
495 info->bpos, info->bufsz));
498 #ifdef FEEDRATE_STRAY
504 RATE_ASSERT((int)(info->bpos
505 #ifdef FEEDRATE_STRAY
509 (info->bpos - info->stray) < info->bufsz,
510 ("%s: DANGER - BUFFER OVERRUN! bufsz=%d, pos=%d\n",
511 __func__, info->bufsz, info->bpos
512 #ifdef FEEDRATE_STRAY
516 fetch = FEEDER_FEED(f->source, c,
517 info->buffer + info->bpos
518 #ifdef FEEDRATE_STRAY
522 #ifdef FEEDRATE_STRAY
529 RATE_TEST((fetch % smpsz) == 0,
530 ("%s: Fetch size not sample integral (%d)\n",
532 #ifdef FEEDRATE_STRAY
533 info->stray += fetch % smpsz;
534 RATE_TEST(info->stray == 0,
535 ("%s: Stray bytes detected (%d)\n", __func__,
538 fetch -= fetch % smpsz;
541 RATE_ASSERT(slot >= 0, ("%s: Negative Slot: %d\n",
543 if (slot == 0 || info->bpos == info->bufsz)
546 if (info->pos == info->bpos) {
547 RATE_TEST(info->pos == smpsz,
548 ("%s: EOF while in progress\n", __func__));
551 RATE_ASSERT(info->pos <= info->bpos,
552 ("%s: [2] Buffer overrun: %d > %d\n", __func__, info->pos,
554 RATE_ASSERT(info->pos < info->bpos,
555 ("%s: Zero buffer!\n", __func__));
556 RATE_ASSERT(((info->bpos - info->pos) % smpsz) == 0,
557 ("%s: Buffer not sample integral (%d)\n", __func__,
558 info->bpos - info->pos));
559 i += info->convert(info, b + i, count - i);
560 RATE_ASSERT(info->pos <= info->bpos,
561 ("%s: [3] Buffer overrun: %d > %d\n", __func__, info->pos,
563 if (info->pos == info->bpos) {
565 * End of buffer cycle. Copy last unit sample
566 * to beginning of buffer so next cycle can
567 * interpolate using it.
569 #ifdef FEEDRATE_STRAY
570 RATE_TEST(info->stray == 0,
571 ("%s: [2] Stray bytes: %u\n", __func__,
574 bcopy(info->buffer + info->pos - smpsz, info->buffer,
575 sizeof(*info->buffer) * smpsz);
583 RATE_TEST((slot == 0 && count == i) || (slot > 0 && count > i &&
584 info->pos == info->bpos && info->pos == smpsz),
585 ("%s: Inconsistent slot/count! "
586 "Count Expect: %u , Got: %u, Slot Left: %d\n", __func__, count, i,
589 #ifdef FEEDRATE_STRAY
590 RATE_TEST(info->stray == 0, ("%s: [3] Stray bytes: %u\n", __func__,
597 static struct pcm_feederdesc feeder_rate_desc[] = {
598 {FEEDER_RATE, AFMT_S8, AFMT_S8, 0},
599 {FEEDER_RATE, AFMT_S16_LE, AFMT_S16_LE, 0},
600 {FEEDER_RATE, AFMT_S24_LE, AFMT_S24_LE, 0},
601 {FEEDER_RATE, AFMT_S32_LE, AFMT_S32_LE, 0},
602 {FEEDER_RATE, AFMT_S16_BE, AFMT_S16_BE, 0},
603 {FEEDER_RATE, AFMT_S24_BE, AFMT_S24_BE, 0},
604 {FEEDER_RATE, AFMT_S32_BE, AFMT_S32_BE, 0},
605 {FEEDER_RATE, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
606 {FEEDER_RATE, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
607 {FEEDER_RATE, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
608 {FEEDER_RATE, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
609 {FEEDER_RATE, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
610 {FEEDER_RATE, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
611 {FEEDER_RATE, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
612 {FEEDER_RATE, AFMT_U8, AFMT_U8, 0},
613 {FEEDER_RATE, AFMT_U16_LE, AFMT_U16_LE, 0},
614 {FEEDER_RATE, AFMT_U24_LE, AFMT_U24_LE, 0},
615 {FEEDER_RATE, AFMT_U32_LE, AFMT_U32_LE, 0},
616 {FEEDER_RATE, AFMT_U16_BE, AFMT_U16_BE, 0},
617 {FEEDER_RATE, AFMT_U24_BE, AFMT_U24_BE, 0},
618 {FEEDER_RATE, AFMT_U32_BE, AFMT_U32_BE, 0},
619 {FEEDER_RATE, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
620 {FEEDER_RATE, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
621 {FEEDER_RATE, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
622 {FEEDER_RATE, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
623 {FEEDER_RATE, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
624 {FEEDER_RATE, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
625 {FEEDER_RATE, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
629 static kobj_method_t feeder_rate_methods[] = {
630 KOBJMETHOD(feeder_init, feed_rate_init),
631 KOBJMETHOD(feeder_free, feed_rate_free),
632 KOBJMETHOD(feeder_set, feed_rate_set),
633 KOBJMETHOD(feeder_get, feed_rate_get),
634 KOBJMETHOD(feeder_feed, feed_rate),
638 FEEDER_DECLARE(feeder_rate, 2, NULL);