mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-25 16:34:45 -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:
@ -11,6 +11,7 @@ import (
|
||||
|
||||
func DeserializeAsm(asmcode string) (*Song, error) {
|
||||
var bpm int
|
||||
output16Bit := false
|
||||
scanner := bufio.NewScanner(strings.NewReader(asmcode))
|
||||
patterns := make([][]byte, 0)
|
||||
tracks := make([]Track, 0)
|
||||
@ -86,6 +87,8 @@ func DeserializeAsm(asmcode string) (*Song, error) {
|
||||
return nil, err
|
||||
}
|
||||
bpm = ints[0]
|
||||
} else if defineName == "OUTPUT_16BIT" {
|
||||
output16Bit = true
|
||||
}
|
||||
}
|
||||
case "PATTERN":
|
||||
@ -158,7 +161,7 @@ func DeserializeAsm(asmcode string) (*Song, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s := Song{BPM: bpm, Patterns: patterns, Tracks: tracks, Patch: patch}
|
||||
s := Song{BPM: bpm, Patterns: patterns, Tracks: tracks, Patch: patch, Output16Bit: output16Bit}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
@ -252,6 +255,9 @@ func SerializeAsm(song *Song) (string, error) {
|
||||
}
|
||||
// The actual printing starts here
|
||||
println("%%define BPM %d", song.BPM)
|
||||
if song.Output16Bit {
|
||||
println("%%define OUTPUT_16BIT")
|
||||
}
|
||||
// delay modulation is pretty much the only %define that the asm preprocessor cannot figure out
|
||||
// as the preprocessor has no clue if a SEND modulates a delay unit. So, unfortunately, for the
|
||||
// time being, we need to figure during export if INCLUDE_DELAY_MODULATION needs to be defined.
|
||||
@ -369,3 +375,68 @@ func SerializeAsm(song *Song) (string, error) {
|
||||
ret := b.String()
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func ExportCHeader(song *Song, maxSamples int) string {
|
||||
template :=
|
||||
`// auto-generated by Sointu, editing not recommended
|
||||
#ifndef SU_RENDER_H
|
||||
#define SU_RENDER_H
|
||||
|
||||
#define SU_MAX_SAMPLES %v
|
||||
#define SU_BUFFER_LENGTH (SU_MAX_SAMPLES*2)
|
||||
|
||||
#define SU_SAMPLE_RATE 44100
|
||||
#define SU_BPM %v
|
||||
#define SU_PATTERN_SIZE %v
|
||||
#define SU_MAX_PATTERNS %v
|
||||
#define SU_TOTAL_ROWS (SU_MAX_PATTERNS*SU_PATTERN_SIZE)
|
||||
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*4*60/(SU_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 %v SUsample;
|
||||
#define SU_SAMPLE_RANGE %v
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void SU_CALLCONV su_render_song(SUsample *buffer);
|
||||
%v
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
`
|
||||
maxSamplesText := "SU_TOTAL_ROWS*SU_SAMPLES_PER_ROW"
|
||||
if maxSamples > 0 {
|
||||
maxSamplesText = fmt.Sprintf("%v", maxSamples)
|
||||
}
|
||||
sampleType := "float"
|
||||
sampleRange := "1.0f"
|
||||
if song.Output16Bit {
|
||||
sampleType = "short"
|
||||
sampleRange = "32768"
|
||||
}
|
||||
defineGmdls := ""
|
||||
for _, instr := range song.Patch.Instruments {
|
||||
for _, unit := range instr.Units {
|
||||
if unit.Type == "oscillator" && unit.Parameters["type"] == Sample {
|
||||
defineGmdls = "\n#define SU_LOAD_GMDLS\nvoid SU_CALLCONV su_load_gmdls(void);"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
header := fmt.Sprintf(template, maxSamplesText, song.BPM, song.PatternRows(), song.SequenceLength(), sampleType, sampleRange, defineGmdls)
|
||||
return header
|
||||
}
|
||||
|
Reference in New Issue
Block a user