Amuse
AudioGroupPool.hpp
1 #ifndef __AMUSE_AUDIOGROUPPOOL_HPP__
2 #define __AMUSE_AUDIOGROUPPOOL_HPP__
3 
4 #include <stdint.h>
5 #include <vector>
6 #include <cmath>
7 #include <unordered_map>
8 #include "Entity.hpp"
9 #include "Common.hpp"
10 
11 namespace amuse
12 {
13 
15 static inline double TimeCentsToSeconds(int32_t tc)
16 {
17  if (tc == 0x80000000)
18  return 0.0;
19  return std::exp2(tc / (1200.0 * 65536.0));
20 }
21 
23 struct ADSR
24 {
25  uint8_t attackFine; /* 0-255ms */
26  uint8_t attackCoarse; /* 0-65280ms */
27  uint8_t decayFine; /* 0-255ms */
28  uint8_t decayCoarse; /* 0-65280ms */
29  uint8_t sustainFine; /* multiply by 0.0244 for percentage */
30  uint8_t sustainCoarse; /* multiply by 6.25 for percentage */
31  uint8_t releaseFine; /* 0-255ms */
32  uint8_t releaseCoarse; /* 0-65280ms */
33 
34  double getAttack() const {return (attackCoarse * 255 + attackFine) / 1000.0;}
35  double getDecay() const {return decayCoarse == 128 ? 0.0 : ((decayCoarse * 255 + decayFine) / 1000.0);}
36  double getSustain() const {return decayCoarse == 128 ? 1.0 : ((sustainCoarse * 6.25 + sustainFine * 0.0244) / 100.0);}
37  double getRelease() const {return (releaseCoarse * 255 + releaseFine) / 1000.0;}
38 };
39 
41 struct ADSRDLS
42 {
43  uint32_t attack; /* 16.16 Time-cents */
44  uint32_t decay; /* 16.16 Time-cents */
45  uint16_t sustain; /* 0x1000 == 100% */
46  uint16_t release; /* milliseconds */
47  uint32_t velToAttack; /* 16.16, 1000.0 == 100%; attack = <attack> + (vel/128) * <velToAttack> */
48  uint32_t keyToDecay; /* 16.16, 1000.0 == 100%; decay = <decay> + (note/128) * <keyToDecay> */
49 
50  double getAttack() const {return TimeCentsToSeconds(attack);}
51  double getDecay() const {return TimeCentsToSeconds(decay);}
52  double getSustain() const {return sustain / double(0x1000);}
53  double getRelease() const {return release / double(1000);}
54  double getVelToAttack(int8_t vel) const
55  {
56  if (velToAttack == 0x80000000)
57  return getAttack();
58  return getAttack() + vel * (velToAttack / 65536.0 / 1000.0) / 128.0;
59  }
60  double getKeyToDecay(int8_t note) const
61  {
62  if (keyToDecay == 0x80000000)
63  return getDecay();
64  return getDecay() + note * (keyToDecay / 65536.0 / 1000.0) / 128.0;
65  }
66 };
67 
70 struct Keymap
71 {
72  int16_t objectId;
73  int8_t transpose;
74  int8_t pan; /* -128 for surround-channel only */
75  int8_t prioOffset;
76  int8_t pad[3];
77 };
78 
81 {
82  int16_t objectId;
83  int8_t keyLo;
84  int8_t keyHi;
85  int8_t transpose;
86  int8_t volume;
87  int8_t pan; /* -128 for surround-channel only */
88  int8_t prioOffset;
89  int8_t unk; /* usually 0x40 */
90 };
91 
94 {
95  std::unordered_map<ObjectId, const unsigned char*> m_soundMacros;
96  std::unordered_map<ObjectId, const unsigned char*> m_tables;
97  std::unordered_map<ObjectId, const Keymap*> m_keymaps;
98  std::unordered_map<ObjectId, std::vector<const LayerMapping*>> m_layers;
99 public:
100  AudioGroupPool(const unsigned char* data);
101  const unsigned char* soundMacro(ObjectId id) const;
102  const Keymap* keymap(ObjectId id) const;
103  const std::vector<const LayerMapping*>* layer(ObjectId id) const;
104  const ADSR* tableAsAdsr(ObjectId id) const;
105  const ADSRDLS* tableAsAdsrDLS(ObjectId id) const
106  {return reinterpret_cast<const ADSRDLS*>(tableAsAdsr(id));}
107  const Curve* tableAsCurves(ObjectId id) const
108  {return reinterpret_cast<const Curve*>(tableAsAdsr(id));}
109 };
110 
111 }
112 
113 #endif // __AMUSE_AUDIOGROUPPOOL_HPP__