diff options
author | Wohlstand <admin@wohlnet.ru> | 2023-10-12 00:38:09 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2023-10-12 00:38:09 +0300 |
commit | 66dd466965f70e045c193fb92b9ce5984f3acd22 (patch) | |
tree | 9ced8d55c7f45382a0da4519ccf19f898ae8cd3c /examples | |
parent | 2ff142064bcb6fcc05daa6505c99a22077255536 (diff) | |
download | libADLMIDI-66dd466965f70e045c193fb92b9ce5984f3acd22.tar.gz libADLMIDI-66dd466965f70e045c193fb92b9ce5984f3acd22.tar.bz2 libADLMIDI-66dd466965f70e045c193fb92b9ce5984f3acd22.zip |
Added simple Golang example
Diffstat (limited to 'examples')
-rw-r--r-- | examples/golang-mid2wav/.gitignore | 2 | ||||
-rw-r--r-- | examples/golang-mid2wav/README.txt | 15 | ||||
-rw-r--r-- | examples/golang-mid2wav/mid2wav.go | 129 |
3 files changed, 146 insertions, 0 deletions
diff --git a/examples/golang-mid2wav/.gitignore b/examples/golang-mid2wav/.gitignore new file mode 100644 index 0000000..6f02588 --- /dev/null +++ b/examples/golang-mid2wav/.gitignore @@ -0,0 +1,2 @@ +mid2wav +mid2wav.exe diff --git a/examples/golang-mid2wav/README.txt b/examples/golang-mid2wav/README.txt new file mode 100644 index 0000000..055b9cd --- /dev/null +++ b/examples/golang-mid2wav/README.txt @@ -0,0 +1,15 @@ +To build this example, run the next command from a terminal: +------------------------------ +go build mid2wav.go +------------------------------ + +Usage of ./mid2wav: + -b int + bank (default 59) + -c int + chips (default 2) + -i string + input midi file + -o string + output wave file +------------------------------ diff --git a/examples/golang-mid2wav/mid2wav.go b/examples/golang-mid2wav/mid2wav.go new file mode 100644 index 0000000..d8fc059 --- /dev/null +++ b/examples/golang-mid2wav/mid2wav.go @@ -0,0 +1,129 @@ +package main + +import ( + "flag" + "log" + "unsafe" +) + +// #cgo LDFLAGS: -lADLMIDI -Lbin +// #cgo CFLAGS: +// #include <stdio.h> +// #include <stdlib.h> +// #include <adlmidi.h> +// typedef struct wav_header { +// // RIFF Header +// char riff_header[4]; // Contains "RIFF" +// int wav_size; // Size of the wav portion of the file, which follows the first 8 bytes. File size - 8 +// char wave_header[4]; // Contains "WAVE" +// // Format Header +// char fmt_header[4]; // Contains "fmt " (includes trailing space) +// int fmt_chunk_size; // Should be 16 for PCM +// short audio_format; // Should be 1 for PCM. 3 for IEEE Float +// short num_channels; +// int sample_rate; +// int byte_rate; // Number of bytes per second. sample_rate * num_channels * Bytes Per Sample +// short sample_alignment; // num_channels * Bytes Per Sample +// short bit_depth; // Number of bits per sample +// // Data +// char data_header[4]; // Contains "data" +// int data_bytes; // Number of bytes in data. Number of samples * num_channels * sample byte size +// // uint8_t bytes[]; // Remainder of wave file is bytes +// } wav_header; +import "C" + +func main() { + inputPtr := flag.String("i", "", "input midi file") + outputPtr := flag.String("o", "", "output wave file") + bank := flag.Int("b", 59, "bank") + chips := flag.Int("c", 2, "chips") + + flag.Parse() + + if *inputPtr == "" { + log.Fatal("no input midi file") + } + + if *outputPtr == "" { + log.Fatal("no output file") + } + + // Convert into raw C-String + cInputFile := C.CString(*inputPtr) + + // Initializing the instance of libADLMIDI + cAdlMidiPlayer := C.adl_init(48000) + // Set number of parallel chips + C.adl_setNumChips(cAdlMidiPlayer, C.int(*chips)) + // Disable looping (it's not needed for WAV output) + C.adl_setLoopEnabled(cAdlMidiPlayer, 0) + // Setting one of embedded banks + C.adl_setBank(cAdlMidiPlayer, C.int(*bank)) + // Open an external MIDI file to play it + C.adl_openFile(cAdlMidiPlayer, cInputFile) + // Remove the file path buffer + C.free(unsafe.Pointer(cInputFile)) + + // Create the audio buffer that will be used to store taken audio chunks and write them into WAV file + cBuffer := C.malloc(2048 * 2) + + cOutputFileName := C.CString(*outputPtr) + cFileMode := C.CString("wb") + + cFILE := C.fopen(cOutputFileName, cFileMode) + C.free(unsafe.Pointer(cOutputFileName)) + C.free(unsafe.Pointer(cFileMode)) + + var cWavHeader C.wav_header + cWavHeader.riff_header[0] = 'R' + cWavHeader.riff_header[1] = 'I' + cWavHeader.riff_header[2] = 'F' + cWavHeader.riff_header[3] = 'F' + cWavHeader.wav_size = 0 + cWavHeader.wave_header[0] = 'W' + cWavHeader.wave_header[1] = 'A' + cWavHeader.wave_header[2] = 'V' + cWavHeader.wave_header[3] = 'E' + cWavHeader.fmt_header[0] = 'f' + cWavHeader.fmt_header[1] = 'm' + cWavHeader.fmt_header[2] = 't' + cWavHeader.fmt_header[3] = ' ' + cWavHeader.fmt_chunk_size = 16 + cWavHeader.audio_format = 1 + cWavHeader.num_channels = 2 + cWavHeader.sample_rate = 48000 + cWavHeader.byte_rate = 192000 + cWavHeader.sample_alignment = 4 + cWavHeader.bit_depth = 16 + cWavHeader.data_header[0] = 'd' + cWavHeader.data_header[1] = 'a' + cWavHeader.data_header[2] = 't' + cWavHeader.data_header[3] = 'a' + cWavHeader.data_bytes = 0 + + C.fwrite(unsafe.Pointer(&cWavHeader), 44, 1, cFILE) + + finished := false + dataBytes := 0 + + for !finished { + count := C.adl_play(cAdlMidiPlayer, 2048, (*C.int16_t)(cBuffer)) + if C.adl_atEnd(cAdlMidiPlayer) == 1 { + finished = true + } + if count > 0 { + dataBytes += int(count) * 4 + C.fwrite(cBuffer, 1, C.size_t(count * 2), cFILE) + } + } + C.adl_close(cAdlMidiPlayer) + + cWavHeader.wav_size = C.int(36 + dataBytes) + cWavHeader.data_bytes = C.int(dataBytes) + + C.fseek(cFILE, 0, C.SEEK_SET) + C.fwrite(unsafe.Pointer(&cWavHeader), 44, 1, cFILE) + + C.fclose(cFILE) + C.free(cBuffer) +} |