在 Fmod Studio C++ 中保存 FFT 谱
Posted
技术标签:
【中文标题】在 Fmod Studio C++ 中保存 FFT 谱【英文标题】:Saving FFT Spectrum in Fmod Studio C++ 【发布时间】:2015-05-17 14:46:32 【问题描述】:我正在尝试将频谱保存在我的 FMOD_DSP_PARAMETER_FFT 中,但我只收到全零的频谱,如果你能看到我的错误,我会同意,我认为我没有很好地将 DSP 连接到通道或类似的东西,因为我没有在代码中找到错误。
我现在的代码是这样的:
FMOD::System *system;
FMOD::Sound *sound1;
FMOD::Channel *channel = 0;
FMOD::ChannelGroup *mastergroup;
FMOD::ChannelControl *control;
FMOD::DSP *mydsp, *dsphead, *dspchannelmixer;
FMOD::DSPConnection *conection;
FMOD_RESULT result;
unsigned int version;
result = FMOD::System_Create(&system);
result = system->getVersion(&version);
result = system->init(32, FMOD_INIT_NORMAL, NULL);
result = system->createSound("MySong.mp3",FMOD_DEFAULT, 0, &sound1);
result = sound1->setMode(FMOD_LOOP_NORMAL);
result = system->playSound(sound1, 0, true, &channel);
/*
Create the DSP effect.
*/
result = system->getMasterChannelGroup(&mastergroup);
result = system->createDSPByType(FMOD_DSP_TYPE_FFT, &mydsp);
result = system->getMasterChannelGroup(&mastergroup);
result = mastergroup->addDSP(0, mydsp);
result = mydsp->setBypass(true);
result = mydsp->setActive(true);
char s[256];
unsigned int len;
float freq[32];
float fft = 0;
std::vector<float> fftheights;
float m_spectrum_data[FFT_NUM_BINS];
while (1) //program loop
unsigned int ms = 0;
unsigned int lenms = 0;
bool playing = 0;
bool paused = 0;
int channelsplaying = 0;
if (channel)
FMOD::Sound *currentsound = 0;
result = channel->setPaused(false);
result = channel->setMute(false);
result = channel->isPlaying(&playing);
result = channel->getPaused(&paused);
result = channel->setVolume(0.5);
result = channel->getPosition(&ms, FMOD_TIMEUNIT_MS);
channel->getCurrentSound(¤tsound);
if (currentsound)
result = currentsound->getLength(&lenms, FMOD_TIMEUNIT_MS);
system->getChannelsPlaying(&channelsplaying);
FMOD_DSP_PARAMETER_FFT *fftparameter;
float val;
char s[256];
unsigned int len;
float *data = 0;
float freq[32];
int rate, chan, nyquist;
int windowsize = 1024;
result = system->getSoftwareFormat(&rate, 0, 0);
result = mydsp->setParameterInt(FMOD_DSP_FFT_WINDOWTYPE, FMOD_DSP_FFT_WINDOW_TRIANGLE);
result = mydsp->setParameterInt(FMOD_DSP_FFT_WINDOWSIZE, windowsize);
result = mydsp->getParameterFloat(FMOD_DSP_FFT_DOMINANT_FREQ, &val, 0, 0);
result = mydsp->getParameterData(FMOD_DSP_FFT_SPECTRUMDATA, (void **)&fftparameter, &len, s, 256);
nyquist = windowsize / 2;
for (chan = 0; chan < 2; chan++)
float average = 0.0f;
float power = 0.0f;
for (int i = 0; i < nyquist - 1; ++i)
float hz = i * (rate * 0.5f) / (nyquist - 1);
int index = i + (16384 * chan);
if (fftparameter->spectrum[chan][i] > 0.0001f) // arbitrary cutoff to filter out noise
average += data[index] * hz;
power += data[index];
if (power > 0.001f)
freq[chan] = average / power;
else
freq[chan] = 0;
printf("\ndom freq = %d : %.02f %.02f\n", (int)val, freq[0], freq[1]);
我的 fftparameter->spectrum 始终是一个零值数组... 是否可以在不修改正在播放的声音的情况下连接它? 谢谢。
【问题讨论】:
您是否尝试过将 playSound 调用移到设置 DSP 通道之后? 还是一样的结果... 【参考方案1】:您的代码示例中有一些突出的问题。
-
FFT DSP 已被
result = mydsp->setBypass(true);
绕过,导致它无法处理。
主循环中没有对 System::update 的调用。
主循环没有睡眠,所以它会尽可能快地旋转。
我认为您的主要问题可能是 setBypass 调用,请使用 setBypass(false)。
【讨论】:
以上是关于在 Fmod Studio C++ 中保存 FFT 谱的主要内容,如果未能解决你的问题,请参考以下文章