[script] Call of Duty: Black Ops/Modern Warfare 3 (Wii) dsp to GENH

Codecs, formats, encoding/decoding of game audio, video and music
AlphaTwentyThree
Posts: 909
Joined: Sat Aug 09, 2014 11:21 am

[script] Call of Duty: Black Ops/Modern Warfare 3 (Wii) dsp to GENH

Post by AlphaTwentyThree »

Hi there!
I've taken my time today to write a script that lets me convert the dsp files from CoD:BO to something actually playable as this particular header doesn't seem to be supported by vgmstream. So I wrote a script that deinterleaves the stream (those have an interleave of 0x8000 if stereo), reinterleaves it with INTSIZE 8 and slabs on a GENH with the proper variables and coefficients. The script is a little bit slow but if you process the whole batch it's ok.
This script also serves as a template for other re-interleave dsp scripts. One thing to note is that the dsp files from CoD:BO have an incomplete last block so it has to be filled with zero in order to create a properly interleaved file.
The dsp files were created by this script: viewtopic.php?f=9&t=2513
Have fun with the script!

Code: Select all

# converts the dsp files from Call of Duty: Black Ops (Wii)
# to playable GENH streams.
# written by AlphaTwentyThree of Zenhax
# script ver. 1.01
# script for QuickBMS http://quickbms.aluigi.org

set HEADER 0xa0 # = data start
set INTSIZE 0x4000 # interleave of source file
set LAYERS 2 # only works for mono and stereo files
set INTERLEAVE 8 # interleave of generated GENH
set CH 2
set OFF_COEFF1 0x1c
set OFF_COEFF2 0x58
set OFF_NOS 0x8
set OFF_FREQ 0xc
endian big
goto OFF_FREQ
get FREQ long
goto OFF_NOS
get NOS long
endian little

goto OFF_COEFF2
get TEST long
if TEST == 0 # mono
   set CH 1
   callfunction GENH 1
   get SIZE asize
   math SIZE -= HEADER
   append
   log MEMORY_FILE HEADER SIZE
   append
   callfunction wrapup 1
endif

set PRESERVE 0
set ADJUST 0
set COMPLETE_LAST_BLOCK 1
set BLOCKSIZE 0 # size of one complete block

if BLOCKSIZE == 0
   xmath BLOCKSIZE "INTSIZE * LAYERS"
endif
if INTSIZE == 0
   xmath INTSIZE "BLOCKSIZE / LAYERS"
endif

xmath WSIZE "BLOCKSIZE / LAYERS"
get FSIZE asize
xmath CYCLES "(FSIZE - HEADER) / BLOCKSIZE"

get FSIZE asize
xmath LASTBLOCK "(FSIZE - HEADER) % INTSIZE"
if LASTBLOCK != 0
   if COMPLETE_LAST_BLOCK == 1
      math CYCLES += 1
   endif
endif

callfunction deinterleave
   
startfunction deinterleave
   xmath PSIZE "CYCLES * WSIZE"
   putVarChr MEMORY_FILE2 PSIZE 0
   putVarChr MEMORY_FILE3 PSIZE 0
   
   for i = 1 <= LAYERS
      putVarChr MEMORY_FILE PSIZE 0
      log MEMORY_FILE 0 0
      
      xmath BIAS_A "(i - 1) * WSIZE" # bias at start
      xmath BIAS_B "BLOCKSIZE - BIAS_A - WSIZE" # bias at end
      
      goto HEADER
      for k = 1 <= CYCLES
         if k != CYCLES
            getDstring DUMMY BIAS_A
            getDstring WDATA WSIZE
            putDstring WDATA WSIZE MEMORY_FILE
            getDstring DUMMY BIAS_B
         else
            getDstring DUMMY BIAS_A
            if i != LAYERS
               getDstring WDATA WSIZE
               putDstring WDATA WSIZE MEMORY_FILE
               getDstring DUMMY LASTBLOCK
            else
               if COMPLETE_LAST_BLOCK == 1
                  if LASTBLOCK != 0
                     getDstring WDATA LASTBLOCK
                     putDstring WDATA LASTBLOCK MEMORY_FILE
                     get SIZE asize MEMORY_FILE
                     math SIZE x= INTSIZE
                     math SIZE -= 1
                     putVarChr MEMORY_FILE SIZE 0
                  else
                     getDstring WDATA WSIZE
                     putDstring WDATA WSIZE MEMORY_FILE
                     getDstring DUMMY LASTBLOCK
                  endif
               endif
            endif
         endif
      next k
      get SIZE asize MEMORY_FILE
      if i == 1
         log MEMORY_FILE2 0 SIZE MEMORY_FILE
      elif i == 2
         log MEMORY_FILE3 0 SIZE MEMORY_FILE
      endif
   next i
endfunction

xmath PSIZE "SIZE + SIZE + 0xc"
putVarChr MEMORY_FILE PSIZE 0
log MEMORY_FILE 0 0
callfunction GENH 1

startfunction GENH
   putVarChr MEMORY_FILE 0 0x484e4547 long # "GENH"
   putVarChr MEMORY_FILE 4 CH long # ch
   putVarChr MEMORY_FILE 8 INTERLEAVE long # interleave
   putVarChr MEMORY_FILE 0xc FREQ long
   putVarChr MEMORY_FILE 0x10 0xffffffff long
   putVarChr MEMORY_FILE 0x14 NOS long # number of samples
   putVarChr MEMORY_FILE 0x18 0xc long # ?
   putVarChr MEMORY_FILE 0x1c 0xc0 long # stream start
   putVarChr MEMORY_FILE 0x20 0xc0 long # stream start
   putVarChr MEMORY_FILE 0x24 0x80 long # coeff1
   putVarChr MEMORY_FILE 0x28 0xa0 long # coeff2
   putVarChr MEMORY_FILE 0x2c 1 long
   putVarChr MEMORY_FILE 0x34 0x80 long # coeff1
   putVarChr MEMORY_FILE 0x38 0xa0 long # coeff2
   putVarChr MEMORY_FILE 0x7f 0 byte
   append
   log MEMORY_FILE OFF_COEFF1 0x20
   log MEMORY_FILE OFF_COEFF2 0x20
   append
endfunction

get SIZE asize MEMORY_FILE2
get SIZE2 asize MEMORY_FILE3
xmath LOOPS "SIZE / INTERLEAVE"
set OFFSET 0
append
for i = 1 <= LOOPS
   log MEMORY_FILE OFFSET INTERLEAVE MEMORY_FILE2
   log MEMORY_FILE OFFSET INTERLEAVE MEMORY_FILE3
   math OFFSET += INTERLEAVE
next i
append
callfunction wrapup 1

startfunction wrapup
   get SIZE asize MEMORY_FILE
   get NAME basename
   string NAME += ".genh"
   log NAME 0 SIZE MEMORY_FILE
   cleanexit
endfunction
Last edited by AlphaTwentyThree on Wed May 25, 2016 6:53 pm, edited 2 times in total.
AlphaTwentyThree
Posts: 909
Joined: Sat Aug 09, 2014 11:21 am

Re: [script] Call of Duty: Black Ops/Modern Warfare 3 (Wii) dsp to GENH

Post by AlphaTwentyThree »

Vital information: To process the files from CoD: World at War, change the interleave from 8000 to 4000!
AlphaTwentyThree
Posts: 909
Joined: Sat Aug 09, 2014 11:21 am

Re: [script] Call of Duty: Black Ops/Modern Warfare 3 (Wii) dsp to GENH

Post by AlphaTwentyThree »

Just updated the script to 1.01. It produced an error when the last block was in fact complete. ;)