Mconvert tutorial

From Uzebox Wiki
Revision as of 06:31, 7 October 2017 by D3thAdd3r (talk | contribs) (Created page with "==Introduction== ----------------TODO, PLEASE UNDERSTAND THIS IS NOT FINALIZED------- mconvert is a utility designed specifically to accommodate data preparation for use wit...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Introduction


TODO, PLEASE UNDERSTAND THIS IS NOT FINALIZED-------

mconvert is a utility designed specifically to accommodate data preparation for use with the streaming music player. It does not perform direct conversions of raw .MID files, as this is already accomplished well by midiconv. In general the goal is to let what midiconv does well in general, and focus on the specifics of streaming music that would be messy and a bad fit to place inside midiconv.

mconvert will take the direct C array output provided by midiconv, and outputs data that is ready to be used in the streaming music player. This includes raw C arrays for direct inclusion in your game(costs flash but no buffer is required, not yet implemented), and abilities to create an SD file which contains all the music and an index to the start of individual song(the more common method). It is recommended to take a look at SPIRamMusicDemo to help understand this. There are several options available that will affect the format of the output data to your individual program needs.


Usage

mconvert takes only one argument, and that is the name of a configuration file from which it shall operate. This configuration file is of a simple format which is easy to process, that allows the tool's source code to be small and simple to understand. The options should be enough for anyone's requirements. It is important to remember that, though the tool does cope with some deviance on spaces, etc. it is recommended to exactly follow the format described to avoid possible errors. The tool can be triggered from the command line like so:

mconvert ../path/to/config.file

It is likely better to call it directly from your makefile, so that you do not need to manually intervene when things change. This is similar to what you will find in the tutorial for gconvert, in the makefile integration section: Generating Tiles and Maps with gconvert

...

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Include Directories
INCLUDES = -I"$(KERNEL_DIR)" 

## Build
all: ../data/urbanmess.inc $(TARGET) $(GAME).hex $(GAME).eep $(GAME).lss $(GAME).uze size 

## Regenerate the music SD image
SDMUSIC.DAT: ../data/song1.inc ../data/song2.inc
	mconvert ../data/SDMusicImage.cfg

## Compile Kernel files
uzeboxVideoEngineCore.o: $(KERNEL_DIR)/uzeboxVideoEngineCore.s
	$(CC) $(INCLUDES) $(ASMFLAGS) -c  $<
..


Configuration File

The format of this file is not nearly as fancy or flexible as the xml found in gconvert. The source code is smaller, and uses nothing but the standard C library(and therefore easier to understand quickly) while doing everything that is required to get the job done: that is the reasoning behind this perhaps questionable design decision versus a full blown big xml setup. Lets look at an example of a configuration file:

1,512,1,MUSIC.DAT,
../tools/mconvert/song1.inc,0,
../tools/mconvert/song2.inc,3,
../tools/mconvert/song3.inc,0,

That is it. It should handle some minor changes from the ideal format, but it is wise to simple use this format to avoid potential issues. Do no put a newline after the last 0, in this example, to avoid what will appear like the start of a new entry to the simple parser. Let's think about what these arguments mean.

The first line is the setup line which will dictate some things about how the entries will be processed. The first byte, '1' in this case, specifies to use the binary format as opposed to the C array hex format. This is expected to be the most common choice, and if you are doing SD/SPI Ram streaming you need this. 0 is for the flash version(not yet implemented). The second number "512" represents where the first output byte of the first converted song will start at. 512 is a good location for most things. It is important to remember that for each converted song, mconvert will automatically fill in directory values starting from 0 and moving up 4 bytes for each entry. This allows songs to be anywhere in an image, and your code to easily be able to find them. 512 is an arbitrary choice that leaves lots of room, and has potential performance benefits in the case of SD streaming. The next item after this, '1' in this case, specifies whether the tool should apply padding to the end of songs. The padding, if enabled, will ensure that the total number of bytes output for each song is an even multiple of 512. These padding bytes will all be 0xFF(they should never be reached, but if they were, this value would stop the song). The reason for padding out the data is primarily intended to help with SD streaming. SD cards have a penalty for crossing a 512 byte sector, and you also cannot start reading except directly on a sector boundary. By having all the music start on sector boundaries, the amount of wasted byte reads can be minimized which increases performance.

Each line after that is just 2 arguments. The first argument is the path to the song file which you wish to convert. The order the song will be written in the directory is implied by the order you specify them in the configuration file. The second value, if a bit cryptic, is mainly aimed at advanced users...advanced MIDI users that are too lazy to delete spurious MIDI events from their source material ;) This is a decimal representation of a byte which is used as binary flags. These individual bits can be used to eliminate specific controller events from the stream, which can help improve performance and will likely not be missed. The flags can be OR'ed together in any configuration. The values are as so:

#define FILTER_CHANNEL_VOLUME	1//filter out channel volume events
#define FILTER_EXPRESSION	2//filter out expression events
#define FILTER_TREMOLO_VOLUME	4//filter out tremolo volume events
#define FILTER_TREMOLO_RATE	8//filter out tremolo rate events
#define FILTER_NOTE_OFF	16//filter out all NOTE_ONs which have a volume of 0(that is how Uzebox does "NOTE_OFFs")