diff options
author | Wohlstand <admin@wohlnet.ru> | 2022-10-17 18:39:08 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2022-10-17 18:39:08 +0300 |
commit | 9fbaa58e87a63749ff1694bdb9f4d1241db98689 (patch) | |
tree | e876a7ea5bed72a36836137f8915eed1fe84edd2 /src/cvt_xmi2mid.hpp | |
parent | e27764edeb24936ce50da6229a781006e7ebdc75 (diff) | |
download | libADLMIDI-9fbaa58e87a63749ff1694bdb9f4d1241db98689.tar.gz libADLMIDI-9fbaa58e87a63749ff1694bdb9f4d1241db98689.tar.bz2 libADLMIDI-9fbaa58e87a63749ff1694bdb9f4d1241db98689.zip |
Improved the multi-song XMI support
- Allow selecting every individual song of the XMI file
- Allow dynamic song switch without re-opening of a file
- Fixed XMI2MID converter with adding an ability to export every individual song
- Added hooks for loop start and end events
- Added an option to immediately stop the song processing on loop end reaching (needed to perform dynamic song switch at the loop end point)
Diffstat (limited to 'src/cvt_xmi2mid.hpp')
-rw-r--r-- | src/cvt_xmi2mid.hpp | 100 |
1 files changed, 92 insertions, 8 deletions
diff --git a/src/cvt_xmi2mid.hpp b/src/cvt_xmi2mid.hpp index 84c2f83..181c7db 100644 --- a/src/cvt_xmi2mid.hpp +++ b/src/cvt_xmi2mid.hpp @@ -31,6 +31,8 @@ #include <stdint.h> #include <assert.h> +#include <vector> + #ifdef __DJGPP__ typedef signed char int8_t; typedef unsigned char uint8_t; @@ -124,7 +126,7 @@ static int32_t xmi2mid_ConvertSystemMessage(struct xmi2mid_xmi_ctx *ctx, static int32_t xmi2mid_ConvertFiletoList(struct xmi2mid_xmi_ctx *ctx, const xmi2mid_rbrn *rbrn); static uint32_t xmi2mid_ConvertListToMTrk(struct xmi2mid_xmi_ctx *ctx, midi_event *mlist); static int xmi2mid_ParseXMI(struct xmi2mid_xmi_ctx *ctx); -static int xmi2mid_ExtractTracks(struct xmi2mid_xmi_ctx *ctx); +static int xmi2mid_ExtractTracks(struct xmi2mid_xmi_ctx *ctx, int32_t dstTrackNumber); static uint32_t xmi2mid_ExtractTracksFromXmi(struct xmi2mid_xmi_ctx *ctx); static uint32_t xmi2mid_read1(struct xmi2mid_xmi_ctx *ctx) @@ -517,11 +519,12 @@ static const char xmi2mid_mt32asgs[256] = { static int Convert_xmi2midi(uint8_t *in, uint32_t insize, uint8_t **out, uint32_t *outsize, - uint32_t convert_type) + uint32_t convert_type, int32_t trackNumber = -1) { struct xmi2mid_xmi_ctx ctx; unsigned int i; int ret = -1; + int hasSelectedTrack = 0; if (convert_type > XMIDI_CONVERT_MT32_TO_GS) { /*_WM_ERROR_NEW("%s:%i: %d is an invalid conversion type.", __FUNCTION__, __LINE__, convert_type);*/ @@ -539,11 +542,15 @@ static int Convert_xmi2midi(uint8_t *in, uint32_t insize, goto _end; } - if (xmi2mid_ExtractTracks(&ctx) < 0) { + if (xmi2mid_ExtractTracks(&ctx, trackNumber) < 0) { /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_MIDI, NULL, 0);*/ goto _end; } + hasSelectedTrack = trackNumber >= 0; + if (trackNumber >= ctx.info.tracks) + trackNumber = ctx.info.tracks - 1; + ctx.dst = (uint8_t*)malloc(DST_CHUNK); ctx.dst_ptr = ctx.dst; ctx.dstsize = DST_CHUNK; @@ -558,10 +565,12 @@ static int Convert_xmi2midi(uint8_t *in, uint32_t insize, xmi2mid_write4(&ctx, 6); xmi2mid_write2(&ctx, ctx.info.type); - xmi2mid_write2(&ctx, ctx.info.tracks); - xmi2mid_write2(&ctx, ctx.timing[0]);/* write divisions from track0 */ + xmi2mid_write2(&ctx, hasSelectedTrack ? 1 : ctx.info.tracks); + xmi2mid_write2(&ctx, ctx.timing[hasSelectedTrack ? trackNumber : 0]);/* write divisions from track0 */ - for (i = 0; i < ctx.info.tracks; i++) + if (hasSelectedTrack) + xmi2mid_ConvertListToMTrk(&ctx, ctx.events[trackNumber]); + else for (i = 0; i < ctx.info.tracks; i++) xmi2mid_ConvertListToMTrk(&ctx, ctx.events[i]); *out = ctx.dst; *outsize = ctx.dstsize - ctx.dstrem; @@ -583,6 +592,81 @@ _end: /* cleanup */ return (ret); } +static int Convert_xmi2midi_multi(uint8_t *in, uint32_t insize, + std::vector<uint8_t *> &out, std::vector<uint32_t> &outsize, + uint32_t convert_type) +{ + struct xmi2mid_xmi_ctx ctx; + unsigned int i; + int ret = -1; + + if (convert_type > XMIDI_CONVERT_MT32_TO_GS) { + /*_WM_ERROR_NEW("%s:%i: %d is an invalid conversion type.", __FUNCTION__, __LINE__, convert_type);*/ + return (ret); + } + + memset(&ctx, 0, sizeof(struct xmi2mid_xmi_ctx)); + ctx.src = ctx.src_ptr = in; + ctx.srcsize = insize; + ctx.src_end = ctx.src + insize; + ctx.convert_type = convert_type; + + if (xmi2mid_ParseXMI(&ctx) < 0) { + /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_XMI, NULL, 0);*/ + goto _end; + } + + if (xmi2mid_ExtractTracks(&ctx, 0) < 0) { + /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_MIDI, NULL, 0);*/ + goto _end; + } + + for (i = 0; i < ctx.info.tracks; i++) + { + ctx.dst = (uint8_t*)malloc(DST_CHUNK); + ctx.dst_ptr = ctx.dst; + ctx.dstsize = DST_CHUNK; + ctx.dstrem = DST_CHUNK; + + /* Header is 14 bytes long and add the rest as well */ + xmi2mid_write1(&ctx, 'M'); + xmi2mid_write1(&ctx, 'T'); + xmi2mid_write1(&ctx, 'h'); + xmi2mid_write1(&ctx, 'd'); + + xmi2mid_write4(&ctx, 6); + + xmi2mid_write2(&ctx, ctx.info.type); + xmi2mid_write2(&ctx, 1); + xmi2mid_write2(&ctx, ctx.timing[i]);/* write divisions from track0 */ + + xmi2mid_ConvertListToMTrk(&ctx, ctx.events[i]); + out.push_back(ctx.dst); + outsize.push_back(ctx.dstsize - ctx.dstrem); + } + + ret = 0; + +_end: /* cleanup */ + if (ret < 0) { + for(size_t j = 0; j < out.size(); ++j) + { + free(out[j]); + out[j] = NULL; + } + out.clear(); + outsize.clear(); + } + if (ctx.events) { + for (i = 0; i < ctx.info.tracks; i++) + xmi2mid_DeleteEventList(ctx.events[i]); + free(ctx.events); + } + free(ctx.timing); + + return (ret); +} + static void xmi2mid_DeleteEventList(midi_event *mlist) { midi_event *event; midi_event *next; @@ -1222,13 +1306,13 @@ badfile: /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too shor return (-1); } -static int xmi2mid_ExtractTracks(struct xmi2mid_xmi_ctx *ctx) { +static int xmi2mid_ExtractTracks(struct xmi2mid_xmi_ctx *ctx, int32_t dstTrackNumber) { uint32_t i; ctx->events = (midi_event **)calloc(ctx->info.tracks, sizeof(midi_event*)); ctx->timing = (int16_t *)calloc(ctx->info.tracks, sizeof(int16_t)); /* type-2 for multi-tracks, type-0 otherwise */ - ctx->info.type = (ctx->info.tracks > 1)? 2 : 0; + ctx->info.type = (ctx->info.tracks > 1 && (dstTrackNumber < 0 || ctx->info.tracks >= dstTrackNumber))? 2 : 0; xmi2mid_seeksrc(ctx, ctx->datastart); i = xmi2mid_ExtractTracksFromXmi(ctx); |