Skip to content

Commit 0575011

Browse files
authored
0.4.3 - Fix HCA decoding bug.
1 parent 9b554e8 commit 0575011

File tree

6 files changed

+70
-24
lines changed

6 files changed

+70
-24
lines changed

CriCodecs/hca.cpp

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ int clHCA_getInfo(clHCA* hca, clHCA_stInfo *info) {
336336
}
337337

338338
//HCADecoder_DecodeBlockInt32
339-
void clHCA_ReadSamples16(clHCA* hca, signed short *&samples) {
339+
void clHCA_ReadSamples16(clHCA* hca, signed short *samples) {
340340
const float scale_f = 32768.0f;
341341
float f;
342342
signed int s;
@@ -3373,34 +3373,80 @@ static PyObject* HcaDecode(PyObject* self, PyObject* args){
33733373

33743374
wavData->size = (hca->frame_count * HCA_SAMPLES_PER_FRAME - hca->encoder_delay - hca->encoder_padding) * hca->channels * sizeof(short); // 16bits = 4 bytes
33753375
wavriff->size = 0x24 + ((hca->loop_flag) ? 0x3C+8 : 0) + sizeof(wavData) + wavData->size;
3376+
33763377
data += header_size;
3378+
33773379
if(subkey){
33783380
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
33793381
}
33803382
clHCA_SetKey(hca, keycode);
3383+
33813384
unsigned char *buf = new unsigned char [hca->frame_size];
3385+
memset(buf, 0, hca->frame_size);
3386+
33823387
unsigned char *wavebuf = wav.GetWaveBuffer(wavData->size/wavfmt->BlockAlign, wavfmt->Channels, wavfmt->SampleRate, wav.wav.chunks.Looping); // wav bytes.
33833388
signed short *outbuf = wav.PCM_16;
3384-
short *tempbuf = new short[HCA_SAMPLES_PER_FRAME * hca->channels];
3385-
memset(tempbuf, 0, HCA_SAMPLES_PER_FRAME * hca->channels * sizeof(short));
3386-
int res = 0;
3387-
memset(buf, 0, hca->frame_size);
3388-
int count = 0;
3389-
for(unsigned int i = hca->frame_count*hca->frame_size; i > 0; i -= hca->frame_size, data += hca->frame_size){
3390-
memcpy(buf, data, hca->frame_size);
3391-
res = clHCA_DecodeBlock(hca, buf, hca->frame_size);
3392-
if(res < 0){
3393-
// decode error. most likely wrong key.
3394-
return py_codec_err(-2);
3389+
3390+
const unsigned int samples_to_do = (wavData->size >> 1) / hca->channels;
3391+
unsigned int samples_filled = 0;
3392+
unsigned int samples_to_discard = hca->encoder_delay;
3393+
int samples_done = 0;
3394+
unsigned int samples_consumed = 0;
3395+
unsigned int current_block = 0;
3396+
signed short *sample_buffer = new signed short[hca->channels * HCA_SAMPLES_PER_FRAME];
3397+
memset(sample_buffer, 0, hca->channels * HCA_SAMPLES_PER_FRAME * sizeof(short));
3398+
3399+
while (samples_done < samples_to_do) {
3400+
3401+
if (samples_filled) {
3402+
int samples_to_get = samples_filled;
3403+
3404+
if (samples_to_discard) {
3405+
/* discard samples for looping */
3406+
if (samples_to_get > samples_to_discard)
3407+
samples_to_get = samples_to_discard;
3408+
samples_to_discard -= samples_to_get;
3409+
}else {
3410+
/* get max samples and copy */
3411+
if (samples_to_get > samples_to_do - samples_done)
3412+
samples_to_get = samples_to_do - samples_done;
3413+
3414+
memcpy(outbuf + samples_done*hca->channels,
3415+
sample_buffer + samples_consumed*hca->channels,
3416+
samples_to_get*hca->channels * sizeof(short));
3417+
samples_done += samples_to_get;
3418+
}
3419+
3420+
/* mark consumed samples */
3421+
samples_consumed += samples_to_get;
3422+
samples_filled -= samples_to_get;
33953423
}
3396-
if(hca->encoder_delay){
3397-
if(HCA_SAMPLES_PER_FRAME > hca->encoder_delay)
3398-
hca->encoder_delay = 0;
3399-
if(hca->encoder_delay)
3400-
hca->encoder_delay -= HCA_SAMPLES_PER_FRAME;
3401-
continue;
3424+
else {
3425+
/* EOF/error */
3426+
if (current_block >= hca->frame_count) {
3427+
memset(outbuf, 0, (samples_to_do - samples_done) * hca->channels * sizeof(short));
3428+
break;
3429+
}
3430+
3431+
/* read frame */
3432+
memcpy(buf, data, hca->frame_size);
3433+
data += hca->frame_size;
3434+
3435+
current_block++;
3436+
3437+
/* decode frame */
3438+
int res = clHCA_DecodeBlock(hca, buf, hca->frame_size);
3439+
if(res < 0){
3440+
// decode error. most likely wrong key.
3441+
return py_codec_err(-2);
3442+
}
3443+
3444+
/* extract samples */
3445+
clHCA_ReadSamples16(hca, sample_buffer);
3446+
3447+
samples_consumed = 0;
3448+
samples_filled += HCA_SAMPLES_PER_FRAME;
34023449
}
3403-
clHCA_ReadSamples16(hca, outbuf);
34043450
}
34053451
free(hca);
34063452
return Py_BuildValue("y#", wavebuf, wavriff->size+8);

CriCodecs/hca.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int clHCA_DecodeBlock(clHCA *, unsigned char *data, unsigned int size);
7373
/* Extracts signed and clipped 16 bit samples into sample buffer.
7474
* May be called after clHCA_DecodeBlock, and will return the same data until
7575
* next decode. Buffer must be at least (samplesPerBlock*channels) long. */
76-
void clHCA_ReadSamples16(clHCA *, signed short *&outSamples);
76+
void clHCA_ReadSamples16(clHCA *, signed short *outSamples);
7777

7878
/* Sets a 64 bit encryption key, to properly decode blocks. This may be called
7979
* multiple times to change the key, before or after clHCA_DecodeHeader.

CriCodecs/pcm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ struct PCM{
526526
return PCM_16;
527527
}
528528

529-
unsigned char*& GetWaveBuffer(unsigned int SampleCount, unsigned int Channels, unsigned int SampleRate, bool Looping){
529+
unsigned char*& GetWaveBuffer(unsigned int SampleCount, unsigned int Channels, unsigned int SampleRate, bool Looping){
530530
unsigned int header_size = Looping ? 0x70 : 0x2C;
531531
wav.size = header_size + SampleCount * Channels * sizeof(short);
532532
WAVEBuffer = new unsigned char[wav.size];

CriCodecs/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
setup(
44
name="CriCodecs",
5-
version="0.2.0",
5+
version="0.2.1",
66
ext_modules=[Extension('CriCodecs', ["adx.cpp", "CriCodecs.cpp", "crilayla.cpp", "hca.cpp"])]
77
)

PyCriCodecs/adx.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ def decode(data: bytes) -> bytes:
1111
# Encodes WAV to ADX.
1212
def encode(data: bytes, BitDepth = 0x4, Blocksize = 0x12, Encoding = 3, AdxVersion = 0x4, Highpass_Frequency = 0x1F4, Filter = 0, force_not_looping = False) -> bytes:
1313
""" Encodes WAV to ADX. """
14-
return bytearray(CriCodecs.AdxEncode(bytes(data), BitDepth, Blocksize, Encoding, Highpass_Frequency, Filter, AdxVersion, force_not_looping))
14+
return CriCodecs.AdxEncode(bytes(data), BitDepth, Blocksize, Encoding, Highpass_Frequency, Filter, AdxVersion, force_not_looping)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
setup(
55
name="PyCriCodecs",
6-
version="0.4.2",
6+
version="0.4.3",
77
description="Python frontend with a C++ backend of managing Criware files of all kinds.",
88
packages=["PyCriCodecs"],
99
ext_modules=[Extension('CriCodecs', ["CriCodecs\\CriCodecs.cpp"], include_dirs=[os.path.realpath("CriCodecs")])]

0 commit comments

Comments
 (0)