mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-12 05:28:43 -04:00
ADPCM4 decode impl
This commit is contained in:
+3
-1
@@ -87,7 +87,9 @@ add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES}
|
||||
src/dusk/audio/DuskAudioSystem.cpp
|
||||
src/dusk/audio/JASCriticalSection.cpp
|
||||
src/dusk/audio/DuskDsp.hpp
|
||||
src/dusk/audio/DuskDsp.cpp)
|
||||
src/dusk/audio/DuskDsp.cpp
|
||||
src/dusk/audio/Adpcm.cpp
|
||||
src/dusk/audio/Adpcm.hpp)
|
||||
target_compile_definitions(game_debug PRIVATE TARGET_PC AVOID_UB=1 VERSION=0 $<$<CONFIG:Debug>:DEBUG=1>)
|
||||
|
||||
# Make these properties PUBLIC so that the regular game target also sees them.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "Adpcm.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
|
||||
#include "JSystem/JAudio2/JASAramStream.h"
|
||||
|
||||
// https://github.com/magcius/vgmtrans/blob/8e34ddc2fb43948dc1e1a8759c739a0c1c7b62d7/src/main/formats/JaiSeqScanner.cpp#L489-L531
|
||||
// https://github.com/XAYRGA/JaiSeqX/blob/f29c024ec3663503f506aa02bcd503ada6e7d8aa/JaiSeqXLJA/DSP/JAIDSPADPCM4.cs#L86-L87
|
||||
|
||||
static constexpr u16 Coefficient0[] = {
|
||||
0,0x0800,0,0x0400,
|
||||
0x1000,0x0e00,0x0c00,0x1200,
|
||||
0x1068,0x12c0,0x1400,0x0800,
|
||||
0x0400,0xfc00,0xfc00,0xf800
|
||||
};
|
||||
|
||||
static constexpr u16 Coefficient1[] = {
|
||||
0,0,0x0800,0x0400,0xf800,
|
||||
0xfa00,0xfc00,0xf600,0xf738,
|
||||
0xf704,0xf400,0xf800,0xfc00,
|
||||
0x0400,0,0,
|
||||
};
|
||||
|
||||
constexpr int AdpcmFrameSize = 9;
|
||||
|
||||
static s16 Clamp16(s32 value) {
|
||||
if (value > 0x7FFF) return 0x7FFF;
|
||||
if (value < -0x8000) return -0x8000;
|
||||
return value;
|
||||
}
|
||||
|
||||
void dusk::audio::Adpcm4ToPcm16(const u8* adpcm, size_t adpcmLength, s16* pcm, size_t pcmLength, s16& hist2, s16& hist1) {
|
||||
assert (adpcmLength % AdpcmFrameSize == 0 && "ADPCM must be divisible by frame size");
|
||||
|
||||
const auto expectedPcmLength = (adpcmLength / AdpcmFrameSize) * 16;
|
||||
assert (expectedPcmLength <= pcmLength && "PCM output buffer is too small!");
|
||||
|
||||
for (int i = 0; i < adpcmLength; i += AdpcmFrameSize) {
|
||||
u8 header = adpcm[i];
|
||||
|
||||
s32 scale = 1 << (header >> 4);
|
||||
u8 coefIndex = header & 0xF;
|
||||
|
||||
s16 coef0 = (s16)Coefficient0[coefIndex];
|
||||
s16 coef1 = (s16)Coefficient1[coefIndex];
|
||||
|
||||
for (int sampleIdx = 0; sampleIdx < 16; sampleIdx++) {
|
||||
u8 adpcmValue = adpcm[i + 1 + sampleIdx / 2];
|
||||
u8 unsignedNibble = sampleIdx % 2 == 0 ? adpcmValue >> 4 : adpcmValue & 0xF;
|
||||
s8 signedNibble = ((s8)(unsignedNibble << 4)) >> 4;
|
||||
s16 sample = Clamp16((((signedNibble * scale) << 11) + (coef0 * hist1 + coef1 * hist2)) >> 11);
|
||||
|
||||
hist2 = hist1;
|
||||
hist1 = sample;
|
||||
|
||||
*pcm++ = sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef DUSK_ADPCM_HPP
|
||||
#define DUSK_ADPCM_HPP
|
||||
|
||||
#include <dolphin/types.h>
|
||||
|
||||
namespace dusk::audio {
|
||||
constexpr u32 Adpcm4FrameSize = 9;
|
||||
constexpr u32 AdpcmSampleCount = 16;
|
||||
constexpr u32 Adpcm2FrameSize = 5;
|
||||
|
||||
void Adpcm4ToPcm16(const u8* adpcm, size_t adpcmLength, s16* pcm, size_t pcmLength, s16& hist1, s16& hist0);
|
||||
}
|
||||
|
||||
#endif // DUSK_ADPCM_HPP
|
||||
Reference in New Issue
Block a user