Python IMA ADPCM编解码器

时间:2015-04-12 17:54:05

标签: python audio

我正在开发小型流音频应用程序,audiochat客户端。服务器使用IMA ADPCM音频编解码器,帧速率为8000,帧大小为256字节。

  

我正在使用algoritm描述here
  推荐使用压缩声音here

解码后的声音质量很差,编码声音不会被服务器识别为更正的ima adpcm声音。

请帮我在代码中找到问题。

# -*-  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"

1 个答案:

答案 0 :(得分:0)

我可以看到一个问题:

elif indexcode>88:
    indexcode=88
stepsizecode=stepsizeTable[indexcode]

应该是:

elif indexcode>88:
    indexcode=88
    stepsizecode=stepsizeTable[indexcode]

这是一个非常显着的差异。

除此之外,我会尝试生成正弦测试音,通过算法运行并检查结果。我还试图排除字节和短路之间转换的任何问题。

此外,文档提供了一些测试向量,您可以使用它们来调试器。