Important information: this site is currently scheduled to go offline indefinitely by end of the year.

Saints Row 2 XWB compressed wave

Get help on any and all audio formats, or chip in and help others!
Liandril
advanced
Posts: 55
Joined: Mon Aug 02, 2010 4:11 pm
Been thanked: 4 times

Re: Saints Row 2 XWB compressed wave

Post by Liandril »

Hi IdolNinja,

thanks for the files! So far, my tool just extracts .XWBs and provides info about .xsb/.xwb. Inserting a cue (see explanation below) into an .xsb is difficult, because .xsb uses (among other obstacles) a hash function...and I don't know, what this function looks like. But the good news is: extracting the Saint Row 2 .XWBs to .WAVs works (and therefor the subject/main question of this thread is solved :) ).

1. Extracting .XWBs containing xWMA (for .xwbs containing ADPCM or XMA use aluigis unxwb !)
As mentioned some postings above, my tool extracts .xwb files to valid .xwma files. You need xWMAEncode (part of Microsofts DirectX SDK or download it directly from here (last link, on the bottom of the page)) in order to convert xWMAs (there's almost no player for .xwma) to "normal" .wav files. Just copy my xactxtract.exe and the downloaded xWMAEncode.exe into the directory with the .xwb files and type (command line):
xactxtract.exe -x2 *.xwb
This tells xactxtract to extract and convert all .xwb files in the directory. To be more precisely, xactxtract will:
1. create a directory for each .xwb file (e.g. for "MUS 420.xwb" a directory "MUS 420" will be created)
2. extract all .xwma files from the .xwb to that directory
3. call xWMAEncode for each file, i.e. all .xwma files will be converted to .wavs
4. delete all .xwma files (because they are no longer needed)
So in the end you'll have a directory containing playable .wavs for each .xwb :-)
For the Saint Row 2 .xwbs, my tool will show a warning, because it wasn't written for this .xwb version, but you can just ignore this warning (unfortunately, the output messages of my tool are mostly in German, sorry).

Download link for XACTxtract

2. Thoughts & infos about inserting own wave files into Saint Row 2...
(I'll try to keep the explanations as short as possible, first the basics:)

An .xwb Wavebank is a collection of wavs (pcm, adpcm, xma, xWma). In Saint Row 2 (at least in your "MUS 420.xwb") only xWma is used.

The .xsb (Soundbanks) contains infos/commands, when and how to play the wavs. There are 4 types of such commands: events, tracks, sounds and cues:
A track contains a "link" to ONE wave and events. The simplest case is: the event "play" followed by a link to the wavebank (e.g. "MUS 420.xwb") and the wave number in the wavebank.
A sound contains one or more tracks and properties (volume, category...)
A cue contains one or more Sounds and properties (e.g.playing possibility for each sound, crossfading,...)

Usually, each cue has a cuename - so to speak the "interface" between game and .xsb files: the game calls the XACT engine with the cuename, the XACT engine looks up the .xsb files and plays the cue. In Saint Row 2, the cuename infos obviously were left out... this is strange, because it's more work for the developers. So some info, that usually is in the .xsb files, is now in the .xtbl tables you included. REALLY strange is, that there seem to be no "links" to the cues in the tables:
the audio_banks.xtbl just describes the connection between Sound/Wavebanks and Categories, whereas the music.xtbl consists of elements (<Music_Set>) containing info that are usually in the cues.
It seems to me that
EITHER the developers tried to avoid using the .xsb files and created their own way (.xtbl) to adress the .xwbs
OR the .xtbl tables are relicts of the production period, but then: how does the game address the .XSBs without cuenames?
In short: It's possible to create your own .xsb/.xwb, but I can't tell you, how the game adresses the soundbanks :-(
Last edited by Liandril on Tue Apr 12, 2016 6:38 pm, edited 1 time in total.
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

Liandril,

I did some testing and your tool works perfectly on all the xwbs we were having problems with like the radio commercials and music. :)
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

There seems to be one xwb that has a problem and gives an "Out of Memory" error. I've confirmed the error with two of the other modders who are using your new tool. I've uploaded it here if you would like to take a look at it:
http://finalack.com/Idol/wazza/SR2_CUTSCENES.xwb.rar

The rest of the xwb files have been confirmed extractable. :)

Also, if you're curious, the xtbl files do at least partially control the playback and cues instead of the xsb. I can change them and see/hear the results in-game. There also seems to be more instructions in the exe itself which looks to be that missing link for how the engine works with the banks.

EDIT:
Would you also please consider releasing the source? Thanks!
FordGT90Concept
advanced
Posts: 47
Joined: Thu Apr 15, 2010 7:16 am
Has thanked: 3 times
Been thanked: 13 times

Re: Saints Row 2 XWB compressed wave

Post by FordGT90Concept »

So I was basically trying to decompress an xWMA file?

I always take the hard way because it the most fun. XD
Liandril
advanced
Posts: 55
Joined: Mon Aug 02, 2010 4:11 pm
Been thanked: 4 times

Re: Saints Row 2 XWB compressed wave

Post by Liandril »

IdolNinja wrote:The rest of the xwb files have been confirmed extractable. :)
Ah, very good :)
And thanks for the "Out of Memory" bug report, too. I know, where the problem is..but I can't solve it. It's a bug with PAR::Packer (a perl module I'm using for building the executable). But I managed to extract SR2_CUTSCENES.xwb. Wow, this is the largest .xwb I've ever seen. And the extracted & converted .wav files need 4.5 GB! :eek:
IdolNinja wrote:Also, if you're curious, the xtbl files do at least partially control the playback and cues instead of the xsb. I can change them and see/hear the results in-game.
OK, that's interesting. I wonder, if the .xsb files are used at all. Maybe you could do a test (as I don't have the game):
I modified the "MUS 420.xsb" so that always - that means, whenever you turn to "Radio 420" (? I suppose, it represents a radio channel in the game) MUS 420_00009.wav is played. MUS 420_00009.wav is the first "non music" file in "MUS 420.xwb".. the one, where the Radio DJ says something like: 'Tis next artist's been spittin our tracks...' - so that's what you will (hopefully) hear when turning to Radio 420, IF the .xsb files are used (and IF I modified them correctly). If there is no difference in the game, then the .xsb files probably aren't used at all.
MUS 420.rar
FordGT90Concept wrote:I always take the hard way because it the most fun
Me too :D ... for almost one month I tried the 'hard way': building .wma files (=very difficult and NOT funny) from the (x)wma data in the .xwb. Then I stumbled across aluigis mention of xWMA... one hour later I had written a routine to produce a valid xWMA header.
You do not have the required permissions to view the files attached to this post.
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

Apparently the .xsb files are used. Your modified one for MUS 420 resulted in exactly what you thought it would. That same DJ track just repeats over and over on that station.
FordGT90Concept
advanced
Posts: 47
Joined: Thu Apr 15, 2010 7:16 am
Has thanked: 3 times
Been thanked: 13 times

Re: Saints Row 2 XWB compressed wave

Post by FordGT90Concept »

What vpp_pc file are those xtbl files in?
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

FordGT90Concept wrote:What vpp_pc file are those xtbl files in?
The xtbl files containing audio info are in common.vpp_pc.
Liandril
advanced
Posts: 55
Joined: Mon Aug 02, 2010 4:11 pm
Been thanked: 4 times

Re: Saints Row 2 XWB compressed wave

Post by Liandril »

IdolNinja wrote:Apparently the .xsb files are used. Your modified one for MUS 420 resulted in exactly what you thought it would. That same DJ track just repeats over and over on that station.
Over and over? OMG, I hope you didn't get an earache :D

Hmm... then the playback is controlled by the xtbl files AND the cues in the xsbs ...and the "link" between those two is missing. Sounds difficult. I think the easiest way to insert (well, rather replace) sounds into the game would be the following:
I could try to expand the program so that it replaces wavs in the Wavebanks (.xwb) with an option like this:
xactxtract -r "MUS 420.xwb" 5 mywav.wav
meaning: Wave Nr. 5 in the "MUS 420.xwb" is replaced by mywav.wav
Would this help in modding the game?
The problem is: this would take quite some time....and especially in the next 1-2 months I'll have VERY little time :(

Edit:
If you don't want to wait that long, you could try to create your own modified .xwb file:
1) unpack the .xwb
2) replace the .wavs you want to change with your own .wavs
3) download from Microsoft: DirectX SDK from Mar2008, because this one creates .xwb files of the same version used in Saints Row 2 (Tool version 44, file format version 42)
4) try to follow the instructions here and (more detailed) here
Problem with this way is, of course, that you have to include the WHOLE .xwb in your mod. If I succeed in adding the functionality to my script, then you only have to include xactxtract and the .wavs to your mod.
Last edited by Liandril on Tue Oct 19, 2010 2:02 am, edited 2 times in total.
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

It would help SR2 modding tremendously to be able to insert our own sound files. At the most basic beginning, we could begin importing our own custom music stations.

Would your planned tool also work on replacing adpcm and xma? I wasn't able to find the cell phone calls that happen in-game and I'm wondering if maybe they are in adpcm or wma format instead of wav and I just missed them when extracting/looking with unxwb a while back. The reason I'm wondering is that these phone calls usually give direction to the player during missions and would be my highest priority to get working for custom missions.

Ideally, I would like to be able to create and add my own sound banks, but that might not be doable with the missing links in the exe. So, the new missions could certainly just use existing banks with our own wav files inserted using your planned updated tool (if you have time :))

Also, sorry to hear about your busy schedule. Real life often gets in the way of fun projects like this. Any effort you could make on this would certainly be appreciated. :)

EDIT:
I'm looking through everything now to try and locate those cell phone calls.
FordGT90Concept
advanced
Posts: 47
Joined: Thu Apr 15, 2010 7:16 am
Has thanked: 3 times
Been thanked: 13 times

Re: Saints Row 2 XWB compressed wave

Post by FordGT90Concept »

I'd guess phone calls are somewhere in audio.vpp_pc. The Gen X radio station, for some reason, is in audio.vpp_pc instead of the music#.vpp_pc file.
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

Yeah, all the audio seems to be scattered. I'm wondering what bank they are in though. Here's what I've come up with so far:

AUDIO.VPP_PC contains:
* Ambients.xwb - background noise
* Animation.xwb and Animation Debug.xwb - sound fx
* All the vehicle xwb files for stuff like engine rev, horns, etc
* Movement.xwb and Movement Debug.xwb - Nothing extracted. I think they might be in adcpm format that you'll need unxwb for
* MUS GENX.xwb - The music and DJ spots from the GenX radio station
* Other inMemory.xwb and Other InMemory Debug.xwb - Misc sounds like end screen unlock sounds
* Other Streaming.xwb - Sound FX: Explosions, radio, static, fireworks, etc
* SR2_ACTIVITY_CUTSCENES - All activity cutscene audio
* Weapons.xwb and Weapons Debug.xwb - Weapon sounds

MUSIC1.VPP_PC contains:
* MUS K12.xwb - K12 electronica station dj spots and music
* MUS KLASSIC.xwb - Classical music station dj spots and music
* MUS KRHYME.xwb - Rap and hip hop station dj spots and music
* MUS KRUCH.xwb - Metal station dj spots and music

MUSIC2.VPP_PC contains:
* MUS 420.xwb - Reggae station dj spots and music
* MUS DISPATCH.xwb - police chatter
* MUS EZZZY.xwb - Easy listening station dj spots and music
* MUS FUNK .xwb - Funk station dj spots and music
* MUS MIX.xwb - 80s station dj spots and music
* MUS MUSIC.xwb - nothing (4kb file)
* MUS SHARED.xwb - All commercials and main menu pause music
* MUS UNDERGROUND - pirate radio dj spots and songs
* MUS WORLD - World music station dj spots and music

MUSIC3.VPP_PC contains:
* SR2_VOC_AF.xwb - Asian female npc random voices
* SR2_VOC_AM.xwb - Asian male npc random voices
* SR2_VOC_BF.xwb - Black female npc random voices
* SR2_VOC_BM.xwb - Black male npc random voices
* SR2_VOC_HF.xwb - Hispanic female npc random voices
* SR2_VOC_HM.xwb - Hispanic male npc random voices
* SR2_VOC_WF.xwb - White female npc random voices
* SR2_VOC_WM.xwb - White male npc random voices

MUSIC 4.VPP_PC contains:
* MUS_AMBIENT.xwb - store music, barbershop quartet, guitar player, etc
* SR2_CUTSCENES.xwb - "out of memory" error trying to extract
* SR2_VOC_SP.xwb - phone answering machine messages
Liandril
advanced
Posts: 55
Joined: Mon Aug 02, 2010 4:11 pm
Been thanked: 4 times

Re: Saints Row 2 XWB compressed wave

Post by Liandril »

IdolNinja wrote:Would your planned tool also work on replacing adpcm and xma? I wasn't able to find the cell phone calls that happen in-game and I'm wondering if maybe they are in adpcm or wma format instead of wav and I just missed them when extracting/looking with unxwb a while back.
Yes, replacing adpcm and xma should be possible. Unfortunately, my tool just extracts (x)WMA and PCM so far... I wanted to add extracting & converting for ADPCM, but didn't (and don't) have the time :( .BTW: If you want to have a detailed list with infos about the .xwbs, just type:
xactxtract.exe *.xwb >xwb-info.txt
and you'll get a text file with informations (type (wma,xma,adpcm,pcm), channels,...) for every wave in the wave banks. But when I look at your overview, then it will be a LONG text file :D
Other inMemory.xwb
seems like a good guess for the phone calls to me (waves that are used often are usually kept in an in-memory wave bank)
FordGT90Concept
advanced
Posts: 47
Joined: Thu Apr 15, 2010 7:16 am
Has thanked: 3 times
Been thanked: 13 times

Re: Saints Row 2 XWB compressed wave

Post by FordGT90Concept »

There really aren't that many phone calls in SR2 (compared to, say, GTA4). They could theoretically be in any XWB file. Ones that are part of a mission are probably in cutscenes. The rest are probably in VOC_SP.


I need to get xWMA support into my code so I can get that SR2_CUTSCENES extracted. Then my focus will shift to giving everything proper titles (from xtbl and, if necessary, xsb). I have no idea when I'll get around to it though.
IdolNinja
n00b
Posts: 14
Joined: Thu Oct 14, 2010 9:33 am

Re: Saints Row 2 XWB compressed wave

Post by IdolNinja »

FordGT90Concept wrote:There really aren't that many phone calls in SR2 (compared to, say, GTA4). They could theoretically be in any XWB file. Ones that are part of a mission are probably in cutscenes. The rest are probably in VOC_SP.

I need to get xWMA support into my code so I can get that SR2_CUTSCENES extracted. Then my focus will shift to giving everything proper titles (from xtbl and, if necessary, xsb). I have no idea when I'll get around to it though.
SR2_VOC_SP seems to be only the phone answering messages when you call a business using the phone numbers on signs scattered throughout the game. I'm still looking, but I think you may be on the right track with the SR2_CUTSCENES bank.

Now that I think about it, it is both incoming phone calls and also triggered in-game dialogue between characters that drives some of the missions, and these are probably all located together in the same bank. The lua scripts use a couple of different functions to trigger audio conversations:

Example of a function call in a mission script triggering dialogue between two characters.

Code: Select all

audio_play_conversation_in_vehicle(Tss03_gat_player_drive_conversation)
^This is the conversation between you and Gat in mission 3 (tss03.lua) where you drive to Redlight District to clean out the bums from under the church:

Example of a function call to play a triggered cell phone conversation:

Code: Select all

audio_play_conversation(VOICE_INTRO_PHONECALL, INCOMING_CALL)
^This is the phone call you receive from Shaundi at the start of the Brotherhood mission "The Enemy of my Enemy" (bh09.lua.) The VOICE_INTRO_PHONECALL global constant is assigned the following values:

Code: Select all

VOICE_INTRO_PHONECALL =
{{"BR09_INTRO_L1", CELLPHONE_CHARACTER, 0},
{"PLAYER_BR09_INTRO_L2", LOCAL_PLAYER, 0},
{"BR09_INTRO_L3", CELLPHONE_CHARACTER, .25},
 {"PLAYER_BR09_INTRO_L4", LOCAL_PLAYER, .25},
{"BR09_INTRO_L5", CELLPHONE_CHARACTER, .25},
{"PLAYER_BR09_INTRO_L6", LOCAL_PLAYER, .25},
{"BR09_INTRO_L7", CELLPHONE_CHARACTER, .25},
{"BR09_INTRO_L8", CELLPHONE_CHARACTER, 0},
{"PLAYER_BR09_INTRO_L9", LOCAL_PLAYER, .25},
{"BR09_INTRO_L10", CELLPHONE_CHARACTER, 0},
{"PLAYER_BR09_INTRO_L11", LOCAL_PLAYER, .25}}
The conversation is broken up this way so that any of the six chosen voices for the main character can be inserted into the conversation.

And here is the actual code of these two audio functions from ug_lib.lua:

Code: Select all

function audio_play_conversation( dialog_stream, cellphone_call )
   if ( cellphone_call == nil ) then
      cellphone_call = NOT_CALL
   end

   -- Open with the cellphone, if this is a cellphone
   -- conversation
   if ( cellphone_call == INCOMING_CALL ) then
      cellphone_animate_start_do()
      delay(0.5)
   elseif ( cellphone_call == OUTGOING_CALL ) then
      cellphone_animate_start_do()
      audio_play( CELLPHONE_OUTGOING, "foley", true )
      delay(0.5)
   end

    -- Build a list of characters that will be tested for readyness before any line in the
    -- conversation is played. We only use this list for NOT_CALL conversations.
    local character_list = {}
    if (cellphone_call == NOT_CALL) then
        for segment_index, dialog_segment in pairs( dialog_stream ) do
            local speaking_character = dialog_segment[DIALOG_STREAM_CHAR_NAME_INDEX]
            character_list[speaking_character] = speaking_character
        end
    end

    local function dialog_characters_ready()
        for i,character in pairs(character_list) do
            if (not character_is_ready_to_speak(character)) then
                return false
            end
        end
        return true
    end

   for segment_index, dialog_segment in pairs( dialog_stream ) do
      local audio_name = dialog_segment[DIALOG_STREAM_AUDIO_NAME_INDEX]
      local speaking_character = dialog_segment[DIALOG_STREAM_CHAR_NAME_INDEX]
      local delay_seconds = dialog_segment[DIALOG_STREAM_DELAY_SECONDS_INDEX]
        local anim_action = dialog_segment[DIALOG_STREAM_ANIM_ACTION_INDEX]

      -- Play the dialog stream for each character
      if ( cellphone_call == NOT_CALL ) then
         repeat
            thread_yield()
         until ( dialog_characters_ready() )

            local playing_action = (    (anim_action ~= nil)
                                                and (not character_is_in_vehicle(speaking_character)) 
                                                and (not character_is_combat_ready(speaking_character))
                                                and (not mesh_mover_wielding(speaking_character))
                                                and (vehicle_exit_check_done(speaking_character))
                                                and (vehicle_enter_check_done(speaking_character))
                                            )

            if (playing_action ) then    
                inv_item_equip(nil,speaking_character)
                action_play(speaking_character, anim_action, anim_action, true, 0.0, true)
            end
         audio_play_for_character( audio_name, speaking_character, "voice", false, true)
         delay( delay_seconds )
      -- Cellphone calls are different - just play the audio, don't use the character function unless
      -- it's the player.
      else
         -- For players, use audio_play_for_character so that the tag can be correctly translated
         if (    speaking_character ~= nil and character_is_player( speaking_character ) ) then
            -- Don't play lines unless and until the player is alive and in a state to deliver them
            repeat
               thread_yield()
            until ( character_is_ready_to_speak( speaking_character ) )
            audio_play_for_character( audio_name, speaking_character, "voice", false, true)
         elseif ( speaking_character == CELLPHONE_CHARACTER or speaking_character == nil ) then
            -- for_cutscene = false, blocking = true, variant = nil, voice_distance = nil, cellphone_line = true
            audio_play_for_character( audio_name, LOCAL_PLAYER, "voice", false, true, nil, nil, true )
         else
            script_assert( false, "You must specify CELLPHONE_CHARACTER as the speaking character ( or leave it at nil ) for the other side of a cellphone conversation." )
             audio_play( audio_name, "voice", true )
         end
         delay( delay_seconds )
      end
   end

   -- Close the cellphone, if this was a cellphone
   -- conversation
   if ( cellphone_call ~= NOT_CALL ) then
      cellphone_animate_stop_do()
   end
end

Code: Select all

-- Plays a conversation, which consists of a series of lines played by characters.
--
-- dialog_stream: A table containing dialog stream segments. Each segment has a speaking character name,
--                the name of the audio to play, and a delay in seconds after the audio is played for the
--                next one to be played. Conversation will not exectute unless the speaker is in a vehicle.
--
function audio_play_conversation_in_vehicle(dialog_stream)
    -- Loop through the table conversation...
   for segment_index, dialog_segment in pairs( dialog_stream ) do
      local audio_name = dialog_segment[DIALOG_STREAM_AUDIO_NAME_INDEX]
      local speaking_character = dialog_segment[DIALOG_STREAM_CHAR_NAME_INDEX]
      local delay_seconds = dialog_segment[DIALOG_STREAM_DELAY_SECONDS_INDEX]

        -- Conversation requires them to be in a vehicle
        while (not character_is_in_vehicle(speaking_character)) do
            thread_yield()
        end

      -- Play the dialog stream for each character
        audio_play_for_character(audio_name, speaking_character, "voice", false, true)
        delay(delay_seconds)
   end
end
And finally the global constants that these functions are using in ug_lib.lua:

Code: Select all

-- Constants use by the audio_play_conversation function.
-- These indices are the indices of each segment of a dialog stream
-- in the dialog stream table.
DIALOG_STREAM_AUDIO_NAME_INDEX = 1
DIALOG_STREAM_CHAR_NAME_INDEX = 2
DIALOG_STREAM_DELAY_SECONDS_INDEX = 3
DIALOG_STREAM_ANIM_ACTION_INDEX = 4

-- Types of conversations
NOT_CALL = 1
OUTGOING_CALL = 2
INCOMING_CALL = 3

-- Used in a dialog stream to denote that this is a character speaking through the cellphone
CELLPHONE_CHARACTER  = "cellphone character"

-- Ring sounds
CELLPHONE_INCOMING = "SYS_CELL_RING_1"
CELLPHONE_OUTGOING = "SYS_CELL_RING_OTHER"
Post Reply