Jump to content

Sound replacement possible?


TRekNexus

Recommended Posts

Hello everybody!

 

So I've been wanting to replace some music files within XCom EU/EW for some time since much of the original music in there frankly bugs the crap out of me. I'd *really* like something more atmospheric and suspense-building than the current techno-action we're stuck with. But before I try to wrap my head around XCom modding I wanted to check with you guys if it's even possible to do sound file replacements with the current tools available?

 

EDIT: Even swapping sound files for others would help a lot. Replacing the action tracks with some of the ambient ones would go a long way.

Edited by TRekNexus
Link to comment
Share on other sites

  • Replies 199
  • Created
  • Last Reply

Top Posters In This Topic

So far I don't think anyone has successfully replaced any sound files in XCOM. Things that have been done that indicate we're getting close :

 

  • Users have extracted sound files from the packages (which are internally stored in ogg format, apparently)
  • I've replaced some textures (internally stored in DXT1 format) with other textures
  • I've worked out how to add new textures by cooking a new package containing textures -- currently this is only the inventory and weapon panel UI texture data, not 3D model textures

 

In terms of adding/replacing sounds there are two possibilities that occur to me :

  1. Directly swapping out the hex of the sound file, which will likely involve resizing the upk
  2. Cooking a new package file with the new sound file(s), and adjusting the config data / unrealscript to play the new sounds

Unfortunately I have nothing practical working at this point. I'm not even sure if anyone has replicated my use of the September 2011 UDK for creating XCOM-compatible package files.

Link to comment
Share on other sites

Hex editing and resizing the upk sounds like something beyond my feeble technical talents right now. Bundling sound files into a new upk on the other hand, I'll give it a go. Time to look at the wiki. Thanks for the reply :)

Link to comment
Share on other sites

  • 1 month later...

Sorry for the thread necromancy, but I've just successfully patched in a custom sound file. This is for a sound effect, not music, but the steps are likely similar. I couldn't see any other recent posts that described this so if this isn't yet well-known, I'll post more detailed steps and keep working on it. I still need to experiment more with how this works because there are still a lot of unkowns to me, being an xcom modding newb. Hopefully someone else will be able to repro this too. Here are the steps I took:

 

 

 

  • Used audacity to create a simple replacement sound. Use 22050Hz 16-bit PCM for the format. I generated a short sample with the Generate->Chirp option, and used the same length as the target sound I was going to replace (about 1.6 seconds). Export it as an ogg vorbis file.
  • Find a target sound to replace. I used FemaleVoice6_French_Bank11.SF06LootSpotted07. Since I didn't want to muck around with resizing the upk I made sure to find a sound that was smaller in data size (duration and other settings in the cue and soundwave entries don't seem to be required to match the new file, but it will probably impact timing if you don't change em). Next steps will be to properly resize the upk so the new sound size won't be constrained.
  • Decompress the voice bank found in XEW\XComGame\CookedPCConsole\Voice. e.g. decompress FemaleVoice6_French_Bank11_SF.upk.
  • Open the decompressed file in UE explorer and find the target soundnodewave entry in the object list. View the buffer and note the offset (in my case, 0x47bfe). Also note the size (in my case 10486 = 0x28F6)
  • With a hex editor, paste the ogg you generated into the decompressed UE at the offset found + 0x9C bytes. This is the start of the audio data, and should be the bytes 0x4F 0x67 0x67 0x53 (OggS). Make sure you overwrite, don't insert the bytes and change the file size.
  • Now the more complicated bit. Because the new file is smaller, you have junk data at the end of the entry from the old sound. This needs to be fixed up, likely so the engine's upk parser can find the next entry. If you look at any other sound entry, after the ogg data there is 0x30 bytes of stuff before the start of the next object. (Or this is some upk structure header/footer for the object, I don't know much about the details of the upk format so I'm just guessing). The important thing is the format: 3 lines of 16 bytes, where each line is 12 bytes of 00s followed by 4 bytes that are the absolute position in the file of the byte immediately following those 4 bytes. After these 3 lines, the next object begins with 0xFF 0xFF 0xFF 0xFF. I'm going to do some more experimenting because it looks like the first two lines don't do much, it's the 3rd (or subsequent) ones that matter. So: in my example, the last byte of ogg data for my particular data file was at position 0x492D6. So the next byte is 0x492D7 So: 12 bytes of 0s, then 4 bytes for the address of the byte following those 16 bytes: 0x492E7 (byte-swapped: 0xE7 0x92 0x04 0x00). 12 more bytes of 0, then the offset 0x492F7. Then twelve more bytes and we can just give it the offset of the start of the next entry. Recall it started at 0x47BFE and is 0x28F6 bytes long, so the next one starts at 0x4A4F4. That's the address to put in the end of the third line: 0xF4 0xA4 0x04. When I did this I actually zeroed out the whole block of bytes from the end of my ogg to the start of the next object, but I don't think that's required. With a proper resized upk you'd just need the 0x30 bytes without any wasted space.
  • Save the file and close UE explorer, then load up the game. UE explorer appears to hold the file open and the engine won't load it. Make sure you're in a mission, then open the console and play the sound "PlaySoundWave FemaleVoice6_French_Bank11.SF06LootSpotted07". You should hear the chirp. In testing, it looks like you need to actually have a soldier with that sound bank set in their customization or it won't load the sound. I also still need to verify it actually plays correctly when the sound is played normally, but I suspect it will. I should've chosen something like an overwatch sound so I can quickly trigger it. Sigh.

 

 

Link to comment
Share on other sites

Congrats. Nice work on a new FIRST! Unless you object, I'm going to add it to the "Sound Files" wiki article (with credit to you).

 

You should look at wghost81's UPK Format document to understand the 0x30 bytes of "stuff" after the OGG data, and how to resize an object such as a sound file.

 

To properly resize an object, you have to edit its export table entry. Patcher[GUI] will work with any packages, not just scripts and maps, as the structure is the same. Use BEFORE_HEX/AFTER_HEX to automatically resize an object.

 

(PatcherGUI and the UPK Format document are separate downloads from the UPKUtils package on that download page.)

 

Also, don't know if you have been following the "Scripting with UDK" thread, but they have been making some great progress there as well. With wghost81's mutator config, it should now be possible to add new sound files instead of just replacing existing ones. "Just" (famous last words) needs someone interested in trying it out.

 

Edit: Added the tutorial to the "Sound Files" article. However, I have to say while I did my best to clean it up, your specific case examples left me (without having the file open in UE/HxD in front of me) confused as to which hex values belong to the object entry for your file and which for the linked chain entry for the next object. Please look over wghost's UPK Format document and then try to clear that up. (You can make those edits directly to the article or just post them here and I'll do it for you.)

 

-Dubious-

Edited by dubiousintent
Link to comment
Share on other sites

Thanks for the links. I'll look over the documents and edit the article when I have a better understanding of it. Also I've discovered while experimenting with replacing a music file that when overwriting an existing entry with a shorter one, zeroing out the whole rest of the entry seems to be required. That will probably also make more sense to me after I read up more on the format.

Link to comment
Share on other sites

I've read the format documents, and I now understand more of the sound object format, but not all of it. I've also now successfully resized the memorial music upk to replace it with a much longer and larger track using PatchUPK. This took a little manual post-processing of the upk to get it to work, though. I need to take a look at what PatchUPK is doing and see what's going wrong, it appears to be putting the new entry under a different name in the export table rather than updating the existing one, but this could be pilot error. The sound object also contains absolute file offsets that PatchUPK doesn't appear to be aware of that need to be updated after the new object is injected into the UPK.

 

More details on the SoundNodeWave object structure:

 

 

 

The structure of a sound object seems to be "USoundNodeWave : UObject". The object begins with the ObjectRef and then a default property array with the following elements:

 

Duration: UFloatProperty

NumChannels: IntProperty

SampleRate: IntProperty

RawPCMDataSize: IntProperty

 

None of that is new, UE explorer will decode that successfully. As LiQUiD911 mentioned in the music thread, the duration and rawpcmdatasize don't appear to be used. It's possible the others are not as well, possibly ignored because the same data are contained in the ogg.

 

After the property array is the following data:

 

12 bytes of 00, then 4 bytes for the absolute offset of the next position in the file

4 bytes of 00

4 bytes - length of the ogg data

4 bytes - length of the ogg data

4 bytes - absolute offset of the next position in the file

variable length - ogg data

12 bytes of 0, 4 bytes of the absolute offset of the next position in the file

12 bytes of 0, 4 bytes of the absolute offset of the next position in the file

12 bytes of 0, 4 bytes of the absolute offset of the next position in the file

 

Then the next object begins. I don't know what to make of these 16 byte chunks that appear 5 times in the object surrounding the ogg data. Most of them are all 0s, except the one just before the ogg data that encodes the length of the audio data (twice). I couldn't find anything that looked similar in the UPK format document. The only thing that looked sort of similar was FCompressedChunk, but that doesn't seem to be it. Every sound file I've looked at has exactly the same structure, with all the seemingly "empty" entries with the 12 00s. These are interesting because instead of referencing table entries, they are absolute offsets into the file. Which means that unless they are some standard UPK data structure that I missed in the doc, utilities like PatchUPK need to be aware of them to properly patch in the new addresses when moving/resizing sounds. I think I'll try to add a feature to PatchUPK so that it understands SoundNodeWave files natively and can do this and submit it back to the author. I'd like to know what these are, or at least if they are something new or an already known UPK structure.

 

Also: When just overwriting ogg data with a smaller file with a hex editor, it does appear that you need to patch up the 30 hex bytes at the end of the new ogg data and also zero out all remaining bytes from the old file. Now that I can use PatchUPK to avoid size limitations I am not resorting to this anymore, though.

 

 

 

Link to comment
Share on other sites

tracktwo, when you resize an export object with PatchUPK, it doesn't delete an existing serialized data for that object, but appends a new serialized data to the end of a package and updates export table entry with new offset and size. It is useful for script packages, which consist of a thousands of objects. For sound packages with one sound object only (?) it will lead to unnecessary package bloating, but it won't affect it's functionality.

 

But, if sound object uses absolute file offset to determine data location, resizing object data by moving it can cause a problems. Although, due to varying structure of upk objects, they don't usually use absolute offsets.

 

Can you post an example of a modfile you're using?

Edited by wghost81
Link to comment
Share on other sites

Here's the modfile I used:

UPK_FILE=HQSound_MemorialMusic_SF.upk

OBJECT=SoundMissionControlMusic.MemorialScreen3

MODDED_FILE=SoundMissionControlMusic.MemorialScreen3:AUTO

I'm not sure if the OBJECT field is redundant or inferred from the MODDED_FILE filename. After I run this and open the file in UE explorer the object list appears unchanged, but there is a new entry in the export table. The old SoundNodeWave entry "MemorialScreen3" is still there, pointing to the original version. The new entry is a package called "SoundMissionControlMusic" and has the new offset and size directly inside it. If I manually patch the old export entry with the new offset and size, it works. Well, it works after I also go in with a hex editor and update the absolute offsets within the sound object to the new addresses in the modded file, that is. Am I using incorrect names here?

 

Regarding the absolute offsets, I'm still not sure exactly what those data structures in the SoundNodeWave object are, but they sure look and act like absolute file offsets. It's interesting if they aren't used elsewhere in the format, though.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...