mirror of https://github.com/AxioDL/amuse.git
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
|
||||
{
|
||||
friend class Engine;
|
||||
friend class AudioGroupProject;
|
||||
protected:
|
||||
unsigned char* m_proj;
|
||||
unsigned char* m_pool;
|
||||
|
@ -41,6 +40,8 @@ public:
|
|||
{
|
||||
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 */
|
||||
|
|
|
@ -26,21 +26,29 @@ public:
|
|||
uint32_t m_adpcmParmOffset;
|
||||
void swapBig();
|
||||
};
|
||||
struct ADPCMParms
|
||||
union ADPCMParms
|
||||
{
|
||||
uint16_t m_bytesPerFrame;
|
||||
uint8_t m_ps;
|
||||
uint8_t m_lps;
|
||||
int16_t m_hist2;
|
||||
int16_t m_hist1;
|
||||
int16_t m_coefs[8][2];
|
||||
void swapBig();
|
||||
struct DSPParms
|
||||
{
|
||||
uint16_t m_bytesPerFrame;
|
||||
uint8_t m_ps;
|
||||
uint8_t m_lps;
|
||||
int16_t m_hist2;
|
||||
int16_t m_hist1;
|
||||
int16_t m_coefs[8][2];
|
||||
} dsp;
|
||||
struct VADPCMParms
|
||||
{
|
||||
int16_t m_coefs[8][2][8];
|
||||
} vadpcm;
|
||||
void swapBigDSP();
|
||||
void swapBigVADPCM();
|
||||
};
|
||||
private:
|
||||
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
|
||||
public:
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -48,10 +48,11 @@ class Voice : public Entity
|
|||
|
||||
enum class SampleFormat : uint8_t
|
||||
{
|
||||
DSP,
|
||||
IMA,
|
||||
PCM,
|
||||
N64
|
||||
DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */
|
||||
IMA, /**< IMA-ADPCM (rarely used within MusyX itself) */
|
||||
PCM, /**< Big-endian PCM found in MusyX2 demo GM instruments */
|
||||
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 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)
|
||||
: m_proj(data.getProj(), N64DataTag{}),
|
||||
m_pool(data.getPool()),
|
||||
m_sdir(data.getSdir(), N64DataTag{}),
|
||||
m_sdir(data.getSdir(), data.getSamp(), N64DataTag{}),
|
||||
m_samp(data.getSamp()),
|
||||
m_fmt(DataFormat::N64)
|
||||
{}
|
||||
|
|
|
@ -187,8 +187,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, N64DataT
|
|||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||
{
|
||||
++midiSetupCount;
|
||||
setupData += 8 * 16 + 4;
|
||||
|
@ -252,8 +251,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, N64DataTag)
|
|||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||
{
|
||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||
|
@ -329,8 +327,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, PCDataTa
|
|||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||
{
|
||||
++midiSetupCount;
|
||||
setupData += 8 * 16 + 4;
|
||||
|
@ -392,10 +389,9 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, PCDataTag)
|
|||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff)
|
||||
{
|
||||
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 =
|
||||
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)
|
||||
{
|
||||
switch (data.m_fmt)
|
||||
switch (data.getDataFormat())
|
||||
{
|
||||
case DataFormat::GCN:
|
||||
return AudioGroupProject(data.getProj(), GCNDataTag{});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "amuse/AudioGroupSampleDirectory.hpp"
|
||||
#include "amuse/Common.hpp"
|
||||
#include <string.h>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
@ -16,18 +17,25 @@ void AudioGroupSampleDirectory::Entry::swapBig()
|
|||
m_adpcmParmOffset = SBig(m_adpcmParmOffset);
|
||||
}
|
||||
|
||||
void AudioGroupSampleDirectory::ADPCMParms::swapBig()
|
||||
void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||
{
|
||||
m_bytesPerFrame = SBig(m_bytesPerFrame);
|
||||
m_hist2 = SBig(m_hist2);
|
||||
m_hist1 = SBig(m_hist1);
|
||||
dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
|
||||
dsp.m_hist2 = SBig(dsp.m_hist2);
|
||||
dsp.m_hist1 = SBig(dsp.m_hist1);
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
{
|
||||
m_coefs[i][0] = SBig(m_coefs[i][0]);
|
||||
m_coefs[i][1] = SBig(m_coefs[i][1]);
|
||||
dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
|
||||
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)
|
||||
{
|
||||
const unsigned char* cur = data;
|
||||
|
@ -46,7 +54,7 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
|
|||
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data +
|
||||
store.first.m_adpcmParmOffset);
|
||||
store.second = *adpcm;
|
||||
store.second.swapBig();
|
||||
store.second.swapBigDSP();
|
||||
}
|
||||
|
||||
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;
|
||||
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];
|
||||
ent.setIntoMusyX2(store.first);
|
||||
|
||||
memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
||||
store.second.swapBigVADPCM();
|
||||
|
||||
cur += 24;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -518,19 +518,16 @@ static bool ValidateRS1N64(FILE* fp)
|
|||
if (endPos > 32 * 1024 * 1024)
|
||||
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]);
|
||||
fread(data.get(), 1, endPos, fp);
|
||||
|
||||
if ((data[0] & 0x80) != 0x80 && (data[3] & 0x80) == 0x80)
|
||||
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,
|
||||
"dbg_data\0\0\0\0\0\0\0\0", 16));
|
||||
if (dataSeg)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "amuse/N64MusyXCodec.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Acknowledgements:
|
||||
* 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;
|
||||
}
|
||||
|
||||
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,
|
||||
const int16_t coefs[8][2][8],
|
||||
unsigned lastSample)
|
||||
{
|
||||
int16_t frame[32];
|
||||
|
||||
unsigned remSamples = lastSample;
|
||||
unsigned samples = 0;
|
||||
unsigned procSamples;
|
||||
unsigned procSamples, procRes;
|
||||
|
||||
unsigned char c2 = in[0x8];
|
||||
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);
|
||||
|
||||
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);
|
||||
samples += procSamples;
|
||||
remSamples -= procSamples;
|
||||
if (samples == lastSample)
|
||||
return samples;
|
||||
|
||||
#define adpcm_decode_upto_end_samples(inOffset, bookPredictors, outOffset, size) \
|
||||
procSamples = (lastSample < size) ? lastSample : size; \
|
||||
samples += adpcm_decode_upto_8_samples(out + inOffset, frame + inOffset, bookPredictors, out + outOffset, procSamples); \
|
||||
#define adpcm_decode_upto_end_samples(inOffset, outOffset, size) \
|
||||
procSamples = (remSamples < size) ? remSamples : size; \
|
||||
procRes = adpcm_decode_upto_8_samples(out + inOffset, frame + inOffset, bookPredictors, \
|
||||
out + outOffset, procSamples); \
|
||||
samples += procRes; \
|
||||
remSamples -= procRes; \
|
||||
if (samples == lastSample) \
|
||||
return samples;
|
||||
|
||||
adpcm_decode_upto_end_samples(2, bookPredictors, 0, 6);
|
||||
adpcm_decode_upto_end_samples(8, bookPredictors, 6, 8);
|
||||
adpcm_decode_upto_end_samples(16, bookPredictors, 14, 8);
|
||||
adpcm_decode_upto_end_samples(24, bookPredictors, 22, 8);
|
||||
adpcm_decode_upto_end_samples(2, 0, 6);
|
||||
adpcm_decode_upto_end_samples(8, 6, 8);
|
||||
adpcm_decode_upto_end_samples(16, 14, 8);
|
||||
adpcm_decode_upto_end_samples(24, 22, 8);
|
||||
|
||||
out += 32;
|
||||
|
||||
|
@ -141,21 +118,22 @@ unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in,
|
|||
c2 = in[0x18];
|
||||
c2 = c2 % 0x80;
|
||||
|
||||
bookPredictors = coefs[(c2 & 0xf0) >> 8][0];
|
||||
bookPredictors = coefs[(c2 & 0xf0) >> 4][0];
|
||||
rshift = (c2 & 0x0f);
|
||||
|
||||
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);
|
||||
samples += procSamples;
|
||||
remSamples -= procSamples;
|
||||
if (samples == lastSample)
|
||||
return samples;
|
||||
|
||||
adpcm_decode_upto_end_samples(2, bookPredictors, 0, 6);
|
||||
adpcm_decode_upto_end_samples(8, bookPredictors, 6, 8);
|
||||
adpcm_decode_upto_end_samples(16, bookPredictors, 14, 8);
|
||||
adpcm_decode_upto_end_samples(24, bookPredictors, 22, 8);
|
||||
adpcm_decode_upto_end_samples(2, 0, 6);
|
||||
adpcm_decode_upto_end_samples(8, 6, 8);
|
||||
adpcm_decode_upto_end_samples(16, 14, 8);
|
||||
adpcm_decode_upto_end_samples(24, 22, 8);
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
@ -164,61 +142,10 @@ unsigned N64MusyXDecompressFrameRanged(int16_t* out, const uint8_t* in,
|
|||
const int16_t coefs[8][2][8],
|
||||
unsigned firstSample, unsigned lastSample)
|
||||
{
|
||||
int16_t frame[32];
|
||||
|
||||
unsigned samples = 0;
|
||||
unsigned procSamples;
|
||||
|
||||
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);
|
||||
|
||||
int16_t final[64];
|
||||
unsigned procSamples = N64MusyXDecompressFrame(final, in, coefs, firstSample + lastSample);
|
||||
unsigned samples = procSamples - firstSample;
|
||||
memcpy(out, final + firstSample, samples * 2);
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,11 @@ bool Voice::_checkSamplePos(bool& looped)
|
|||
{
|
||||
/* Turn over looped sample */
|
||||
m_curSamplePos = m_curSample->first.m_loopStartSample;
|
||||
m_prev1 = m_curSample->second.m_hist1;
|
||||
m_prev2 = m_curSample->second.m_hist2;
|
||||
if (m_curFormat == SampleFormat::DSP)
|
||||
{
|
||||
m_prev1 = m_curSample->second.dsp.m_hist1;
|
||||
m_prev2 = m_curSample->second.dsp.m_hist2;
|
||||
}
|
||||
looped = true;
|
||||
}
|
||||
else
|
||||
|
@ -408,10 +411,17 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||
case SampleFormat::DSP:
|
||||
{
|
||||
decSamples = DSPDecompressFrameRanged(data, m_curSampleData + 8 * block,
|
||||
m_curSample->second.m_coefs,
|
||||
m_curSample->second.dsp.m_coefs,
|
||||
&m_prev1, &m_prev2, rem, remCount);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::N64:
|
||||
{
|
||||
decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block,
|
||||
m_curSample->second.vadpcm.m_coefs,
|
||||
rem, remCount);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::PCM:
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case SampleFormat::N64:
|
||||
case SampleFormat::PCM_PC:
|
||||
{
|
||||
decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block,
|
||||
reinterpret_cast<const int16_t(*)[2][8]>(m_curSampleData),
|
||||
rem, remCount);
|
||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||
memcpy(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
||||
decSamples = remCount;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -465,10 +476,17 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||
case SampleFormat::DSP:
|
||||
{
|
||||
decSamples = DSPDecompressFrame(data, m_curSampleData + 8 * block,
|
||||
m_curSample->second.m_coefs,
|
||||
m_curSample->second.dsp.m_coefs,
|
||||
&m_prev1, &m_prev2, remCount);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::N64:
|
||||
{
|
||||
decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block,
|
||||
m_curSample->second.vadpcm.m_coefs,
|
||||
remCount);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::PCM:
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case SampleFormat::N64:
|
||||
case SampleFormat::PCM_PC:
|
||||
{
|
||||
decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block,
|
||||
reinterpret_cast<const int16_t(*)[2][8]>(m_curSampleData),
|
||||
remCount);
|
||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||
memcpy(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
||||
decSamples = remCount;
|
||||
break;
|
||||
}
|
||||
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_prev1 = 0;
|
||||
m_prev2 = 0;
|
||||
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
||||
if (m_audioGroup.getDataFormat() == DataFormat::PC)
|
||||
m_curFormat = SampleFormat::PCM_PC;
|
||||
else
|
||||
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
||||
m_lastSamplePos = m_curSample->first.m_loopLengthSamples ?
|
||||
(m_curSample->first.m_loopStartSample + m_curSample->first.m_loopLengthSamples) : numSamples;
|
||||
|
||||
if (m_curFormat != SampleFormat::DSP &&
|
||||
m_curFormat != SampleFormat::PCM &&
|
||||
m_curFormat != SampleFormat::N64)
|
||||
m_curFormat != SampleFormat::N64 &&
|
||||
m_curFormat != SampleFormat::PCM_PC)
|
||||
{
|
||||
m_curSample = nullptr;
|
||||
return;
|
||||
|
@ -746,11 +769,11 @@ void Voice::startSample(int16_t sampId, int32_t offset)
|
|||
uint32_t block = m_curSamplePos / 14;
|
||||
uint32_t rem = m_curSamplePos % 14;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue