简体   繁体   English

Python IMA ADPCM编解码器

[英]Python IMA ADPCM codec

I am developing small streaming audio app, audiochat client. 我正在开发小型流音频应用程序,audiochat客户端。 Server uses IMA ADPCM audio codec, framerate 8000, 256 bytes frame size. 服务器使用IMA ADPCM音频编解码器,帧速率为8000,帧大小为256字节。

I'm using algoritm described here 我使用algoritm描述这里
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. 解码声音的质量很差,并且服务器无法将编码声音识别为已校正的ima adpcm声音。

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. 此外,文档还提供了一些测试向量,您可以使用它们逐步调试程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM