как заставить 1-байтовое заполнение при записи двоичного файла в Windows - работает на Mac, а не на Win - PullRequest
1 голос
/ 01 мая 2011

это довольно сложно объяснить вне контекста, но я собираюсь попробовать, потому что это сводит меня с ума.

Я пытаюсь написать бинарный файл для представления программы и состояния банка аудио-плагина vst, основываясь на спецификации vst 2.4 - программа - это значения параметров для одного звука, а банк - это набор программ (в мой случай 32). Моя программа сохранения / загрузки кода отлично работает на Windows и Mac. Мой код сохранения банка отлично работает на Mac - я могу сохранить состояние из своего плагина и открыть его с помощью механизмов отзыва vst-host. Файлы, которые я создаю на Mac, загружаются компьютерами Mac и Windows, что свидетельствует о сохранении «правильного» формата файла vst bank. Однако в Windows я получаю дополнительные байты в файле банка vst, и он не загружается через механизм хоста. Я предполагаю, что это потому, что на окнах есть некоторые отступы. Похоже, это не происходит в программных файлах vst, которые меньше. Я пробовал #pragma pack (push, 1) во многих разных местах безрезультатно. Кто-нибудь может подсказать, что я могу сделать, чтобы это исправить, или в чем может быть причина?

спасибо

mac hex good: mac hex good

выиграть гекс плохо: win hex bad

Вот код. Формат файла 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, &currentPgm, 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;
}

1 Ответ

3 голосов
/ 01 мая 2011

Попробуйте изменить fopen вызов на:

FILE* fp = fopen(fileName.Get(), "wb");

b запрашивает двоичный режим, который должен предотвращать любой тип обработки текстового маркера конца строки.

См. Документацию fopen на MSDN, чтобы узнать, какой перевод может происходить в текстовом режиме.

...