Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/perseant-stdc-iso10646]: src/sys/dev/ic 2873897
details: https://anonhg.NetBSD.org/src/rev/94afd6d1e1ed
branches: perseant-stdc-iso10646
changeset: 850633:94afd6d1e1ed
user: isaki <isaki%NetBSD.org@localhost>
date: Sat Jul 15 10:17:10 2017 +0000
description:
2873897
diffstat:
sys/dev/ic/msm6258.c | 430 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 430 insertions(+), 0 deletions(-)
diffs (truncated from 434 to 300 lines):
diff -r 016e82d35dbe -r 94afd6d1e1ed sys/dev/ic/msm6258.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/msm6258.c Sat Jul 15 10:17:10 2017 +0000
@@ -0,0 +1,430 @@
+/* $NetBSD: msm6258.c,v 1.18.2.2 2017/07/15 10:17:10 isaki Exp $ */
+
+/*
+ * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * OKI MSM6258 ADPCM voice synthesizer codec.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: msm6258.c,v 1.18.2.2 2017/07/15 10:17:10 isaki Exp $");
+
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/select.h>
+#include <sys/audioio.h>
+
+#include <dev/audio_if.h>
+#include <dev/auconv.h>
+#include <dev/audiovar.h>
+#include <dev/mulaw.h>
+#include <dev/ic/msm6258var.h>
+
+struct msm6258_codecvar {
+ stream_filter_t base;
+ short mc_amp;
+ char mc_estim;
+};
+
+static stream_filter_t *msm6258_factory
+ (struct audio_softc *,
+ int (*)(struct audio_softc *, stream_fetcher_t *, audio_stream_t *, int));
+static void msm6258_dtor(struct stream_filter *);
+static inline uint8_t pcm2adpcm_step(struct msm6258_codecvar *, int16_t);
+static inline int16_t adpcm2pcm_step(struct msm6258_codecvar *, uint8_t);
+
+static const int adpcm_estimindex[16] = {
+ 2, 6, 10, 14, 18, 22, 26, 30,
+ -2, -6, -10, -14, -18, -22, -26, -30
+};
+
+static const int adpcm_estim[49] = {
+ 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
+ 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
+ 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
+ 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
+};
+
+static const int adpcm_estimstep[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+static stream_filter_t *
+msm6258_factory(struct audio_softc *asc,
+ int (*fetch_to)(struct audio_softc *, stream_fetcher_t *, audio_stream_t *, int))
+{
+ struct msm6258_codecvar *this;
+
+ this = kmem_alloc(sizeof(struct msm6258_codecvar), KM_SLEEP);
+ this->base.base.fetch_to = fetch_to;
+ this->base.dtor = msm6258_dtor;
+ this->base.set_fetcher = stream_filter_set_fetcher;
+ this->base.set_inputbuffer = stream_filter_set_inputbuffer;
+ return &this->base;
+}
+
+static void
+msm6258_dtor(struct stream_filter *this)
+{
+ if (this != NULL)
+ kmem_free(this, sizeof(struct msm6258_codecvar));
+}
+
+/*
+ * signed 16bit linear PCM -> OkiADPCM
+ */
+static inline uint8_t
+pcm2adpcm_step(struct msm6258_codecvar *mc, int16_t a)
+{
+ int estim = (int)mc->mc_estim;
+ int df;
+ short dl, c;
+ uint8_t b;
+ uint8_t s;
+
+ df = a - mc->mc_amp;
+ dl = adpcm_estim[estim];
+ c = (df / 16) * 8 / dl;
+ if (df < 0) {
+ b = (unsigned char)(-c) / 2;
+ s = 0x08;
+ } else {
+ b = (unsigned char)(c) / 2;
+ s = 0;
+ }
+ if (b > 7)
+ b = 7;
+ s |= b;
+ mc->mc_amp += (short)(adpcm_estimindex[(int)s] * dl);
+ estim += adpcm_estimstep[b];
+ if (estim < 0)
+ estim = 0;
+ else if (estim > 48)
+ estim = 48;
+
+ mc->mc_estim = estim;
+ return s;
+}
+
+#define DEFINE_FILTER(name) \
+static int \
+name##_fetch_to(struct audio_softc *, stream_fetcher_t *, audio_stream_t *, int); \
+stream_filter_t * \
+name(struct audio_softc *sc, const audio_params_t *from, \
+ const audio_params_t *to) \
+{ \
+ return msm6258_factory(sc, name##_fetch_to); \
+} \
+static int \
+name##_fetch_to(struct audio_softc *asc, stream_fetcher_t *self, audio_stream_t *dst, int max_used)
+
+DEFINE_FILTER(msm6258_slinear16_to_adpcm)
+{
+ stream_filter_t *this;
+ struct msm6258_codecvar *mc;
+ uint8_t *d;
+ const uint8_t *s;
+ int m, err, enc_src;
+
+ this = (stream_filter_t *)self;
+ mc = (struct msm6258_codecvar *)self;
+ if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used * 4)))
+ return err;
+ m = dst->end - dst->start;
+ m = min(m, max_used);
+ d = dst->inp;
+ s = this->src->outp;
+ enc_src = this->src->param.encoding;
+ if (enc_src == AUDIO_ENCODING_SLINEAR_LE) {
+ while (dst->used < m && this->src->used >= 4) {
+ uint8_t f;
+ int16_t ss;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ss = *(const int16_t*)s;
+ s = audio_stream_add_outp(this->src, s, 2);
+ f = pcm2adpcm_step(mc, ss);
+ ss = *(const int16_t*)s;
+#else
+ ss = (s[1] << 8) | s[0];
+ s = audio_stream_add_outp(this->src, s, 2);
+ f = pcm2adpcm_step(mc, ss);
+ ss = (s[1] << 8) | s[0];
+#endif
+ f |= pcm2adpcm_step(mc, ss) << 4;
+ *d = f;
+ d = audio_stream_add_inp(dst, d, 1);
+ s = audio_stream_add_outp(this->src, s, 2);
+ }
+#if defined(DIAGNOSTIC)
+ } else if (enc_src == AUDIO_ENCODING_SLINEAR_BE) {
+#else
+ } else {
+#endif
+ while (dst->used < m && this->src->used >= 4) {
+ uint8_t f;
+ int16_t ss;
+#if BYTE_ORDER == BIG_ENDIAN
+ ss = *(const int16_t*)s;
+ s = audio_stream_add_outp(this->src, s, 2);
+ f = pcm2adpcm_step(mc, ss);
+ ss = *(const int16_t*)s;
+#else
+ ss = (s[0] << 8) | s[1];
+ s = audio_stream_add_outp(this->src, s, 2);
+ f = pcm2adpcm_step(mc, ss);
+ ss = (s[0] << 8) | s[1];
+#endif
+ f |= pcm2adpcm_step(mc, ss) << 4;
+ *d = f;
+ d = audio_stream_add_inp(dst, d, 1);
+ s = audio_stream_add_outp(this->src, s, 2);
+ }
+ }
+#if defined(DIAGNOSTIC)
+ else {
+ panic("msm6258_slinear16_to_adpcm: unsupported enc_src(%d)", enc_src);
+ }
+#endif
+ dst->inp = d;
+ this->src->outp = s;
+ return 0;
+}
+
+DEFINE_FILTER(msm6258_linear8_to_adpcm)
+{
+ stream_filter_t *this;
+ struct msm6258_codecvar *mc;
+ uint8_t *d;
+ const uint8_t *s;
+ int m, err, enc_src;
+
+ this = (stream_filter_t *)self;
+ mc = (struct msm6258_codecvar *)self;
+ if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used * 2)))
+ return err;
+ m = dst->end - dst->start;
+ m = min(m, max_used);
+ d = dst->inp;
+ s = this->src->outp;
+ enc_src = this->src->param.encoding;
+ if (enc_src == AUDIO_ENCODING_SLINEAR_LE) {
+ while (dst->used < m && this->src->used >= 4) {
+ uint8_t f;
+ int16_t ss;
+ ss = ((int16_t)s[0]) * 256;
+ s = audio_stream_add_outp(this->src, s, 1);
+ f = pcm2adpcm_step(mc, ss);
+ ss = ((int16_t)s[0]) * 256;
+ f |= pcm2adpcm_step(mc, ss) << 4;
+ *d = f;
+ d = audio_stream_add_inp(dst, d, 1);
+ s = audio_stream_add_outp(this->src, s, 1);
+ }
+#if defined(DIAGNOSTIC)
+ } else if (enc_src == AUDIO_ENCODING_ULINEAR_LE) {
+#else
+ } else {
+#endif
+ while (dst->used < m && this->src->used >= 4) {
+ uint8_t f;
+ int16_t ss;
+ ss = ((int16_t)(s[0] ^ 0x80)) * 256;
+ s = audio_stream_add_outp(this->src, s, 1);
+ f = pcm2adpcm_step(mc, ss);
+ ss = ((int16_t)(s[0] ^ 0x80)) * 256;
+ f |= pcm2adpcm_step(mc, ss) << 4;
+ *d = f;
+ d = audio_stream_add_inp(dst, d, 1);
+ s = audio_stream_add_outp(this->src, s, 1);
+ }
+ }
+#if defined(DIAGNOSTIC)
+ else {
+ panic("msm6258_linear8_to_adpcm: unsupported enc_src(%d)", enc_src);
+ }
+#endif
+ dst->inp = d;
+ this->src->outp = s;
+ return 0;
+}
+
+/*
+ * OkiADPCM -> signed 16bit linear PCM
+ */
+static inline int16_t
+adpcm2pcm_step(struct msm6258_codecvar *mc, uint8_t b)
+{
+ int estim = (int)mc->mc_estim;
+
+ mc->mc_amp += adpcm_estim[estim] * adpcm_estimindex[b];
+ estim += adpcm_estimstep[b];
+
+ if (estim < 0)
+ estim = 0;
+ else if (estim > 48)
+ estim = 48;
+
+ mc->mc_estim = estim;
+
+ return mc->mc_amp;
+}
Home |
Main Index |
Thread Index |
Old Index