Add AudioGroup pool reading

This commit is contained in:
Jack Andersen 2016-05-04 20:39:18 -10:00
parent 3510c0a2e8
commit fa66632b7c
4 changed files with 165 additions and 0 deletions

View File

@ -1,13 +1,70 @@
#ifndef __AMUSE_AUDIOGROUPPOOL_HPP__
#define __AMUSE_AUDIOGROUPPOOL_HPP__
#include <stdint.h>
#include <vector>
#include <unordered_map>
namespace amuse
{
/** Defines phase-based volume curve for macro volume control */
struct ADSR
{
uint8_t attackFine; /* 0-255ms */
uint8_t attackCoarse; /* 0-65280ms */
uint8_t decayFine; /* 0-255ms */
uint8_t decayCoarse; /* 0-65280ms */
uint8_t sustainFine; /* multiply by 0.0244 for percentage */
uint8_t sustainCoarse; /* multiply by 6.25 for percentage */
uint8_t releaseFine; /* 0-255ms */
uint8_t releaseCoarse; /* 0-65280ms */
};
/** Curves for mapping velocity to volume and other functional mappings */
using Curves = uint8_t[128];
/** Maps individual MIDI keys to sound-entity as indexed in table
* (macro-voice, keymap, layer) */
struct Keymap
{
int16_t objectId;
int8_t transpose;
int8_t pan; /* -128 for surround-channel only */
int8_t prioOffset;
int8_t pad[3];
};
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
struct LayerMapping
{
int16_t objectId;
int8_t keyLo;
int8_t keyHi;
int8_t transpose;
int8_t volume;
int8_t pan; /* -128 for surround-channel only */
int8_t prioOffset;
int8_t unk; /* usually 0x40 */
};
/** Database of functional objects within Audio Group */
class AudioGroupPool
{
std::unordered_map<int, const unsigned char*> m_soundMacros;
std::unordered_map<int, const unsigned char*> m_tables;
std::unordered_map<int, const Keymap*> m_keymaps;
std::unordered_map<int, std::vector<const LayerMapping*>> m_layers;
public:
AudioGroupPool(const unsigned char* data);
const ADSR* tableAsAdsr(int id) const
{
auto search = m_tables.find(id);
if (search == m_tables.cend())
return nullptr;
return reinterpret_cast<const ADSR*>(search->second);
}
const Curves* tableAsCurves(int id) const {return reinterpret_cast<const Curves*>(tableAsAdsr(id));}
};
}

View File

@ -58,6 +58,7 @@ public:
void setPedal(bool pedal);
void setDoppler(float doppler);
void setReverbVol(float rvol);
void setAdsr(int adsrIdx, uint8_t type);
};

View File

@ -0,0 +1,83 @@
#include "amuse/AudioGroupPool.hpp"
#include "amuse/Common.hpp"
namespace amuse
{
struct Header
{
uint32_t soundMacrosOffset;
uint32_t tablesOffset;
uint32_t keymapsOffset;
uint32_t layersOffset;
void swapBig()
{
soundMacrosOffset = SBig(soundMacrosOffset);
tablesOffset = SBig(tablesOffset);
keymapsOffset = SBig(keymapsOffset);
layersOffset = SBig(layersOffset);
}
};
AudioGroupPool::AudioGroupPool(const unsigned char* data)
{
Header head = *reinterpret_cast<const Header*>(data);
head.swapBig();
if (head.soundMacrosOffset)
{
const unsigned char* cur = data + head.soundMacrosOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = SBig(*reinterpret_cast<const uint32_t*>(cur));
uint16_t id = SBig(*reinterpret_cast<const uint16_t*>(cur + 4));
m_soundMacros[id] = cur + 8;
cur += size;
}
}
if (head.tablesOffset)
{
const unsigned char* cur = data + head.tablesOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = SBig(*reinterpret_cast<const uint32_t*>(cur));
uint16_t id = SBig(*reinterpret_cast<const uint16_t*>(cur + 4));
m_tables[id] = cur + 8;
cur += size;
}
}
if (head.keymapsOffset)
{
const unsigned char* cur = data + head.keymapsOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = SBig(*reinterpret_cast<const uint32_t*>(cur));
uint16_t id = SBig(*reinterpret_cast<const uint16_t*>(cur + 4));
m_keymaps[id] = reinterpret_cast<const Keymap*>(cur + 8);
cur += size;
}
}
if (head.layersOffset)
{
const unsigned char* cur = data + head.layersOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = SBig(*reinterpret_cast<const uint32_t*>(cur));
uint16_t id = SBig(*reinterpret_cast<const uint16_t*>(cur + 4));
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];
uint32_t count = SBig(*reinterpret_cast<const uint32_t*>(cur+8));
mappingsOut.reserve(count);
const unsigned char* subcur = cur + 12;
for (int i=0 ; i<count ; ++i)
mappingsOut.push_back(reinterpret_cast<const LayerMapping*>(subcur + i * 12));
cur += size;
}
}
}
}

View File

@ -285,8 +285,32 @@ bool SoundMacroState::advance(Voice& vox, float dt)
break;
}
case Op::PianoPan:
{
int8_t scale = cmd.m_data[0];
int8_t cenKey = cmd.m_data[1];
int8_t cenPan = cmd.m_data[2];
int32_t pan = int32_t(m_midiKey - cenKey) * scale / 127 + cenPan;
pan = std::max(-127, std::min(127, pan));
vox.setPanning(pan / 127.f);
break;
}
case Op::SetAdsr:
{
int16_t tableId = *reinterpret_cast<int16_t*>(&cmd.m_data[0]);
uint8_t type = cmd.m_data[2];
vox.setAdsr(tableId, type);
break;
}
case Op::ScaleVolume:
{
int8_t scale = cmd.m_data[0];
int8_t add = cmd.m_data[1];
int16_t curve = *reinterpret_cast<int16_t*>(&cmd.m_data[2]);
bool orgVel = cmd.m_data[4];
break;
}
case Op::Panning:
case Op::Envelope:
case Op::StartSample: