mirror of
https://github.com/ScrelliCopter/VGM-Tools
synced 2025-02-21 04:09:25 +11:00
get adpcm tools working on mac and somewhat unify the codebase
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#ifndef COMMON_H
|
#ifndef COMMON_ENDIAN_H
|
||||||
#define COMMON_H
|
#define COMMON_ENDIAN_H
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include <machine/endian.h>
|
# include <machine/endian.h>
|
||||||
@@ -66,7 +66,4 @@ static inline uint16_t swap16(uint16_t v)
|
|||||||
# define SWAP_BE16(V) (V)
|
# define SWAP_BE16(V) (V)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIN(A, B) (((A) < (B)) ? (A) : (B))
|
#endif//COMMON_ENDIAN_H
|
||||||
#define MAX(A, B) (((A) > (B)) ? (A) : (B))
|
|
||||||
|
|
||||||
#endif//COMMON_H
|
|
||||||
16
common/util.h
Normal file
16
common/util.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef COMMON_UTIL_H
|
||||||
|
#define COMMON_UTIL_H
|
||||||
|
|
||||||
|
#define MIN(A, B) (((A) < (B)) ? (A) : (B))
|
||||||
|
#define MAX(A, B) (((A) > (B)) ? (A) : (B))
|
||||||
|
#define CLAMP(X, A, B) (MIN(MAX((X), (A)), (B)))
|
||||||
|
|
||||||
|
#if ( defined( __GNUC__ ) && ( __GNUC__ >= 4 ) ) || defined( __clang__ )
|
||||||
|
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||||
|
#elif defined( _MSC_VER )
|
||||||
|
#define FORCE_INLINE __forceinline
|
||||||
|
#else
|
||||||
|
#define FORCE_INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif//COMMON_UTIL_H
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/* wave.c (c) 2023 a dinosaur (zlib) */
|
/* wave.c (c) 2023 a dinosaur (zlib) */
|
||||||
|
|
||||||
#include "wave.h"
|
#include "wave.h"
|
||||||
#include "common.h"
|
#include "endian.h"
|
||||||
|
|
||||||
#define FOURCC_RIFF "RIFF"
|
#define FOURCC_RIFF "RIFF"
|
||||||
#define FOURCC_WAVE "WAVE"
|
#define FOURCC_WAVE "WAVE"
|
||||||
@@ -116,15 +116,13 @@ static int waveWriteHeader(const WaveSpec* spec, size_t dataLen, const WaveStrea
|
|||||||
|
|
||||||
int waveWrite(const WaveSpec* spec, const void* data, size_t dataLen, const WaveStreamCb* cb, void* user)
|
int waveWrite(const WaveSpec* spec, const void* data, size_t dataLen, const WaveStreamCb* cb, void* user)
|
||||||
{
|
{
|
||||||
if (!data)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
// Write RIFF/Wave header and raw interleaved samples
|
// Write RIFF/Wave header and raw interleaved samples
|
||||||
int res = waveWriteHeader(spec, dataLen, cb, user);
|
int res = waveWriteHeader(spec, dataLen, cb, user);
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
//FIXME: not endian safe
|
//FIXME: not endian safe
|
||||||
cb->write(user, data, 1, dataLen);
|
if (data)
|
||||||
|
cb->write(user, data, 1, dataLen);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,8 @@ typedef struct
|
|||||||
int (*eof)(void* user);
|
int (*eof)(void* user);
|
||||||
} WaveStreamCb;
|
} WaveStreamCb;
|
||||||
|
|
||||||
|
extern const WaveStreamCb waveStreamDefaultCb;
|
||||||
|
|
||||||
int waveWrite(const WaveSpec* spec, const void* data, size_t dataLen, const WaveStreamCb* cb, void* user);
|
int waveWrite(const WaveSpec* spec, const void* data, size_t dataLen, const WaveStreamCb* cb, void* user);
|
||||||
int waveWriteFile(const WaveSpec* spec, const void* data, size_t dataLen, const char* path);
|
int waveWriteFile(const WaveSpec* spec, const void* data, size_t dataLen, const char* path);
|
||||||
int waveWriteBlock(const WaveSpec* spec, const void* blocks[], size_t blockLen, const WaveStreamCb* cb, void* user);
|
int waveWriteBlock(const WaveSpec* spec, const void* blocks[], size_t blockLen, const WaveStreamCb* cb, void* user);
|
||||||
@@ -32,14 +32,22 @@ static int waveFileEof(void* user)
|
|||||||
return feof((FILE*)user) || ferror((FILE*)user);
|
return feof((FILE*)user) || ferror((FILE*)user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WaveStreamCb waveStreamDefaultCb =
|
||||||
|
{
|
||||||
|
.read = waveFileRead,
|
||||||
|
.write = waveFileWrite,
|
||||||
|
.seek = waveFileSeek,
|
||||||
|
.tell = waveFileTell,
|
||||||
|
.eof = waveFileEof
|
||||||
|
};
|
||||||
|
|
||||||
int waveWriteFile(const WaveSpec* spec, const void* data, size_t dataLen, const char* path)
|
int waveWriteFile(const WaveSpec* spec, const void* data, size_t dataLen, const char* path)
|
||||||
{
|
{
|
||||||
FILE* file = fopen(path, "wb");
|
FILE* file = fopen(path, "wb");
|
||||||
if (!file)
|
if (!file)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const WaveStreamCb cb = { .write = waveFileWrite };
|
int res = waveWrite(spec, data, dataLen, &waveStreamDefaultCb, (void*)file);
|
||||||
int res = waveWrite(spec, data, dataLen, &cb, (void*)file);
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -50,8 +58,7 @@ int waveWriteBlockFile(const WaveSpec* spec, const void* blocks[], size_t blockL
|
|||||||
if (!file)
|
if (!file)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const WaveStreamCb cb = { .write = waveFileWrite };
|
int res = waveWriteBlock(spec, blocks, blockLen, &waveStreamDefaultCb, (void*)file);
|
||||||
int res = waveWriteBlock(spec, blocks, blockLen, &cb, (void*)file);
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||||
project(dsptools LANGUAGES C)
|
project(dsptools LANGUAGES C)
|
||||||
|
|
||||||
|
set(COMMON "${CMAKE_SOURCE_DIR}/../common")
|
||||||
|
|
||||||
add_subdirectory(libdsptool)
|
add_subdirectory(libdsptool)
|
||||||
|
|
||||||
set(HEADERS wave.h)
|
set(HEADERS ${COMMON}/wave.h ${COMMON}/endian.h)
|
||||||
set(SOURCES wavefile.c wave.c dspdecode.c)
|
set(SOURCES ${COMMON}/wavefile.c ${COMMON}/wave.c dspdecode.c)
|
||||||
|
|
||||||
add_executable(dspdecode ${HEADERS} ${SOURCES})
|
add_executable(dspdecode ${HEADERS} ${SOURCES})
|
||||||
|
|
||||||
set_property(TARGET dspdecode PROPERTY C_STANDARD 99)
|
set_property(TARGET dspdecode PROPERTY C_STANDARD 99)
|
||||||
|
target_include_directories(dspdecode PRIVATE ${COMMON})
|
||||||
target_link_libraries(dspdecode DspTool::DspTool)
|
target_link_libraries(dspdecode DspTool::DspTool)
|
||||||
target_compile_options(dspdecode PRIVATE
|
target_compile_options(dspdecode PRIVATE
|
||||||
$<$<C_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra -pedantic>
|
$<$<C_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra -pedantic>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "dsptool.h"
|
#include "dsptool.h"
|
||||||
#include "wave.h"
|
#include "wave.h"
|
||||||
#include "common.h"
|
#include "endian.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ project(DspTool LANGUAGES C)
|
|||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build as a Shared Object or DLL" OFF)
|
option(BUILD_SHARED_LIBS "Build as a Shared Object or DLL" OFF)
|
||||||
|
|
||||||
set(HEADERS ../common.h dsptool.h)
|
set(HEADERS dsptool.h ${COMMON}/util.h)
|
||||||
set(SOURCES math.c decode.c encode.c)
|
set(SOURCES math.c decode.c encode.c)
|
||||||
|
|
||||||
add_library(DspTool ${HEADERS} ${SOURCES})
|
add_library(DspTool ${HEADERS} ${SOURCES})
|
||||||
add_library(DspTool::DspTool ALIAS DspTool)
|
add_library(DspTool::DspTool ALIAS DspTool)
|
||||||
|
|
||||||
target_include_directories(DspTool PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
set_property(TARGET DspTool PROPERTY C_STANDARD 99)
|
set_property(TARGET DspTool PROPERTY C_STANDARD 99)
|
||||||
|
target_include_directories(DspTool
|
||||||
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
PRIVATE ${COMMON})
|
||||||
if (BUILD_SHARED_LIBS)
|
if (BUILD_SHARED_LIBS)
|
||||||
target_compile_definitions(DspTool PRIVATE BUILD_SHARED)
|
target_compile_definitions(DspTool PRIVATE BUILD_SHARED)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* (c) 2017 Alex Barney (MIT) */
|
/* (c) 2017 Alex Barney (MIT) */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../common.h"
|
#include "util.h"
|
||||||
#include "dsptool.h"
|
#include "dsptool.h"
|
||||||
|
|
||||||
static inline uint8_t GetHighNibble(uint8_t value)
|
static inline uint8_t GetHighNibble(uint8_t value)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "../common.h"
|
#include "util.h"
|
||||||
#include "dsptool.h"
|
#include "dsptool.h"
|
||||||
|
|
||||||
/* Temporal Vector
|
/* Temporal Vector
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
project(neoadpcmtools)
|
project(neoadpcmtools LANGUAGES C)
|
||||||
cmake_minimum_required(VERSION "3.1" FATAL_ERROR)
|
cmake_minimum_required(VERSION "3.1" FATAL_ERROR)
|
||||||
|
|
||||||
add_executable(adpcm adpcm.c)
|
set(COMMON "${CMAKE_SOURCE_DIR}/../common")
|
||||||
target_compile_options(adpcm PRIVATE
|
set(WARNINGS
|
||||||
-fomit-frame-pointer -Werror -Wall
|
$<$<C_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra -pedantic -Wno-unused-parameter>
|
||||||
-W -Wno-sign-compare -Wno-unused
|
$<$<C_COMPILER_ID:MSVC>:/Wall /wd4100>)
|
||||||
-Wpointer-arith -Wbad-function-cast -Wcast-align -Waggregate-return
|
|
||||||
-pedantic
|
|
||||||
-Wshadow
|
|
||||||
-Wstrict-prototypes)
|
|
||||||
target_link_libraries(adpcm m)
|
|
||||||
|
|
||||||
add_executable(adpcmb adpcmb.c)
|
add_executable(adpcm ${COMMON}/util.h ${COMMON}/wave.h ${COMMON}/wave.c ${COMMON}/wavefile.c adpcm.c)
|
||||||
|
set_property(TARGET adpcm PROPERTY C_STANDARD 99)
|
||||||
|
target_compile_options(adpcm PRIVATE ${WARNINGS})
|
||||||
|
target_include_directories(adpcm PRIVATE ${COMMON})
|
||||||
|
target_link_libraries(adpcm $<$<C_COMPILER_ID:Clang,GNU>:m>)
|
||||||
|
|
||||||
|
add_executable(adpcmb ${COMMON}/util.h adpcmb.c)
|
||||||
|
target_compile_options(adpcmb PRIVATE ${WARNINGS})
|
||||||
|
target_include_directories(adpcmb PRIVATE ${COMMON})
|
||||||
|
|
||||||
add_executable(neoadpcmextract autoextract.c neoadpcmextract.c)
|
add_executable(neoadpcmextract autoextract.c neoadpcmextract.c)
|
||||||
set_property(TARGET neoadpcmextract PROPERTY C_STANDARD 99)
|
set_property(TARGET neoadpcmextract PROPERTY C_STANDARD 99)
|
||||||
target_compile_options(neoadpcmextract PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(neoadpcmextract PRIVATE ${WARNINGS})
|
||||||
|
|||||||
178
neotools/adpcm.c
178
neotools/adpcm.c
@@ -1,54 +1,58 @@
|
|||||||
|
/* adpcm.c
|
||||||
|
* original ADPCM to PCM converter v 1.01 By MARTINEZ Fabrice aka SNK of SUPREMACY
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "util.h"
|
||||||
|
#include "wave.h"
|
||||||
|
|
||||||
#define BUFFER_SIZE 1024*256
|
#define BUFFER_SIZE (1024 * 256)
|
||||||
#define ADPCMA_VOLUME_RATE 1
|
#define ADPCMA_VOLUME_RATE 1
|
||||||
#define ADPCMA_DECODE_RANGE 1024
|
#define ADPCMA_DECODE_RANGE 1024
|
||||||
#define ADPCMA_DECODE_MIN (-(ADPCMA_DECODE_RANGE*ADPCMA_VOLUME_RATE))
|
#define ADPCMA_DECODE_MIN (-(ADPCMA_DECODE_RANGE * ADPCMA_VOLUME_RATE))
|
||||||
#define ADPCMA_DECODE_MAX ((ADPCMA_DECODE_RANGE*ADPCMA_VOLUME_RATE)-1)
|
#define ADPCMA_DECODE_MAX ((ADPCMA_DECODE_RANGE * ADPCMA_VOLUME_RATE) - 1)
|
||||||
#define ADPCMA_VOLUME_DIV 1
|
|
||||||
|
|
||||||
unsigned char RiffWave[44] = {
|
static int decode_tableA1[16] =
|
||||||
0x52, 0x49, 0x46, 0x46, 0x24, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74,
|
{
|
||||||
0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x44, 0x48, 0x00, 0x00, 0x88, 0x90,
|
-1 * 16, -1 * 16, -1 * 16, -1 * 16, 2 * 16, 5 * 16, 7 * 16, 9 * 16,
|
||||||
0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
|
-1 * 16, -1 * 16, -1 * 16, -1 * 16, 2 * 16, 5 * 16, 7 * 16, 9 * 16
|
||||||
} ;
|
|
||||||
|
|
||||||
static int decode_tableA1[16] = {
|
|
||||||
-1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16,
|
|
||||||
-1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16
|
|
||||||
};
|
};
|
||||||
static int jedi_table[49*16];
|
|
||||||
static int signal;
|
|
||||||
static int delta;
|
|
||||||
|
|
||||||
void adpcm_init(void);
|
static int jedi_table[49 * 16];
|
||||||
void adpcm_decode(void *, void *, int);
|
static int cursignal;
|
||||||
int Limit(int, int, int);
|
static int delta;
|
||||||
FILE* errorlog;
|
|
||||||
|
void adpcm_init(void);
|
||||||
|
void adpcm_decode(void *, void *, int);
|
||||||
|
|
||||||
|
FILE* errorlog;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *Fp1, *Fp2;
|
FILE *InputFile, *OutputFile;
|
||||||
void *InputBuffer, *OutputBuffer;
|
void *InputBuffer, *OutputBuffer;
|
||||||
int Readed;
|
int bytesRead;
|
||||||
unsigned int Filelen;
|
unsigned int Filelen;
|
||||||
|
|
||||||
puts("**** ADPCM to PCM converter v 1.01\n");
|
puts("**** ADPCM to PCM converter v 1.01\n");
|
||||||
if (argc!=3) {
|
if (argc != 3)
|
||||||
|
{
|
||||||
puts("USAGE: adpcm <InputFile.pcm> <OutputFile.wav>");
|
puts("USAGE: adpcm <InputFile.pcm> <OutputFile.wav>");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fp1 = fopen(argv[1], "rb");
|
InputFile = fopen(argv[1], "rb");
|
||||||
if (Fp1==NULL) {
|
if (!InputFile)
|
||||||
|
{
|
||||||
printf("Could not open inputfile %s\n", argv[1]);
|
printf("Could not open inputfile %s\n", argv[1]);
|
||||||
exit(-2);
|
exit(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fp2 = fopen(argv[2], "wb");
|
OutputFile = fopen(argv[2], "wb");
|
||||||
if (Fp2==NULL) {
|
if (!OutputFile)
|
||||||
|
{
|
||||||
printf("Could not open outputfile %s\n", argv[2]);
|
printf("Could not open outputfile %s\n", argv[2]);
|
||||||
exit(-3);
|
exit(-3);
|
||||||
}
|
}
|
||||||
@@ -56,104 +60,106 @@ int main(int argc, char *argv[])
|
|||||||
errorlog = fopen("error.log", "wb");
|
errorlog = fopen("error.log", "wb");
|
||||||
|
|
||||||
InputBuffer = malloc(BUFFER_SIZE);
|
InputBuffer = malloc(BUFFER_SIZE);
|
||||||
if (InputBuffer == NULL) {
|
if (InputBuffer == NULL)
|
||||||
|
{
|
||||||
printf("Could not allocate input buffer. (%d bytes)\n", BUFFER_SIZE);
|
printf("Could not allocate input buffer. (%d bytes)\n", BUFFER_SIZE);
|
||||||
exit(-4);
|
exit(-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputBuffer = malloc(BUFFER_SIZE*10);
|
OutputBuffer = malloc(BUFFER_SIZE * 10);
|
||||||
if (OutputBuffer == NULL) {
|
if (OutputBuffer == NULL)
|
||||||
printf("Could not allocate output buffer. (%d bytes)\n", BUFFER_SIZE*4);
|
{
|
||||||
|
printf("Could not allocate output buffer. (%d bytes)\n", BUFFER_SIZE * 4);
|
||||||
exit(-5);
|
exit(-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
adpcm_init();
|
adpcm_init();
|
||||||
|
|
||||||
fseek(Fp1, 0, SEEK_END);
|
fseek(InputFile, 0, SEEK_END);
|
||||||
Filelen = ftell(Fp1);
|
Filelen = ftell(InputFile);
|
||||||
fseek(Fp1, 0, SEEK_SET);
|
fseek(InputFile, 0, SEEK_SET);
|
||||||
|
|
||||||
*((unsigned int*)(&RiffWave[4])) = Filelen*4 + 0x2C;
|
// Write wave header
|
||||||
*((unsigned int*)(&RiffWave[0x28])) = Filelen*4;
|
waveWrite(&(const WaveSpec)
|
||||||
|
{
|
||||||
|
.format = WAVE_FMT_PCM,
|
||||||
|
.channels = 1,
|
||||||
|
.rate = 18500,
|
||||||
|
.bytedepth = 2
|
||||||
|
},
|
||||||
|
NULL, Filelen * 4, &waveStreamDefaultCb, OutputFile);
|
||||||
|
|
||||||
fwrite(RiffWave, 0x2c, 1, Fp2);
|
// Convert ADPCM to PCM and write to wave
|
||||||
|
do
|
||||||
do {
|
{
|
||||||
Readed = fread(InputBuffer, 1, BUFFER_SIZE, Fp1);
|
bytesRead = fread(InputBuffer, 1, BUFFER_SIZE, InputFile);
|
||||||
if (Readed>0) {
|
if (bytesRead > 0)
|
||||||
adpcm_decode(InputBuffer, OutputBuffer, Readed);
|
{
|
||||||
fwrite(OutputBuffer, Readed*4, 1, Fp2);
|
adpcm_decode(InputBuffer, OutputBuffer, bytesRead);
|
||||||
|
fwrite(OutputBuffer, bytesRead * 4, 1, OutputFile);
|
||||||
}
|
}
|
||||||
} while (Readed==BUFFER_SIZE);
|
} while (bytesRead == BUFFER_SIZE);
|
||||||
|
|
||||||
free(InputBuffer);
|
free(InputBuffer);
|
||||||
free(OutputBuffer);
|
free(OutputBuffer);
|
||||||
fclose(Fp1);
|
fclose(InputFile);
|
||||||
fclose(Fp2);
|
fclose(OutputFile);
|
||||||
|
|
||||||
puts("Done...");
|
puts("Done...");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adpcm_init(void)
|
void adpcm_init(void)
|
||||||
{
|
{
|
||||||
int step, nib;
|
int step, nib;
|
||||||
|
|
||||||
for (step = 0; step <= 48; step++)
|
for (step = 0; step <= 48; step++)
|
||||||
{
|
{
|
||||||
int stepval = floor (16.0 * pow (11.0 / 10.0, (double)step) * ADPCMA_VOLUME_RATE);
|
int stepval = floor(16.0 * pow (11.0 / 10.0, (double)step) * ADPCMA_VOLUME_RATE);
|
||||||
/* loop over all nibbles and compute the difference */
|
// Loop over all nibbles and compute the difference
|
||||||
for (nib = 0; nib < 16; nib++)
|
for (nib = 0; nib < 16; nib++)
|
||||||
{
|
{
|
||||||
int value = stepval*((nib&0x07)*2+1)/8;
|
int value = stepval * ((nib & 0x07) * 2 + 1) / 8;
|
||||||
jedi_table[step*16+nib] = (nib&0x08) ? -value : value;
|
jedi_table[step * 16 + nib] = (nib & 0x08) ? -value : value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delta = 0;
|
delta = 0;
|
||||||
signal = 0;
|
cursignal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adpcm_decode(void *InputBuffer, void *OutputBuffer, int Length)
|
void adpcm_decode(void *InputBuffer, void *OutputBuffer, int Length)
|
||||||
{
|
{
|
||||||
char *in;
|
char *in;
|
||||||
short *out;
|
short *out;
|
||||||
int i, data, oldsignal;
|
int i, data, oldsignal;
|
||||||
|
|
||||||
in = (char *)InputBuffer;
|
in = (char *)InputBuffer;
|
||||||
out = (short *)OutputBuffer;
|
out = (short *)OutputBuffer;
|
||||||
|
|
||||||
for(i=0;i<Length;i++) {
|
for (i = 0; i < Length; i++)
|
||||||
data = ((*in)>>4)&0x0F;
|
{
|
||||||
oldsignal = signal;
|
data = ((*in) >> 4) & 0x0F;
|
||||||
signal = Limit(signal + (jedi_table[data+delta]), ADPCMA_DECODE_MAX, ADPCMA_DECODE_MIN);
|
oldsignal = cursignal;
|
||||||
delta = Limit(delta + decode_tableA1[data], 48*16, 0*16);
|
cursignal = CLAMP(cursignal + (jedi_table[data + delta]), ADPCMA_DECODE_MIN, ADPCMA_DECODE_MAX);
|
||||||
if (abs(oldsignal-signal)>2500) {
|
delta = CLAMP(delta + decode_tableA1[data], 0 * 16, 48 * 16);
|
||||||
fprintf(errorlog, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, signal, i, delta);
|
if (abs(oldsignal - cursignal) > 2500)
|
||||||
fprintf(errorlog, "data:%02x dx:%08x\n", data, jedi_table[data+delta]);
|
{
|
||||||
|
fprintf(errorlog, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, cursignal, i, delta);
|
||||||
|
fprintf(errorlog, "data:%02x dx:%08x\n", data, jedi_table[data + delta]);
|
||||||
}
|
}
|
||||||
*(out++) = (signal&0xffff)*32;
|
*(out++) = (cursignal & 0xffff) * 32;
|
||||||
|
|
||||||
data = (*in++)&0x0F;
|
data = (*in++) & 0x0F;
|
||||||
oldsignal = signal;
|
oldsignal = cursignal;
|
||||||
signal = Limit(signal + (jedi_table[data+delta]), ADPCMA_DECODE_MAX, ADPCMA_DECODE_MIN);
|
cursignal = CLAMP(cursignal + (jedi_table[data + delta]), ADPCMA_DECODE_MIN, ADPCMA_DECODE_MAX);
|
||||||
delta = Limit(delta + decode_tableA1[data], 48*16, 0*16);
|
delta = CLAMP(delta + decode_tableA1[data], 0 * 16, 48 * 16);
|
||||||
if (abs(oldsignal-signal)>2500) {
|
if (abs(oldsignal - cursignal) > 2500)
|
||||||
fprintf(errorlog, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, signal, i, delta);
|
{
|
||||||
fprintf(errorlog, "data:%02x dx:%08x\n", data, jedi_table[data+delta]);
|
fprintf(errorlog, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, cursignal, i, delta);
|
||||||
|
fprintf(errorlog, "data:%02x dx:%08x\n", data, jedi_table[data + delta]);
|
||||||
}
|
}
|
||||||
*(out++) = (signal&0xffff)*32;
|
*(out++) = (cursignal & 0xffff) * 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Limit( int val, int max, int min ) {
|
|
||||||
|
|
||||||
if ( val > max )
|
|
||||||
val = max;
|
|
||||||
else if ( val < min )
|
|
||||||
val = min;
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
**** ADPCM to PCM converter v 1.01
|
|
||||||
|
|
||||||
USAGE: adpcm <InputFile.pcm> <OutputFile.wav>
|
|
||||||
|
|
||||||
By MARTINEZ Fabrice aka SNK of SUPREMACY
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--(ADPCM.diz.txt)--
|
|
||||||
|
|
||||||
ADPCM To WAV Converter
|
|
||||||
This simple utility converts ADPCM files from NeoGeo cartridge systems
|
|
||||||
(*_v?.rom) or NeoGeo CD systems (*.PCM). This tool converts ADPCM A type
|
|
||||||
samples (99% of the samples), ADPCM B type samples will sound distorted...
|
|
||||||
Get it here
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/*; YM2610 ADPCM-B Codec
|
/*; YM2610 ADPCM-B Codec
|
||||||
;
|
;
|
||||||
;**** PCM to ADPCM-B & ADPCM-B to PCM converters for NEO-GEO System ****
|
;**** PCM to ADPCM-B & ADPCM-B to PCM converters for NEO-GEO System ****
|
||||||
;ADPCM-B - 1 channel 1.8-55.5 KHz, 16 MB Sample ROM size, 256 B min size of sample, 16 MB max, compatable with YM2608
|
;ADPCM-B - 1 channel 1.8-55.5 KHz, 16 MB Sample ROM size, 256 B min size of sample, 16 MB max, compatable with YM2608
|
||||||
@@ -15,59 +15,26 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define INLINE static __inline
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#define INLINE static __inline__
|
|
||||||
#else
|
|
||||||
#define INLINE static inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_STDINT
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
typedef uint8_t UINT8;
|
#include "util.h"
|
||||||
typedef int8_t INT8;
|
|
||||||
typedef uint16_t UINT16;
|
|
||||||
typedef int16_t INT16;
|
|
||||||
typedef uint32_t UINT32;
|
|
||||||
typedef int32_t INT32;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
typedef unsigned char UINT8;
|
|
||||||
typedef signed char INT8;
|
|
||||||
typedef unsigned short UINT16;
|
|
||||||
typedef signed short INT16;
|
|
||||||
typedef unsigned int UINT32;
|
|
||||||
typedef signed int INT32;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef UINT8 BYTE;
|
|
||||||
typedef UINT16 WORD;
|
|
||||||
typedef UINT32 DWORD;
|
|
||||||
|
|
||||||
// -- from mmsystem.h --
|
// -- from mmsystem.h --
|
||||||
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
//FIXME: DEELT THIS
|
||||||
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
|
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||||
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
|
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
|
||||||
|
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
|
||||||
|
|
||||||
// -- from mmreg.h, slightly modified --
|
// -- from mmreg.h, slightly modified --
|
||||||
|
|
||||||
/* general waveform format structure (information common to all formats) */
|
/* general waveform format structure (information common to all formats) */
|
||||||
typedef struct waveformat_tag {
|
typedef struct waveformat_tag {
|
||||||
WORD wFormatTag; /* format type */
|
uint16_t wFormatTag; /* format type */
|
||||||
WORD nChannels; /* number of channels (i.e. mono, stereo...) */
|
uint16_t nChannels; /* number of channels (i.e. mono, stereo...) */
|
||||||
DWORD nSamplesPerSec; /* sample rate */
|
uint32_t nSamplesPerSec; /* sample rate */
|
||||||
DWORD nAvgBytesPerSec; /* for buffer estimation */
|
uint32_t nAvgBytesPerSec; /* for buffer estimation */
|
||||||
WORD nBlockAlign; /* block size of data */
|
uint16_t nBlockAlign; /* block size of data */
|
||||||
WORD wBitsPerSample;
|
uint16_t wBitsPerSample;
|
||||||
} WAVEFORMAT;
|
} WAVEFORMAT;
|
||||||
|
|
||||||
/* flags for wFormatTag field of WAVEFORMAT */
|
/* flags for wFormatTag field of WAVEFORMAT */
|
||||||
@@ -75,21 +42,21 @@ typedef struct waveformat_tag {
|
|||||||
|
|
||||||
// -- from mm*.h end --
|
// -- from mm*.h end --
|
||||||
|
|
||||||
#define FOURCC_RIFF MAKEFOURCC('R', 'I', 'F', 'F')
|
#define FOURCC_RIFF MAKEFOURCC('R', 'I', 'F', 'F')
|
||||||
#define FOURCC_WAVE MAKEFOURCC('W', 'A', 'V', 'E')
|
#define FOURCC_WAVE MAKEFOURCC('W', 'A', 'V', 'E')
|
||||||
#define FOURCC_fmt_ MAKEFOURCC('f', 'm', 't', ' ')
|
#define FOURCC_fmt_ MAKEFOURCC('f', 'm', 't', ' ')
|
||||||
#define FOURCC_data MAKEFOURCC('d', 'a', 't', 'a')
|
#define FOURCC_data MAKEFOURCC('d', 'a', 't', 'a')
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT32 RIFFfcc; // 'RIFF'
|
uint32_t RIFFfcc; // 'RIFF'
|
||||||
UINT32 RIFFLen;
|
uint32_t RIFFLen;
|
||||||
UINT32 WAVEfcc; // 'WAVE'
|
uint32_t WAVEfcc; // 'WAVE'
|
||||||
UINT32 fmt_fcc; // 'fmt '
|
uint32_t fmt_fcc; // 'fmt '
|
||||||
UINT32 fmt_Len;
|
uint32_t fmt_Len;
|
||||||
WAVEFORMAT fmt_Data;
|
WAVEFORMAT fmt_Data;
|
||||||
UINT32 datafcc; // 'data'
|
uint32_t datafcc; // 'data'
|
||||||
UINT32 dataLen;
|
uint32_t dataLen;
|
||||||
} WAVE_FILE;
|
} WAVE_FILE;
|
||||||
|
|
||||||
|
|
||||||
@@ -99,12 +66,12 @@ static const long stepsizeTable[16] =
|
|||||||
57, 57, 57, 57, 77, 102, 128, 153
|
57, 57, 57, 57, 77, 102, 128, 153
|
||||||
};
|
};
|
||||||
|
|
||||||
static int YM2610_ADPCM_Encode(INT16 *src, UINT8 *dest, int len)
|
static int YM2610_ADPCM_Encode(int16_t *src, uint8_t *dest, int len)
|
||||||
{
|
{
|
||||||
int lpc, flag;
|
int lpc, flag;
|
||||||
long i, dn, xn, stepSize;
|
long i, dn, xn, stepSize;
|
||||||
UINT8 adpcm;
|
uint8_t adpcm;
|
||||||
UINT8 adpcmPack;
|
uint8_t adpcmPack;
|
||||||
|
|
||||||
xn = 0;
|
xn = 0;
|
||||||
stepSize = 127;
|
stepSize = 127;
|
||||||
@@ -115,10 +82,10 @@ static int YM2610_ADPCM_Encode(INT16 *src, UINT8 *dest, int len)
|
|||||||
dn = *src - xn;
|
dn = *src - xn;
|
||||||
src ++;
|
src ++;
|
||||||
|
|
||||||
i = (abs(dn) << 16) / (stepSize << 14);
|
i = (labs(dn) << 16) / (stepSize << 14);
|
||||||
if (i > 7)
|
if (i > 7)
|
||||||
i = 7;
|
i = 7;
|
||||||
adpcm = (UINT8)i;
|
adpcm = (uint8_t)i;
|
||||||
|
|
||||||
i = (adpcm * 2 + 1) * stepSize / 8;
|
i = (adpcm * 2 + 1) * stepSize / 8;
|
||||||
|
|
||||||
@@ -156,15 +123,14 @@ static int YM2610_ADPCM_Encode(INT16 *src, UINT8 *dest, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int YM2610_ADPCM_Decode(UINT8 *src, INT16 *dest, int len)
|
static int YM2610_ADPCM_Decode(uint8_t *src, int16_t *dest, int len)
|
||||||
{
|
{
|
||||||
int lpc, flag, shift, step;
|
int lpc, shift, step;
|
||||||
long i, xn, stepSize;
|
long i, xn, stepSize;
|
||||||
UINT8 adpcm;
|
uint8_t adpcm;
|
||||||
|
|
||||||
xn = 0;
|
xn = 0;
|
||||||
stepSize = 127;
|
stepSize = 127;
|
||||||
flag = 0;
|
|
||||||
shift = 4;
|
shift = 4;
|
||||||
step = 0;
|
step = 0;
|
||||||
|
|
||||||
@@ -178,10 +144,7 @@ static int YM2610_ADPCM_Decode(UINT8 *src, INT16 *dest, int len)
|
|||||||
else
|
else
|
||||||
xn += i;
|
xn += i;
|
||||||
|
|
||||||
if (xn > 32767)
|
xn = CLAMP(xn, -32768, 32767);
|
||||||
xn = 32767;
|
|
||||||
else if (xn < -32768)
|
|
||||||
xn = -32768;
|
|
||||||
|
|
||||||
stepSize = stepSize * stepsizeTable[adpcm] / 64;
|
stepSize = stepSize * stepsizeTable[adpcm] / 64;
|
||||||
|
|
||||||
@@ -190,7 +153,7 @@ static int YM2610_ADPCM_Decode(UINT8 *src, INT16 *dest, int len)
|
|||||||
else if (stepSize > 24576)
|
else if (stepSize > 24576)
|
||||||
stepSize = 24576;
|
stepSize = 24576;
|
||||||
|
|
||||||
*dest = (INT16)xn;
|
*dest = (int16_t)xn;
|
||||||
dest ++;
|
dest ++;
|
||||||
|
|
||||||
src += step;
|
src += step;
|
||||||
@@ -201,25 +164,25 @@ static int YM2610_ADPCM_Decode(UINT8 *src, INT16 *dest, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE UINT32 DeltaTReg2SampleRate(UINT16 DeltaN, UINT32 Clock)
|
static FORCE_INLINE uint32_t DeltaTReg2SampleRate(uint16_t DeltaN, uint32_t Clock)
|
||||||
{
|
{
|
||||||
return (UINT32)(DeltaN * (Clock / 72.0) / 65536.0 + 0.5);
|
return (uint32_t)(DeltaN * (Clock / 72.0) / 65536.0 + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
int ErrVal;
|
int ErrVal;
|
||||||
int ArgBase;
|
int ArgBase;
|
||||||
DWORD OutSmplRate;
|
uint32_t OutSmplRate;
|
||||||
FILE* hFile;
|
FILE* hFile;
|
||||||
unsigned int AdpcmSize;
|
unsigned int AdpcmSize;
|
||||||
UINT8* AdpcmData;
|
uint8_t* AdpcmData;
|
||||||
unsigned int WaveSize;
|
unsigned int WaveSize;
|
||||||
UINT16* WaveData;
|
uint16_t* WaveData;
|
||||||
WAVE_FILE WaveFile;
|
WAVE_FILE WaveFile;
|
||||||
WAVEFORMAT* TempFmt;
|
WAVEFORMAT* TempFmt;
|
||||||
unsigned int TempLng;
|
unsigned int TempLng;
|
||||||
UINT16 DTRegs;
|
uint16_t DTRegs;
|
||||||
char* TempPnt;
|
char* TempPnt;
|
||||||
|
|
||||||
printf("NeoGeo ADPCM-B En-/Decoder\n--------------------------\n");
|
printf("NeoGeo ADPCM-B En-/Decoder\n--------------------------\n");
|
||||||
@@ -258,7 +221,7 @@ int main(int argc, char* argv[])
|
|||||||
OutSmplRate = strtol(argv[2] + 3, NULL, 0);
|
OutSmplRate = strtol(argv[2] + 3, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
DTRegs = (UINT16)strtoul(argv[2] + 3, &TempPnt, 0);
|
DTRegs = (uint16_t)strtoul(argv[2] + 3, &TempPnt, 0);
|
||||||
TempLng = 0;
|
TempLng = 0;
|
||||||
if (*TempPnt == ',')
|
if (*TempPnt == ',')
|
||||||
{
|
{
|
||||||
@@ -292,12 +255,12 @@ int main(int argc, char* argv[])
|
|||||||
AdpcmSize = ftell(hFile);
|
AdpcmSize = ftell(hFile);
|
||||||
|
|
||||||
fseek(hFile, 0x00, SEEK_SET);
|
fseek(hFile, 0x00, SEEK_SET);
|
||||||
AdpcmData = (UINT8*)malloc(AdpcmSize);
|
AdpcmData = (uint8_t*)malloc(AdpcmSize);
|
||||||
fread(AdpcmData, 0x01, AdpcmSize, hFile);
|
fread(AdpcmData, 0x01, AdpcmSize, hFile);
|
||||||
fclose(hFile);
|
fclose(hFile);
|
||||||
|
|
||||||
WaveSize = AdpcmSize * 2; // 4-bit ADPCM -> 2 values per byte
|
WaveSize = AdpcmSize * 2; // 4-bit ADPCM -> 2 values per byte
|
||||||
WaveData = (UINT16*)malloc(WaveSize * 2);
|
WaveData = (uint16_t*)malloc(WaveSize * 2);
|
||||||
printf("Decoding ...");
|
printf("Decoding ...");
|
||||||
YM2610_ADPCM_Decode(AdpcmData, WaveData, WaveSize);
|
YM2610_ADPCM_Decode(AdpcmData, WaveData, WaveSize);
|
||||||
printf(" OK\n");
|
printf(" OK\n");
|
||||||
@@ -355,7 +318,7 @@ int main(int argc, char* argv[])
|
|||||||
fread(&WaveFile.fmt_Len, 0x04, 0x01, hFile);
|
fread(&WaveFile.fmt_Len, 0x04, 0x01, hFile);
|
||||||
while(WaveFile.fmt_fcc != FOURCC_fmt_)
|
while(WaveFile.fmt_fcc != FOURCC_fmt_)
|
||||||
{
|
{
|
||||||
if (! TempLng) // TempLng == 0 -> EOF reached
|
if (! TempLng) // TempLng == 0 -> EOF reached
|
||||||
{
|
{
|
||||||
fclose(hFile);
|
fclose(hFile);
|
||||||
printf("Error in wave file: Can't find format-tag!\n");
|
printf("Error in wave file: Can't find format-tag!\n");
|
||||||
@@ -398,7 +361,7 @@ int main(int argc, char* argv[])
|
|||||||
fread(&WaveFile.dataLen, 0x04, 0x01, hFile);
|
fread(&WaveFile.dataLen, 0x04, 0x01, hFile);
|
||||||
while(WaveFile.datafcc != FOURCC_data)
|
while(WaveFile.datafcc != FOURCC_data)
|
||||||
{
|
{
|
||||||
if (! TempLng) // TempLng == 0 -> EOF reached
|
if (! TempLng) // TempLng == 0 -> EOF reached
|
||||||
{
|
{
|
||||||
fclose(hFile);
|
fclose(hFile);
|
||||||
printf("Error in wave file: Can't find data-tag!\n");
|
printf("Error in wave file: Can't find data-tag!\n");
|
||||||
@@ -411,13 +374,13 @@ int main(int argc, char* argv[])
|
|||||||
fread(&WaveFile.dataLen, 0x04, 0x01, hFile);
|
fread(&WaveFile.dataLen, 0x04, 0x01, hFile);
|
||||||
};
|
};
|
||||||
WaveSize = WaveFile.dataLen / 2;
|
WaveSize = WaveFile.dataLen / 2;
|
||||||
WaveData = (UINT16*)malloc(WaveSize * 2);
|
WaveData = (uint16_t*)malloc(WaveSize * 2);
|
||||||
fread(WaveData, 0x02, WaveSize, hFile);
|
fread(WaveData, 0x02, WaveSize, hFile);
|
||||||
|
|
||||||
fclose(hFile);
|
fclose(hFile);
|
||||||
|
|
||||||
AdpcmSize = WaveSize / 2;
|
AdpcmSize = WaveSize / 2;
|
||||||
AdpcmData = (UINT8*)malloc(AdpcmSize);
|
AdpcmData = (uint8_t*)malloc(AdpcmSize);
|
||||||
printf("Encoding ...");
|
printf("Encoding ...");
|
||||||
YM2610_ADPCM_Encode(WaveData, AdpcmData, WaveSize);
|
YM2610_ADPCM_Encode(WaveData, AdpcmData, WaveSize);
|
||||||
printf(" OK\n");
|
printf(" OK\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user