mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-15 00:27:31 +00:00
398 lines
9.1 KiB
C++
398 lines
9.1 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
/*
|
|
* VGMTrans (c) 2002-2019
|
|
* Licensed under the zlib license,
|
|
* refer to the included VGMTrans_LICENSE.txt file
|
|
*/
|
|
#ifndef AUDIO_SOUNDFONT_SF2FILE_H
|
|
#define AUDIO_SOUNDFONT_SF2FILE_H
|
|
|
|
#include "common/endian.h"
|
|
#include "common/scummsys.h"
|
|
#include "common/array.h"
|
|
#include "common/str.h"
|
|
#include "rifffile.h"
|
|
|
|
typedef enum {
|
|
// Oscillator
|
|
startAddrsOffset, // sample start address -4 (0 to 0xffffff) 0
|
|
endAddrsOffset,
|
|
startloopAddrsOffset, // loop start address -4 (0 to 0xffffff)
|
|
endloopAddrsOffset, // loop end address -3 (0 to 0xffffff)
|
|
|
|
// Pitch
|
|
startAddrsCoarseOffset, // CHANGED FOR SF2
|
|
modLfoToPitch, // main fm: lfo1-> pitch 5
|
|
vibLfoToPitch, // aux fm: lfo2-> pitch
|
|
modEnvToPitch, // pitch env: env1(aux)-> pitch
|
|
|
|
// Filter
|
|
initialFilterFc, // initial filter cutoff
|
|
initialFilterQ, // filter Q
|
|
modLfoToFilterFc, // filter modulation: lfo1 -> filter cutoff 10
|
|
modEnvToFilterFc, // filter env: env1(aux)-> filter cutoff
|
|
|
|
// Amplifier
|
|
endAddrsCoarseOffset, // CHANGED FOR SF2
|
|
modLfoToVolume, // tremolo: lfo1-> volume
|
|
unused1,
|
|
|
|
// Effects
|
|
chorusEffectsSend, // chorus 15
|
|
reverbEffectsSend, // reverb
|
|
pan,
|
|
unused2,
|
|
unused3,
|
|
unused4, // 20
|
|
|
|
// Main lfo1
|
|
delayModLFO, // delay 0x8000-n*(725us)
|
|
freqModLFO, // frequency
|
|
|
|
// Aux lfo2
|
|
delayVibLFO, // delay 0x8000-n*(725us)
|
|
freqVibLFO, // frequency
|
|
|
|
// Env1(aux/value)
|
|
delayModEnv, // delay 0x8000 - n(725us) 25
|
|
attackModEnv, // attack
|
|
holdModEnv, // hold
|
|
decayModEnv, // decay
|
|
sustainModEnv, // sustain
|
|
releaseModEnv, // release 30
|
|
keynumToModEnvHold,
|
|
keynumToModEnvDecay,
|
|
|
|
// Env2(ampl/vol)
|
|
delayVolEnv, // delay 0x8000 - n(725us)
|
|
attackVolEnv, // attack
|
|
holdVolEnv, // hold 35
|
|
decayVolEnv, // decay
|
|
sustainVolEnv, // sustain
|
|
releaseVolEnv, // release
|
|
keynumToVolEnvHold,
|
|
keynumToVolEnvDecay, // 40
|
|
|
|
// Preset
|
|
instrument,
|
|
reserved1,
|
|
keyRange,
|
|
velRange,
|
|
startloopAddrCoarseOffset, // CHANGED FOR SF2 45
|
|
keynum,
|
|
velocity,
|
|
initialAttenuation, // CHANGED FOR SF2
|
|
reserved2,
|
|
endloopAddrsCoarseOffset, // CHANGED FOR SF2 50
|
|
coarseTune,
|
|
fineTune,
|
|
sampleID,
|
|
sampleModes, // CHANGED FOR SF2
|
|
reserved3, // 55
|
|
scaleTuning,
|
|
exclusiveClass,
|
|
overridingRootKey,
|
|
unused5,
|
|
endOper // 60
|
|
} SFGeneratorType;
|
|
|
|
typedef uint16 SFGenerator;
|
|
|
|
typedef enum {
|
|
/* Start of MIDI modulation operators */
|
|
cc1_Mod,
|
|
cc7_Vol,
|
|
cc10_Pan,
|
|
cc64_Sustain,
|
|
cc91_Reverb,
|
|
cc93_Chorus,
|
|
|
|
ccPitchBend,
|
|
ccIndirectModX,
|
|
ccIndirectModY,
|
|
|
|
endMod
|
|
} SFModulatorType;
|
|
|
|
typedef uint16 SFModulator;
|
|
|
|
typedef enum {
|
|
linear
|
|
} SFTransformType;
|
|
|
|
typedef uint16 SFTransform;
|
|
/*
|
|
#define monoSample 0x0001
|
|
#define rightSample 0x0002
|
|
#define leftSample 0x0004
|
|
#define linkedSample 0x0008
|
|
|
|
#define ROMSample 0x8000 //32768
|
|
#define ROMMonoSample 0x8001 //32769
|
|
#define ROMRightSample 0x8002 //32770
|
|
#define ROMLeftSample 0x8004 //32772
|
|
#define ROMLinkedSample 0x8008 //32776
|
|
*/
|
|
|
|
// enum scaleTuning
|
|
//{
|
|
// equalTemp,
|
|
// fiftyCents
|
|
//};
|
|
//
|
|
// enum SFSampleField //used by Sample Read Module
|
|
//{
|
|
// NAME_FIELD = 1,
|
|
// START_FIELD,
|
|
// END_FIELD,
|
|
// START_LOOP_FIELD,
|
|
// END_LOOP_FIELD,
|
|
// SMPL_RATE_FIELD,
|
|
// ORG_KEY_FIELD,
|
|
// CORRECTION_FIELD,
|
|
// SMPL_LINK_FIELD,
|
|
// SMPL_TYPE_FIELD
|
|
//};
|
|
//
|
|
// enum SFInfoChunkField //used by Bank Read Module
|
|
//{
|
|
// IFIL_FIELD = 1,
|
|
// IROM_FIELD,
|
|
// IVER_FIELD,
|
|
// ISNG_FIELD,
|
|
// INAM_FIELD,
|
|
// IPRD_FIELD,
|
|
// IENG_FIELD,
|
|
// ISFT_FIELD,
|
|
// ICRD_FIELD,
|
|
// ICMT_FIELD,
|
|
// ICOP_FIELD
|
|
//};
|
|
|
|
static inline void uint16Write(uint8 **buffer, uint16 value) {
|
|
WRITE_LE_UINT16(*buffer, value);
|
|
*buffer += 2;
|
|
}
|
|
|
|
static inline void uint32Write(uint8 **buffer, uint32 value) {
|
|
WRITE_LE_UINT32(*buffer, value);
|
|
*buffer += 4;
|
|
}
|
|
|
|
static inline void writeBytes(uint8 **buffer, byte *bytes, uint32 size) {
|
|
memcpy(*buffer, bytes, size);
|
|
*buffer += size;
|
|
}
|
|
|
|
#pragma pack(push) /* push current alignment to stack */
|
|
#pragma pack(2) /* set alignment to 2 byte boundary */
|
|
|
|
struct sfVersionTag {
|
|
uint16 wMajor;
|
|
uint16 wMinor;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, wMajor);
|
|
uint16Write(&buffer, wMinor);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct sfPresetHeader {
|
|
char achPresetName[20];
|
|
uint16 wPreset;
|
|
uint16 wBank;
|
|
uint16 wPresetBagNdx;
|
|
uint32 dwLibrary;
|
|
uint32 dwGenre;
|
|
uint32 dwMorphology;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
writeBytes(&buffer, (byte *)achPresetName, 20);
|
|
uint16Write(&buffer, wPreset);
|
|
uint16Write(&buffer, wBank);
|
|
uint16Write(&buffer, wPresetBagNdx);
|
|
uint32Write(&buffer, dwLibrary);
|
|
uint32Write(&buffer, dwGenre);
|
|
uint32Write(&buffer, dwMorphology);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct sfPresetBag {
|
|
uint16 wGenNdx;
|
|
uint16 wModNdx;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, wGenNdx);
|
|
uint16Write(&buffer, wModNdx);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct sfModList {
|
|
SFModulator sfModSrcOper;
|
|
SFGenerator sfModDestOper;
|
|
int16 modAmount;
|
|
SFModulator sfModAmtSrcOper;
|
|
SFTransform sfModTransOper;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, sfModSrcOper);
|
|
uint16Write(&buffer, sfModDestOper);
|
|
uint16Write(&buffer, modAmount);
|
|
uint16Write(&buffer, sfModAmtSrcOper);
|
|
uint16Write(&buffer, sfModTransOper);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct genAmountType {
|
|
byte data[2];
|
|
|
|
void setRangeLo(uint8 lo) { data[0] = lo; }
|
|
void setRangeHi(uint8 hi) { data[1] = hi; }
|
|
void setShAmount(int16 shAmount) { WRITE_LE_INT16(data, shAmount); }
|
|
void setwAmount(int16 wAmount) { WRITE_LE_UINT16(data, wAmount); }
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
writeBytes(&buffer, (byte *)data, 2);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct sfGenList {
|
|
SFGenerator sfGenOper;
|
|
genAmountType genAmount;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, sfGenOper);
|
|
return genAmount.write(buffer);
|
|
}
|
|
};
|
|
|
|
struct sfInstGenList {
|
|
SFGenerator sfGenOper;
|
|
genAmountType genAmount;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, sfGenOper);
|
|
return genAmount.write(buffer);
|
|
}
|
|
};
|
|
|
|
struct sfInst {
|
|
char achInstName[20];
|
|
uint16 wInstBagNdx;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
writeBytes(&buffer, (byte *)achInstName, 20);
|
|
uint16Write(&buffer, wInstBagNdx);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
struct sfInstBag {
|
|
uint16 wInstGenNdx;
|
|
uint16 wInstModNdx;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
uint16Write(&buffer, wInstGenNdx);
|
|
uint16Write(&buffer, wInstModNdx);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
typedef enum {
|
|
monoSample = 1,
|
|
rightSample = 2,
|
|
leftSample = 4,
|
|
linkedSample = 8,
|
|
RomMonoSample = 0x8001,
|
|
RomRightSample = 0x8002,
|
|
RomLeftSample = 0x8004,
|
|
RomLinkedSample = 0x8008
|
|
} SFSampleLinkType;
|
|
|
|
typedef uint16 SFSampleLink;
|
|
|
|
struct sfSample {
|
|
char achSampleName[20];
|
|
uint32 dwStart;
|
|
uint32 dwEnd;
|
|
uint32 dwStartloop;
|
|
uint32 dwEndloop;
|
|
uint32 dwSampleRate;
|
|
uint8 byOriginalKey;
|
|
char chCorrection;
|
|
uint16 wSampleLink;
|
|
SFSampleLink sfSampleType;
|
|
|
|
uint8 *write(uint8 *buffer) {
|
|
writeBytes(&buffer, (byte *)achSampleName, 20);
|
|
uint32Write(&buffer, dwStart);
|
|
uint32Write(&buffer, dwEnd);
|
|
uint32Write(&buffer, dwStartloop);
|
|
uint32Write(&buffer, dwEndloop);
|
|
uint32Write(&buffer, dwSampleRate);
|
|
*buffer++ = byOriginalKey;
|
|
*buffer++ = chCorrection;
|
|
uint16Write(&buffer, wSampleLink);
|
|
uint16Write(&buffer, sfSampleType);
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
#pragma pack(pop) /* restore original alignment from stack */
|
|
|
|
class SF2StringChunk : public Chunk {
|
|
public:
|
|
SF2StringChunk(Common::String ckSig, Common::String info) : Chunk(ckSig) {
|
|
SetData(info.c_str(), (uint32) info.size());
|
|
}
|
|
};
|
|
|
|
class SF2InfoListChunk : public LISTChunk {
|
|
public:
|
|
SF2InfoListChunk(Common::String name);
|
|
};
|
|
|
|
class SF2sdtaChunk : public LISTChunk {
|
|
public:
|
|
SF2sdtaChunk();
|
|
};
|
|
|
|
inline void WriteLIST(Common::Array<uint8> &buf, Common::String listName, uint32 listSize);
|
|
inline void AlignName(Common::String &name);
|
|
|
|
class SynthFile;
|
|
|
|
class SF2File : public RiffFile {
|
|
public:
|
|
SF2File(SynthFile *synthfile);
|
|
~SF2File(void);
|
|
|
|
const void *SaveToMem();
|
|
};
|
|
|
|
#endif // AUDIO_SOUNDFONT_SF2FILE_H
|