Skip to content

Instantly share code, notes, and snippets.

@MikuAuahDark
Last active October 13, 2019 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MikuAuahDark/04d1a4a788c917c4b64a7869cdd9857c to your computer and use it in GitHub Desktop.
Save MikuAuahDark/04d1a4a788c917c4b64a7869cdd9857c to your computer and use it in GitHub Desktop.
Lazy HCA2WAV using clHCA
/* HCA2WAV */
/* This is one shot tool, error handling is lazy, */
/* memory may not be freed. Any efforts fixing this */
/* is useless */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include <stdio.h>
#include <stdlib.h>
#include "clHCA.h"
#define BUFSIZE 16384
char tempBuffer[BUFSIZE];
unsigned int keyLow = 3765733752, keyHigh = 2240287;
size_t write32LE(FILE * f, unsigned int buf)
{
unsigned char temp[4] = {buf, buf >> 8, buf >> 16, buf >> 24};
return fwrite(temp, 1, 4, f);
}
int decode(FILE *input, FILE *output)
{
char *fileData = NULL;
short *samples = NULL;
size_t fileSize = 0;
size_t read = 0;
unsigned int sampleBufSize = 0;
unsigned int sampleSize = 0;
unsigned int wavSize = 0;
unsigned int currentBlock = 0;
clHCA *hca;
clHCA_stInfo hcaInfo;
int headerSize = 0;
do
{
read = fread(tempBuffer, 1, BUFSIZE, input);
if ((fileData = realloc(fileData, read + fileSize)) == NULL)
{
fprintf(stderr, "cannot allocate memory\n");
return 1;
}
memcpy(fileData + fileSize, tempBuffer, read);
fileSize += read;
} while (read == BUFSIZE);
fprintf(stderr, "file readed %u\n", (unsigned int) fileSize);
if ((headerSize = clHCA_isOurFile0(fileData)) < 0)
{
fprintf(stderr, "not HCA (1)\n");
free(fileData);
return 1;
}
if (clHCA_isOurFile1(fileData, headerSize) < 0)
{
fprintf(stderr, "not HCA (2)\n");
free(fileData);
return 1;
}
hca = (clHCA *) calloc(clHCA_sizeof(), 1);
fprintf(stderr, "used key: %u,%u\n", keyLow, keyHigh);
clHCA_clear(hca, keyLow, keyHigh);
if (clHCA_Decode(hca, fileData, fileSize, 0) < 0)
{
fprintf(stderr, "1st block decode failed\n");
free(fileData);
return 1;
}
clHCA_getInfo(hca, &hcaInfo);
fprintf(stderr, "sample rate: %d\nchannels: %d\nblocksize: %d\n", hcaInfo.samplingRate, hcaInfo.channelCount, hcaInfo.blockSize);
/* Write WAV */
sampleBufSize = 1024 * hcaInfo.channelCount * 2;
samples = calloc(sampleBufSize, 1);
sampleSize = 1024 * hcaInfo.channelCount * hcaInfo.blockCount * 2;
wavSize =
(36 - 8) + /* header */
8 + sampleSize; /* data */
fwrite("RIFF", 1, 4, output);
write32LE(output, wavSize);
fwrite("WAVEfmt \x10\x00\x00\x00\x01\x00", 1, 14, output);
fputc(hcaInfo.channelCount, output);
fputc(0, output);
write32LE(output, hcaInfo.samplingRate);
write32LE(output, hcaInfo.samplingRate * hcaInfo.channelCount * 2);
fputc(hcaInfo.channelCount * 2, output);
fputc(0, output);
fwrite("\x10\x00" /*separate*/ "data", 1, 6, output);
write32LE(output, sampleSize);
/* Decode */
for (; currentBlock < hcaInfo.blockCount; currentBlock++)
{
unsigned int address = hcaInfo.dataOffset + currentBlock * hcaInfo.blockSize;
if (clHCA_Decode(hca, fileData + address, hcaInfo.blockSize, address) < 0)
{
free(samples);
free(fileData);
fprintf(stderr, "decode block %d failed, wav file may incomplete\n", currentBlock);
clHCA_done(hca);
return 1;
}
memset(samples, 0, sampleBufSize);
clHCA_DecodeSamples16(hca, samples);
fwrite(samples, 1, sampleBufSize, output);
}
clHCA_done(hca);
return 0;
}
int parseKey(char *v)
{
char *temp;
keyLow = strtoul(v, &temp, 0);
if (*temp == 0)
return 0;
keyHigh = strtoul(++temp, NULL, 0);
fprintf(stderr, "parsed key: %u,%u\n", keyLow, keyHigh);
return 1;
}
#ifdef _WIN32
/* We live in a society */
#define WIN32_LEAN_AND_MEAN
#include <wchar.h>
#include <io.h>
#include <windows.h>
int wmain(int argc, wchar_t *argv[])
{
FILE *input = NULL, *output = NULL;
int r = 0;
if (argc < 3)
{
//fprintf(stderr, "arguments: %s input output [key=0,0]", argv[0]);
_fwprintf_p(stderr, L"arguments: %s <input> <output> [key=3765733752,2240287]\n", argv[0]);
return 1;
}
input = _wfopen(argv[1], L"rb");
if (input == NULL)
{
fprintf(stderr, "cannot open file for reading\n");
return 1;
}
if (argv[2][0] == '-' && argv[2][1] == 0)
{
output = stdout;
_setmode(_fileno(stdout), 0x8000);
}
else
{
output = _wfopen(argv[2], L"wb");
if (output == NULL)
{
fprintf(stderr, "cannot open file for writing. using stdout\n");
_setmode(_fileno(stdout), 0x8000);
output = stdout;
}
}
if (argc >= 4)
{
/* may not work, I'm lazy */
size_t keylen = wcslen(argv[3]);
char *temp = calloc(1, keylen + 1);
int i = 0;
for (; i < keylen; temp[i] = argv[3][i++]);
if (parseKey(temp) == 0)
{
fprintf(stderr, "cannot parse key. assume 3765733752,2240287\n");
keyLow = 3765733752;
keyHigh = 2240287;
}
free(temp);
}
r = decode(input, output);
fclose(input);
if (output != stdout) fclose(output);
return r;
}
#else
int main(int argc, char *argv[])
{
FILE *input = NULL, *output = NULL;
int r = 0;
if (argc < 3)
{
fprintf(stderr, "arguments: %s input output [key=3765733752,2240287]\n", argv[0]);
return 1;
}
input = fopen(argv[1], "rb");
if (input == NULL)
{
fprintf(stderr, "cannot open file for reading\n");
return 1;
}
if (argv[2][0] == '-' && argv[2][1] == 0)
output = stdout;
else
{
output = fopen(argv[2], L"wb");
if (output == NULL)
{
fprintf(stderr, "cannot open file for writing. using stdout\n");
output = stdout;
}
}
if (argc >= 4)
if (parseKey(argv[3]))
{
fprintf(stderr, "cannot parse key. assume 3765733752,2240287\n");
keyLow = 3765733752;
keyHigh = 2240287;
}
r = decode(input, output);
fclose(input);
if (output != stdout) fclose(output);
return r;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment