mirror of
https://github.com/AxioDL/amuse.git
synced 2025-05-14 03:11:22 +00:00
MusyX 1 compatibility fixes, Rogue Squadron N64 decoding confirmed
This commit is contained in:
parent
3ba25fd06a
commit
80cc9f7c94
@ -10,7 +10,6 @@ namespace amuse
|
|||||||
class AudioGroupData
|
class AudioGroupData
|
||||||
{
|
{
|
||||||
friend class Engine;
|
friend class Engine;
|
||||||
friend class AudioGroupProject;
|
|
||||||
protected:
|
protected:
|
||||||
unsigned char* m_proj;
|
unsigned char* m_proj;
|
||||||
unsigned char* m_pool;
|
unsigned char* m_pool;
|
||||||
@ -41,6 +40,8 @@ public:
|
|||||||
{
|
{
|
||||||
return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr;
|
return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataFormat getDataFormat() const {return m_fmt;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A buffer-owning version of AudioGroupData */
|
/** A buffer-owning version of AudioGroupData */
|
||||||
|
@ -26,7 +26,9 @@ public:
|
|||||||
uint32_t m_adpcmParmOffset;
|
uint32_t m_adpcmParmOffset;
|
||||||
void swapBig();
|
void swapBig();
|
||||||
};
|
};
|
||||||
struct ADPCMParms
|
union ADPCMParms
|
||||||
|
{
|
||||||
|
struct DSPParms
|
||||||
{
|
{
|
||||||
uint16_t m_bytesPerFrame;
|
uint16_t m_bytesPerFrame;
|
||||||
uint8_t m_ps;
|
uint8_t m_ps;
|
||||||
@ -34,13 +36,19 @@ public:
|
|||||||
int16_t m_hist2;
|
int16_t m_hist2;
|
||||||
int16_t m_hist1;
|
int16_t m_hist1;
|
||||||
int16_t m_coefs[8][2];
|
int16_t m_coefs[8][2];
|
||||||
void swapBig();
|
} dsp;
|
||||||
|
struct VADPCMParms
|
||||||
|
{
|
||||||
|
int16_t m_coefs[8][2][8];
|
||||||
|
} vadpcm;
|
||||||
|
void swapBigDSP();
|
||||||
|
void swapBigVADPCM();
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
|
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
|
||||||
public:
|
public:
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
|
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, N64DataTag);
|
AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData, N64DataTag);
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, PCDataTag);
|
AudioGroupSampleDirectory(const unsigned char* data, PCDataTag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,10 +48,11 @@ class Voice : public Entity
|
|||||||
|
|
||||||
enum class SampleFormat : uint8_t
|
enum class SampleFormat : uint8_t
|
||||||
{
|
{
|
||||||
DSP,
|
DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */
|
||||||
IMA,
|
IMA, /**< IMA-ADPCM (rarely used within MusyX itself) */
|
||||||
PCM,
|
PCM, /**< Big-endian PCM found in MusyX2 demo GM instruments */
|
||||||
N64
|
N64, /**< 2-stage VADPCM coding with SAMP-embedded codebooks */
|
||||||
|
PCM_PC /**< Little-endian PCM found in PC Rogue Squadron (actually enum 0 which conflicts with DSP-ADPCM) */
|
||||||
};
|
};
|
||||||
const Sample* m_curSample = nullptr; /**< Current sample entry playing */
|
const Sample* m_curSample = nullptr; /**< Current sample entry playing */
|
||||||
const unsigned char* m_curSampleData = nullptr; /**< Current sample data playing */
|
const unsigned char* m_curSampleData = nullptr; /**< Current sample data playing */
|
||||||
|
@ -15,7 +15,7 @@ AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
|||||||
AudioGroup::AudioGroup(const AudioGroupData& data, N64DataTag)
|
AudioGroup::AudioGroup(const AudioGroupData& data, N64DataTag)
|
||||||
: m_proj(data.getProj(), N64DataTag{}),
|
: m_proj(data.getProj(), N64DataTag{}),
|
||||||
m_pool(data.getPool()),
|
m_pool(data.getPool()),
|
||||||
m_sdir(data.getSdir(), N64DataTag{}),
|
m_sdir(data.getSdir(), data.getSamp(), N64DataTag{}),
|
||||||
m_samp(data.getSamp()),
|
m_samp(data.getSamp()),
|
||||||
m_fmt(DataFormat::N64)
|
m_fmt(DataFormat::N64)
|
||||||
{}
|
{}
|
||||||
|
@ -187,8 +187,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, N64DataT
|
|||||||
|
|
||||||
/* MIDI setups */
|
/* MIDI setups */
|
||||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||||
while (setupData < setupEnd)
|
|
||||||
{
|
{
|
||||||
++midiSetupCount;
|
++midiSetupCount;
|
||||||
setupData += 8 * 16 + 4;
|
setupData += 8 * 16 + 4;
|
||||||
@ -252,8 +251,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, N64DataTag)
|
|||||||
|
|
||||||
/* MIDI setups */
|
/* MIDI setups */
|
||||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||||
while (setupData < setupEnd)
|
|
||||||
{
|
{
|
||||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
||||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||||
@ -329,8 +327,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, PCDataTa
|
|||||||
|
|
||||||
/* MIDI setups */
|
/* MIDI setups */
|
||||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||||
while (setupData < setupEnd)
|
|
||||||
{
|
{
|
||||||
++midiSetupCount;
|
++midiSetupCount;
|
||||||
setupData += 8 * 16 + 4;
|
setupData += 8 * 16 + 4;
|
||||||
@ -392,10 +389,9 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, PCDataTag)
|
|||||||
|
|
||||||
/* MIDI setups */
|
/* MIDI setups */
|
||||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||||
while (setupData < setupEnd)
|
|
||||||
{
|
{
|
||||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
uint16_t songId = *reinterpret_cast<const uint16_t*>(setupData);
|
||||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||||
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
||||||
|
|
||||||
@ -438,7 +434,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, PCDataTag)
|
|||||||
|
|
||||||
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupData& data)
|
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupData& data)
|
||||||
{
|
{
|
||||||
switch (data.m_fmt)
|
switch (data.getDataFormat())
|
||||||
{
|
{
|
||||||
case DataFormat::GCN:
|
case DataFormat::GCN:
|
||||||
return AudioGroupProject(data.getProj(), GCNDataTag{});
|
return AudioGroupProject(data.getProj(), GCNDataTag{});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "amuse/AudioGroupSampleDirectory.hpp"
|
#include "amuse/AudioGroupSampleDirectory.hpp"
|
||||||
#include "amuse/Common.hpp"
|
#include "amuse/Common.hpp"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
@ -16,18 +17,25 @@ void AudioGroupSampleDirectory::Entry::swapBig()
|
|||||||
m_adpcmParmOffset = SBig(m_adpcmParmOffset);
|
m_adpcmParmOffset = SBig(m_adpcmParmOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioGroupSampleDirectory::ADPCMParms::swapBig()
|
void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||||
{
|
{
|
||||||
m_bytesPerFrame = SBig(m_bytesPerFrame);
|
dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
|
||||||
m_hist2 = SBig(m_hist2);
|
dsp.m_hist2 = SBig(dsp.m_hist2);
|
||||||
m_hist1 = SBig(m_hist1);
|
dsp.m_hist1 = SBig(dsp.m_hist1);
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i=0 ; i<8 ; ++i)
|
||||||
{
|
{
|
||||||
m_coefs[i][0] = SBig(m_coefs[i][0]);
|
dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
|
||||||
m_coefs[i][1] = SBig(m_coefs[i][1]);
|
dsp.m_coefs[i][1] = SBig(dsp.m_coefs[i][1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
|
||||||
|
{
|
||||||
|
int16_t* allCoefs = reinterpret_cast<int16_t*>(vadpcm.m_coefs[0][0]);
|
||||||
|
for (int i=0 ; i<128 ; ++i)
|
||||||
|
allCoefs[i] = SBig(allCoefs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag)
|
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag)
|
||||||
{
|
{
|
||||||
const unsigned char* cur = data;
|
const unsigned char* cur = data;
|
||||||
@ -46,7 +54,7 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
|
|||||||
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data +
|
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data +
|
||||||
store.first.m_adpcmParmOffset);
|
store.first.m_adpcmParmOffset);
|
||||||
store.second = *adpcm;
|
store.second = *adpcm;
|
||||||
store.second.swapBig();
|
store.second.swapBigDSP();
|
||||||
}
|
}
|
||||||
|
|
||||||
cur += 32;
|
cur += 32;
|
||||||
@ -86,7 +94,8 @@ struct MusyX1SdirEntry
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, N64DataTag)
|
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
|
||||||
|
const unsigned char* sampData, N64DataTag)
|
||||||
{
|
{
|
||||||
const unsigned char* cur = data;
|
const unsigned char* cur = data;
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||||
@ -97,6 +106,9 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
|
|||||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||||
ent.setIntoMusyX2(store.first);
|
ent.setIntoMusyX2(store.first);
|
||||||
|
|
||||||
|
memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
||||||
|
store.second.swapBigVADPCM();
|
||||||
|
|
||||||
cur += 24;
|
cur += 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,19 +518,16 @@ static bool ValidateRS1N64(FILE* fp)
|
|||||||
if (endPos > 32 * 1024 * 1024)
|
if (endPos > 32 * 1024 * 1024)
|
||||||
return false; /* N64 ROM definitely won't exceed 32MB */
|
return false; /* N64 ROM definitely won't exceed 32MB */
|
||||||
|
|
||||||
FSeek(fp, 59, SEEK_SET);
|
|
||||||
uint32_t gameId;
|
|
||||||
fread(&gameId, 1, 4, fp);
|
|
||||||
if (gameId != 0x4e525345 && gameId != 0x4553524e)
|
|
||||||
return false; /* GameId not 'NRSE' */
|
|
||||||
FSeek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> data(new uint8_t[endPos]);
|
std::unique_ptr<uint8_t[]> data(new uint8_t[endPos]);
|
||||||
fread(data.get(), 1, endPos, fp);
|
fread(data.get(), 1, endPos, fp);
|
||||||
|
|
||||||
if ((data[0] & 0x80) != 0x80 && (data[3] & 0x80) == 0x80)
|
if ((data[0] & 0x80) != 0x80 && (data[3] & 0x80) == 0x80)
|
||||||
SwapN64Rom(data.get(), endPos);
|
SwapN64Rom(data.get(), endPos);
|
||||||
|
|
||||||
|
const uint32_t* gameId = reinterpret_cast<const uint32_t*>(&data[59]);
|
||||||
|
if (*gameId != 0x4e525345 && *gameId != 0x4553524e)
|
||||||
|
return false; /* GameId not 'NRSE' */
|
||||||
|
|
||||||
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos,
|
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos,
|
||||||
"dbg_data\0\0\0\0\0\0\0\0", 16));
|
"dbg_data\0\0\0\0\0\0\0\0", 16));
|
||||||
if (dataSeg)
|
if (dataSeg)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "amuse/N64MusyXCodec.h"
|
#include "amuse/N64MusyXCodec.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* Acknowledgements:
|
/* Acknowledgements:
|
||||||
* SubDrag for N64 Sound Tool (http://www.goldeneyevault.com/viewfile.php?id=212)
|
* SubDrag for N64 Sound Tool (http://www.goldeneyevault.com/viewfile.php?id=212)
|
||||||
@ -72,68 +73,44 @@ static unsigned adpcm_decode_upto_8_samples(int16_t* dst, const int16_t* src,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned adpcm_decode_upto_8_samples_ranged(int16_t* dst, const int16_t* src,
|
|
||||||
const int16_t* cb_entry,
|
|
||||||
const int16_t* last_samples,
|
|
||||||
unsigned firstSample,
|
|
||||||
unsigned size)
|
|
||||||
{
|
|
||||||
if (firstSample >= size)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const int16_t* book1 = cb_entry;
|
|
||||||
const int16_t* book2 = cb_entry + 8;
|
|
||||||
|
|
||||||
int16_t l1 = last_samples[0];
|
|
||||||
int16_t l2 = last_samples[1];
|
|
||||||
|
|
||||||
int accu;
|
|
||||||
|
|
||||||
unsigned ret = 0;
|
|
||||||
for (unsigned i=firstSample ; i<size ; ++i)
|
|
||||||
{
|
|
||||||
accu = (int)src[i] << 11;
|
|
||||||
accu += book1[i] * l1 + book2[i] * l2 + rdot(i, book2, src);
|
|
||||||
*dst++ = N64MusyXSampClamp(accu >> 11);
|
|
||||||
++ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in,
|
unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in,
|
||||||
const int16_t coefs[8][2][8],
|
const int16_t coefs[8][2][8],
|
||||||
unsigned lastSample)
|
unsigned lastSample)
|
||||||
{
|
{
|
||||||
int16_t frame[32];
|
int16_t frame[32];
|
||||||
|
|
||||||
|
unsigned remSamples = lastSample;
|
||||||
unsigned samples = 0;
|
unsigned samples = 0;
|
||||||
unsigned procSamples;
|
unsigned procSamples, procRes;
|
||||||
|
|
||||||
unsigned char c2 = in[0x8];
|
unsigned char c2 = in[0x8];
|
||||||
c2 = c2 % 0x80;
|
c2 = c2 % 0x80;
|
||||||
|
|
||||||
const int16_t* bookPredictors = coefs[(c2 & 0xf0) >> 8][0];
|
const int16_t* bookPredictors = coefs[(c2 & 0xf0) >> 4][0];
|
||||||
unsigned int rshift = (c2 & 0x0f);
|
unsigned int rshift = (c2 & 0x0f);
|
||||||
|
|
||||||
adpcm_get_predicted_frame(frame, &in[0x0], &in[0x8], rshift);
|
adpcm_get_predicted_frame(frame, &in[0x0], &in[0x8], rshift);
|
||||||
|
|
||||||
procSamples = (lastSample < 2) ? lastSample : 2;
|
procSamples = (remSamples < 2) ? remSamples : 2;
|
||||||
memcpy(out, frame, 2 * procSamples);
|
memcpy(out, frame, 2 * procSamples);
|
||||||
samples += procSamples;
|
samples += procSamples;
|
||||||
|
remSamples -= procSamples;
|
||||||
if (samples == lastSample)
|
if (samples == lastSample)
|
||||||
return samples;
|
return samples;
|
||||||
|
|
||||||
#define adpcm_decode_upto_end_samples(inOffset, bookPredictors, outOffset, size) \
|
#define adpcm_decode_upto_end_samples(inOffset, outOffset, size) \
|
||||||
procSamples = (lastSample < size) ? lastSample : size; \
|
procSamples = (remSamples < size) ? remSamples : size; \
|
||||||
samples += adpcm_decode_upto_8_samples(out + inOffset, frame + inOffset, bookPredictors, out + outOffset, procSamples); \
|
procRes = adpcm_decode_upto_8_samples(out + inOffset, frame + inOffset, bookPredictors, \
|
||||||
|
out + outOffset, procSamples); \
|
||||||
|
samples += procRes; \
|
||||||
|
remSamples -= procRes; \
|
||||||
if (samples == lastSample) \
|
if (samples == lastSample) \
|
||||||
return samples;
|
return samples;
|
||||||
|
|
||||||
adpcm_decode_upto_end_samples(2, bookPredictors, 0, 6);
|
adpcm_decode_upto_end_samples(2, 0, 6);
|
||||||
adpcm_decode_upto_end_samples(8, bookPredictors, 6, 8);
|
adpcm_decode_upto_end_samples(8, 6, 8);
|
||||||
adpcm_decode_upto_end_samples(16, bookPredictors, 14, 8);
|
adpcm_decode_upto_end_samples(16, 14, 8);
|
||||||
adpcm_decode_upto_end_samples(24, bookPredictors, 22, 8);
|
adpcm_decode_upto_end_samples(24, 22, 8);
|
||||||
|
|
||||||
out += 32;
|
out += 32;
|
||||||
|
|
||||||
@ -141,21 +118,22 @@ unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in,
|
|||||||
c2 = in[0x18];
|
c2 = in[0x18];
|
||||||
c2 = c2 % 0x80;
|
c2 = c2 % 0x80;
|
||||||
|
|
||||||
bookPredictors = coefs[(c2 & 0xf0) >> 8][0];
|
bookPredictors = coefs[(c2 & 0xf0) >> 4][0];
|
||||||
rshift = (c2 & 0x0f);
|
rshift = (c2 & 0x0f);
|
||||||
|
|
||||||
adpcm_get_predicted_frame(frame, &in[0x4], &in[0x18], rshift);
|
adpcm_get_predicted_frame(frame, &in[0x4], &in[0x18], rshift);
|
||||||
|
|
||||||
procSamples = (lastSample < 2) ? lastSample : 2;
|
procSamples = (remSamples < 2) ? remSamples : 2;
|
||||||
memcpy(out, frame, 2 * procSamples);
|
memcpy(out, frame, 2 * procSamples);
|
||||||
samples += procSamples;
|
samples += procSamples;
|
||||||
|
remSamples -= procSamples;
|
||||||
if (samples == lastSample)
|
if (samples == lastSample)
|
||||||
return samples;
|
return samples;
|
||||||
|
|
||||||
adpcm_decode_upto_end_samples(2, bookPredictors, 0, 6);
|
adpcm_decode_upto_end_samples(2, 0, 6);
|
||||||
adpcm_decode_upto_end_samples(8, bookPredictors, 6, 8);
|
adpcm_decode_upto_end_samples(8, 6, 8);
|
||||||
adpcm_decode_upto_end_samples(16, bookPredictors, 14, 8);
|
adpcm_decode_upto_end_samples(16, 14, 8);
|
||||||
adpcm_decode_upto_end_samples(24, bookPredictors, 22, 8);
|
adpcm_decode_upto_end_samples(24, 22, 8);
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
@ -164,61 +142,10 @@ unsigned N64MusyXDecompressFrameRanged(int16_t* out, const uint8_t* in,
|
|||||||
const int16_t coefs[8][2][8],
|
const int16_t coefs[8][2][8],
|
||||||
unsigned firstSample, unsigned lastSample)
|
unsigned firstSample, unsigned lastSample)
|
||||||
{
|
{
|
||||||
int16_t frame[32];
|
int16_t final[64];
|
||||||
|
unsigned procSamples = N64MusyXDecompressFrame(final, in, coefs, firstSample + lastSample);
|
||||||
unsigned samples = 0;
|
unsigned samples = procSamples - firstSample;
|
||||||
unsigned procSamples;
|
memcpy(out, final + firstSample, samples * 2);
|
||||||
|
|
||||||
unsigned char c2 = in[0x8];
|
|
||||||
c2 = c2 % 0x80;
|
|
||||||
|
|
||||||
const int16_t* bookPredictors = coefs[(c2 & 0xf0) >> 8][0];
|
|
||||||
unsigned int rshift = (c2 & 0x0f);
|
|
||||||
|
|
||||||
adpcm_get_predicted_frame(frame, &in[0x0], &in[0x8], rshift);
|
|
||||||
|
|
||||||
procSamples = (lastSample < 2) ? lastSample : 2;
|
|
||||||
memcpy(out, frame, 2 * procSamples);
|
|
||||||
samples += procSamples;
|
|
||||||
firstSample = (2 > firstSample) ? 0 : (firstSample - 2);
|
|
||||||
if (samples == lastSample)
|
|
||||||
return samples;
|
|
||||||
|
|
||||||
#define adpcm_decode_upto_end_samples_ranged(inOffset, bookPredictors, outOffset, size) \
|
|
||||||
procSamples = (lastSample < size) ? lastSample : size; \
|
|
||||||
samples += adpcm_decode_upto_8_samples_ranged(out + inOffset, frame + inOffset, bookPredictors, out + outOffset, firstSample, procSamples); \
|
|
||||||
firstSample = (size > firstSample) ? 0 : (firstSample - size); \
|
|
||||||
if (samples == lastSample) \
|
|
||||||
return samples;\
|
|
||||||
|
|
||||||
adpcm_decode_upto_end_samples_ranged(2, bookPredictors, 0, 6);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(8, bookPredictors, 6, 8);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(16, bookPredictors, 14, 8);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(24, bookPredictors, 22, 8);
|
|
||||||
|
|
||||||
out += 32;
|
|
||||||
|
|
||||||
|
|
||||||
c2 = in[0x18];
|
|
||||||
c2 = c2 % 0x80;
|
|
||||||
|
|
||||||
bookPredictors = coefs[(c2 & 0xf0) >> 8][0];
|
|
||||||
rshift = (c2 & 0x0f);
|
|
||||||
|
|
||||||
adpcm_get_predicted_frame(frame, &in[0x4], &in[0x18], rshift);
|
|
||||||
|
|
||||||
procSamples = (lastSample < 2) ? lastSample : 2;
|
|
||||||
memcpy(out, frame, 2 * procSamples);
|
|
||||||
samples += procSamples;
|
|
||||||
firstSample = (2 > firstSample) ? 0 : (firstSample - 2);
|
|
||||||
if (samples == lastSample)
|
|
||||||
return samples;
|
|
||||||
|
|
||||||
adpcm_decode_upto_end_samples_ranged(2, bookPredictors, 0, 6);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(8, bookPredictors, 6, 8);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(16, bookPredictors, 14, 8);
|
|
||||||
adpcm_decode_upto_end_samples_ranged(24, bookPredictors, 22, 8);
|
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +94,11 @@ bool Voice::_checkSamplePos(bool& looped)
|
|||||||
{
|
{
|
||||||
/* Turn over looped sample */
|
/* Turn over looped sample */
|
||||||
m_curSamplePos = m_curSample->first.m_loopStartSample;
|
m_curSamplePos = m_curSample->first.m_loopStartSample;
|
||||||
m_prev1 = m_curSample->second.m_hist1;
|
if (m_curFormat == SampleFormat::DSP)
|
||||||
m_prev2 = m_curSample->second.m_hist2;
|
{
|
||||||
|
m_prev1 = m_curSample->second.dsp.m_hist1;
|
||||||
|
m_prev2 = m_curSample->second.dsp.m_hist2;
|
||||||
|
}
|
||||||
looped = true;
|
looped = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -408,10 +411,17 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||||||
case SampleFormat::DSP:
|
case SampleFormat::DSP:
|
||||||
{
|
{
|
||||||
decSamples = DSPDecompressFrameRanged(data, m_curSampleData + 8 * block,
|
decSamples = DSPDecompressFrameRanged(data, m_curSampleData + 8 * block,
|
||||||
m_curSample->second.m_coefs,
|
m_curSample->second.dsp.m_coefs,
|
||||||
&m_prev1, &m_prev2, rem, remCount);
|
&m_prev1, &m_prev2, rem, remCount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SampleFormat::N64:
|
||||||
|
{
|
||||||
|
decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block,
|
||||||
|
m_curSample->second.vadpcm.m_coefs,
|
||||||
|
rem, remCount);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SampleFormat::PCM:
|
case SampleFormat::PCM:
|
||||||
{
|
{
|
||||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
@ -421,11 +431,12 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||||||
decSamples = remCount;
|
decSamples = remCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SampleFormat::N64:
|
case SampleFormat::PCM_PC:
|
||||||
{
|
{
|
||||||
decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block,
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
reinterpret_cast<const int16_t(*)[2][8]>(m_curSampleData),
|
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||||
rem, remCount);
|
memcpy(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
||||||
|
decSamples = remCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -465,10 +476,17 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||||||
case SampleFormat::DSP:
|
case SampleFormat::DSP:
|
||||||
{
|
{
|
||||||
decSamples = DSPDecompressFrame(data, m_curSampleData + 8 * block,
|
decSamples = DSPDecompressFrame(data, m_curSampleData + 8 * block,
|
||||||
m_curSample->second.m_coefs,
|
m_curSample->second.dsp.m_coefs,
|
||||||
&m_prev1, &m_prev2, remCount);
|
&m_prev1, &m_prev2, remCount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SampleFormat::N64:
|
||||||
|
{
|
||||||
|
decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block,
|
||||||
|
m_curSample->second.vadpcm.m_coefs,
|
||||||
|
remCount);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SampleFormat::PCM:
|
case SampleFormat::PCM:
|
||||||
{
|
{
|
||||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
@ -478,11 +496,12 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||||||
decSamples = remCount;
|
decSamples = remCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SampleFormat::N64:
|
case SampleFormat::PCM_PC:
|
||||||
{
|
{
|
||||||
decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block,
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
reinterpret_cast<const int16_t(*)[2][8]>(m_curSampleData),
|
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||||
remCount);
|
memcpy(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
||||||
|
decSamples = remCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -725,13 +744,17 @@ void Voice::startSample(int16_t sampId, int32_t offset)
|
|||||||
m_curSampleData = m_audioGroup.getSampleData(m_curSample->first.m_sampleOff);
|
m_curSampleData = m_audioGroup.getSampleData(m_curSample->first.m_sampleOff);
|
||||||
m_prev1 = 0;
|
m_prev1 = 0;
|
||||||
m_prev2 = 0;
|
m_prev2 = 0;
|
||||||
|
if (m_audioGroup.getDataFormat() == DataFormat::PC)
|
||||||
|
m_curFormat = SampleFormat::PCM_PC;
|
||||||
|
else
|
||||||
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
||||||
m_lastSamplePos = m_curSample->first.m_loopLengthSamples ?
|
m_lastSamplePos = m_curSample->first.m_loopLengthSamples ?
|
||||||
(m_curSample->first.m_loopStartSample + m_curSample->first.m_loopLengthSamples) : numSamples;
|
(m_curSample->first.m_loopStartSample + m_curSample->first.m_loopLengthSamples) : numSamples;
|
||||||
|
|
||||||
if (m_curFormat != SampleFormat::DSP &&
|
if (m_curFormat != SampleFormat::DSP &&
|
||||||
m_curFormat != SampleFormat::PCM &&
|
m_curFormat != SampleFormat::PCM &&
|
||||||
m_curFormat != SampleFormat::N64)
|
m_curFormat != SampleFormat::N64 &&
|
||||||
|
m_curFormat != SampleFormat::PCM_PC)
|
||||||
{
|
{
|
||||||
m_curSample = nullptr;
|
m_curSample = nullptr;
|
||||||
return;
|
return;
|
||||||
@ -746,11 +769,11 @@ void Voice::startSample(int16_t sampId, int32_t offset)
|
|||||||
uint32_t block = m_curSamplePos / 14;
|
uint32_t block = m_curSamplePos / 14;
|
||||||
uint32_t rem = m_curSamplePos % 14;
|
uint32_t rem = m_curSamplePos % 14;
|
||||||
for (uint32_t b = 0 ; b < block ; ++b)
|
for (uint32_t b = 0 ; b < block ; ++b)
|
||||||
DSPDecompressFrameStateOnly(m_curSampleData + 8 * b, m_curSample->second.m_coefs,
|
DSPDecompressFrameStateOnly(m_curSampleData + 8 * b, m_curSample->second.dsp.m_coefs,
|
||||||
&m_prev1, &m_prev2, 14);
|
&m_prev1, &m_prev2, 14);
|
||||||
|
|
||||||
if (rem)
|
if (rem)
|
||||||
DSPDecompressFrameStateOnly(m_curSampleData + 8 * block, m_curSample->second.m_coefs,
|
DSPDecompressFrameStateOnly(m_curSampleData + 8 * block, m_curSample->second.dsp.m_coefs,
|
||||||
&m_prev1, &m_prev2, rem);
|
&m_prev1, &m_prev2, rem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user