如何使用FMOD解压OGG声音文件?



是否有一种方法可以使用c++中的FMOD库解压声音文件?

我正在开发一个声音编辑器,使用FMOD引擎库,但我得到了压缩音频文件,特别是OGG类型的问题。

现在我只是使用FMOD::Sound::readData()读取原始数据,然后将其规范化并使用SFML将其显示到屏幕上。这对WAV文件很好,因为它们没有被压缩,但我需要为压缩格式做更多的步骤。

这就是我现在正在做的:

FMOD_RESULT r;
FMOD::System* m_fmodSystem = nullptr;
int m_maxChannels = 64;

// Create fmod system
r = FMOD::System_Create(&m_fmodSystem);
FMOD_ERROR_CHECK(r);

// Initialize system
r = m_fmodSystem->init(m_maxChannels, FMOD_INIT_NORMAL, nullptr);
FMOD_ERROR_CHECK(r);

// Create sound
FMOD::Sound* soundResource = nullptr;
FMOD::Channel* channel = nullptr;
r = m_fmodSystem->createSound("640709__chobesha__laser-gun-sound.ogg",
FMOD_DEFAULT | FMOD_OPENONLY,
nullptr,
&soundResource);
FMOD_ERROR_CHECK(r);


// Get sound length in raw bytes
unsigned int audioLength = 0;
FMOD_TIMEUNIT timeUnit = FMOD_TIMEUNIT_RAWBYTES;
r = soundResource->getLength(&audioLength, timeUnit);
FMOD_ERROR_CHECK(r);

// Read sound data
char* audioBuffer = new char[audioLength];
unsigned int readData = 0;
r = soundResource->readData(reinterpret_cast<void*>(audioBuffer),
audioLength,
&readData);
FMOD_ERROR_CHECK(r);

signed short* interpretedData = reinterpret_cast<signed short*>(audioBuffer);
// Analize data to normalize it
signed short maxValue = -32767;
signed short minValue = 32767;
int interpretedDataSize = readData / sizeof(signed short);
for (int i = 0; i < interpretedDataSize; ++i) {
if (interpretedData[i] > maxValue) {
maxValue = interpretedData[i];
}
if (interpretedData[i] < minValue) {
minValue = interpretedData[i];
}
}

float maxValF = static_cast<float>(maxValue);
float minValF = static_cast<float>(minValue);
float* normalizedArray = new float[interpretedDataSize];

// Normalize data
float maxAbsValF = abs(maxValF);
maxAbsValF = maxAbsValF > abs(minValF) ? maxAbsValF : abs(minValF);
for (int i = 0; i < interpretedDataSize; ++i) {
normalizedArray[i] = interpretedData[i] / maxAbsValF;
}

我在其他帖子和FMOD文档上读到,我可以使用标志FMOD_CREATESAMPLE来告诉createSound函数在加载时解压缩数据,而不是播放时间,但它在我当前的代码结构中不起作用,我猜是因为FMOD_OPENONLY阻止它关闭,因此它没有机会解压缩,或者别的什么。这是我从文档中得到的。

不使用FMOD_OPENONLY标志的问题是,我不能使用readData函数读取数据,或者它返回一个错误标志。

搜索,我发现我可以使用lock函数,帮助它解压缩并获得指向声音数据的指针,但即使有了所有这些,它似乎仍然被压缩。我不知道我是否错过了什么。

这是代码的版本2,修改如下:

// Create sound
FMOD::Sound* soundResource = nullptr;
FMOD::Channel* channel = nullptr;
r = m_fmodSystem->createSound("640709__chobesha__laser-gun-sound.ogg",
FMOD_DEFAULT | FMOD_CREATESAMPLE,
nullptr,
&soundResource);
FMOD_ERROR_CHECK(r);


// Get sound length in raw bytes
unsigned int audioLength = 0;
FMOD_TIMEUNIT timeUnit = FMOD_TIMEUNIT_RAWBYTES;
r = soundResource->getLength(&audioLength, timeUnit);
FMOD_ERROR_CHECK(r);

// Read sound data
char* audioBuffer = new char[audioLength];
void* ptr2 = nullptr;
unsigned int len1, len2;
r = soundResource->lock(0, audioLength, reinterpret_cast<void**>(&audioBuffer), &ptr2, &len1, &len2);
FMOD_ERROR_CHECK(r);
r = soundResource->unlock(reinterpret_cast<void*>(audioBuffer), ptr2, len1, len2);
FMOD_ERROR_CHECK(r);

这是我得到的WAV声音曲线图

左边是Audacity应用程序中加载的声音,右边是我的图表。

这是第一次尝试使用OGG文件

的图形这是经过修改的OGG文件的图形

对于我所看到的,第一个和第二个是一样的,所以我假设两者都被压缩了,我所改变的没有做任何事情。

有人知道一个更好的方法来解压缩和读取声音的原始数据,最好使用FMOD的这个库。如果用FMOD是不可能的,什么是最好的方法来解压缩任何声音文件,知道它的格式。

这个答案只是几个少数人的立场和对我曾经使用过的过程的粗略描述。也许这些想法值得考虑。

一个想法:编辑声音的人(你的目标受众?)有解压缩文件的技术(例如,使用Audacity),所以也许添加这个功能(处理所有可能的传入音频格式)是一个较低的优先级?

另一个想法:可能有许多库可以解压声音。您可以在向FMOD展示结果之前使用其中一个。我刚刚在github上搜索了"oggc++"。并显示了51个存储库。

根据我自己的经验,对于我大约七年前编写的一个应用程序,我从Vorbis解码器源中调整了一些代码,使其输出PCM而不是作为。wav输出。使用OGG, .wav数据在压缩之前被转换为PCM。所以它解压缩回PCM之前转换. wav。我在代码中找到了转换发生的点,并将其编辑出来,将数据保留在解压缩的PCM形式中。

我的应用程序被构建为接受PCM,所以我实际上最终节省了一个中间步骤。

相关内容

  • 没有找到相关文章

最新更新