psgpam_enc.c revision 1.2 1 1.2 tsutsui /* $NetBSD: psgpam_enc.c,v 1.2 2022/10/01 13:41:12 tsutsui Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*
4 1.1 tsutsui * Copyright (c) 2018 Yosuke Sugahara. All rights reserved.
5 1.1 tsutsui *
6 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
7 1.1 tsutsui * modification, are permitted provided that the following conditions
8 1.1 tsutsui * are met:
9 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
10 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
11 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
13 1.1 tsutsui * documentation and/or other materials provided with the distribution.
14 1.1 tsutsui *
15 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 1.1 tsutsui * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 1.1 tsutsui * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 1.1 tsutsui * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 1.1 tsutsui * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 tsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 tsutsui * SUCH DAMAGE.
26 1.1 tsutsui */
27 1.1 tsutsui
28 1.1 tsutsui /*
29 1.1 tsutsui * PSGPAM, PSGPCM encoders
30 1.1 tsutsui * Function names are PSGPAM, but also used by PSGPCM.
31 1.1 tsutsui *
32 1.1 tsutsui * PSGPAM and PSGPCM internally use the unsigned type auint_t for
33 1.1 tsutsui * intermediate calculations to manage non-linear conversions.
34 1.1 tsutsui */
35 1.1 tsutsui
36 1.1 tsutsui #include <sys/types.h>
37 1.1 tsutsui
38 1.1 tsutsui #if defined(_KERNEL)
39 1.1 tsutsui #include <sys/device.h>
40 1.1 tsutsui #include <sys/audioio.h>
41 1.1 tsutsui #include <dev/audio/audio_if.h>
42 1.1 tsutsui #include <luna68k/dev/psgpam_enc.h>
43 1.1 tsutsui #include <luna68k/dev/psgpam_table.h>
44 1.1 tsutsui #else
45 1.1 tsutsui #include <stdint.h>
46 1.1 tsutsui #include <stdlib.h>
47 1.1 tsutsui #include "audio/userland.h"
48 1.1 tsutsui #include "psgpam_enc.h"
49 1.1 tsutsui #include "psgpam_table.c"
50 1.1 tsutsui #include "psgpam_table.h"
51 1.1 tsutsui #endif
52 1.1 tsutsui
53 1.1 tsutsui void
54 1.1 tsutsui psgpam_init_context(struct psgpam_codecvar *ctx, u_int sample_rate)
55 1.1 tsutsui {
56 1.1 tsutsui
57 1.1 tsutsui ctx->offset = 65535;
58 1.1 tsutsui ctx->sample_rate = sample_rate;
59 1.1 tsutsui ctx->expire_initial = sample_rate / 10;
60 1.1 tsutsui ctx->expire = ctx->expire_initial;
61 1.1 tsutsui }
62 1.1 tsutsui
63 1.1 tsutsui static inline auint_t
64 1.1 tsutsui dynamic_offset(struct psgpam_codecvar *ctx, auint_t v)
65 1.1 tsutsui {
66 1.1 tsutsui
67 1.1 tsutsui /*
68 1.1 tsutsui * if (the passed value cannot be handled by current offset) {
69 1.1 tsutsui * update offset to handle the passed value
70 1.1 tsutsui * } else {
71 1.1 tsutsui * increment offset
72 1.1 tsutsui * }
73 1.2 tsutsui */
74 1.1 tsutsui if (v <= ctx->offset) {
75 1.1 tsutsui ctx->offset = v;
76 1.1 tsutsui } else {
77 1.1 tsutsui if (--ctx->expire < 0) {
78 1.2 tsutsui ctx->offset += 1;
79 1.1 tsutsui ctx->expire = ctx->expire_initial;
80 1.1 tsutsui }
81 1.1 tsutsui }
82 1.1 tsutsui return v - ctx->offset;
83 1.1 tsutsui }
84 1.1 tsutsui
85 1.1 tsutsui #define BULK(table) *d++ = table[v]
86 1.1 tsutsui
87 1.1 tsutsui #define W8(table) *d++ = table[v]
88 1.1 tsutsui
89 1.1 tsutsui #define W16(table) do { \
90 1.1 tsutsui uint16_t t = (uint16_t)table[v]; \
91 1.1 tsutsui *d++ = ((t & 0xf0) << 4) | (t & 0x0f); \
92 1.1 tsutsui } while (0)
93 1.1 tsutsui
94 1.1 tsutsui #define W32(table) do { \
95 1.1 tsutsui uint32_t t = (uint32_t)table[v]; \
96 1.1 tsutsui *d++ = ((t & 0xf000) << 12) \
97 1.1 tsutsui | ((t & 0x0f00) << 8) \
98 1.1 tsutsui | ((t & 0x00f0) << 4) \
99 1.1 tsutsui | ((t & 0x000f)); \
100 1.1 tsutsui } while (0)
101 1.1 tsutsui
102 1.1 tsutsui #define SPLIT3(table) do { \
103 1.1 tsutsui uint16_t t = (uint16_t)table[v]; \
104 1.1 tsutsui *d++ = ((t & 0xf000) >> 12); \
105 1.1 tsutsui *d++ = ((t & 0x0f00) >> 8); \
106 1.1 tsutsui *d++ = ((t & 0x000f)); \
107 1.1 tsutsui } while (0)
108 1.1 tsutsui
109 1.1 tsutsui #define ENCODER_DEFINE(enc, TT, table, writer) \
110 1.1 tsutsui void \
111 1.1 tsutsui psgpam_aint_to_##enc(audio_filter_arg_t *arg) \
112 1.1 tsutsui { \
113 1.1 tsutsui const aint_t *s = arg->src; \
114 1.1 tsutsui TT *d = arg->dst; \
115 1.1 tsutsui \
116 1.1 tsutsui for (int i = 0; i < arg->count; i++) { \
117 1.1 tsutsui auint_t v = (*s++) ^ AINT_T_MIN; \
118 1.1 tsutsui v >>= (AUDIO_INTERNAL_BITS - table##_BITS); \
119 1.1 tsutsui writer(table); \
120 1.1 tsutsui } \
121 1.1 tsutsui }
122 1.1 tsutsui
123 1.1 tsutsui #define ENCODER_D_DEFINE(enc, TT, table, writer) \
124 1.1 tsutsui void \
125 1.1 tsutsui psgpam_aint_to_##enc##_d(audio_filter_arg_t *arg) \
126 1.1 tsutsui { \
127 1.1 tsutsui const aint_t *s = arg->src; \
128 1.1 tsutsui TT *d = arg->dst; \
129 1.1 tsutsui \
130 1.1 tsutsui for (int i = 0; i < arg->count; i++) { \
131 1.1 tsutsui auint_t v = (*s++) ^ AINT_T_MIN; \
132 1.1 tsutsui v >>= (AUDIO_INTERNAL_BITS - table##_BITS); \
133 1.1 tsutsui v = dynamic_offset(arg->context, v); \
134 1.1 tsutsui writer(table); \
135 1.1 tsutsui } \
136 1.1 tsutsui }
137 1.1 tsutsui
138 1.1 tsutsui ENCODER_DEFINE(pam2a, uint16_t, PAM2A_TABLE, W16)
139 1.1 tsutsui ENCODER_DEFINE(pam2b, uint16_t, PAM2B_TABLE, W16)
140 1.1 tsutsui ENCODER_DEFINE(pam3a, uint32_t, PAM3A_TABLE, W32)
141 1.1 tsutsui ENCODER_DEFINE(pam3b, uint32_t, PAM3B_TABLE, W32)
142 1.1 tsutsui ENCODER_DEFINE(pcm1, uint8_t, PCM1_TABLE, W8)
143 1.1 tsutsui ENCODER_DEFINE(pcm2, uint16_t, PCM2_TABLE, W16)
144 1.1 tsutsui ENCODER_DEFINE(pcm3, uint8_t, PCM3_TABLE, SPLIT3)
145 1.1 tsutsui
146 1.1 tsutsui ENCODER_D_DEFINE(pam2a, uint16_t, PAM2A_TABLE, W16)
147 1.1 tsutsui ENCODER_D_DEFINE(pam2b, uint16_t, PAM2B_TABLE, W16)
148 1.1 tsutsui ENCODER_D_DEFINE(pam3a, uint32_t, PAM3A_TABLE, W32)
149 1.1 tsutsui ENCODER_D_DEFINE(pam3b, uint32_t, PAM3B_TABLE, W32)
150 1.1 tsutsui ENCODER_D_DEFINE(pcm1, uint8_t, PCM1_TABLE, W8)
151 1.1 tsutsui ENCODER_D_DEFINE(pcm2, uint16_t, PCM2_TABLE, W16)
152 1.1 tsutsui ENCODER_D_DEFINE(pcm3, uint8_t, PCM3_TABLE, SPLIT3)
153