I am developing small streaming audio app, audiochat client. Server uses IMA ADPCM audio codec, framerate 8000, 256 bytes frame size.
I'm using algoritm described here
Refernce compressed sound available here
The quality of decoded sound is poor, and coded sound don't recognising by server as corrected ima adpcm sound.
Please help me to find problem in my code.
# -*- coding: Utf-8 -*-t
import wave, struct
indexTable=[
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
]
stepsizeTable=[
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
]
def pcm2adpcm(frame): #frame - 1024 Bytes uncompressed
indexcode = 0
stepsizecode = 7
global indexTable
global stepsizeTable
predictedSample = 0
lstres=list()
for i in range(0,len(frame)): # Taking bytes
if (i+1)%2==0:
binsample=frame[i-1:i+1:]
originalsample=struct.unpack('h',binsample)[0] # To signed int
difference = originalsample-predictedSample
if difference>=0:
newSampleCode=0
else:
newSampleCode=8
difference=-difference
mask=4
tempStepsize=stepsizecode
for i in range(0,3):
if difference>=tempStepsize:
newSampleCode|=mask
difference-=tempStepsize
tempStepsize>>=1
mask>>=1
lstres.append(newSampleCode)
difference=0
if newSampleCode&4:
difference+=stepsizecode
if newSampleCode&2:
difference+=stepsizecode>>1
if newSampleCode&1:
difference+=stepsizecode>>2
difference+=stepsizecode>>3
if newSampleCode&8:
difference=-difference
predictedSample+=difference
if predictedSample>32767:
predictedSample=32767
if predictedSample<-32767:
predictedSample=-32767
indexcode+=indexTable[newSampleCode]
if indexcode<0:
indexcode=0
elif indexcode>88:
indexcode=88
stepsizecode=stepsizeTable[indexcode]
resultBinary=''
for i in range(0,len(lstres)):
if (i+1)%2==0:
#print lstres[i], lstres[i-1], (lstres[i]<<4)|lstres[i-1]
resultBinary+=chr((lstres[i]<<4)|lstres[i-1])
return resultBinary
def adpcm2pcm(frame): #frame - 256 Bytes compressed
index = 0
stepsize = 7
global indexTable
global stepsizeTable
newSample = 0
resultBinary=''
for i in range(0,len(frame)): # Taking bytes
binsample=frame[i]
originalsample=ord(frame[i]) #
secoundsample=originalsample>>4 # Secound 4 bit sample
firstsample=(secoundsample<<4)^originalsample # first 4 bit sample
lst=[firstsample,secoundsample] # To list
for originalsample in lst:
difference=0
if originalsample & 4:
difference+=stepsize
if originalsample & 2:
difference+=stepsize >> 1
if originalsample & 1:
difference+=stepsize >> 2
difference+=stepsize >> 3
if originalsample & 8:
difference=-difference
newSample+=difference
if newSample>32767:
newSample=32767
elif newSample<-32767:
newSample=-32767
resultBinary+=struct.pack('h',newSample)
index+=indexTable[originalsample]
if index<0:
index = 0
elif index>88:
index = 88
stepsize=stepsizeTable[index]
return resultBinary
if __name__ == '__main__':
#===========================================================================
# fout=wave.open('res.wav', 'wb')
# fout.setnchannels(1)
# fout.setsampwidth(2)
# fout.setframerate(8000)
# f=open('1.wav','rb')
# f.seek(60)
# for i in range (0,153):
# out=adpcm2pcm(f.read(256))
# fout.writeframesraw(out)
# fout.close()
#===========================================================================
f=open('1.wav','rb')
header=f.read(60)
foutcompr=open('resCompr.wav','wb')
foutcompr.write(header)
fout=wave.open('res.wav', 'rb')
n=0
while n<fout.getnframes():
foutcompr.write(pcm2adpcm(fout.readframes(512)))
n+=512
foutcompr.close()
print "finish"
I can see one problem:
elif indexcode>88:
indexcode=88
stepsizecode=stepsizeTable[indexcode]
should be:
elif indexcode>88:
indexcode=88
stepsizecode=stepsizeTable[indexcode]
That's a pretty significant difference.
Aside from that I would try generating a sine test tone, running that through the algorithm and examining the result. I'd also try to rule out any issues with the conversion between bytes and shorts.
Also, the documentation gives some test vectors that you could use to step through with a debugger.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.