惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
博客园_首页
罗磊的独立博客
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
Last Week in AI
Last Week in AI
D
DataBreaches.Net
Jina AI
Jina AI
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
D
Docker
MongoDB | Blog
MongoDB | Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
H
Help Net Security
T
The Blog of Author Tim Ferriss

吐槽大王部落格

在 X (Twitter) 上找 IT 工作靠谱吗? 如何在上游分支被反复重写时优雅地 Rebase 我的 2025 我在经营自己的社交帐号,但可能「玩脱了」 我依然没有学会怎么在网上提出技术问题 我是怎么差点被恶意 npm 包攻击的 我对 Vue Router「动态路由」的一点暴论 不用 eas-cli 编译 React Native (Expo) 应用的 Android 版本 【更正版】简单实现类型安全的、能触发 CustomEvent 的 EventTarget 在 IE11 使用 CSS Grid 实现多列卡片列表布局 自建云游戏服务的尝试(2024 更新) 在 Termux 编译和使用 bwm-ng(需要 root) 如何在已有的 Vue CLI 项目使用 esbuild 我的 2021 npm、镜像源与 package-lock.json 新的桌面工作站:HP Z2 G5 Tower 我的 2020 在 Intel 版 MacBook Pro 以 EFI 的形式安装 Windows 10 为什么大家都在安利这一样东西? 新的家庭服务器:MicroServer Gen10 我的 2019 在树莓派(Raspbian)上安装最新稳定版 nginx 驾照 宿舍用小型 UPS 电源与新台灯 拆解我爸 2010 年装的廉价 PC 我的 2018 2018 厦门面基记 我(曾经)设想过的外置智能大脑 没用的无懈可击 tcdw 与 ECMAScript
FIR Filter Fader
tcdw · 2015-06-29 · via 吐槽大王部落格

SNES SPC 引擎不是有个 FIR Filter 选项吗(位于 DSP 寄存器的 $0F - $7F),那么我们有时候希望在 AddmusicK 里面加入 FIR 滤镜过渡特效。 由于计算太麻烦,所以我拿 Node.js 写了个代码很渣的 FIR 滤镜过渡计算器,代码如下:

//过渡起点
firRag1 = new Array(0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
//过渡终点
firRag2 = new Array(0x0c, 0x21, 0x2b, 0x2b, 0x13, 0xfe, 0xf3, 0xf9);
//演绎次数。第一次完全与起点相同,最后一次完全与终点相同。
firFadeTime = 10;
//循环演绎次数
for(j=0; j<firFadeTime; j++){
    // FIR 滤镜倾向 FIR1 的值,0 完全倾向,1 完全不倾向。
    firRange = j / (firFadeTime - 1);
    //循环 FIR 滤镜的八个值
    for(i=0; i<8; i++){
        //数值格式转换
        firCalc1 = firRag1[i].toString(10);
        (firCalc1 > 127) ? (fir1 = firCalc1 - 256) : (fir1 = firCalc1);
        firCalc2 = firRag2[i].toString(10);
        (firCalc2 > 127) ? (fir2 = firCalc2 - 256) : (fir2 = firCalc2);
        //混合计算
        fir = Math.round(Number(fir1) + (Number(fir2) - Number(fir1)) * firRange);
        //转换成 AddmusicK 标准数值
        (fir < 0) ? (firNew[i] = (fir + 256).toString(16)) : (firNew[i] = fir.toString(16));
        firUK = firNew[i].toUpperCase();
        firNew[i] = (String(firUK).split("").length == 1) ? "$0" + firUK : "$" + firUK;
    }
    //打印演绎结果
    console.log("$F5 " + firNew.join(" "));
}

把上面的代码保存成 fir.js,在 Shell 下执行,得到下列结果:

tcdw@tcdw:~$ node fir.js
$F5 $7F $00 $00 $00 $00 $00 $00 $00
$F5 $72 $04 $05 $05 $02 $00 $FF $FF
$F5 $65 $07 $0A $0A $04 $00 $FD $FE
$F5 $59 $0B $0E $0E $06 $FF $FC $FE
$F5 $4C $0F $13 $13 $08 $FF $FA $FD
$F5 $3F $12 $18 $18 $0B $FF $F9 $FC
$F5 $32 $16 $1D $1D $0D $FF $F7 $FB
$F5 $26 $1A $21 $21 $0F $FE $F6 $FB
$F5 $19 $1D $26 $26 $11 $FE $F4 $FA
$F5 $0C $21 $2B $2B $13 $FE $F3 $F9

然后你只要在中间加上相应的音符,就能实现 FIR 滤镜过渡特效了。

Update: Jixun 姐姐的改进版本

//过渡起点、终点
var firRag1 = [0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
  firRag2 = [0x0c, 0x21, 0x2b, 0x2b, 0x13, 0xfe, 0xf3, 0xf9];

//演绎次数。第一次完全与起点相同,最后一次完全与终点相同。
var firFadeTime = 10;

function toSignedByte(x) {
  if (x > 0x7f) x -= 0x100;

  return x;
}

function toUnsignedByte(x) {
  if (x < 0) x += 0x100;

  return x;
}

function byteToHex(x) {
  return ("0" + x.toString(16)).slice(-2);
}

firRag1 = firRag1.map(toSignedByte);
firRag2 = firRag2.map(toSignedByte);
var firCalc1, firCalc2;

//循环演绎次数
firFadeTime--;
var firNew = new Array(8);
for (j = 0; j <= firFadeTime; j++) {
  // FIR 滤镜倾向 FIR1 的值,0 完全倾向,1 完全不倾向。
  firRange = j / firFadeTime;

  // 循环 FIR 滤镜的八个值
  for (i = 0; i < 8; i++) {
    fir1 = firRag1[i];
    fir2 = firRag2[i];

    // 混合计算
    fir = Math.round(fir1 + (fir2 - fir1) * firRange);

    // 转换成 AddmusicK 标准数值
    firNew[i] = "$" + byteToHex(toUnsignedByte(fir));
  }

  // 打印演绎结果
  console.log("$F5 " + firNew.join(" ").toUpperCase());
}