如何在 Windows 上写入二进制文件时强制 1 字节填充 - 适用于 Mac,不适用于 Win
这很难脱离上下文来解释,但我会尝试一下,因为它让我发疯。
我正在尝试编写一个二进制文件来表示基于 vst 2.4 规范的 vst 音频插件的程序和库状态 - 程序是一个声音的参数值,库是程序的集合(在我的例子中是 32 )。我的程序保存/加载代码在 Windows 和 Mac 上运行良好。我的银行储蓄代码在 Mac 上运行良好 - 我可以从我的插件中保存状态,并通过 vst 主机的调用机制打开它。我在 mac 上创建的文件可由 mac 主机和 windows 主机加载,表明这正在保存“正确的”vst 银行文件格式。然而,在 Windows 上,我在 vst 库文件中获得了额外的字节,并且它不会通过主机机制加载。我认为这是因为在 Windows 上有一些填充。在较小的 vst 程序文件中似乎不会发生这种情况。我已经在许多不同的地方尝试过 #pragma pack(push, 1) 但无济于事。谁能建议我可以做什么来解决这个问题或者可能是什么原因?
谢谢
mac 十六进制好:
win hex 坏:
这是代码。 vst fxb 文件格式需要大端数据,因此需要字节交换内容。更多信息在这里: http://forum.cockos.com/showthread.php?t= 78573
bool IPlugBase::SaveBankAsFXB(const char* defaultFileName)
{
if (mGraphics)
{
WDL_String fileName(defaultFileName, strlen(defaultFileName));
mGraphics->PromptForFile(&fileName, IGraphics::kFileSave, "", "fxb");
if (fileName.GetLength())
{
FILE* fp = fopen(fileName.Get(), "w");
VstInt32 chunkMagic = WDL_bswap_if_le('CcnK');
VstInt32 byteSize = 0;
VstInt32 fxbMagic;
VstInt32 fxbVersion = WDL_bswap_if_le(kFXBVersionNum);
VstInt32 pluginID = WDL_bswap_if_le(GetUniqueID());
VstInt32 pluginVersion = WDL_bswap_if_le(GetEffectVersion(true));
VstInt32 numPgms = WDL_bswap_if_le(NPresets());
VstInt32 currentPgm = WDL_bswap_if_le(GetCurrentPresetIdx());
char future[124];
memset(future, 0, 124);
unsigned int bnkHeaderSize = 80;
unsigned int pgmHeaderSize = 84;
unsigned int pgmSize;
unsigned int bnkSize; // total size in bytes
unsigned int bytePos = 0;
unsigned char *bnk;
if (DoesStateChunks())
{
//TODO
}
else
{
pgmSize = NParams() * 4;
bnkSize = bnkHeaderSize + (NPresets() * (pgmHeaderSize + pgmSize));
bnk = new unsigned char[bnkSize];
fxbMagic = WDL_bswap_if_le('FxBk');
// fxb header
memcpy(bnk + bytePos, &chunkMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &byteSize, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxbMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxbVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginID, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &numPgms, 4);
bytePos += 4;
memcpy(bnk + bytePos, ¤tPgm, 4);
bytePos += 4;
memcpy(bnk + bytePos, &future, 124);
bytePos += 124;
VstInt32 fxpMagic = WDL_bswap_if_le('FxCk');
VstInt32 fxpVersion = WDL_bswap_if_le(kFXPVersionNum);
VstInt32 numParams = WDL_bswap_if_le(NParams());
for (int p = 0; p < NPresets(); p++)
{
IPreset* pPreset = mPresets.Get(p);
char prgName[28];
memset(prgName, 0, 28);
strcpy(prgName, pPreset->mName);
//fxp header
memcpy(bnk + bytePos, &chunkMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &byteSize, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxpMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxpVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginID, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &numParams, 4);
bytePos += 4;
memcpy(bnk + bytePos, &prgName, 28);
bytePos += 28;
//fxp data
for (int i = 0; i< NParams(); i++)
{
double v;
pPreset->mChunk.Get(&v, i * sizeof(double));
WDL_EndianFloat v32;
v32.f = (float) mParams.Get(i)->GetNormalized(v);
unsigned int swapped = WDL_bswap_if_le(v32.int32);
memcpy(bnk + bytePos, &swapped, 4);
bytePos += 4;
}
}
}
fwrite(bnk, bnkSize, 1, fp);
fclose(fp);
return true;
}
return false;
}
return false;
}
this is quite hard to explain out of context but i am going to try because its driving me nuts.
i am trying to write a binary file to represent the program and bank state of a vst audio plugin, based on the vst 2.4 spec - a program is the parameter values for one sound and a bank is a collection of programs (in my case 32). My program saving/loading code works fine on windows and mac. My bank saving code works fine on mac - I can save the state from my plugin, and open it via a vst-host's recall mechanisms. The files i create on mac are loadable by mac hosts and windows hosts, showing that this is saving the "correct" vst bank file format. On windows however, I get extra bytes in the vst bank file and it won't load via the host mechanism. I assume this is because on windows there is some padding. It doesn't seem to happen in the vst program files, which are smaller. I have tried #pragma pack(push, 1) in many different places to no avail. Can anyone suggest what I might do to fix this or what might be the cause?
thanks
mac hex good:
win hex bad:
Here is the code. The vst fxb file format wants big endian data hence the byte swap stuff. More info here: http://forum.cockos.com/showthread.php?t=78573
bool IPlugBase::SaveBankAsFXB(const char* defaultFileName)
{
if (mGraphics)
{
WDL_String fileName(defaultFileName, strlen(defaultFileName));
mGraphics->PromptForFile(&fileName, IGraphics::kFileSave, "", "fxb");
if (fileName.GetLength())
{
FILE* fp = fopen(fileName.Get(), "w");
VstInt32 chunkMagic = WDL_bswap_if_le('CcnK');
VstInt32 byteSize = 0;
VstInt32 fxbMagic;
VstInt32 fxbVersion = WDL_bswap_if_le(kFXBVersionNum);
VstInt32 pluginID = WDL_bswap_if_le(GetUniqueID());
VstInt32 pluginVersion = WDL_bswap_if_le(GetEffectVersion(true));
VstInt32 numPgms = WDL_bswap_if_le(NPresets());
VstInt32 currentPgm = WDL_bswap_if_le(GetCurrentPresetIdx());
char future[124];
memset(future, 0, 124);
unsigned int bnkHeaderSize = 80;
unsigned int pgmHeaderSize = 84;
unsigned int pgmSize;
unsigned int bnkSize; // total size in bytes
unsigned int bytePos = 0;
unsigned char *bnk;
if (DoesStateChunks())
{
//TODO
}
else
{
pgmSize = NParams() * 4;
bnkSize = bnkHeaderSize + (NPresets() * (pgmHeaderSize + pgmSize));
bnk = new unsigned char[bnkSize];
fxbMagic = WDL_bswap_if_le('FxBk');
// fxb header
memcpy(bnk + bytePos, &chunkMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &byteSize, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxbMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxbVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginID, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &numPgms, 4);
bytePos += 4;
memcpy(bnk + bytePos, ¤tPgm, 4);
bytePos += 4;
memcpy(bnk + bytePos, &future, 124);
bytePos += 124;
VstInt32 fxpMagic = WDL_bswap_if_le('FxCk');
VstInt32 fxpVersion = WDL_bswap_if_le(kFXPVersionNum);
VstInt32 numParams = WDL_bswap_if_le(NParams());
for (int p = 0; p < NPresets(); p++)
{
IPreset* pPreset = mPresets.Get(p);
char prgName[28];
memset(prgName, 0, 28);
strcpy(prgName, pPreset->mName);
//fxp header
memcpy(bnk + bytePos, &chunkMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &byteSize, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxpMagic, 4);
bytePos += 4;
memcpy(bnk + bytePos, &fxpVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginID, 4);
bytePos += 4;
memcpy(bnk + bytePos, &pluginVersion, 4);
bytePos += 4;
memcpy(bnk + bytePos, &numParams, 4);
bytePos += 4;
memcpy(bnk + bytePos, &prgName, 28);
bytePos += 28;
//fxp data
for (int i = 0; i< NParams(); i++)
{
double v;
pPreset->mChunk.Get(&v, i * sizeof(double));
WDL_EndianFloat v32;
v32.f = (float) mParams.Get(i)->GetNormalized(v);
unsigned int swapped = WDL_bswap_if_le(v32.int32);
memcpy(bnk + bytePos, &swapped, 4);
bytePos += 4;
}
}
}
fwrite(bnk, bnkSize, 1, fp);
fclose(fp);
return true;
}
return false;
}
return false;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试将
fopen
调用更改为:b
请求二进制模式,这应该会阻止任何类型的文本行尾标记处理。请参阅 MSDN 上的 fopen 文档看看在文本模式下会发生什么样的翻译。
Try changing your
fopen
call to:The
b
requests binary mode, which should prevent any type of text end-of-line marker processing.See the fopen documentation on MSDN to see what sort of translation can happen in text mode.