mopafo3971
Member
Fix for audio corruption for DOA3 emulated in CXBX-R:
Edit2: reverted the fix. It was rushed. Somehow a file still remained corrupted with that fix.
Python:
#-------------------------------------------------------------------------------
# no more corrupted sound in doa3 in CXBX-R emulator
# will fix doa3 wva loop_start in 'loadfile.afs' to the nearest sound chunk begining
#-------------------------------------------------------------------------------
loadfile_afs_path = r"C:\doa3\loadfile.afs"
read_only = 0
import os, struct
if not os.path.isfile(loadfile_afs_path):
print(loadfile_afs_path, 'is not found. Set "loadfile_afs_path=" to the location of doa3 "loadfile.afs"!!!')
else:
with open(loadfile_afs_path, 'rb+') as f:
afsmagic, afscount = struct.unpack('<4sL', f.read(8))
if afsmagic != b'AFS\x00':
print(loadfile_afs_path,'is not an AFS archive!!!')
else:
afsrecords = [struct.unpack('<LL', f.read(8)) for i in range(afscount)] #afs_offset and max_size
f.seek(0x80000-8)
info_block_offset, info_block_size = struct.unpack('<LL', f.read(8))
f.seek(info_block_offset)
info_records = [struct.unpack('<32sLHHHHL', f.read(0x30)) for i in range(afscount)]
for i in range(afscount):
afsoffset, max_size = afsrecords[i]
name, u1, w2, w3, w4, w5, length = info_records[i]
name = name.decode('ascii').rstrip('\x00')
if name[-4:] == '.wva':
f.seek(afsoffset)
count = struct.unpack('<L', f.read(4))[0]
offsets = [struct.unpack('<L', f.read(4))[0] for i in range(count)]
for j in range(count):
offset = offsets[j]
if offset:
f.seek(offset+afsoffset)
size = struct.unpack('<L', f.read(4))[0]
head = f.read(0x14)
loop_a, loop_b = struct.unpack('<LL',f.read(8)) #LoopStart=(dwLoopStart*wconst4)/8 // LoopLength=(dwLoopLength*wconst4)/8-LoopStart
format_type69, audio_channels, audio_sample_rate, bitrate_nominal, audio_chunk_size, wconst4, wconst2, wconst40 = struct.unpack('<HHLLHHHH', head)
if loop_a or loop_b:
audio_chunk_size = audio_chunk_size * 2
nearest_left = loop_a - (loop_a%audio_chunk_size)
nearest_right = loop_a + (audio_chunk_size-(loop_a%audio_chunk_size))
nearest = nearest_left if (nearest_right - loop_a) > (loop_a - nearest_left) else nearest_right
print("loop_a_fix =%5x "%nearest, "loop_a =%5x "%loop_a, "loop_b =%5x "%loop_b, "audio_length =%5x "%size, "%s_[%d].wva"%(name[:-4],j))
if not read_only:
f.seek(offset+afsoffset+0x18) #offset of loop_a value
f.write(struct.pack('<L', nearest)) #write in place of loop_a offset, the offset of the begining of the nearest audio_chunk
Edit2: reverted the fix. It was rushed. Somehow a file still remained corrupted with that fix.
Code:
script output on the first pass: (you should run the script only once)
loop_a_fix = 168 loop_a = 180 loop_b = 2b00 audio_length = 1854 env_cas_[0].wva
loop_a_fix = 1560 loop_a = 1580 loop_b = cf80 audio_length = 74b8 env_hil_[1].wva
loop_a_fix = 1560 loop_a = 1580 loop_b = cf80 audio_length = 74b8 env_hil_[3].wva
loop_a_fix = e10 loop_a = e00 loop_b = 8e40 audio_length = 504c env_cav_[2].wva
loop_a_fix = 5df0 loop_a = 5e00 loop_b =19a40 audio_length = e6c4 env_bea_[0].wva
loop_a_fix = e10 loop_a = e00 loop_b = 8e40 audio_length = 504c env_jcs_[1].wva
loop_a_fix = 1878 loop_a = 1880 loop_b = ab80 audio_length = 609c env_dz2_[5].wva
loop_a_fix = 20e8 loop_a = 2100 loop_b = a000 audio_length = 5a90 env_dz2_[6].wva
loop_a_fix = ee8 loop_a = f00 loop_b = f4c0 audio_length = 89ac env_oct_[3].wva
loop_a_fix = 360 loop_a = 340 loop_b = 5bc0 audio_length = 33c0 env_snw_[1].wva
loop_a_fix = 14d0 loop_a = 14c0 loop_b = c580 audio_length = 6f18 env_snw_[2].wva
loop_a_fix = 1170 loop_a = 1180 loop_b =18c00 audio_length = df08 env_snw_[3].wva
loop_a_fix = 4e30 loop_a = 4e40 loop_b =33f00 audio_length =1d3b8 env_bos_[0].wva
loop_a_fix = c450 loop_a = c440 loop_b =18a80 audio_length = de54 ay_01_[8].wva
loop_a_fix = 5df0 loop_a = 5e00 loop_b =19a40 audio_length = e6c4 ba_02_[10].wva
loop_a_fix = 9d80 loop_a = 9d80 loop_b =13b80 audio_length = b1e4 ay_02_[10].wva
loop_a_fix = 3e28 loop_a = 3e40 loop_b =11480 audio_length = 9bd0 ay_02_[11].wva
loop_a_fix = c450 loop_a = c440 loop_b =18a80 audio_length = de54 ay_02_[12].wva
loop_a_fix = 2718 loop_a = 2700 loop_b =25640 audio_length =15138 ni_02_[4].wva
loop_a_fix = 5d60 loop_a = 5d40 loop_b = e4c0 audio_length = 80d0 km_01_[4].wva
loop_a_fix = 7740 loop_a = 7740 loop_b = bf80 audio_length = 6bb8 su_03_[4].wva
loop_a_fix = 5f58 loop_a = 5f40 loop_b = 8500 audio_length = 4ad0 su_03_[5].wva
loop_a_fix = 4b60 loop_a = 4b40 loop_b = 8e80 audio_length = 5028 su_03_[6].wva
loop_a_fix = 6ff0 loop_a = 7000 loop_b =16940 audio_length = cb58 su_03_[7].wva
loop_a_fix = 3e28 loop_a = 3e40 loop_b =11480 audio_length = 9bd0 bn_01_[2].wva
script output on the second pass:
loop_a_fix = 168 loop_a = 168 loop_b = 2b00 audio_length = 1854 env_cas_[0].wva
loop_a_fix = 1560 loop_a = 1560 loop_b = cf80 audio_length = 74b8 env_hil_[1].wva
loop_a_fix = 1560 loop_a = 1560 loop_b = cf80 audio_length = 74b8 env_hil_[3].wva
loop_a_fix = e10 loop_a = e10 loop_b = 8e40 audio_length = 504c env_cav_[2].wva
loop_a_fix = 5df0 loop_a = 5df0 loop_b =19a40 audio_length = e6c4 env_bea_[0].wva
loop_a_fix = e10 loop_a = e10 loop_b = 8e40 audio_length = 504c env_jcs_[1].wva
loop_a_fix = 1878 loop_a = 1878 loop_b = ab80 audio_length = 609c env_dz2_[5].wva
loop_a_fix = 20e8 loop_a = 20e8 loop_b = a000 audio_length = 5a90 env_dz2_[6].wva
loop_a_fix = ee8 loop_a = ee8 loop_b = f4c0 audio_length = 89ac env_oct_[3].wva
loop_a_fix = 360 loop_a = 360 loop_b = 5bc0 audio_length = 33c0 env_snw_[1].wva
loop_a_fix = 14d0 loop_a = 14d0 loop_b = c580 audio_length = 6f18 env_snw_[2].wva
loop_a_fix = 1170 loop_a = 1170 loop_b =18c00 audio_length = df08 env_snw_[3].wva
loop_a_fix = 4e30 loop_a = 4e30 loop_b =33f00 audio_length =1d3b8 env_bos_[0].wva
loop_a_fix = c450 loop_a = c450 loop_b =18a80 audio_length = de54 ay_01_[8].wva
loop_a_fix = 5df0 loop_a = 5df0 loop_b =19a40 audio_length = e6c4 ba_02_[10].wva
loop_a_fix = 9d80 loop_a = 9d80 loop_b =13b80 audio_length = b1e4 ay_02_[10].wva
loop_a_fix = 3e28 loop_a = 3e28 loop_b =11480 audio_length = 9bd0 ay_02_[11].wva
loop_a_fix = c450 loop_a = c450 loop_b =18a80 audio_length = de54 ay_02_[12].wva
loop_a_fix = 2718 loop_a = 2718 loop_b =25640 audio_length =15138 ni_02_[4].wva
loop_a_fix = 5d60 loop_a = 5d60 loop_b = e4c0 audio_length = 80d0 km_01_[4].wva
loop_a_fix = 7740 loop_a = 7740 loop_b = bf80 audio_length = 6bb8 su_03_[4].wva
loop_a_fix = 5f58 loop_a = 5f58 loop_b = 8500 audio_length = 4ad0 su_03_[5].wva
loop_a_fix = 4b60 loop_a = 4b60 loop_b = 8e80 audio_length = 5028 su_03_[6].wva
loop_a_fix = 6ff0 loop_a = 6ff0 loop_b =16940 audio_length = cb58 su_03_[7].wva
loop_a_fix = 3e28 loop_a = 3e28 loop_b =11480 audio_length = 9bd0 bn_01_[2].wva
The sound loops will be the same as in cxbx, but no worry, the beginning of the loop is shifted like for a fraction of a second, that's so insignificant that you won't be able to tell the difference.would that then affect the loadfile.afs when played on an OG xbox or in XEMU?
Last edited: