Initial commit
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
ctypesLibFound = False
|
||||
structLibFound = False
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
except ImportError:
|
||||
print ("[Error] ctypes python library is required to be installed!")
|
||||
else:
|
||||
ctypesLibFound = True
|
||||
|
||||
if (not ctypesLibFound):
|
||||
sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
|
||||
sys.exit(1)
|
||||
|
||||
from struct import *
|
||||
|
||||
MY_MODULE_VERSION = "0.70"
|
||||
MY_MODULE_NAME = "audFileDecode"
|
||||
|
||||
aud_ima_index_adjust_table = [-1, -1, -1, -1, 2, 4, 6, 8]
|
||||
|
||||
# aud_ima_step_table has 89 entries
|
||||
aud_ima_step_table = [
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16,
|
||||
17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
41, 45, 50, 55, 60, 66, 73, 80, 88,
|
||||
97, 107, 118, 130, 143, 157, 173, 190, 209,
|
||||
230, 253, 279, 307, 337, 371, 408, 449, 494,
|
||||
544, 598, 658, 724, 796, 876, 963, 1060, 1166,
|
||||
1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749,
|
||||
3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
||||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
|
||||
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 ]
|
||||
|
||||
aud_ws_step_table2 = [-2, -1, 0, 1]
|
||||
|
||||
aud_ws_step_table4 = [
|
||||
-9, -8, -6, -5, -4, -3, -2, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 8
|
||||
]
|
||||
|
||||
# (const xccTHA::byte* audio_in, short* audio_out, int& index, int& sample, int cs_chunk)
|
||||
# index and sample are passed by reference and changed here...
|
||||
# audio_out is definitely affected!
|
||||
def aud_decode_ima_chunk(audioBufferIn, index, sample, cs_chunk):
|
||||
code = -1
|
||||
delta = -1
|
||||
step = -1
|
||||
|
||||
audioBufferOut = []
|
||||
#for i in range(0, len(audioBufferIn)):
|
||||
#if self.m_traceModeEnabled:
|
||||
# print ("[Debug] %d: %d" % (i, int(audioBufferIn[i])))
|
||||
|
||||
for sample_index in range (0, cs_chunk):
|
||||
try:
|
||||
code = audioBufferIn[sample_index >> 1]
|
||||
except:
|
||||
code = 0xa9 # dummy workaround because the c code is accessing an out of bounds index sometimes due to this shift here
|
||||
#print ("[Debug] cs_chunk: %d, sample_index: %d, shifted: %d, code: %d" % (cs_chunk, sample_index, sample_index >> 1, int(audioBufferIn[sample_index >> 1])))
|
||||
#print ("[Debug] cs_chunk: %s, sample_index: %s, shifted: %s, code: %s" % \
|
||||
# (''.join('{:04X}'.format(cs_chunk)), ''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(sample_index >> 1)), ''.join('{:04X}'.format(int(code)))))
|
||||
code = code >> 4 if (sample_index & 1) else code & 0xf
|
||||
step = aud_ima_step_table[index]
|
||||
delta = step >> 3
|
||||
if (code & 1):
|
||||
delta += step >> 2
|
||||
if (code & 2):
|
||||
delta += step >> 1
|
||||
if (code & 4):
|
||||
delta += step
|
||||
if (code & 8):
|
||||
sample -= delta
|
||||
if (sample < -32768):
|
||||
sample = -32768
|
||||
else:
|
||||
sample += delta
|
||||
if (sample > 32767):
|
||||
sample = 32767
|
||||
audioBufferOut.append(ctypes.c_short( sample ).value )
|
||||
#audioBufferOut.append(sample) # it's not different from above... ctypes.c_short( sample ).value
|
||||
#if self.m_traceModeEnabled:
|
||||
# print ("[Debug] audio_out[%s]: %s" % (''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(audioBufferOut[sample_index]))))
|
||||
index += aud_ima_index_adjust_table[code & 7]
|
||||
if (index < 0):
|
||||
index = 0
|
||||
elif (index > 88):
|
||||
index = 88
|
||||
## output buffer of shorts
|
||||
#binDataOut = struct.pack('h'*len(audioBufferOut), *audioBufferOut)
|
||||
#return (binDataOut, index, sample)
|
||||
return (audioBufferOut, index, sample)
|
||||
#
|
||||
#
|
||||
#
|
||||
def aud_decode_clip8(v):
|
||||
if (v < 0):
|
||||
return 0
|
||||
return 0xff if (v > 0xff) else v
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
# (const xccTHA::byte* r, char* w, int cb_s, int cb_d)
|
||||
def aud_decode_ws_chunk(inputChunkBuffer, cb_s, cb_d):
|
||||
outputChunkBuffer = []
|
||||
inpChBuffIter = 0
|
||||
outChBuffIter = 0
|
||||
|
||||
if (cb_s == cb_d):
|
||||
# outputChunkBuffer = inputChunkBuffer[:cb_s] # memcpy(w, r, cb_s) # FIX
|
||||
for mcp in range(0, cb_s):
|
||||
outputChunkBuffer.append(ctypes.c_char(inputChunkBuffer[inpChBuffIter + mcp]).value)
|
||||
#binDataOut = struct.pack('b'*len(outputChunkBuffer), *outputChunkBuffer)
|
||||
#return binDataOut
|
||||
return outputChunkBuffer
|
||||
|
||||
# const xccTHA::byte* s_end = inputChunkBuffer + cb_s; # FIX
|
||||
|
||||
s_end = inpChBuffIter + cb_s
|
||||
sample = ctypes.c_int(0x80).value #int sample
|
||||
while (inpChBuffIter < s_end):
|
||||
inpChBuffIter += 1
|
||||
count = ctypes.c_char(inputChunkBuffer[inpChBuffIter] & 0x3f).value # char count
|
||||
switchKey = inputChunkBuffer[inpChBuffIter - 1] >> 6 # inputChunkBuffer[-1] # b[-1] is *(b - 1)
|
||||
if switchKey == 0:
|
||||
count += 1
|
||||
for iter0 in range (count, 0, -1):
|
||||
inpChBuffIter += 1
|
||||
code = ctypes.c_int(inputChunkBuffer[inpChBuffIter]).value # int code
|
||||
# assignment in C was right to left so:
|
||||
# *(outputChunkBuffer++) = sample = clip8(sample + aud_ws_step_table2[code & 3])
|
||||
# is:
|
||||
# *(outputChunkBuffer++) = (sample = clip8(sample + aud_ws_step_table2[code & 3]))
|
||||
# which is equivalent to these two commands:
|
||||
# sample = clip8(sample + aud_ws_step_table2[code & 3])
|
||||
# *(outputChunkBuffer++) = sample
|
||||
# SO:
|
||||
sample = aud_decode_clip8(sample + aud_ws_step_table2[code & 3])
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
sample = aud_decode_clip8(sample + aud_ws_step_table2[code >> 2 & 3])
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
sample = aud_decode_clip8(sample + aud_ws_step_table2[code >> 4 & 3])
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
sample = aud_decode_clip8(sample + aud_ws_step_table2[code >> 6])
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
elif switchKey == 1:
|
||||
count += 1
|
||||
for iter0 in range (count, 0, -1):
|
||||
inpChBuffIter += 1
|
||||
code = inputChunkBuffer[inpChBuffIter] # int code
|
||||
sample += aud_ws_step_table4[code & 0xf]
|
||||
sample = aud_decode_clip8(sample)
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
sample += aud_ws_step_table4[code >> 4]
|
||||
sample = aud_decode_clip8(sample)
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
elif switchKey == 2:
|
||||
if (count & 0x20):
|
||||
#sample += static_cast<char>(count << 3) >> 3
|
||||
#*(outputChunkBuffer++) = sample
|
||||
sample += ((count & 0xFF) << 3 ) >> 3
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += 1
|
||||
else:
|
||||
count += 1
|
||||
# memcpy(outputChunkBuffer, inputChunkBuffer, count) # FIX
|
||||
for mcp in range(0, count):
|
||||
outputChunkBuffer.append(ctypes.c_char(inputChunkBuffer[inpChBuffIter + mcp]).value)
|
||||
inpChBuffIter += count
|
||||
outChBuffIter += count
|
||||
sample = inputChunkBuffer[inpChBuffIter - 1]
|
||||
else:
|
||||
count += 1
|
||||
# memset(outputChunkBuffer, sample, ++count)
|
||||
for mst in range(0, count):
|
||||
outputChunkBuffer.append(ctypes.c_char(sample).value)
|
||||
outChBuffIter += count;
|
||||
# output buffer of chars
|
||||
#binDataOut = struct.pack('b'*len(outputChunkBuffer), *outputChunkBuffer)
|
||||
#return binDataOut
|
||||
return outputChunkBuffer
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
class audFileDecode(object):
|
||||
m_index = -1
|
||||
m_sample = -1
|
||||
m_traceModeEnabled = False
|
||||
|
||||
# traceModeEnabled is bool to enable more printed debug messages
|
||||
def __init__(self, traceModeEnabled = True, index = 0, sample = 0):
|
||||
self.m_traceModeEnabled = traceModeEnabled
|
||||
self.m_index = index;
|
||||
self.m_sample = sample;
|
||||
return
|
||||
|
||||
def index(self):
|
||||
return self.m_index
|
||||
|
||||
# (const xccTHA::byte* audio_in, short* audio_out, int cs_chunk)
|
||||
def decode_chunk(self, audio_in, cs_chunk):
|
||||
(audio_Out, outIndex, outSample) = aud_decode_ima_chunk(audio_in, self.m_index, self.m_sample, cs_chunk)
|
||||
self.m_index = outIndex
|
||||
self.m_sample = outSample
|
||||
return audio_Out
|
||||
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
decodeInstance = audFileDecode()
|
||||
if decodeInstance.m_traceModeEnabled:
|
||||
print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
|
||||
else:
|
||||
#debug
|
||||
#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
pass
|
||||
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
osLibFound = False
|
||||
sysLibFound = False
|
||||
shutilLibFound = False
|
||||
waveLibFound = False
|
||||
ctypesLibFound = False
|
||||
structLibFound = False
|
||||
|
||||
try:
|
||||
import os
|
||||
except ImportError:
|
||||
print ("[Error] os python library is required to be installed!")
|
||||
else:
|
||||
osLibFound = True
|
||||
|
||||
try:
|
||||
import sys
|
||||
except ImportError:
|
||||
print ("[Error] sys python library is required to be installed!")
|
||||
else:
|
||||
sysLibFound = True
|
||||
|
||||
try:
|
||||
import wave
|
||||
except ImportError:
|
||||
print ("[Error] Wave python library is required to be installed!")
|
||||
else:
|
||||
waveLibFound = True
|
||||
|
||||
try:
|
||||
import struct
|
||||
except ImportError:
|
||||
print ("[Error] struct python library is required to be installed!")
|
||||
else:
|
||||
structLibFound = True
|
||||
|
||||
if (not osLibFound) \
|
||||
or (not sysLibFound) \
|
||||
or (not waveLibFound) \
|
||||
or (not structLibFound):
|
||||
sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
|
||||
sys.exit(1)
|
||||
|
||||
from struct import *
|
||||
from audFileDecode import *
|
||||
|
||||
MY_MODULE_VERSION = "0.90"
|
||||
MY_MODULE_NAME = "audFileLib"
|
||||
|
||||
#constants
|
||||
aud_chunk_id = 0x0000deaf
|
||||
SIZE_OF_AUD_HEADER_IN_BYTES = 12
|
||||
SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES = 8
|
||||
|
||||
class AudHeader(object):
|
||||
m_samplerate = 0 # Frequency // int16_t // TODO should be unsigned (?)
|
||||
m_size_in = 0 # Size of file (without header) // int32_t // TODO should be unsigned (?)
|
||||
m_size_out = 0 # Size of output data // int32_t // TODO should be unsigned (?)
|
||||
m_flags = 0 # bit 0=stereo, bit 1=16bit // int8_t
|
||||
m_compression = 0 # 1=WW compressed, 99=IMA ADPCM (0x63) // int8_t
|
||||
m_populated = False
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
|
||||
# The rest of the AUD files is divided in chunks.
|
||||
# These are usually 512 bytes long, except for the last one.
|
||||
class AudChunkHeader(object):
|
||||
m_ch_size_in = 0 # Size of compressed data // int16_t // TODO should be unsigned (?)
|
||||
m_ch_size_out = 0 # Size of output data // int16_t // TODO should be unsigned (?)
|
||||
m_ch_id = 0x0000FFFF # Always 0x0000DEAF // int32_t
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
class audFile(object):
|
||||
m_header = AudHeader()
|
||||
m_traceModeEnabled = False
|
||||
m_simpleAudioFileName = 'GENERIC.AUD'
|
||||
|
||||
# traceModeEnabled is bool to enable more printed debug messages
|
||||
def __init__(self, traceModeEnabled = True):
|
||||
self.m_simpleAudioFileName = 'GENERIC.AUD'
|
||||
self.m_traceModeEnabled = traceModeEnabled
|
||||
return
|
||||
|
||||
# std::fstream& fs, AudFileNS::pos_type startAudFilepos, AudFileNS::pos_type endAudFilepos, const std::string& filename
|
||||
def export_as_wav(self, audBytesBuff, filename):
|
||||
if (not self.header().m_populated):
|
||||
print ("[Error] file was not loaded properly (header info missing): " + filename)
|
||||
return 1
|
||||
|
||||
print ("[Info] Exporting to wav: " + filename)
|
||||
|
||||
cvirtualBinaryD = None
|
||||
if self.header().m_compression > 0:
|
||||
cvirtualBinaryD = self.decode(self.header().m_compression, audBytesBuff)
|
||||
elif self.header().m_flags == 2: # compression 0, 16bit stereo
|
||||
cbinaryDataOutLst = []
|
||||
offsInAudFile = SIZE_OF_AUD_HEADER_IN_BYTES
|
||||
for i in range(0, (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) // 2):
|
||||
if (self.m_traceModeEnabled):
|
||||
print ("[Trace] Reading bytes %d, %d" % (2*i, 2*i + 1))
|
||||
tmpTupleL = struct.unpack_from('B', audBytesBuff, offsInAudFile)
|
||||
offsInAudFile += 1
|
||||
tmpTupleH = struct.unpack_from('B', audBytesBuff, offsInAudFile)
|
||||
offsInAudFile += 1
|
||||
cbinaryDataOutLst.append(tmpTupleL[0])
|
||||
cbinaryDataOutLst.append(tmpTupleH[0])
|
||||
cvirtualBinaryD = struct.pack('B'*len(cbinaryDataOutLst), *cbinaryDataOutLst)
|
||||
|
||||
if (not cvirtualBinaryD and (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) > 0):
|
||||
print ("[Error] audio file could not be exported properly (0 data read): %s" % (filename))
|
||||
return 1
|
||||
elif (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) == 0:
|
||||
print ("[Warning] Creating empty wav file: %s" % (filename))
|
||||
|
||||
cb_sample = self.get_cb_sample()
|
||||
cs_remaining = self.get_c_samples()
|
||||
|
||||
waveWritFile = wave.open(filename, 'wb')
|
||||
waveWritFile.setnchannels(self.get_c_channels())
|
||||
waveWritFile.setsampwidth(cb_sample)
|
||||
waveWritFile.setframerate(self.get_samplerate())
|
||||
waveWritFile.setnframes(cs_remaining)
|
||||
#waveWritFile.setcomptype(None, '')
|
||||
waveWritFile.writeframesraw(cvirtualBinaryD)
|
||||
waveWritFile.close()
|
||||
# t_wav_header header;
|
||||
# memset(&header, 0, sizeof(t_wav_header));
|
||||
# header.file_header.id = wav_file_id; // # "RIFF"
|
||||
# header.file_header.size = sizeof(header) - sizeof(header.file_header) + (cs_remaining << 1);
|
||||
# header.form_type = wav_form_id; // # "WAVE"
|
||||
# header.format_chunk.header.id = wav_format_id; // #"fmt "
|
||||
# header.format_chunk.header.size = sizeof(header.format_chunk) - sizeof(header.format_chunk.header);
|
||||
# header.format_chunk.formattag = 1;
|
||||
# header.format_chunk.c_channels = 1;
|
||||
# header.format_chunk.samplerate = get_samplerate();
|
||||
# header.format_chunk.byterate = cb_sample * get_samplerate();
|
||||
# header.format_chunk.blockalign = cb_sample;
|
||||
# header.format_chunk.cbits_sample = cb_sample << 3;
|
||||
# header.data_chunk_header.id = wav_data_id; # "data"
|
||||
# header.data_chunk_header.size = cb_sample * cs_remaining;
|
||||
# error = f.write(&header, sizeof(t_wav_header));
|
||||
# return error ? error : f.write(d);
|
||||
return 0 # TODO fix
|
||||
|
||||
|
||||
def loadAudFile(self, audBytesBuff, maxLength, audFileName):
|
||||
self.m_simpleAudioFileName = audFileName
|
||||
offsInAudFile = 0
|
||||
tmpTuple = struct.unpack_from('H', audBytesBuff, offsInAudFile)
|
||||
self.header().m_samplerate = tmpTuple[0]
|
||||
offsInAudFile += 2
|
||||
tmpTuple = struct.unpack_from('I', audBytesBuff, offsInAudFile)
|
||||
self.header().m_size_in = tmpTuple[0]
|
||||
offsInAudFile += 4
|
||||
tmpTuple = struct.unpack_from('I', audBytesBuff, offsInAudFile)
|
||||
self.header().m_size_out = tmpTuple[0]
|
||||
offsInAudFile += 4
|
||||
tmpTuple = struct.unpack_from('B', audBytesBuff, offsInAudFile)
|
||||
self.header().m_flags = tmpTuple[0]
|
||||
offsInAudFile += 1
|
||||
tmpTuple = struct.unpack_from('B', audBytesBuff, offsInAudFile)
|
||||
self.header().m_compression = tmpTuple[0]
|
||||
offsInAudFile += 1
|
||||
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Debug] Sample rate: %d\tsizeIn: %d\tsizeOut: %d\tflags: %d\tcompression: %d" % (self.get_samplerate(), self.header().m_size_in, self.header().m_size_out, self.header().m_flags, self.header().m_compression))
|
||||
|
||||
if self.get_samplerate() < 8000 or self.get_samplerate() > 48000 or self.header().m_size_in > (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES ):
|
||||
print ("[Warning] Bad AUD Header info in file %s, size_in: %d, maxLen: %d" % (self.m_simpleAudioFileName, self.header().m_size_in, (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES)))
|
||||
if self.header().m_size_in == 0:
|
||||
# handle special case where only the header of the AUD file is present and the size_in is 0.
|
||||
# fill the header with "valid" info for an empty wav file
|
||||
self.header().m_size_out = 0
|
||||
self.header().m_samplerate = 22050
|
||||
self.header().m_compression = 0
|
||||
self.header().m_flags = 2
|
||||
self.header().m_populated = True
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if self.header().m_compression == 1:
|
||||
if (self.header().m_flags != 0):
|
||||
return False
|
||||
elif self.header().m_compression == 0x63:
|
||||
if (self.header().m_flags != 2):
|
||||
return False
|
||||
elif self.header().m_compression == 0: # no compression. At least some AUD files in SFX.MIX have this
|
||||
if (self.header().m_flags != 2):
|
||||
return False
|
||||
self.header().m_populated = True
|
||||
return True
|
||||
|
||||
# int AudFile::get_chunk_header(int i, std::fstream& fs, AudFileNS::pos_type startAudFilepos, AudFileNS::pos_type endAudFilepos, AudChunkHeader& outAudChunkHeader)
|
||||
def get_chunk_header(self, chunkIdx, inAudFileBytesBuffer, inAudFileSize):
|
||||
#fs.seekg(int(startAudFilepos) + int(SIZE_OF_AUD_HEADER_IN_BYTES), fs.beg);
|
||||
#AudFileNS::pos_type rAudPos;
|
||||
#rAudPos = fs.tellg();
|
||||
outAudChunkHeader = AudChunkHeader()
|
||||
rAudPos = SIZE_OF_AUD_HEADER_IN_BYTES
|
||||
|
||||
if (self.m_traceModeEnabled):
|
||||
print ("[Trace] Getting chunk header at %d" % (rAudPos))
|
||||
#AudChunkHeader tmpInremediateChunkheader;
|
||||
tmpInremediateChunkheader = AudChunkHeader()
|
||||
#while (i--) # value of i is decreased after checked by while loop
|
||||
while(chunkIdx > 0):
|
||||
chunkIdx -= 1
|
||||
if (rAudPos + SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES > inAudFileSize):
|
||||
return (-1, rAudPos, None)
|
||||
|
||||
tmpAudFileOffset = rAudPos
|
||||
tmpTuple = struct.unpack_from('H', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
tmpInremediateChunkheader.m_ch_size_in = tmpTuple[0]
|
||||
tmpAudFileOffset += 2
|
||||
tmpTuple = struct.unpack_from('H', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
tmpInremediateChunkheader.m_ch_size_out = tmpTuple[0]
|
||||
tmpAudFileOffset += 2
|
||||
tmpTuple = struct.unpack_from('I', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
tmpInremediateChunkheader.m_ch_id = tmpTuple[0]
|
||||
tmpAudFileOffset += 4
|
||||
#fs.read((char*)&tmpInremediateChunkheader, SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES);
|
||||
rAudPos += SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES + tmpInremediateChunkheader.m_ch_size_in
|
||||
#fs.seekg(int(rAudPos), fs.beg);
|
||||
|
||||
if (rAudPos + SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES > inAudFileSize ):
|
||||
return (-1, rAudPos, None)
|
||||
# write to FINAL output chunk header
|
||||
tmpAudFileOffset = rAudPos
|
||||
tmpTuple = struct.unpack_from('H', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
outAudChunkHeader.m_ch_size_in = tmpTuple[0]
|
||||
tmpAudFileOffset += 2
|
||||
tmpTuple = struct.unpack_from('H', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
outAudChunkHeader.m_ch_size_out = tmpTuple[0]
|
||||
tmpAudFileOffset += 2
|
||||
tmpTuple = struct.unpack_from('I', inAudFileBytesBuffer, tmpAudFileOffset)
|
||||
outAudChunkHeader.m_ch_id = tmpTuple[0]
|
||||
tmpAudFileOffset += 4
|
||||
#fs.read((char*)&outAudChunkHeader, SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES);
|
||||
if (rAudPos + SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES + outAudChunkHeader.m_ch_size_in > inAudFileSize):
|
||||
return (-1, rAudPos, None)
|
||||
rAudPos += SIZE_OF_AUD_CHUNK_HEADER_IN_BYTES
|
||||
return (0, rAudPos, outAudChunkHeader) # //reinterpret_cast<const AudChunkHeader*>(r);
|
||||
|
||||
# int AudFile::get_chunk_data(int i, std::fstream& fs, int sizeToRead, AudFileNS::byte* byteChunkDataPtr)
|
||||
def get_chunk_data(self, inAudFileBytesBuffer, startOffs, sizeToRead):
|
||||
#fs.read((char*)byteChunkDataPtr, sizeToRead)
|
||||
outChunkDataLst = []
|
||||
if (self.m_traceModeEnabled):
|
||||
print ("[Trace] Getting chunk data")
|
||||
print ("[Trace] startOffs: %d, sizeToRead: %d" % (startOffs, sizeToRead))
|
||||
for i in range(startOffs, startOffs + sizeToRead):
|
||||
#outChunkDataLst.append(ctypes.c_char(inAudFileBytesBuffer[i]).value)
|
||||
#outChunkDataLst.append(ctypes.c_byte(inAudFileBytesBuffer[i]).value)
|
||||
tmpTuple = struct.unpack_from('B', inAudFileBytesBuffer, i)
|
||||
outChunkDataLst.append(tmpTuple[0])
|
||||
#byteChunkDataOut = struct.pack('b'*len(outChunkDataLst), *outChunkDataLst)
|
||||
#return (0, byteChunkDataOut)
|
||||
return (0, outChunkDataLst)
|
||||
|
||||
|
||||
# std::fstream& fs, AudFileNS::pos_type startAudFilepos, AudFileNS::pos_type endAudFilepos
|
||||
# returned Cvirtual_binary
|
||||
def decode(self, speccompression, audBytesBuff):
|
||||
# The * operator unpacks an argument list. It allows you to call a function with the list items as individual arguments.
|
||||
# binDataOut = struct.pack('i'*len(data), *data)
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Debug] Decoding AUD file format...")
|
||||
# Cvirtual_binary d;
|
||||
binaryDataOutLst = []
|
||||
binaryDataOutBuff = None
|
||||
cb_audio = self.get_cb_sample() * self.get_c_samples() # int cb_audio - basically this should be the size_out
|
||||
if speccompression == 1:
|
||||
# write_start allocates space for virtualBinary
|
||||
# AudFileNS::byte* w = d.write_start(cb_audio);
|
||||
errGetChunk = 0 # int errGetChunk
|
||||
#for (int chunk_i = 0; w != d.data_end(); chunk_i++)
|
||||
chunk_i = 0
|
||||
wIndex = 0
|
||||
while (wIndex < cb_audio):
|
||||
#AudChunkHeader out_chunk_header;
|
||||
#out_chunk_header = AudChunkHeader()
|
||||
(errGetChunk, bufferDataPos, out_chunk_header) = self.get_chunk_header(chunk_i, audBytesBuff, len(audBytesBuff))
|
||||
if errGetChunk != 0:
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] Error OR End file case while getting uncompressed chunk header!")
|
||||
break
|
||||
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] Get uncompressed chunk header returned: %d " % (out_chunk_header.m_ch_id))
|
||||
#Cvirtual_binary out_chunk_data;
|
||||
#AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.m_ch_size_in);
|
||||
(errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.m_ch_size_in)
|
||||
# export decoded chunk to w (output) buffer (of CHARS) at the point where we're currently at (so append there)
|
||||
decodedAudioChunkAsLst = aud_decode_ws_chunk(byteChunkDataLst, out_chunk_header.m_ch_size_in, out_chunk_header.m_ch_size_out)
|
||||
binaryDataOutLst.extend(decodedAudioChunkAsLst)
|
||||
wIndex += out_chunk_header.m_ch_size_out
|
||||
chunk_i += 1
|
||||
binaryDataOutBuff = struct.pack('b'*len(binaryDataOutLst), *binaryDataOutLst)
|
||||
elif speccompression == 0x63:
|
||||
decodeInstance = audFileDecode(self.m_traceModeEnabled);
|
||||
#decodeInstance.init();
|
||||
#AudFileNS::byte* w = d.write_start(cb_audio);
|
||||
errGetChunk = 0 # int errGetChunk
|
||||
# for (int chunk_i = 0; w != d.data_end(); chunk_i++)
|
||||
chunk_i = 0
|
||||
wIndex = 0
|
||||
while (wIndex < cb_audio):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] chunkI: %d\t Windex: %d\t cb_audio: %d" % (chunk_i,wIndex,cb_audio))
|
||||
#AudChunkHeader out_chunk_header;
|
||||
#out_chunk_header = AudChunkHeader()
|
||||
#errGetChunk = self.get_chunk_header(chunk_i, fs, startAudFilepos, endAudFilepos, out_chunk_header);
|
||||
(errGetChunk, bufferDataPos, out_chunk_header) = self.get_chunk_header(chunk_i, audBytesBuff, len(audBytesBuff))
|
||||
if errGetChunk != 0:
|
||||
print ("[Warning] Error OR End file case while getting COMPRESSED chunk header!")
|
||||
break
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] Get COMPRESSED chunk header returned:: headerInSize: %d headerOutSize: %d id: %d" % (out_chunk_header.m_ch_size_in, out_chunk_header.m_ch_size_out, out_chunk_header.m_ch_id))
|
||||
#Cvirtual_binary out_chunk_data;
|
||||
#AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.m_ch_size_in);
|
||||
(errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.m_ch_size_in)
|
||||
# export decoded chunk to w (output) buffer (of SHORTS) at the point where we're currently at (so append there)
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] byteChunkDataLst len: %d, m_ch_size_in was: %d" % (len(byteChunkDataLst), out_chunk_header.m_ch_size_in))
|
||||
# Use "//" for floor int division in decode_chunk(), since in python 3 just using "/" would result in float and that leads to error
|
||||
decodedAudioChunkAsLst = decodeInstance.decode_chunk(byteChunkDataLst, (out_chunk_header.m_ch_size_out // self.get_cb_sample()));
|
||||
binaryDataOutLst.extend(decodedAudioChunkAsLst)
|
||||
wIndex += out_chunk_header.m_ch_size_out
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] New Windex: %d\t cb_audio: %d" % (wIndex,cb_audio))
|
||||
chunk_i += 1
|
||||
binaryDataOutBuff = struct.pack('h'*len(binaryDataOutLst), *binaryDataOutLst)
|
||||
if self.m_traceModeEnabled:
|
||||
if binaryDataOutBuff is not None:
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] Decoding Done.")
|
||||
else: #if binaryDataOutBuff is None:
|
||||
print ("[Error] Decoding yielded errors (data out buffer is null).")
|
||||
return binaryDataOutBuff
|
||||
|
||||
def header(self):
|
||||
return self.m_header
|
||||
|
||||
def get_c_samples(self):
|
||||
# Use "//" for floor int division in return value, since in python 3 just using "/" would result in float and that leads to error
|
||||
return (self.m_header.m_size_out // self.get_cb_sample())
|
||||
|
||||
def get_samplerate(self):
|
||||
return self.m_header.m_samplerate;
|
||||
|
||||
# flag bit 0 is stereo(set) mono(clear)
|
||||
def get_c_channels(self):
|
||||
return 2 if (self.m_header.m_flags & 0x01) else 1;
|
||||
|
||||
# flag bit 1 is 16bit(set) 8bit (clear)
|
||||
def get_cb_sample(self):
|
||||
return 2 if (self.m_header.m_flags & 0x02) else 1
|
||||
#
|
||||
#
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
errorFound = False
|
||||
# By default assumes a file of name 000000.AUD in same directory
|
||||
# otherwise tries to use the first command line argument as input file
|
||||
inAUDFile = None
|
||||
inAUDFileName = '00000000.AUD'
|
||||
|
||||
if len(sys.argv[1:]) > 0 \
|
||||
and os.path.isfile(os.path.join(u'.', sys.argv[1])) \
|
||||
and len(sys.argv[1]) >= 5 \
|
||||
and sys.argv[1][-3:].upper() == 'AUD':
|
||||
inAUDFileName = sys.argv[1]
|
||||
print ("[Info] Attempting to use %s as input AUD file..." % (inAUDFileName))
|
||||
elif os.path.isfile(os.path.join(u'.', inAUDFileName)):
|
||||
print ("[Info] Using default %s as input AUD file..." % (inAUDFileName))
|
||||
else:
|
||||
print ("[Error] No valid input file argument was specified and default input file %s is missing." % (inAUDFileName))
|
||||
errorFound = True
|
||||
|
||||
if not errorFound:
|
||||
try:
|
||||
print ("[Info] Opening %s" % (inAUDFileName))
|
||||
inAUDFile = open(os.path.join(u'.', inAUDFileName), 'rb')
|
||||
except:
|
||||
errorFound = True
|
||||
print ("[Error] Unexpected event:", sys.exc_info()[0])
|
||||
raise
|
||||
if not errorFound:
|
||||
allOfAudFileInBuffer = inAUDFile.read()
|
||||
audFileInstance = audFile(True)
|
||||
if audFileInstance.m_traceModeEnabled:
|
||||
print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
if audFileInstance.loadAudFile(allOfAudFileInBuffer, len(allOfAudFileInBuffer), inAUDFileName):
|
||||
print ("[Info] Audio file (AUD) loaded successfully!")
|
||||
audFileInstance.export_as_wav(allOfAudFileInBuffer, './tmp.wav')
|
||||
else:
|
||||
print ("[Error] Error while loading Audio file (AUD)!")
|
||||
inAUDFile.close()
|
||||
else:
|
||||
#debug
|
||||
#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
pass
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
MY_MODULE_VERSION = "1.10"
|
||||
MY_MODULE_NAME = "devCommentaryText"
|
||||
|
||||
# All game versions should have the English text pre-filled in the POGO sheet
|
||||
DEV_AUDIO_COMMENTARY_TUPLE_LIST = [
|
||||
("MA04VO1A.AUD", "*McCoy's apartment*"),
|
||||
("CT01VO1A.AUD", "*Chinatown*"),
|
||||
("HC01VO1A.AUD", "*Hawker's Circle*")
|
||||
]
|
||||
|
||||
EXTRA_SPEECH_AUDIO_TUPLE_LIST = [
|
||||
('COLONY.AUD', "*Blimp Guy talk*"),
|
||||
('67_0470R.AUD', "*Crowd talk*"),
|
||||
('67_0480R.AUD', "*Crowd talk*"),
|
||||
('67_0500R.AUD', "*Crowd talk*"),
|
||||
('67_0540R.AUD', "*Crowd talk*"),
|
||||
('67_0560R.AUD', "*Crowd talk*"),
|
||||
('67_0870R.AUD', "*Crowd talk*"),
|
||||
('67_0880R.AUD', "*Crowd talk*"),
|
||||
('67_0900R.AUD', "*Crowd talk*"),
|
||||
('67_0940R.AUD', "*Crowd talk*"),
|
||||
('67_0960R.AUD', "*Crowd talk*"),
|
||||
('67_1070R.AUD', "*Crowd talk*"),
|
||||
('67_1080R.AUD', "*Crowd talk*"),
|
||||
('67_1100R.AUD', "*Crowd talk*"),
|
||||
('67_1140R.AUD', "*Crowd talk*"),
|
||||
('67_1160R.AUD', "*Crowd talk*")
|
||||
]
|
||||
|
||||
# we use the spoken quote id that triggers the comment as an ID for the DEV commentary quote
|
||||
# Ids 00-9990 and above correspond to clicks or other transitions (no corresponding spoken in-game quote)
|
||||
DEV_ISEZ_QUOTES_TUPLE_LIST = [
|
||||
("IS-00-9990.AUD", "Blade Runner\nFrom the dark recesses of David Leary's imagination comes a game unlike any\nother. Blade Runner immerses you in the underbelly of future Los Angeles. Right\nfrom the start, the story pulls you in with graphic descriptions of a\ngrandmother doing the shimmy in her underwear, child molestation, brutal\ncold-blooded slaying of innocent animals, vomiting on desks, staring at a\nwoman's ass, the list goes on. And when the game starts, the real fun begins -\nshoot down-on-their-luck homeless people and toss them into a dumpster. Watch\nwith sadistic glee as a dog gets blown into chunky, bloody, bits by an\nexplosive, and even murder a shy little girl who loves you. If you think David\nLeary is sick, and you like sick, this is THE game for you.\n\nJW: Don't forget the wasting of helpless mutated cripples in the underground.\nIt's such a beautiful thing!\n\nDL: Go ahead. Just keep beating that snarling pit bull...ignore the foam\naround his jaws. There's room on the top shelf of my fridge for at least one\nmore head... - Psychotic Dave\n"),
|
||||
("IS-99-1860.AUD", "MG: Is David Leary a self-respecting human or is he powered by rechargeable\nBatteries?"), # voice-over
|
||||
("IS-99-1890.AUD", "JM: That McCoy--he's one funny guy! Jet-black fire truck, hehehehe..."), # voice-over
|
||||
("IS-23-0130.AUD", "JM: Did it have a huge, ugly piece of chrome on it?"), # Officer Leary
|
||||
("IS-23-0090.AUD", "JM: This officer has a talent for vivid metaphors."), # Officer Leary
|
||||
("IS-00-4540.AUD", "DL: What is that supposed to mean? I didn't write this line..."),
|
||||
("IS-00-4515.AUD", "MG: Hey, leave that officer alone. Can't you see he's busy?\nJM: (...mmm, donuts...)"), # clicking on Leary after we get his statement
|
||||
("IS-23-0060.AUD", "MG: It's all fun and games until someone loses a tiger cub."), # Officer Leary
|
||||
("IS-00-9991.AUD", "JM: Chrome...is that what that is?"), # pick up chrome
|
||||
("IS-00-4510.AUD", "JM: It's hard to imagine that thing on either a car or a horse.\nMG: McCoy! What a witty chap...\nJM: He keeps me chuckling non-stop!"),
|
||||
("IS-00-9992.AUD", "MG: Leaving already? The fun is just beginning!"), # leaving Runciter's zoo with Spinner
|
||||
("IS-00-4500.AUD", "MG: We don't want any of that abstract art oozing out onto the street.")
|
||||
]
|
||||
#
|
||||
#
|
||||
#
|
||||
class devCommentaryText(object):
|
||||
m_traceModeEnabled = True
|
||||
# traceModeEnabled is bool to enable more printed debug messages
|
||||
def __init__(self, traceModeEnabled = True):
|
||||
self.m_traceModeEnabled = traceModeEnabled
|
||||
return
|
||||
|
||||
def printTexts(self):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] Printing all dev commentary text")
|
||||
print ("\nAUDIO COMMENTARY")
|
||||
print ("------------------")
|
||||
for (idTre, textTre) in DEV_AUDIO_COMMENTARY_TUPLE_LIST:
|
||||
print ("%s\t%s" % (idTre, textTre))
|
||||
print ("\nEXTRA SPEECH AUDIO")
|
||||
print ("------------------")
|
||||
for (idTre, textTre) in EXTRA_SPEECH_AUDIO_TUPLE_LIST:
|
||||
print ("%s\t%s" % (idTre, textTre))
|
||||
print ("\nI_SEZ QUOTES")
|
||||
print ("------------------")
|
||||
for (idTre, textTre) in DEV_ISEZ_QUOTES_TUPLE_LIST:
|
||||
print ("%s\t%s" % (idTre, textTre))
|
||||
return
|
||||
|
||||
def getAudioCommentaryTextEntriesList(self):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] getAudioCommentaryTextEntriesList")
|
||||
return DEV_AUDIO_COMMENTARY_TUPLE_LIST
|
||||
|
||||
def getISEZTextEntriesList(self):
|
||||
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] getISEZTextEntriesList")
|
||||
return DEV_ISEZ_QUOTES_TUPLE_LIST
|
||||
|
||||
def getExtraSpeechAudioEntriesList(self):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] getExtraSpeechAudioEntriesList")
|
||||
return EXTRA_SPEECH_AUDIO_TUPLE_LIST
|
||||
#
|
||||
#
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
traceModeEnabled = False
|
||||
devCommentaryTextInstance = devCommentaryText(traceModeEnabled)
|
||||
devCommentaryTextInstance.printTexts()
|
||||
else:
|
||||
#debug
|
||||
#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
pass
|
||||
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
MY_MODULE_VERSION = "1.10"
|
||||
MY_MODULE_NAME = "pogoTextResource"
|
||||
|
||||
# All game versions should have the English text pre-filled in the POGO sheet
|
||||
POGO_TEXT_RESOURCE_TUPLE_LIST = [
|
||||
(0, "Air Conditioning"),
|
||||
(1, "Amy Shoopman"),
|
||||
(2, "Andy B. and the Milk Carton Kids"),
|
||||
(3, "Area 51"),
|
||||
(4, "Aspirin"),
|
||||
(5, "Babylon 5"),
|
||||
(6, "Bandit"),
|
||||
(7, "Bauer Inline Skates"),
|
||||
(8, "Bill Randolph"),
|
||||
(9, "Bill (Mr. Motorola) and Sarah"),
|
||||
(10, "Boo Berry and Frankenberry"),
|
||||
(11, "Brett W. Sperry"),
|
||||
(12, "Brianhead Ski Resort"),
|
||||
(13, "Bubba"),
|
||||
(14, "Bubbles"),
|
||||
(15, "Building 2 Parking"),
|
||||
(16, "The Buke"),
|
||||
(17, "Chan \"The Emporer\" Lee"),
|
||||
(18, "Cheezy Poofs"),
|
||||
(19, "Chuck \"Walter\" Karras"),
|
||||
(20, "Cinco De Mayo"),
|
||||
(21, "Club Med"),
|
||||
(22, "Code Complete"),
|
||||
(23, "Coffee Pub, Las Vegas"),
|
||||
(24, "Coke"),
|
||||
(25, "Coin Magic"),
|
||||
(26, "Count Chocula"),
|
||||
(27, "Dad"),
|
||||
(28, "David Arkenstone"),
|
||||
(29, "Digital Camera"),
|
||||
(30, "Direct X Team"),
|
||||
(31, "Denis and Joanne Dyack"),
|
||||
(32, "Blue Bayou, Disneyland"),
|
||||
(33, "Dongle-Boy"),
|
||||
(34, "Doves and Sparrows"),
|
||||
(35, "Dovey"),
|
||||
(36, "Draracles"),
|
||||
(37, "Dry Air"),
|
||||
(38, "Ed Del Castillo"),
|
||||
(39, "Eric \"Kick Ass\" Cartman"),
|
||||
(40, "FHM"),
|
||||
(41, "Fog City Diner"),
|
||||
(42, "Fog Studios"),
|
||||
(43, "Gatorade"),
|
||||
(44, "Gandhi Cuisine of India"),
|
||||
(45, "Giant Lava Lamp"),
|
||||
(46, "Eric and Nancy Gooch"),
|
||||
(47, "Grayford Family"),
|
||||
(48, "Comet Hale-Bopp"),
|
||||
(49, "Joseph B. Hewitt IV"),
|
||||
(50, "Hercules"),
|
||||
(51, "Hillbilly Jeopardy"),
|
||||
(52, "Home Cookin'"),
|
||||
(53, "Hooey Stick"),
|
||||
(54, "The Hypnotist"),
|
||||
(55, "Insects on the Move"),
|
||||
(56, "Intel"),
|
||||
(57, "James Hong"),
|
||||
(58, "Jasmine"),
|
||||
(59, "The Mysterious Cockatiel"),
|
||||
(60, "Joe's Frog"),
|
||||
(61, "Jed"),
|
||||
(62, "Jeeps"),
|
||||
(63, "Jeeter"),
|
||||
(64, "Jeff Brown"),
|
||||
(65, "JoeB"),
|
||||
(66, "Joe-Bob McClintock"),
|
||||
(67, "Joseph Turkel"),
|
||||
(68, "Jose Cuervo"),
|
||||
(69, "Juggling Balls"),
|
||||
(70, "Keith Parkinson"),
|
||||
(71, "Khan"),
|
||||
(72, "King of the Hill"),
|
||||
(73, "Kurt O. and the Toothbrush Squad"),
|
||||
(74, "Leonard and Shirley Legg"),
|
||||
(75, "Leroy"),
|
||||
(76, "Brion James"),
|
||||
(77, "Louis and his \"friend\""),
|
||||
(78, "M.C. Crammer and Janie"),
|
||||
(79, "Men's Room Magna-Doodle"),
|
||||
(80, "Mark and Deepti Rowland"),
|
||||
(81, "Metro Pizza, Las Vegas"),
|
||||
(82, "Matt Vella"),
|
||||
(83, "Maui"),
|
||||
(84, "1 Million Candlepower Spotlight"),
|
||||
(85, "Mom"),
|
||||
(86, "Movie-makers"),
|
||||
(87, "Mr. Nonsense"),
|
||||
(88, "Needles"),
|
||||
(89, "Nerf Weaponry"),
|
||||
(90, "Nimbus"),
|
||||
(91, "Norm Vordahl"),
|
||||
(92, "KNPR"),
|
||||
(93, "Olive Garden"),
|
||||
(94, "Onkyo"),
|
||||
(95, "Orangey"),
|
||||
(96, "Osbur, the Human Resource Manager"),
|
||||
(97, "Our Cheery Friend Leary"),
|
||||
(98, "Ousted Gnome King"),
|
||||
(99, "Pepsi"),
|
||||
(100, "Peta Wilson"),
|
||||
(101, "Pogo the Mockingbird"),
|
||||
(102, "Poker Nights"),
|
||||
(103, "Pirates"),
|
||||
(104, "Playmate Lingerie Calendar"),
|
||||
(105, "Pop-Ice"),
|
||||
(106, "Powerhouse Gym"),
|
||||
(107, "Rade McDowell"),
|
||||
(108, "Red Rock Canyon"),
|
||||
(109, "Refrigeration"),
|
||||
(110, "Rhoda"),
|
||||
(111, "Richard and Kimberly Weier"),
|
||||
(112, "Ridley Scott"),
|
||||
(113, "Ruud the Dude"),
|
||||
(114, "Our old pal Rick Parks"),
|
||||
(115, "Ruby's Diner"),
|
||||
(116, "Savatage"),
|
||||
(117, "Scully and Mulder"),
|
||||
(118, "Sean Young"),
|
||||
(119, "Seinfeld"),
|
||||
(120, "The Shadow"),
|
||||
(121, "Shakes"),
|
||||
(122, "Shorts"),
|
||||
(123, "Silly Putty"),
|
||||
(124, "The Simpsons"),
|
||||
(125, "Thomas Christensen"),
|
||||
(126, "We love you Steve Wetherill!!!"),
|
||||
(127, "Skank"),
|
||||
(128, "Slice"),
|
||||
(129, "SSG"),
|
||||
(130, "Steve and Anne Tall"),
|
||||
(131, "South Park"),
|
||||
(132, "Snap 'n Pops"),
|
||||
(133, "Sneaker"),
|
||||
(134, "Star Wars Trilogy"),
|
||||
(135, "Nonstop Summer Pool Parties"),
|
||||
(136, "Sunsets"),
|
||||
(137, "T-Bone and Angie"),
|
||||
(138, "T-shirts"),
|
||||
(139, "Julio Schembari, Tango Pools"),
|
||||
(140, "The Thermostat Key"),
|
||||
(141, "The Wizard"),
|
||||
(142, "Tomb Raider"),
|
||||
(143, "Tom Elmer II"),
|
||||
(144, "Tujia Linden"),
|
||||
(145, "Turbo"),
|
||||
(146, "Tweeter"),
|
||||
(147, "Twonky"),
|
||||
(148, "Ty and Judy Coon"),
|
||||
(149, "The Courtyard"),
|
||||
(150, "U.F.C."),
|
||||
(151, "Uli Boehnke"),
|
||||
(152, "Virgil"),
|
||||
(153, "Virtual Boy"),
|
||||
(154, "Westwood Offroad Excursion Team"),
|
||||
(155, "William Sanderson"),
|
||||
(156, "Xena"),
|
||||
(157, "Zion National Park"),
|
||||
(158, "We 3 coders give special thanks to:")
|
||||
]
|
||||
|
||||
|
||||
class pogoTextResource(object):
|
||||
m_traceModeEnabled = True
|
||||
# traceModeEnabled is bool to enable more printed debug messages
|
||||
def __init__(self, traceModeEnabled = True):
|
||||
self.m_traceModeEnabled = traceModeEnabled
|
||||
return
|
||||
|
||||
def printPogo(self):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] printing Pogo...")
|
||||
for (idTre, textTre) in POGO_TEXT_RESOURCE_TUPLE_LIST:
|
||||
print ("%s\t%s" % (idTre, textTre))
|
||||
return
|
||||
|
||||
def getPogoEntriesList(self):
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Trace] getPogoEntriesList()")
|
||||
return POGO_TEXT_RESOURCE_TUPLE_LIST
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
traceModeEnabled = False
|
||||
pogoTRInstance = pogoTextResource(traceModeEnabled)
|
||||
pogoTRInstance.printPogo()
|
||||
else:
|
||||
#debug
|
||||
#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
pass
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
sysLibFound = False
|
||||
try:
|
||||
import sys
|
||||
except ImportError:
|
||||
print ("[Error] sys python library is required to be installed!")
|
||||
else:
|
||||
sysLibFound = True
|
||||
|
||||
if (not sysLibFound):
|
||||
sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
|
||||
sys.exit(1)
|
||||
|
||||
import sortBladeRunnerWavs02
|
||||
if __name__ == "__main__":
|
||||
sortBladeRunnerWavs02.main(sys.argv[0:])
|
||||
@@ -0,0 +1,75 @@
|
||||
Id Short ActorDesc #skip first row
|
||||
0 MCCOY McCoy
|
||||
1 STEEL Steele
|
||||
2 GORDO Gordo
|
||||
3 DEKTO Dektora
|
||||
4 GUZZA Guzza
|
||||
5 CLOVI Clovis
|
||||
6 LLUCY Lucy
|
||||
7 IIIZO Izo
|
||||
8 SADIK Sadik
|
||||
9 CRAZY Crazylegs
|
||||
10 LUTHE Luther
|
||||
11 GRIGO Grigorian
|
||||
12 TRANS Transient
|
||||
13 LANCE Lance
|
||||
14 BBBOB Bullet Bob
|
||||
15 RUNCI Runciter
|
||||
16 INSEC Insect Dealer
|
||||
17 TGUAR Tyrell Guard
|
||||
18 EARLQ Early Q
|
||||
19 ZUBEN Zuben
|
||||
20 HASAN Hasan
|
||||
21 MARCU Marcus
|
||||
22 MMMIA Mia
|
||||
23 OLEAR Officer Leary
|
||||
24 OGRAY Officer Grayford
|
||||
25 HANOI Hanoi
|
||||
26 BAKER Baker
|
||||
27 DCLER Desk Clerk
|
||||
28 HOWIE Howie Lee
|
||||
29 FISHD Fish Dealer
|
||||
30 KLEIN Klein
|
||||
31 MURRA Murray
|
||||
32 HBARK Hawker's Barkeep
|
||||
33 HOLLO Holloway
|
||||
34 SWALL Sergeant Walls
|
||||
35 MORAJ Moraji
|
||||
36 TBARD The Bard
|
||||
37 PHOTG Photographer
|
||||
38 DISPA Dispatcher
|
||||
39 ANSWM Answering Machine
|
||||
40 RAJIF Rajif
|
||||
41 GKOLV Governor Kolvig
|
||||
42 ERLQB Early Q Bartender
|
||||
43 HPARR Hawker's Parrot
|
||||
44 TAFPA Taffy Patron
|
||||
45 LOCGU Lockup Guard
|
||||
46 TEENA Teenager
|
||||
47 HPATA Hysteria Patron A
|
||||
48 HPATB Hysteria Patron B
|
||||
49 HPATC Hysteria Patron C
|
||||
50 SHOES Shoeshine Man
|
||||
51 TYREL Tyrell
|
||||
52 CCHEW Chew
|
||||
53 GGAFF Gaff
|
||||
54 BRYAN Bryant
|
||||
55 TAFFY Taffy
|
||||
56 SEBAS Sebastian
|
||||
57 RACHA Rachael
|
||||
58 GDOLL General Doll
|
||||
59 ISABE Isabella
|
||||
60 BLIMP Blimp Guy
|
||||
61 NEWSC Newscaster
|
||||
62 LLEON Leon
|
||||
63 MALAN Male Announcer
|
||||
64 FREEA Free Slot A
|
||||
65 FREEB Free Slot B
|
||||
66 MAGGI Maggie
|
||||
67 ACTGA Actor Genwalker A
|
||||
68 ACTGB Actor Genwalker B
|
||||
69 ACTGC Actor Genwalker C
|
||||
70 MUTAA Mutant A
|
||||
71 MUTAB Mutant B
|
||||
72 MUTAC Mutant C
|
||||
99 MAINF Mainframe
|
||||
@@ -0,0 +1,9 @@
|
||||
python2.7 quoteSpreadsheetCreator.py -op /d/BladeRunnerLPBackup/ENG_data/WAV -ip "/d/Westwood/BladeRunnerENG" -ian ../common/actornames.txt -ld EN_ANY -xtre -xwav -xpogo -xdevs --trace
|
||||
|
||||
python2.7 quoteSpreadsheetCreator.py -op /D/BladeRunnerLPBackup/DEU_data/WAV -ip "/d/Westwood/BladeRunnerDEU" -ian ../common/actornames.txt -ld DE_DEU -xtre -xwav -xpogo -xdevs
|
||||
|
||||
python2.7 quoteSpreadsheetCreator.py -op /D/BladeRunnerLPBackup/FRA_data/WAV -ip "/d/Westwood/BladeRunnerFRA" -ian ../common/actornames.txt -ld FR_FRA -xtre -xwav -xpogo -xdevs
|
||||
|
||||
python2.7 quoteSpreadsheetCreator.py -op /D/BladeRunnerLPBackup/ITA_data/WAV -ip "/d/Westwood/BladeRunnerIT" -ian ../common/actornames.txt -ld IT_ITA -xtre -xwav -xpogo -xdevs
|
||||
|
||||
python2.7 quoteSpreadsheetCreator.py -op /D/BladeRunnerLPBackup/ESP_data/WAV -ip "/d/Westwood/BladeRunnerESP" -ian ../common/actornames.txt -ld ES_ESP -xtre -xwav -xpogo -xdevs
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
osLibFound = False
|
||||
sysLibFound = False
|
||||
shutilLibFound = False
|
||||
structLibFound = False
|
||||
|
||||
try:
|
||||
import os
|
||||
except ImportError:
|
||||
print ("[Error] os python library is required to be installed!")
|
||||
else:
|
||||
osLibFound = True
|
||||
|
||||
try:
|
||||
import sys
|
||||
except ImportError:
|
||||
print ("[Error] sys python library is required to be installed!")
|
||||
else:
|
||||
sysLibFound = True
|
||||
|
||||
try:
|
||||
import struct
|
||||
except ImportError:
|
||||
print ("[Error] struct python library is required to be installed!")
|
||||
else:
|
||||
structLibFound = True
|
||||
|
||||
if (not osLibFound) \
|
||||
or (not sysLibFound) \
|
||||
or (not structLibFound):
|
||||
sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
|
||||
sys.exit(1)
|
||||
|
||||
pathToParent = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
|
||||
pathToCommon = os.path.join(pathToParent, "common")
|
||||
sys.path.append(pathToCommon)
|
||||
|
||||
from struct import *
|
||||
from pythonCompat import *
|
||||
|
||||
MY_MODULE_VERSION = "0.70"
|
||||
MY_MODULE_NAME = "treFileLib"
|
||||
|
||||
|
||||
class TreHeader(object):
|
||||
numOfTextResources = -1
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
|
||||
class treFile(object):
|
||||
m_header = TreHeader()
|
||||
simpleTextResourceFileName = 'GENERIC.TRE'
|
||||
stringEntriesLst = [] # list of two-value tuples. First value is ID, second value is String content
|
||||
stringOffsets = []
|
||||
m_traceModeEnabled = False
|
||||
|
||||
# traceModeEnabled is bool to enable more printed debug messages
|
||||
def __init__(self, traceModeEnabled = True):
|
||||
del self.stringEntriesLst[:]
|
||||
del self.stringOffsets[:]
|
||||
self.simpleTextResourceFileName = 'GENERIC.TRE'
|
||||
self.m_traceModeEnabled = traceModeEnabled
|
||||
return
|
||||
|
||||
def loadTreFile(self, treBytesBuff, maxLength, treFileName):
|
||||
self.simpleTextResourceFileName = treFileName
|
||||
offsInTreFile = 0
|
||||
#
|
||||
# parse TRE file fields for header
|
||||
#
|
||||
try:
|
||||
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
|
||||
self.header().numOfTextResources = tmpTuple[0]
|
||||
offsInTreFile += 4
|
||||
#
|
||||
# string IDs table (each entry is unsigned integer 4 bytes)
|
||||
#
|
||||
if self.m_traceModeEnabled:
|
||||
print ("[Info] Total texts in Text Resource file: %d" % (self.header().numOfTextResources))
|
||||
for idx in range(0, self.header().numOfTextResources):
|
||||
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
|
||||
self.stringEntriesLst.append( (tmpTuple[0], '') )
|
||||
offsInTreFile += 4
|
||||
|
||||
# string offsets table (each entry is unsigned integer 4 bytes)
|
||||
for idx in range(0, self.header().numOfTextResources):
|
||||
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
|
||||
self.stringOffsets.append( tmpTuple[0] )
|
||||
offsInTreFile += 4
|
||||
#
|
||||
# strings (all entries are null terminated)
|
||||
# TODO +++
|
||||
absStartOfIndexTable = 4
|
||||
#absStartOfOffsetTable = absStartOfIndexTable + (self.header().numOfTextResources * 4)
|
||||
#absStartOfStringTable = absStartOfOffsetTable + ((self.header().numOfTextResources+1) * 4)
|
||||
|
||||
#print ("[Debug] buffer type: ", type(treBytesBuff)) # it is str
|
||||
|
||||
for idx in range(0, self.header().numOfTextResources):
|
||||
currOffset = self.stringOffsets[idx] + absStartOfIndexTable
|
||||
# the buffer (treBytesBuff) where we read the TRE file into, is "str" type but contains multiple null terminated strings
|
||||
# the solution here (to not get out of index errors when reading the null terminator points) is
|
||||
# to split the substring starting at the indicated offset each time, at the null character, and get the first string token.
|
||||
# This works ok.
|
||||
#
|
||||
print (treBytesBuff[currOffset:])
|
||||
if sys.version_info[0] <= 2:
|
||||
allTextsFound = treBytesBuff[currOffset:].split('\x00')
|
||||
else:
|
||||
allTextsFound = treBytesBuff[currOffset:].split(b'\0')
|
||||
print (allTextsFound[0])
|
||||
### check "problematic" character cases:
|
||||
##if self.m_traceModeEnabled:
|
||||
## if currOffset == 5982 or currOffset == 6050 or currOffset == 2827 or currOffset == 2880:
|
||||
## print ("[Debug] Offs: %d\tFound String: %s" % (currOffset, ''.join(allTextsFound[0]) ))
|
||||
(theId, stringOfIdx) = self.stringEntriesLst[idx]
|
||||
if sys.version_info[0] <= 2:
|
||||
self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0]))
|
||||
else:
|
||||
self.stringEntriesLst[idx] = (theId, allTextsFound[0])
|
||||
|
||||
if self.m_traceModeEnabled:
|
||||
if sys.version_info[0] <= 2:
|
||||
print ("[Trace] ID: %d\tFound String: %s" % (theId, ''.join(allTextsFound[0]) ))
|
||||
else:
|
||||
print ("[Trace] ID: %d\tFound String: %s" % (theId, allTextsFound[0] ))
|
||||
return True
|
||||
except Exception as e:
|
||||
print ("[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName) + " " + str(e))
|
||||
return False
|
||||
|
||||
def header(self):
|
||||
return self.m_header
|
||||
#
|
||||
#
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
errorFound = False
|
||||
# By default assumes a file of name ACTORS.TRE in same directory
|
||||
# otherwise tries to use the first command line argument as input file
|
||||
inTREFile = None
|
||||
inTREFileName = 'ACTORS.TRE'
|
||||
|
||||
if len(sys.argv[1:]) > 0 \
|
||||
and os.path.isfile(os.path.join(u'.', sys.argv[1])) \
|
||||
and len(sys.argv[1]) >= 5 \
|
||||
and sys.argv[1][-3:].upper() == 'TRE':
|
||||
inTREFileName = sys.argv[1]
|
||||
print ("[Info] Attempting to use %s as input TRE file..." % (inTREFileName))
|
||||
elif os.path.isfile(os.path.join(u'.', inTREFileName)):
|
||||
print ("[Info] Using default %s as input TRE file..." % (inTREFileName))
|
||||
else:
|
||||
print ("[Error] No valid input file argument was specified and default input file %s is missing." % (inTREFileName))
|
||||
errorFound = True
|
||||
|
||||
if not errorFound:
|
||||
try:
|
||||
print ("[Info] Opening %s" % (inTREFileName))
|
||||
inTREFile = open(os.path.join(u'.', inTREFileName), 'rb')
|
||||
except:
|
||||
errorFound = True
|
||||
print ("[Error] Unexpected event: ", sys.exc_info()[0])
|
||||
raise
|
||||
if not errorFound:
|
||||
allOfTreFileInBuffer = inTREFile.read()
|
||||
treFileInstance = treFile(True)
|
||||
if treFileInstance.m_traceModeEnabled:
|
||||
print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
if treFileInstance.loadTreFile(allOfTreFileInBuffer, len(allOfTreFileInBuffer), inTREFileName):
|
||||
print ("[Info] Text Resource file loaded successfully!")
|
||||
else:
|
||||
print ("[Error] Error while loading Text Resource file!")
|
||||
inTREFile.close()
|
||||
else:
|
||||
#debug
|
||||
#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
|
||||
pass
|
||||
Reference in New Issue
Block a user