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
|
||||
Reference in New Issue
Block a user