Exploring Halo's Sound Tags

Everything about HD, MD, and their mods.

Moderator: Halo Moderators

Post Reply
Sparky
Delta Force
Posts: 4194
Joined: Wed Mar 31, 2004 8:59 pm
Location: New Jersey, USA
Contact:

Exploring Halo's Sound Tags

Post by Sparky » Thu Oct 18, 2012 3:46 pm

As posted here: http://forum.halomaps.org/index.cfm?pag ... icID=41725

An in-depth survey of Halo's .sound tags
by Sparky
Thursday, October 18, 2012 5:13:20 PM

With the Halo Editing Kit, the standard method of splitting a long sound file into permutations, such as when using a very long music file, is to do the following:

1. Open the music file with a sound editor.
2. Divide the music into segments 1 minute or shorter in duration (the maximum for highest quality ogg conversion later is about 1'28''483 ), copy-pasting each 1 minute segment into a new sound file and saving it with the following properties:
Format: WAV (uses extension ".wav")
Data Size: 16 bit
Frequency: 44.1 kHz
File Names: (numbered, such as) 00.wav, 01.wav, 02.wav, etc.
Maximum File Size: ~15.6 MB (each .ogg sound file permutation later must be at most exactly 4MB)
3. Place those .wav files into the HEK data directory such as Halo Custom Edition\data\your_name\sound\artist_name\composer_name\music_title\00.wav . Upon compilation with Tool, the sound tag will take the name of "music_title" and will be placed within the corresponding tags folder inside "composer_name"; the sound tag's permutations will be added numerically according to their file names to the HEK sound tag.
4. Open Tool with the command prompt (both Tool and the command prompt are typically located inside the Halo Custom Edition directory) and run the command:
tool sounds your_name\sound\artist_name\composer_name\music_title ogg 1
5. Wait for Tool to compile the sound tag. If it displays errors, use a lower quality, such as:
tool sounds your_name\sound\artist_name\composer_name\music_title ogg 0.9
or less, anything between 0 and 1.0. The quality at this point does not matter, you just need it to generate the sound tag.
6. Open the sound tag in Guerilla and do the following, then save the .sound tag:
√ split long sound into permutations
class: music
minimum distance: (for standard background music, set to map portal area size, ie. 100000)
maximum distance: (for standard background music, set to map portal area size, ie. 100000)

Pitch Ranges ->
actual permutation count: 1

Permutations ->
next permutation index: 1 (because the first permutation is index # 0, the second is index #1, and so on)
(next permutation): 2
(next permutation): 3
(next permutations): 4, 5, 6, etc.
(last permutation): -1
7. In Guerilla, start a new .sound_looping tag. Set the following in the sound_looping tag:
Tracks ->
gain: 1
loop: your_name\sound\artist_name\composer_name\music_title
8. Save the .sound_looping tag and reference it as the background sound in a .scenario_structure_bsp tag for background music applied to that particular portal using Sapien, or use the .sound_looping tag elsewhere instead.
9. Build the map cache file in Tool and play the map in Halo Custom Edition.
If each step above is followed as indicated, this process works every time without a problem.

For those who want to do a more "hackish" approach using a hex editor also, you can find more information below:

----
The maximum size of the sound tag "samples" value, which is the size in bytes of the ogg data in the sound tag, is 4MB exactly. That's 4194304 bytes (4096 * 1024) or 0x400000 in hex. So if you open up your .sound tag file in a hex editor and search the beginning of the file for the hex value equal to that samples value as shown in Guerilla, you'll see the offset for that value in the tag. Now if you're dealing with an .ogg sound file, you can actually manually copy-paste any amount of .ogg sound data starting at the offset which begins with the ASCII string "OggS", the first instance of that. This is the beginning of the .ogg sound data, and so you could copy-paste whatever other .ogg sound file's data into there, of any duration. The issue is Halo's engine limitations. If you update the "samples" value manually to any value greater than 4MB, the game will crash. The map file will still compile in tool, but Guerilla won't be able to open the sound tag either, telling you the sound samples size is too large.

So the best thing you can do is copy-paste any sound file you want into there, as .ogg sound data, and maximize the duration that the game can play it by setting that hex value to 4194304 or 0x400000 (4MB). Then the sound tag can be opened in Guerilla and the HEK tools and Halo will only play 4MB of it before stopping.

If you're using OGG quality 10 (which is 1.0 in tool) and convert a 4MB .ogg sound file (which brings it to 1:28 -- 1 minute, 28 seconds -- in duration) to a 16bit 44.1kHz wav audio file, the size of the .wav file would be about 15,608,742 bytes, basically 15.6MB (reading as 14.8MB if you're on Vista), and of course the duration of the sound file would remain the same.

So that means that you SHOULD be able to convert a .wav file that is up to about 15,608,742 bytes with tool into an .ogg sound file with quality 1. In practice, it works as a single permutation at quality 0.9, which unfortunately crunches the samples byte size down to 3472892 bytes instead of our 4194304 maximum.

Now if we split the file into permutations, each permutation again could be 4MB in size. When we do this with our sound file that is 4MB, it splits it into 17 permutations of various sample sizes, about 200-400KB each.

Going back to our hex editor, we can now copy-paste a longer sound file into that permutation-based sound tag.

Here's how to do the entire process of converting a long sound file into a usable .sound tag:

- Take a long music file and in a sound editing program, cut it into segments that are this duration (min, sec, millisec) or slightly shorter: 1'28''483

- Save each segment as an .ogg sound file, quality 10.

- Check the file size of each .ogg file. Each file should be up to 4194304 bytes, but no more than that. If they are larger than that, go back and reduce the duration by a little bit and try again.

- Now you should have several segments of a long music file that are all .ogg files of the same export quality up to 4MB (4194304 bytes) in size.

- Make a note of the exact file size in bytes of each .ogg file you exported. I like renaming the file as something like "1 - 4191023b.ogg" to remind me how many bytes are in the file while still keeping it in order in the directory.

- Run one of those 4MB sound tags through tool at quality 0.9 and then open the resulting tag in Guerilla and check the option at the top to split it into permutations. Run the same tool command, but this time at quality 1.0. Now you have the .sound tag you'll be using. Open it up in Guerilla and you should see about 17 permutations.

- Set the number of permutations to the number of .ogg sound files you will be using. In my case, I'm using 4 .ogg sound files, so first I scroll down to the last item in the Permutations list, then I delete the permutations one at a time until there are only 4 remaining (the "next permutation index" for the fourth item will read "4"). On the last permutation (the fourth one, for me) I set the "next permutation index" to -1 instead of leaving it at 4, since there are no additional permutations thereafter.

- Save the .sound tag and open it in a hex editor. Also open each of your .ogg sound files.

- At the top of the .sound tag file, you will see in ASCII text the name of your sound file listed the number of times that is the number of .ogg files you saved. Select the first name and extend the selection to include 64 (0x40) bytes. Now instead select the following four bytes right after that. In Big Endian (reading with the larger values on the left), which is how the data is stored in this HEK .sound tag at this point, these four bytes should be a 32 bit integer representing the "samples" value for the first permutation, which is the number of bytes the game will expect to read from that .ogg sound file reference.

- Open the first .ogg sound file in the hex editor and select all the hex data. If you didn't know how large the file is in bytes, read the decimal version of the display indicating how many bytes you are selecting when you select all the contents of the file. So now you know how large the first .ogg file is. Go back to the .sound tag and type or paste the size of the first .ogg file into that 32 bit integer location. For example, if the .ogg file is 4191815 bytes, paste the hex equivalent of this (3FF647) into those four bytes. If you're using a decent hex editor, it should be easy to do this. Make sure you're not shifting the hex data around when you modify these values, just overwrite the four bytes... don't extend the four bytes into 5 bytes or shorten it into 3 bytes. Actually, the size will only be up to 400000 in hex, so you'll only be using three bytes of the four bytes here (ie. 00 40 00 00 would be equal to 400000, and in my case, 00 3F F6 47).

- Do the same thing with all the other .ogg files, pasting their file sizes as 32 bit integer values in the four bytes after each permutation's name string, which is 64 (0x40) bytes long. Now you should have the lengths of each "sample" value for your .ogg files set up properly, and since the values should all be 4194304 and less, the game engine won't crash when reading it.

- Now we copy/paste the actual .ogg sound file data into each permutation. What you do here is search inside your .sound tag for the .ogg header string, which starts with "OggS". But don't actually search for that string, because you'll get more results than you want. Depending upon your sound editor, you would be using a different version of the .ogg header than Tool used to compile the existing .ogg files into this HEK .sound tag. What you want to do is copy/paste your ENTIRE .ogg sound files, including their headers, into the .sound tag, overwriting the existing .ogg sound headers and sound data each time. I'll take you through the first one: After the list of permutations that we see at the top of the .sound tag, look for the first instance of "OggS", whose offset should be at around 124 bytes starting from the last permutation's ASCII text string name. I don't know about you, but I don't like juggling numbers very much, so I didn't have you copy-paste the previous "sample" integer sizes from before. Instead, I'd rather open up the sound tag in Guerilla and copy the value from the bottom of the tag. So open up the sound tag in Guerilla and copy the "samples" number of the first permutation. Switch back to the .sound tag in the hex editor and select that exact quantity of bytes -- including the .ogg header -- starting from that first instance of "OggS". Now copy-paste the entire data of the first .ogg sound file over those bytes. Be sure you are in the proper editing mode so that you only delete those bytes and paste the new bytes in place of them... typically, this means you are in "insertion" mode, rather than "overwrite" mode. So do that, and don't screw it up like a newbie ;P By the way, the end of that section you deleted should be butted right up against another string starting with "OggS", which just so happens to be our next permutation's sound data! So go ahead and copy-paste your next .ogg file's sound data, overwriting the next chunk of data whose byte length you obtained from the "samples" field for that permutation in Guerilla. (Make sure you are only dealing with the hex data, not the ASCII strings. You don't want to copy-paste ASCII text into the hex area or vice-versa.) Your last existing permutation should take you straight to the end of the HEK .sound tag hex data.

- Repeat the process as necessary. When finished, save the resulting file as another HEK .sound tag file (with the extension ".sound") and open it up in Guerilla to see if it worked!

Upon building this tag into a map file, I had the game play about the first 5 seconds of each permutation, one after the other, in a loop (because it was used in a sound_looping tag). Clearly, something else needs to be changed...

If we uncheck "split long sound into permutations", then the sound restarts at that breakpoint with the first permutation repeating from the beginning after about 5 seconds. If we change the permutation count value, the permutations are oddly selected, since the "next permutation index" is not set to -1 for each permutation.

I think the values that come 8 bytes before each permutation's 32 bit integer "sample" number in the hex data are what need to be changed. This value is actually an integer in Little Endian (highest digits last) that represents the size of the .wav file that was imported into this permutation as an .ogg. Wandering in the other direction, 16 bytes after this value is a float value in Big Endian that appears to be the compression ratio difference between the .wav file and its resulting compressed .ogg file.

Example: (Related information for each permutation separated by "|")

with 4 permutations:
name "1" | "2" | "3" | "4"
skip fraction 0
gain 1
compression ogg
next permutation index -1
size of .wav sound data compressed for this permutation (little endian) 15,610,164
samples (big endian) 3,487,897
mouth data 0
subtitle data 0
(?) float (big endian) 2.00586 | 2.00983 | 2.00012 | 2.00409
(?) integer (little endian) 7,063,416 -> same
(?) integer (little endian) (total size as single permutation?) 3,016,376 | 3,016,208 | 3,016,304 | 3,016,472
(?) integer (little endian) 7,063,432 -> same
(?) integer (little endian) 3,016,424 | 3,016,256 | 3,016,888 | 3,016,520
(?) integer (little endian) 7,063,448 -> same

with 1 permutation:

(will update with findings later)
Either you are groping for answers, or you are asking God and listening to Jesus.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 49 guests