FIR Filter Fader
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());
}