mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-14 02:54:37 -04:00
feat(go4k&sointu): Export .h C header files from the songs using go, also automatically during build for the tests.
The header files are automatically generated during build. No need to #define anything; everything is fixed by the .asm file. This adds go as a dependency to run the unit tests, but this is probably not a bad thing, as go is probably needed anyway if one wants to actually start developing Sointu.
This commit is contained in:
@ -1,12 +1,20 @@
|
||||
function(regression_test testname)
|
||||
if(${ARGC} LESS 4)
|
||||
set(source ${testname}.asm)
|
||||
set (headerfile ${CMAKE_CURRENT_BINARY_DIR}/${testname}.h)
|
||||
add_custom_command(
|
||||
PRE_BUILD
|
||||
OUTPUT ${headerfile}
|
||||
COMMAND go run ${PROJECT_SOURCE_DIR}/go4k/cmd/asmfmt/main.go -c -d -w -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${source}
|
||||
DEPENDS ${source}
|
||||
)
|
||||
add_executable(${testname} ${source} test_renderer.c ${headerfile})
|
||||
target_compile_definitions(${testname} PUBLIC TEST_HEADER=<${testname}.h>)
|
||||
else()
|
||||
set(source ${ARGV3})
|
||||
add_executable(${testname} ${source} test_renderer.c)
|
||||
endif()
|
||||
|
||||
add_executable(${testname} ${source} test_renderer.c)
|
||||
|
||||
# the tests include the entire ASM but we still want to rebuild when they change
|
||||
file(GLOB SOINTU ${PROJECT_SOURCE_DIR}/src/*.inc
|
||||
${PROJECT_SOURCE_DIR}/src/*.asm
|
||||
@ -20,7 +28,6 @@ function(regression_test testname)
|
||||
set_source_files_properties(${FOURKLANG} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
add_test(${testname} ${testname})
|
||||
target_compile_definitions(${testname} PUBLIC TEST_NAME="${testname}" SU_USE_INTROSPECTION SU_USE_PLAYER)
|
||||
target_link_libraries(${testname} ${HEADERLIB})
|
||||
|
||||
set (rawinput ${CMAKE_CURRENT_SOURCE_DIR}/expected_output/${testname}.raw)
|
||||
@ -30,6 +37,9 @@ function(regression_test testname)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${rawinput} ${rawoutput}
|
||||
)
|
||||
|
||||
target_include_directories(${testname} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_compile_definitions(${testname} PUBLIC TEST_NAME="${testname}")
|
||||
|
||||
add_dependencies(${testname} ${testname}_rawcopy)
|
||||
|
||||
if(ARGC GREATER 1)
|
||||
@ -94,13 +104,7 @@ regression_test(test_oscillat_gate ENVELOPE)
|
||||
regression_test(test_oscillat_stereo ENVELOPE)
|
||||
if(WIN32) # The samples are currently only GMDLs based, and thus require Windows.
|
||||
regression_test(test_oscillat_sample ENVELOPE)
|
||||
target_compile_definitions(test_oscillat_sample PUBLIC INCLUDE_GMDLS)
|
||||
regression_test(test_oscillat_sample_stereo ENVELOPE)
|
||||
target_compile_definitions(test_oscillat_sample_stereo PUBLIC INCLUDE_GMDLS)
|
||||
regression_test(test_oscillat_sample_rtables ENVELOPE "" test_oscillat_sample.asm)
|
||||
target_compile_definitions(test_oscillat_sample_rtables PUBLIC INCLUDE_GMDLS RUNTIME_TABLES)
|
||||
regression_test(test_oscillat_sample_stereo_rtables ENVELOPE "" test_oscillat_sample_stereo.asm)
|
||||
target_compile_definitions(test_oscillat_sample_stereo_rtables PUBLIC INCLUDE_GMDLS RUNTIME_TABLES)
|
||||
endif()
|
||||
regression_test(test_oscillat_unison ENVELOPE)
|
||||
regression_test(test_oscillat_unison_stereo ENVELOPE)
|
||||
@ -147,22 +151,16 @@ regression_test(test_delay_dampmod "ENVELOPE;FOP_MULP;PANNING;VCO_SINE;SEND")
|
||||
regression_test(test_delay_drymod "ENVELOPE;FOP_MULP;PANNING;VCO_SINE;SEND")
|
||||
regression_test(test_delay_flanger "ENVELOPE;FOP_MULP;PANNING;VCO_SINE;SEND")
|
||||
|
||||
regression_test(test_delay_rtables "ENVELOPE;FOP_MULP;PANNING;VCO_SINE" "" test_delay.asm)
|
||||
target_compile_definitions(test_delay_rtables PUBLIC RUNTIME_TABLES)
|
||||
regression_test(test_delay_stereo_rtables "ENVELOPE;FOP_MULP;PANNING;VCO_SINE" "" test_delay_stereo.asm)
|
||||
target_compile_definitions(test_delay_stereo_rtables PUBLIC RUNTIME_TABLES)
|
||||
|
||||
regression_test(test_envelope_mod "VCO_SINE;ENVELOPE;SEND")
|
||||
regression_test(test_envelope_16bit ENVELOPE "" test_envelope.asm)
|
||||
target_compile_definitions(test_envelope_16bit PUBLIC SU_USE_16BIT_OUTPUT)
|
||||
regression_test(test_envelope_16bit ENVELOPE)
|
||||
|
||||
regression_test(test_polyphony "ENVELOPE;VCO_SINE")
|
||||
regression_test(test_chords "ENVELOPE;VCO_SINE")
|
||||
regression_test(test_speed "ENVELOPE;VCO_SINE")
|
||||
target_compile_definitions(test_speed PUBLIC MAX_SAMPLES=211592)
|
||||
|
||||
regression_test(test_render_samples ENVELOPE "" test_render_samples.c)
|
||||
target_link_libraries(test_render_samples ${STATICLIB})
|
||||
target_compile_definitions(test_render_samples PUBLIC TEST_HEADER="test_render_samples.h")
|
||||
|
||||
add_executable(test_render_samples_api test_render_samples_api.c)
|
||||
target_link_libraries(test_render_samples_api ${STATICLIB})
|
||||
|
Binary file not shown.
22
tests/test_envelope_16bit.asm
Normal file
22
tests/test_envelope_16bit.asm
Normal file
@ -0,0 +1,22 @@
|
||||
%define BPM 100
|
||||
%define OUTPUT_16BIT
|
||||
|
||||
%include "sointu/header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
PATTERN 64,HLD,HLD,HLD,HLD,HLD,HLD,HLD,0,0,0,0,0,0,0,0
|
||||
END_PATTERNS
|
||||
|
||||
BEGIN_TRACKS
|
||||
TRACK VOICES(1),0
|
||||
END_TRACKS
|
||||
|
||||
BEGIN_PATCH
|
||||
BEGIN_INSTRUMENT VOICES(1)
|
||||
SU_ENVELOPE STEREO(0),ATTACK(64),DECAY(64),SUSTAIN(64),RELEASE(80),GAIN(128)
|
||||
SU_ENVELOPE STEREO(0),ATTACK(95),DECAY(64),SUSTAIN(64),RELEASE(80),GAIN(128)
|
||||
SU_OUT STEREO(1),GAIN(128)
|
||||
END_INSTRUMENT
|
||||
END_PATCH
|
||||
|
||||
%include "sointu/footer.inc"
|
@ -2,24 +2,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sointu/sointu.h>
|
||||
#include "test_render_samples.h"
|
||||
|
||||
#if UINTPTR_MAX == 0xffffffff // are we 32-bit?
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define CALLCONV __attribute__ ((stdcall))
|
||||
#elif defined(_WIN32)
|
||||
#define CALLCONV __stdcall // on 32-bit platforms, we just use stdcall, as all know it
|
||||
#endif
|
||||
#else // 64-bit
|
||||
#define CALLCONV // the asm will use honor honor correct x64 ABI on all 64-bit platforms
|
||||
#endif
|
||||
|
||||
#define BPM 100
|
||||
#define SAMPLE_RATE 44100
|
||||
#define TOTAL_ROWS 16
|
||||
#define SAMPLES_PER_ROW SAMPLE_RATE * 4 * 60 / (BPM * 16)
|
||||
const int su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS;
|
||||
|
||||
void CALLCONV su_render_song(float* buffer) {
|
||||
void SU_CALLCONV su_render_song(float* buffer) {
|
||||
Synth* synth;
|
||||
const unsigned char commands[] = { su_envelope_id, // MONO
|
||||
su_envelope_id, // MONO
|
||||
@ -41,12 +26,12 @@ void CALLCONV su_render_song(float* buffer) {
|
||||
synth->RandSeed = 1;
|
||||
// triger first voice
|
||||
synth->SynthWrk.Voices[0].Note = 64;
|
||||
samples = su_max_samples / 2;
|
||||
samples = SU_MAX_SAMPLES / 2;
|
||||
time = INT32_MAX;
|
||||
retval = su_render(synth, buffer, &samples, &time);
|
||||
synth->SynthWrk.Voices[0].Release++;
|
||||
buffer = buffer + su_max_samples;
|
||||
samples = su_max_samples / 2;
|
||||
buffer = buffer + SU_MAX_SAMPLES;
|
||||
samples = SU_MAX_SAMPLES / 2;
|
||||
time = INT32_MAX;
|
||||
retval = su_render(synth, buffer, &samples, &time);
|
||||
free(synth);
|
||||
|
38
tests/test_render_samples.h
Normal file
38
tests/test_render_samples.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SU_RENDER_H
|
||||
#define SU_RENDER_H
|
||||
|
||||
#define SU_MAX_SAMPLES 105840
|
||||
#define SU_BUFFER_LENGTH (SU_MAX_SAMPLES*2)
|
||||
|
||||
#define SU_SAMPLE_RATE 44100
|
||||
#define SU_BPM 100
|
||||
#define SU_PATTERN_SIZE 16
|
||||
#define SU_MAX_PATTERNS 1
|
||||
#define SU_TOTAL_ROWS (SU_MAX_PATTERNS*SU_PATTERN_SIZE)
|
||||
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*4*60/(BPM*16))
|
||||
|
||||
#include <stdint.h>
|
||||
#if UINTPTR_MAX == 0xffffffff
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define SU_CALLCONV __attribute__ ((stdcall))
|
||||
#elif defined(_WIN32)
|
||||
#define SU_CALLCONV __stdcall
|
||||
#endif
|
||||
#else
|
||||
#define SU_CALLCONV
|
||||
#endif
|
||||
|
||||
typedef float SUsample;
|
||||
#define SU_SAMPLE_RANGE 1.0f
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void SU_CALLCONV su_render_song(SUsample *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -13,25 +13,7 @@
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if UINTPTR_MAX == 0xffffffff // are we 32-bit?
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define CALLCONV __attribute__ ((stdcall))
|
||||
#elif defined(_WIN32)
|
||||
#define CALLCONV __stdcall // on 32-bit platforms, we just use stdcall, as all know it
|
||||
#endif
|
||||
#else // 64-bit
|
||||
#define CALLCONV // the asm will use honor honor correct x64 ABI on all 64-bit platforms
|
||||
#endif
|
||||
extern void CALLCONV su_render_song(void *);
|
||||
|
||||
#ifdef INCLUDE_GMDLS
|
||||
extern void CALLCONV su_load_gmdls(void);
|
||||
#endif
|
||||
|
||||
extern int su_max_samples;
|
||||
#include TEST_HEADER
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
FILE* f;
|
||||
@ -45,28 +27,19 @@ int main(int argc, char* argv[]) {
|
||||
long bufsize;
|
||||
float max_diff;
|
||||
float diff;
|
||||
#ifndef SU_USE_16BIT_OUTPUT
|
||||
float* buf = NULL;
|
||||
float* filebuf = NULL;
|
||||
float v;
|
||||
bufsize = su_max_samples * 2 * sizeof(float);
|
||||
buf = (float*)malloc(bufsize);
|
||||
SUsample* buf = NULL;
|
||||
SUsample* filebuf = NULL;
|
||||
SUsample v;
|
||||
bufsize = SU_BUFFER_LENGTH * sizeof(SUsample);
|
||||
buf = (SUsample*)malloc(bufsize);
|
||||
memset(buf, 0, bufsize);
|
||||
#else
|
||||
short* buf = NULL;
|
||||
short* filebuf = NULL;
|
||||
short v;
|
||||
bufsize = su_max_samples * 2 * sizeof(short);
|
||||
buf = (short*)malloc(bufsize);
|
||||
memset(buf, 0, bufsize);
|
||||
#endif
|
||||
|
||||
if (buf == NULL) {
|
||||
printf("Could not allocate buffer for 4klang rendering\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_GMDLS
|
||||
#ifdef SU_LOAD_GMDLS
|
||||
su_load_gmdls();
|
||||
#endif
|
||||
|
||||
@ -95,27 +68,19 @@ int main(int argc, char* argv[]) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifndef SU_USE_16BIT_OUTPUT
|
||||
filebuf = (float*)malloc(bufsize);
|
||||
#else
|
||||
filebuf = (short*)malloc(bufsize);
|
||||
#endif
|
||||
filebuf = (SUsample*)malloc(bufsize);
|
||||
|
||||
if (filebuf == NULL) {
|
||||
printf("Could not allocate buffer for file contents\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fread((void*)filebuf, su_max_samples * 2, sizeof(*filebuf), f);
|
||||
fread((void*)filebuf, fsize, 1, f);
|
||||
|
||||
max_diff = 0.0f;
|
||||
|
||||
for (n = 0; n < su_max_samples * 2; n++) {
|
||||
diff = buf[n] - filebuf[n];
|
||||
#ifdef SU_USE_16BIT_OUTPUT
|
||||
diff = diff / 32768.0f;
|
||||
#endif
|
||||
diff = fabs(diff);
|
||||
for (n = 0; n < SU_BUFFER_LENGTH; n++) {
|
||||
diff = fabs((float)(buf[n] - filebuf[n])/SU_SAMPLE_RANGE);
|
||||
if (diff > 1e-3f || isnan(diff)) {
|
||||
printf("4klang rendered different wave than expected\n");
|
||||
goto fail;
|
||||
@ -151,7 +116,7 @@ end:
|
||||
|
||||
snprintf(filename, sizeof filename, "%s%s%s", actual_output_folder, test_name, ".raw");
|
||||
f = fopen(filename, "wb");
|
||||
fwrite((void*)buf, sizeof(*buf), 2 * su_max_samples, f);
|
||||
fwrite((void*)buf, 1, bufsize, f);
|
||||
fclose(f);
|
||||
|
||||
if (buf != 0) {
|
||||
|
Reference in New Issue
Block a user