簡體   English   中英

Python IMA ADPCM編解碼器

[英]Python IMA ADPCM codec

我正在開發小型流音頻應用程序,audiochat客戶端。 服務器使用IMA ADPCM音頻編解碼器,幀速率為8000,幀大小為256字節。

我使用algoritm描述這里
參考壓縮聲音在這里可用

解碼聲音的質量很差,並且服務器無法將編碼聲音識別為已校正的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"

我可以看到一個問題:

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

應該:

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

那是一個相當大的差異。

除此之外,我將嘗試生成正弦測試音,通過算法運行並檢查結果。 我還將嘗試排除字節和短褲之間轉換的任何問題。

此外,文檔還提供了一些測試向量,您可以使用它們逐步調試程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM