Author Topic: Inject custom music into rom  (Read 3428 times)

Dark_Ansem

  • CC:DBT Dream Team
  • Porrean (+50)
  • *
  • Posts: 76
    • View Profile
Inject custom music into rom
« on: January 15, 2015, 07:47:31 pm »
I'm pretty sure someone has asked it before, but how do I inject custom music into the game? from MP3... or WAV, or whatever it takes.

Mauron

  • Guru of Reason Emeritus
  • Errare Explorer (+1500)
  • *
  • Posts: 1774
  • Nu-chan
    • View Profile
    • Maurtopia
Re: Inject custom music into rom
« Reply #1 on: January 15, 2015, 09:08:59 pm »
I found this old tutorial for midi files, hopefully it helps. This is not an easy process, unfortunately.

CT SPC Tool

Quote
How music stored in ROM

Basically, the music are scores and samples.

Scores part includes several parts of data: sequence data, instrument table, drum set, volume information.
Sequence data is similar to midis, it contains commands(or we say events) to play the music.
Instrument table defines instruments that are used in the sequence, it's a list of sample indexes.
Drum set defines a set of notes and instruments that are used in drum mode, some games just don't use it.
Volume information control the piece's volume of course.

Samples part includes several parts of data: sample data, ADSR information, loop point information, pitch correction.
Sample data is a compressed sound format(BRR, Bit Rate Reduction).
Introduction of ADSR can be found here: http://en.wikipedia.org/wiki/ADSR, I'm not sure how it works(which takes how many bits, such).
Loop point defines from which point does the sample begin to loop, if it is set to loop.
I'm not sure how pitch correction works, most times you can leave it to zero.

If you use samples ripped from another game, just copy everything, it should be fine, unlike scores.

Folders and files

out\spc contains score data from CT, there are totally 83(0x53) pieces, from 00 to 53.
Files with no extensions are sequence data.
.instrument files are instrument tables.
.volume files are volume informations.
.drum files are drum sets.

out\sample contains sample data from CT, there are totally 62(0x3E) samples, from 01 to 3E.
Files with no extensions are sample data.
.loop files are loop points.
.ADSR files are ADSR informations.
.pitch files are pitch corrections.

out_bak is the back up folder for out.

mml folder contains some sample MML file.

custom sample folder contains a sample used by the example.

About those exe files and source files, check readme.txt for more informations.

Import data

Sometimes, you can just copy spc data from other games and insert into CT. But keep in mind, the games might use different spc cores from CT, which means soem commands might be different.
Another way is convert other music into spc format, for example, midis. But the problem is midi standard is complex, and much different to spc format. Fortunately, there are tools to convert a midi file into MML(Music Macro Language), which is readable by human, and is more close to spc format. What you need is to add some extra commands that are necessary to spc. So I wrote a tool to convert a MML file into spc format, mml2spc.

In theory, you can convert a wave format file into BRR sample, and I have written a tool to do that(wav2brr), but it doesn't contain other informations such as ADSR. Since all snes games use same sample format, so it is much safer to use a sample from another game.

MIDI to SPC

Let's start with an example.

1. Find a midi file. The midi must have at most 8 channels, because a spc score can only support 8 channels.

2. Use a tool to convert it into MML format. I recommend tinymm, you can find it via google.
The raw MML file is simple:
cdefgab are notes, + means sharp, - means flat. Values behind them are length.
o changes octaves, sometimes it is omitted, so you should add it by hand. The default value seems to be o6.
r means rest.
^ will extend the length of previous note.
means down one octave.
For more information, check the wiki: http://en.wikipedia.org/wiki/Music_Macro_Language

3. Add spc commands for the MML file.
There are too many commands and I haven't figure them all out, but only a few of them will keep you new music in shape.

#WAVE , - This command define an instrument for the spc. Instrument id is a number from 0x20 to 0x2F, it will be used later. Sample id specifies which sample is used by this instrument. You might need to test it for many times...
#DRUM , , , - This command define a drum set. Unlike #WAVE, note are from c to b, so there are 12 of them: c, c+, d, d+, e, f, f+, g, g+, a, a+, b. The drum set will be used later if a channel is set to drum mode. I never use this command though.
t - tempo, followed by a number from 0 to 255, a greater value will make the channel goes faster.
v - volume, followed by a value from 0 to 127, a greater value will make the channel louder.
%e1 - echo on. Without this command the sample will stop playing when a new note is reached, bad for some instruments.
%e0 - echo off. 0 is optional, so you can just use %e.
%v - echo volume. If you use %e1, you should consider this command. The loudness of the rest part of the last sample if a new note is reached.
@ - instrument id, from 0x20 to 0x2F are those defined by #WAVE, from 0 to 0x1F are system defined wave shapes, but I haven't try it out.
%d1 - drum mode. I haven't tried it out.
%d0 - turn off drum mode.
p - panning. Check wiki for more information: http://en.wikipedia.org/wiki/Panning_(audio) (http://en.wikipedia.org/wiki/Panning_(audio)). Usually, p64 is fine.
$ - mark loop point. It means when the end of channel is reached, the music will jump back to here.
[n|] - loop. It defines a loop, [ and ] are start and end point of the loop, n is loop count, | is the break point for the last loop. You can define a loop inside another, but it will make it too complex to read.
/:n/:/ - same as above.
; - end of channel. You will need it at the end of a channel.
{anything you want for a comment, of course, except "}" }
There's an example in mml folder of this package.

4. Convert MML to SPC data using command below:
mml2spc -m "your mml file path" -f -i your_spc_index
This will replace the spc data inside out/spc with the same spc index. Although, you can use a number larger than 0x52, but you have to hack the rom to let it be used.

*Note:
If you want to make a looping piece(with $ command), you need to check the output message, and add some r commands at the end of those shorter channels.
A full note has a length of 64, for example, the longest channel has a length of n, a shorter channel has a length of n-1282, you need to add 20 "r1"s at the end of the shorter channel(64x20=128) and a "r32"(64/32=2), all methods below work:

blahblah...
r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r32;

blahblah...
r1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^1^32;

blanblah...
[20r1]r32;


5. Expand your CT ROM.
Yeah, you need an expanded ROM(NA release). You can do that using Temporal Flux, for example.

6. Inject the data using command below:
inject "your rom file path" position
The position must be greater than 0x410000, or it will override other data. Although, if you plan to add data behind it, do check the actual output size. This tool packs all data and put it at the position you specified, and change some values inside the ROM to let the game look for the new position.

Links

http://slickproductions.org/forum/index.php?topic=612.0 (http://slickproductions.org/forum/index.php?topic=612.0), most mml commands are same as those used by RS3 tool

Later.

Edit: Maybe at some point I'll try making a Temporal Flux plugin for music and sounds, but Techs and AI are my priorities.

Dark_Ansem

  • CC:DBT Dream Team
  • Porrean (+50)
  • *
  • Posts: 76
    • View Profile
Re: Inject custom music into rom
« Reply #2 on: January 16, 2015, 04:48:44 am »
I can wait. Magus needs his techs!