问题参考:
https://qa.fmod.com/t/fmod-lipsync-question-fmod-volume-affect-spectrum-extracting/18274/21
主要是为了解决实时口型的问题,如果使用vca的方式,改变音量,那么口型会被影响。
当音量小的时候,采样不出来了。
于是,我们使用添加fader dsp的方式改变音量。
这里有几个注意点:
1.fader dsp如何加在指定的ChannelGroup上去
2.fader dsp的取值范围是多少,会以线性的方式影响音量吗?
3.master group的音量控制也要相应的修改为fader dsp的方式
问题1:fader dsp如何加在指定的ChannelGroup上去
首先创建一个dsp的方式是:
RuntimeManager.CoreSystem.createDSPByType(FMOD.DSP_TYPE.FFT, out m_fftDsp);
master group的添加的方式很简单:
RuntimeManager.CoreSystem.getMasterChannelGroup(out m_masterGroup);
var result = m_masterGroup.addDSP(-1, m_faderAllDsp);
而一般的channelgroup使用的方式,则要先播放一个event,然后再添加进去,这个在上面的帖子中,大佬已经给出了示例代码,也没有什么难度。
难点在于,到底往前找几次parent group呢?
经过和音频师的讨论,发现还是有规律的,这个跟文件夹的层级有关系。
比如:
比如,这里想在Tone的group下,加一个dsp,那么播放一个ToneEmpty,然后向上找一次即可。
这个ToneEmpty,你可以让音频师,做一个空的声音,然后放在Tone下就可以了。
m_toneEmpty = RuntimeManager.CreateInstance("event:/Tone/ToneEmpty");
var res = m_toneEmpty.start();
然后同一帧,还不能添加成功,奶奶的
private void Update()
{
if (!m_initedDSP)
{
FMOD.Studio.PLAYBACK_STATE state;
m_toneEmpty.getPlaybackState(out state);
if (state != FMOD.Studio.PLAYBACK_STATE.STARTING)
{
AddDSP();
m_initedDSP = true;
}
}
}
问题2:fader dsp其实值在[-80,10]之间
这个[-80,10]是fmod studio中的最小值和最大值,这个我还专门去音频师那里看了下,果然对应了起来。
然后这里有个坑就是,使用fader dsp进行音量的控制不是线性的,你会发现在[-20,10]的时候,衰减的特别明显,以至于滑动条在[-80,-20]直接,拖动没有任何的效果,所以,我们要做一个remap的操作。
这里给出一个绘图工具:
https://www.geogebra.org/graphing
我们实际项目中,使用[-70,0]这个范围。
因为不能改变之前的音量,所以上限取0
下限如果是-80,结果频谱还是一样没有,所以取到-70基本上就没有声音了。
我们可以将(m,n)~(0,0)这个取消,衰减的慢,而(-70,-70)到(m,n)之间衰减的快一点,这样就近似模拟线性衰减的效果了。
具体代码:
public static FMOD.DSP m_fftDsp;
public static FMOD.DSP m_faderDsp;
public static FMOD.DSP m_faderAllDsp;
private FMOD.Studio.EventInstance m_toneEmpty;
private FMOD.ChannelGroup m_masterGroup;
private FMOD.ChannelGroup m_toneGroup;
private bool m_initedDSP = false;
private void Start()
{
InitDSP();
m_toneEmpty = RuntimeManager.CreateInstance("event:/Tone/ToneEmpty");
var res = m_toneEmpty.start();
}
private void InitDSP()
{
var res = RuntimeManager.CoreSystem.createDSPByType(FMOD.DSP_TYPE.FFT, out m_fftDsp);
res = RuntimeManager.CoreSystem.createDSPByType(FMOD.DSP_TYPE.FADER, out m_faderDsp);
res = RuntimeManager.CoreSystem.createDSPByType(FMOD.DSP_TYPE.FADER, out m_faderAllDsp);
}
private void AddDSP()
{
RuntimeManager.CoreSystem.getMasterChannelGroup(out m_masterGroup);
var result = m_masterGroup.addDSP(-1, m_faderAllDsp);
result = m_toneEmpty.getChannelGroup(out FMOD.ChannelGroup g1);
result = g1.getParentGroup(out FMOD.ChannelGroup parentGroup);
result = parentGroup.getParentGroup(out FMOD.ChannelGroup parentGroup2);
m_toneGroup = parentGroup2;
result = m_toneGroup.addDSP(-1, m_faderDsp);
result = m_toneGroup.addDSP(-2, m_fftDsp);
}
private void Update()
{
if (!m_initedDSP)
{
FMOD.Studio.PLAYBACK_STATE state;
m_toneEmpty.getPlaybackState(out state);
if (state != FMOD.Studio.PLAYBACK_STATE.STARTING)
{
AddDSP();
m_initedDSP = true;
}
}
}
private float x = -40;
private float y = -10;
/// <summary>
/// x=-40, y=-10
/// </summary>
/// <param name="value"></param>
private float GetFaderValue(float value)
{
if (value >= x)
{
return y * 1.0f * value / x;
}
else
{
return (y + 70) * 1.0f * value / (x + 70) + y - (y + 70) * 1.0f * x / (x + 70);
}
}
public void SetMainVolume(float volume)
{
if (FMODUnity.RuntimeManager.Instance != null)
{
float faderValue = GetFaderValue(volume);
var res = m_faderAllDsp.setParameterFloat((int)FMOD.DSP_FADER.GAIN, faderValue);
// Debug.LogError(res + " faderValue=" + faderValue);
}
}
这样就不会影响频谱采样喽!!!
问题3:master group的音量控制也要相应的修改为fader dsp的方式
master group的音量控制方式,也要有原来的vca的方式控制,改为fader dsp的方式控制。
其他的group,我们还是可以使用vca的方式进行控制的。
其形式大致如下:
补充于:
2022/3/3
dsp在游戏关闭的时候要记得销毁,否则会有一个"connectionsremaining==0" failed.报错。
/// <summary>
/// 关闭游戏的时候要销毁,否则会有一个报错信息"connectionsremaining==0" failed.
/// </summary>
public void OnDestroy()
{
var result = m_toneGroup.removeDSP(m_faderDsp);
result = m_toneGroup.removeDSP(m_fftDsp);
result = m_masterGroup.removeDSP(m_faderAllDsp);
result = m_fftDsp.release();
result = m_faderDsp.release();
result = m_faderAllDsp.release();
}