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