📄 wtbl_aweunits.c
字号:
/*================================================================== * wtbl_aweunits.c - OSS AWE driver unit conversion functions * Based on the awesfx utility Copyright (C) 1996-1999 Takashi Iwai * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include "config.h"#ifdef AWE_SUPPORT#include <stdio.h>#include <stdlib.h>#include <math.h>#include "wtbl_aweunits.h"/*================================================================ * unit conversion *================================================================*//* * Sample pitch offset for the specified sample rate * rate=44100 is no offset, each 4096 is 1 octave (twice). * eg, when rate is 22050, this offset becomes -4096. */gintawe_calc_rate_offset (guint16 Hz){ if (Hz == 44100) return 0; return (short) (log ((double) Hz / 44100) / log (2.0) * 4096.0);}/*================================================================ * Emu8000 parameters conversion *================================================================*//* * Delay time * sf: timecents * parm: 0x8000 - msec * 0.725 */gintawe_calc_delay (gint16 amount){ /* completely lost here! */ gint delay, temp; if (amount <= -12000) return 0x8000; /* minimum delay */ delay = (amount + 0x30E4) << 16; delay /= 1200; temp = 0x10000 | (delay & 0xffff); /* SI:BX */ delay >>= 16; temp >>= 16 - (delay & 0xff); delay = 0x8000 - temp; if (delay < -32768) delay = -32768; return delay;}/* * Attack and Hold time * This parameter is difficult... * * ADIP says: * bit15 = always 0 * upper byte = 0x7f - hold time / 92, max 11.68sec at 0, no hold at 0x7f. * bit7 = always 0 * lower byte = encoded attack time, 0 = never attack, * 1 = max 11.68sec, 0x7f = min 6msec. * * In VVSG, * if AttackTime_ms >= 360ms: * RegisterValue = 11878/AttackTime_ms - 1 * if AttackTime_ms < 360ms and AttackTime != 0: * RegisterValue = 32 + [16/log(2)] * log(360_ms/AttackTime_ms) * if AttackTime_ms == 0 * RegisterValue = 0x7F *//* attack & decay/release time table (msec) */gintawe_calc_attack (gint16 amount){ gint attack, temp1, temp2; if (amount >= 4300) return 1; if (amount > -600) { attack = (amount + 500) / 150; temp1 = ((~attack) & 7) | 8; temp2 = attack >> 16; attack += temp2 & 7; attack >>= 3; temp1 >>= attack; if (temp1 < 1) temp1 = 1; return temp1; } attack = (37 - amount) / 75 + 8; if (attack >= 128) attack = 127; /* 128 */ return attack;}gintawe_calc_hold (gint16 amount){ gint hold, temp; if (amount < -5368) return 127; /* maximum hold */ hold = (amount + 4130) << 16; hold /= 1200; temp = 0x10000 | (hold & 0xffff); /* SI:BX */ hold >>= 16; temp >>= 16 - (hold & 0xff); hold = 127 - temp; if (hold < 0) hold = 0; return hold;}/* * Sustain level * sf: centibels * parm: 0x7f - sustain_level(dB) * 0.75 */gintawe_calc_sustain (gint16 amount){ gint val = 127 - (amount * 127) / 1000; if (val < 0) return 0; else if (val > 127) return 127; else return val;}/* * Modulation sustain level * sf: 0.1% * parm: 0x7f - sustain_level(dB) * 0.75 */gintawe_calc_mod_sustain (gint16 amount){ gint val = 127 - (amount * 127) / 1000; if (val < 0) return 0; else if (val > 127) return 127; else return val;}/* * This parameter is also difficult to understand... * * ADIP says the value means decay rate, 0x7f minimum time is of 240usec/dB, * 0x01 being the max time of 470msec/dB, and 0 begin no decay. * * In VVSG, 2 * log(0.5) * log(23756/[ms]) (0x7F...0ms), but this is * obviously incorrect. But, the max time 23756 seems to be correct. * (actually, in NRPN control, decay time is within 0.023 and 23.7 secs.) * */gintawe_calc_decay (gint16 amount){ gint decay, temp1, temp2; if (amount > 1800) { decay = (amount - 1800) / 150; temp1 = ((~decay) & 7) | 8; /* here, ASM code has high part of decay & 0x7 too, but we know that this is always clear since amount is between 1800 & 32767, therefore decay is 0..206 */ temp2 = decay >> 3; temp1 >>= temp2; decay = temp1; if (decay < 1) decay = 1; return decay; } /* here, amount < 1800 */ decay = (37 - amount) / 75 + 39; if (decay >= 128) decay = 127; return decay;}/* * Cutoff frequency; return (0-255) * sf: abs cents (cents above 8.176Hz) * parm: quarter semitone; 0 = 125Hz, 0xff=8kHz? * (in VVS, cutoff(Hz) = value * 31.25 + 100) */gintawe_calc_cutoff (gint16 amount){ gint cutoff = (amount + 0xf) / 0x1d - 0x99; if (cutoff < 0) return 0; else if (cutoff > 255) return 255; else return cutoff;}/* * Initial filter Q; return (0-15) * sf: centibels above DC gain. * parm: 0 = no attenuation, 15 = 24dB */gintawe_calc_filterQ (gint16 amount){ gint Q = amount / 12; if (Q < 0) return 0; else if (Q > 15) return 15; else return Q;}/* * Pitch modulation height (0-255) * sf: cents, 100 = 1 semitone * parm: signed char, 0x80 = 1 octave */gintawe_calc_pitch_shift (gint16 amount){ gint val = (amount * 0x1b4f) >> 16; if (val < -128) val = -128; else if (val > 127) val = 127; if (val < 0) return 0x100 + val; else return val;}/* * Filter cutoff for modulation envelope (0-255) * sf: 1200 = +1 octave * par: 0x80 = +6(modenv) octave */gintawe_calc_modenv_cutoff (gint16 amount){ gint val; val = (amount * 0x048D) >> 16; if (val < -128) val = -128; if (val > 127) val = 127; if (val < 0) return (guint8) (0x100 + val); else return (guint8) val;}/* * Filter cutoff for modulation LFO (0-255) * sf: 1200 = +1 octave * par: 0x80 = +3(lfo1) octave */gintawe_calc_modlfo_cutoff (gint16 amount){ gint val; val = (amount * 0x0919) >> 16; if (val < -128) val = -128; if (val > 127) val = 127; if (val < 0) return (guint8) (0x100 + val); else return (guint8) val;}/* * Tremolo volume (0-255) * sf: cB, 10 = 1dB * parm: 0x7f = +/-12dB, 0x80 = -/+12dB */gintawe_calc_tremolo (gint16 amount){ gint val = (amount << 7) / 0x78; if (val < -128) val = -128; if (val > 127) val = 127; if (val < 0) val = 0x100 + val; return (guint8) val;}/* * Envelope/LFO frequency (0-255) * sf: cents * parm: mHz / 42 (42mHz step; 0xff=10.72Hz) */gintawe_calc_freq (gint16 amount){ gint freq, temp; if (amount <= -16000) return 0; /* minimum freq. shift */ freq = (amount + 0x23A6) << 16; freq /= 1200; temp = 0x10000 | (freq & 0xffff); /* DX:AX */ freq >>= 16; /* SI:BX */ temp >>= 16 - (freq & 0xff); if (temp > 255) temp = 255; return temp;}/* * Panning position (0-127) * sf: (left) -500 - 500 (right) (0=center) * parm: (left) 0 - 127 (right), as same as MIDI parameter. * * NOTE: * The value above is converted in the driver to the actual emu8000 * parameter, 8bit, 0 (right) - 0xff (left). */gintawe_calc_pan (gint16 val){ if (val < -500) return 0; else if (val > 500) return 127; return (gint8) ((val + 500) * 127 / 1000);}/* * Value in 0.1% units * sf: 0 - 1000 (max) * parm: 0 - 255 (max) */gintawe_calc_tenthpercent (gint16 val){ if (val < 0) return 0; else if (val > 1000) val = 255; return (guint8) (val * 255 / 1000);}/* * Initial volume attenuation (0-255) * sf: centibels, eg. 60 = 6dB below from full scale * parm: dB * 8 / 3 */gintawe_calc_attenuation (gint16 amount){ gint atten; atten = (amount + 12) / 24; atten = (atten * 8) / 3; if (atten > 255) atten = 255; if (atten < 0) atten = 0; return atten;}#endif /* #ifdef AWE_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -