Skip to content

Commit

Permalink
Add N64-VADPCM decoder; DSP-ADPCM seamless loop fix
Browse files Browse the repository at this point in the history
  • Loading branch information
jackoalan committed May 28, 2016
1 parent 5bee336 commit 5a9fd66
Show file tree
Hide file tree
Showing 25 changed files with 1,027 additions and 142 deletions.
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ set(SOURCES
lib/EffectDelay.cpp
lib/SurroundProfiles.cpp
lib/ContainerRegistry.cpp
lib/dsp.c)
lib/DSPCodec.c
lib/N64MusyXCodec.c)

set(HEADERS
include/amuse/AudioGroup.hpp
Expand Down Expand Up @@ -55,7 +56,8 @@ set(HEADERS
include/amuse/ContainerRegistry.hpp
include/amuse/Common.hpp
include/amuse/amuse.hpp
include/amuse/dsp.h)
include/amuse/DSPCodec.h
include/amuse/N64MusyXCodec.h)

unset(EXTRAS)
if(TARGET boo)
Expand Down
2 changes: 1 addition & 1 deletion driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ struct AppCallback : boo::IApplicationCallback
for (auto& grp : data)
{
/* Load project to assemble group list */
m_projs.emplace_back(grp.second.getProj());
m_projs.push_back(amuse::AudioGroupProject::CreateAudioGroupProject(grp.second));
amuse::AudioGroupProject& proj = m_projs.back();
totalGroups += proj.sfxGroups().size() + proj.songGroups().size();

Expand Down
6 changes: 5 additions & 1 deletion include/amuse/AudioGroup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ class AudioGroup
AudioGroupPool m_pool;
AudioGroupSampleDirectory m_sdir;
const unsigned char* m_samp;
DataFormat m_fmt;
bool m_valid;
public:
operator bool() const {return m_valid;}
AudioGroup(const AudioGroupData& data);
AudioGroup(const AudioGroupData& data, GCNDataTag);
AudioGroup(const AudioGroupData& data, N64DataTag);
AudioGroup(const AudioGroupData& data, PCDataTag);

const Sample* getSample(int sfxId) const;
const unsigned char* getSampleData(uint32_t offset) const;
const AudioGroupProject& getProj() const {return m_proj;}
const AudioGroupPool& getPool() const {return m_pool;}
DataFormat getDataFormat() const {return m_fmt;}
};

}
Expand Down
19 changes: 17 additions & 2 deletions include/amuse/AudioGroupData.hpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
#ifndef __AMUSE_AUDIOGROUPDATA_HPP__
#define __AMUSE_AUDIOGROUPDATA_HPP__

#include "Common.hpp"

namespace amuse
{

/** Simple pointer-container of the four Audio Group chunks */
class AudioGroupData
{
friend class Engine;
friend class AudioGroupProject;
protected:
unsigned char* m_proj;
unsigned char* m_pool;
unsigned char* m_sdir;
unsigned char* m_samp;
DataFormat m_fmt;

AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, DataFormat fmt)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp), m_fmt(fmt) {}
public:
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp) {}
unsigned char* sdir, unsigned char* samp, GCNDataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp), m_fmt(DataFormat::GCN) {}
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, N64DataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp), m_fmt(DataFormat::N64) {}
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, PCDataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp), m_fmt(DataFormat::PC) {}

const unsigned char* getProj() const {return m_proj;}
const unsigned char* getPool() const {return m_pool;}
Expand Down
1 change: 1 addition & 0 deletions include/amuse/AudioGroupPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class AudioGroupPool
std::unordered_map<ObjectId, std::vector<const LayerMapping*>> m_layers;
public:
AudioGroupPool(const unsigned char* data);
AudioGroupPool(const unsigned char* data, PCDataTag);
const unsigned char* soundMacro(ObjectId id) const;
const Keymap* keymap(ObjectId id) const;
const std::vector<const LayerMapping*>* layer(ObjectId id) const;
Expand Down
15 changes: 14 additions & 1 deletion include/amuse/AudioGroupProject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
#define __AMUSE_AUDIOGROUPPROJECT_HPP__

#include "Entity.hpp"
#include "Common.hpp"
#include <vector>
#include <array>
#include <unordered_map>

namespace amuse
{
class AudioGroupData;

/** Common index members of SongGroups and SFXGroups */
struct AudioGroupIndex
Expand Down Expand Up @@ -68,8 +70,19 @@ class AudioGroupProject
{
std::unordered_map<int, SongGroupIndex> m_songGroups;
std::unordered_map<int, SFXGroupIndex> m_sfxGroups;

/* MusyX 1.0 structures converted to MusyX 2.0 structures for pointer-compatible access */
std::unique_ptr<SongGroupIndex::PageEntry[]> m_convNormalPages;
std::unique_ptr<SongGroupIndex::PageEntry[]> m_convDrumPages;
std::unique_ptr<std::array<SongGroupIndex::MIDISetup, 16>[]> m_convMidiSetups;
void _allocateConvBuffers(const unsigned char* data, N64DataTag);
void _allocateConvBuffers(const unsigned char* data, PCDataTag);

public:
AudioGroupProject(const unsigned char* data);
AudioGroupProject(const unsigned char* data, GCNDataTag);
AudioGroupProject(const unsigned char* data, N64DataTag);
AudioGroupProject(const unsigned char* data, PCDataTag);
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);

const SongGroupIndex* getSongGroupIndex(int groupId) const;
const SFXGroupIndex* getSFXGroupIndex(int groupId) const;
Expand Down
7 changes: 5 additions & 2 deletions include/amuse/AudioGroupSampleDirectory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <unordered_map>
#include <stdint.h>
#include "Common.hpp"

namespace amuse
{
Expand Down Expand Up @@ -30,15 +31,17 @@ class AudioGroupSampleDirectory
uint16_t m_bytesPerFrame;
uint8_t m_ps;
uint8_t m_lps;
int16_t m_hist1;
int16_t m_hist2;
int16_t m_hist1;
int16_t m_coefs[8][2];
void swapBig();
};
private:
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
public:
AudioGroupSampleDirectory(const unsigned char* data);
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
AudioGroupSampleDirectory(const unsigned char* data, N64DataTag);
AudioGroupSampleDirectory(const unsigned char* data, PCDataTag);
};

}
Expand Down
17 changes: 17 additions & 0 deletions include/amuse/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,23 @@ static inline double SBig(double val) {return val;}
#endif
#endif

/** Versioned data format to interpret */
enum class DataFormat
{
GCN,
N64,
PC
};

/** Meta-type for selecting GameCube (MusyX 2.0) data formats */
struct GCNDataTag {};

/** Meta-type for selecting N64 (MusyX 1.0) data formats */
struct N64DataTag {};

/** Meta-type for selecting PC (MusyX 1.0) data formats */
struct PCDataTag {};

}

#endif // __AMUSE_COMMON_HPP__
6 changes: 3 additions & 3 deletions include/amuse/dsp.h → include/amuse/DSPCodec.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef _DSP_h
#define _DSP_h
#ifndef _DSPCODEC_h
#define _DSPCODEC_h

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -36,4 +36,4 @@ unsigned DSPDecompressFrameStateOnly(const uint8_t* in,
}
#endif

#endif // _DSP_h
#endif // _DSPCODEC_h
1 change: 1 addition & 0 deletions include/amuse/Engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Engine
std::linear_congruential_engine<uint32_t, 0x41c64e6d, 0x3039, UINT32_MAX> m_random;
int m_nextVid = 0;

AudioGroup* _addAudioGroup(const AudioGroupData& data, std::unique_ptr<AudioGroup>&& grp);
std::pair<AudioGroup*, const SongGroupIndex*> _findSongGroup(int groupId) const;
std::pair<AudioGroup*, const SFXGroupIndex*> _findSFXGroup(int groupId) const;

Expand Down
29 changes: 29 additions & 0 deletions include/amuse/N64MusyXCodec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef _N64MUSYXCODEC_h
#define _N64MUSYXCODEC_h

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

static inline int16_t N64MusyXSampClamp(int32_t val)
{
if (val < -32768) val = -32768;
else if (val > 32767) val = 32767;
return val;
}

unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in,
const int16_t coefs[8][2][8],
unsigned lastSample);

unsigned N64MusyXDecompressFrameRanged(int16_t* out, const uint8_t* in,
const int16_t coefs[8][2][8],
unsigned firstSample, unsigned lastSample);

#ifdef __cplusplus
}
#endif

#endif // _N64MUSYXCODEC_h
4 changes: 2 additions & 2 deletions include/amuse/SoundMacroState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ class SoundMacroState

public:
/** initialize state for SoundMacro data at `ptr` */
void initialize(const unsigned char* ptr, int step);
void initialize(const unsigned char* ptr, int step, bool swapData);
void initialize(const unsigned char* ptr, int step, double ticksPerSec,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod);
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool swapData);

/** advances `dt` seconds worth of commands in the SoundMacro
* @return `true` if END reached
Expand Down
6 changes: 4 additions & 2 deletions include/amuse/Voice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ class Voice : public Entity
{
DSP,
IMA,
PCM
PCM,
N64
};
const Sample* m_curSample = nullptr; /**< Current sample entry playing */
const unsigned char* m_curSampleData = nullptr; /**< Current sample data playing */
Expand Down Expand Up @@ -128,14 +129,15 @@ class Voice : public Entity

void _destroy();
void _reset();
bool _checkSamplePos();
bool _checkSamplePos(bool& looped);
void _doKeyOff();
void _macroKeyOff();
void _macroSampleEnd();
bool _advanceSample(int16_t& samp, int32_t& curPitch);
void _setTotalPitch(int32_t cents, bool slew);
bool _isRecursivelyDead();
void _bringOutYourDead();
static uint32_t _GetBlockSampleCount(SampleFormat fmt);
std::shared_ptr<Voice> _findVoice(int vid, std::weak_ptr<Voice> thisPtr);
std::unique_ptr<int8_t[]>& _ensureCtrlVals();

Expand Down
25 changes: 21 additions & 4 deletions lib/AudioGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,28 @@
namespace amuse
{

AudioGroup::AudioGroup(const AudioGroupData& data)
: m_proj(data.getProj()),
AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
: m_proj(data.getProj(), GCNDataTag{}),
m_pool(data.getPool()),
m_sdir(data.getSdir()),
m_samp(data.getSamp())
m_sdir(data.getSdir(), GCNDataTag{}),
m_samp(data.getSamp()),
m_fmt(DataFormat::GCN)
{}

AudioGroup::AudioGroup(const AudioGroupData& data, N64DataTag)
: m_proj(data.getProj(), N64DataTag{}),
m_pool(data.getPool()),
m_sdir(data.getSdir(), N64DataTag{}),
m_samp(data.getSamp()),
m_fmt(DataFormat::N64)
{}

AudioGroup::AudioGroup(const AudioGroupData& data, PCDataTag)
: m_proj(data.getProj(), PCDataTag{}),
m_pool(data.getPool(), PCDataTag{}),
m_sdir(data.getSdir(), PCDataTag{}),
m_samp(data.getSamp()),
m_fmt(DataFormat::PC)
{}

const Sample* AudioGroup::getSample(int sfxId) const
Expand Down
2 changes: 1 addition & 1 deletion lib/AudioGroupData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ IntrusiveAudioGroupData::~IntrusiveAudioGroupData()
}

IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other)
: AudioGroupData(other.m_proj, other.m_pool, other.m_sdir, other.m_samp)
: AudioGroupData(other.m_proj, other.m_pool, other.m_sdir, other.m_samp, other.m_fmt)
{
m_owns = other.m_owns;
other.m_owns = false;
Expand Down
60 changes: 60 additions & 0 deletions lib/AudioGroupPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,66 @@ AudioGroupPool::AudioGroupPool(const unsigned char* data)
}
}

AudioGroupPool::AudioGroupPool(const unsigned char* data, PCDataTag)
{
const Header* head = reinterpret_cast<const Header*>(data);

if (head->soundMacrosOffset)
{
const unsigned char* cur = data + head->soundMacrosOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = *reinterpret_cast<const uint32_t*>(cur);
ObjectId id = *reinterpret_cast<const ObjectId*>(cur + 4);
m_soundMacros[id] = cur;
cur += size;
}
}

if (head->tablesOffset)
{
const unsigned char* cur = data + head->tablesOffset;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{
uint32_t size = *reinterpret_cast<const uint32_t*>(cur);
ObjectId id = *reinterpret_cast<const ObjectId*>(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 = *reinterpret_cast<const uint32_t*>(cur);
ObjectId id = *reinterpret_cast<const ObjectId*>(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 = *reinterpret_cast<const uint32_t*>(cur);
ObjectId id = *reinterpret_cast<const ObjectId*>(cur + 4);
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];

uint32_t count = *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;
}
}
}

const unsigned char* AudioGroupPool::soundMacro(ObjectId id) const
{
auto search = m_soundMacros.find(id);
Expand Down

0 comments on commit 5a9fd66

Please sign in to comment.