示例#1
0
def EncodeSingleChannel(data, codingParams):
    """Encodes a single-channel block of signed-fraction data based on the parameters in a PACFile object"""

    # prepare various constants
    halfN = codingParams.nMDCTLines
    # print halfN
    # N = 2*halfN
    # print N
    nScaleBits = codingParams.nScaleBits
    maxMantBits = (
        1 << codingParams.nMantSizeBits
    )  # 1 isn't an allowed bit allocation so n size bits counts up to 2^n
    if maxMantBits > 16:
        maxMantBits = 16  # to make sure we don't ever overflow mantissa holders
    sfBands = codingParams.sfBands
    # vectorizing the Mantissa function call
    # vMantissa = np.vectorize(Mantissa)

    # compute target mantissa bit budget for this block of halfN MDCT mantissas
    bitBudget = codingParams.targetBitsPerSample * halfN  # this is overall target bit rate
    bitBudget -= nScaleBits * (
        sfBands.nBands + 1
    )  # less scale factor bits (including overall scale factor)
    bitBudget -= codingParams.nMantSizeBits * sfBands.nBands  # less mantissa bit allocation bits

    # window data for side chain FFT and also window and compute MDCT
    timeSamples = data
    mdctTimeSamples = SineWindow(data)
    mdctLines = MDCT(mdctTimeSamples, halfN, halfN)[:halfN]

    # compute overall scale factor for this block and boost mdctLines using it
    maxLine = np.max(np.abs(mdctLines))
    overallScale = ScaleFactor(
        maxLine, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLines *= (1 << overallScale)

    # # compute SPLs
    # bandPeaks=np.zeros(25)
    # for i in np.arange(sfBands.nBands):
    #     bandPeaks[i]=np.amax(mdctLines[sfBands.lowerLine[i]:sfBands.upperLine[i]])
    # from psychoac import SPL
    # bandPeaks=SPL(bandPeaks)

    # compute the mantissa bit allocations
    # compute SMRs in side chain FFT
    SMRs = CalcSMRs(timeSamples, mdctLines, overallScale,
                    codingParams.sampleRate, sfBands)

    # perform bit allocation using SMR results
    bitAlloc = BitAlloc(bitBudget, maxMantBits, sfBands.nBands, sfBands.nLines,
                        SMRs)
    # bitAlloc = BitAllocUniform(bitBudget, maxMantBits, sfBands.nBands, sfBands.nLines)
    # bitAlloc = BitAllocConstSNR(bitBudget, maxMantBits, sfBands.nBands, sfBands.nLines, bandPeaks)
    # bitAlloc = BitAllocConstMNR(bitBudget, maxMantBits, sfBands.nBands, sfBands.nLines, SMRs)

    # given the bit allocations, quantize the mdct lines in each band
    scaleFactor = np.empty(sfBands.nBands, dtype=np.int32)
    nMant = halfN
    # print nMant
    for iBand in range(sfBands.nBands):
        if not bitAlloc[iBand]:
            nMant -= sfBands.nLines[
                iBand]  # account for mantissas not being transmitted
    # print nMant
    mantissa = np.empty(nMant, dtype=np.int32)
    iMant = 0
    for iBand in range(sfBands.nBands):
        lowLine = sfBands.lowerLine[iBand]
        highLine = sfBands.upperLine[
            iBand] + 1  # extra value is because slices don't include last value
        nLines = sfBands.nLines[iBand]
        scaleLine = np.max(np.abs(mdctLines[lowLine:highLine]))
        scaleFactor[iBand] = ScaleFactor(scaleLine, nScaleBits,
                                         bitAlloc[iBand])
        if bitAlloc[iBand]:
            # print len(mdctLines[lowLine:highLine])
            # print scaleFactor[iBand]
            # print nScaleBits
            # print bitAlloc[iBand]
            # print len(mantissa[iMant:iMant+nLines])
            # output = vMantissa(mdctLines[lowLine:highLine],scaleFactor[iBand], nScaleBits, bitAlloc[iBand])
            # print len(output)
            # print iMant
            # print nMant
            # print nLines
            # print '\n'
            mantissa[iMant:iMant + nLines] = vMantissa(
                mdctLines[lowLine:highLine], scaleFactor[iBand], nScaleBits,
                bitAlloc[iBand])
            iMant += nLines
    # end of loop over scale factor bands

    # return results
    return (scaleFactor, bitAlloc, mantissa, overallScale)
示例#2
0
def EncodeSingleChannel(data, codingParams):
    """Encodes a single-channel block of signed-fraction data based on the parameters in a PACFile object"""

    # prepare various constants
    """----------------------------------------EDIT--------------------------------------------------"""
    # compute the actual window and half window lengths
    N = codingParams.a + codingParams.b
    halfN = (codingParams.a + codingParams.b) / 2.
    """------------------------------------END-EDIT--------------------------------------------------"""

    nScaleBits = codingParams.nScaleBits
    maxMantBits = (
        1 << codingParams.nMantSizeBits
    )  # 1 isn't an allowed bit allocation so n size bits counts up to 2^n
    if maxMantBits > 16:
        maxMantBits = 16  # to make sure we don't ever overflow mantissa holders
    sfBands = codingParams.sfBands
    # vectorizing the Mantissa function call
    #    vMantissa = np.vectorize(Mantissa)

    # compute target mantissa bit budget for this block of halfN MDCT mantissas
    bitBudget = codingParams.targetBitsPerSample * halfN  # this is overall target bit rate
    bitBudget -= nScaleBits * (
        sfBands.nBands + 1
    )  # less scale factor bits (including overall scale factor)
    bitBudget -= codingParams.nMantSizeBits * sfBands.nBands  # less mantissa bit allocation bits
    """----------------------------------------EDIT--------------------------------------------------"""
    # account for (binary) block length bits
    bitBudget -= codingParams.blkswBitA
    bitBudget -= codingParams.blkswBitB
    # add bit reservoir
    bitBudget += codingParams.bitReservoir
    """------------------------------------END-EDIT--------------------------------------------------"""

    # window data for side chain FFT and also window and compute MDCT
    timeSamples = data
    """----------------------------------------EDIT--------------------------------------------------"""
    # use TransitionWindow instead of SineWindow
    # send MDCT and TransitionWindow the actual block lengths
    mdctTimeSamples = TransitionWindow(data, codingParams.a, codingParams.b)
    mdctLines = MDCT(mdctTimeSamples, codingParams.a, codingParams.b)[:halfN]
    """------------------------------------END-EDIT--------------------------------------------------"""

    # compute overall scale factor for this block and boost mdctLines using it
    maxLine = np.max(np.abs(mdctLines))
    overallScale = ScaleFactor(
        maxLine, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLines *= (1 << overallScale)

    # compute the mantissa bit allocations
    # compute SMRs in side chain FFT
    SMRs = CalcSMRs(timeSamples, mdctLines, overallScale,
                    codingParams.sampleRate, sfBands)
    # perform bit allocation using SMR results
    (bitAlloc, remaining_bits) = BitAlloc(bitBudget, maxMantBits,
                                          sfBands.nBands, sfBands.nLines, SMRs)
    bitAlloc = bitAlloc.astype(int)
    """----------------------------------------EDIT--------------------------------------------------"""
    codingParams.bitReservoir = int(remaining_bits)
    """--------------------------------------END-EDIT--------------------------------------------------"""

    # given the bit allocations, quantize the mdct lines in each band
    scaleFactor = np.empty(sfBands.nBands, dtype=np.int32)
    nMant = halfN
    for iBand in range(sfBands.nBands):
        if not bitAlloc[iBand]:
            nMant -= sfBands.nLines[
                iBand]  # account for mantissas not being transmitted
    mantissa = np.empty(nMant, dtype=np.int32)
    iMant = 0
    for iBand in range(sfBands.nBands):
        lowLine = sfBands.lowerLine[iBand]
        highLine = sfBands.upperLine[
            iBand] + 1  # extra value is because slices don't include last value
        nLines = sfBands.nLines[iBand]
        scaleLine = np.max(np.abs(mdctLines[lowLine:highLine]))
        scaleFactor[iBand] = ScaleFactor(scaleLine, nScaleBits,
                                         bitAlloc[iBand])
        if bitAlloc[iBand]:
            mantissa[iMant:iMant + nLines] = vMantissa(
                mdctLines[lowLine:highLine], scaleFactor[iBand], nScaleBits,
                bitAlloc[iBand])
            iMant += nLines
    # end of loop over scale factor bands

    # return results
    return (scaleFactor, bitAlloc, mantissa, overallScale)
示例#3
0
def JointEncodeChannels(dataLeft, dataRight, codingParams):
    """Encodes a single-channel block of signed-fraction data based on the parameters in a PACFile object"""

    #calculate the mid channel and the side channel
    dataMid = (dataLeft + dataRight) / 2.0
    dataSide = (dataLeft - dataRight) / 2.0
    """----------------------------------------EDIT--------------------------------------------------"""
    # compute the actual window and half window lengths
    N = codingParams.a + codingParams.b
    halfN = (codingParams.a + codingParams.b) / 2.
    """------------------------------------END-EDIT--------------------------------------------------"""

    nScaleBits = codingParams.nScaleBits
    maxMantBits = (
        1 << codingParams.nMantSizeBits
    )  # 1 isn't an allowed bit allocation so n size bits counts up to 2^n
    if maxMantBits > 16:
        maxMantBits = 16  # to make sure we don't ever overflow mantissa holders
    sfBands = codingParams.sfBands
    # vectorizing the Mantissa function call
    #    vMantissa = np.vectorize(Mantissa)

    # compute target mantissa bit budget for this block of halfN MDCT mantissas
    bitBudget = codingParams.targetBitsPerSample * halfN  # this is overall target bit rate
    bitBudget -= nScaleBits * (
        sfBands.nBands
    )  # less scale factor bits (including overall scale factor)
    bitBudget -= codingParams.nMantSizeBits * sfBands.nBands  # less mantissa bit allocation bits

    ### need to also factor in subtracting the scale factor bands for a bit determining m/s code
    bitBudget += bitBudget
    bitBudget -= sfBands.nBands
    bitBudget -= nScaleBits * 4

    bitBudget += codingParams.bitReservoir
    """----------------------------------------EDIT--------------------------------------------------"""
    # account for (binary) block length bits
    bitBudget -= codingParams.blkswBitA
    bitBudget -= codingParams.blkswBitB
    """------------------------------------END-EDIT--------------------------------------------------"""

    ### Compute all of the MDCTs For the Left, Right, Mid, Side
    # window data for side chain FFT and also window and compute MDCT
    timeSamples_Left = dataLeft
    """----------------------------------------EDIT--------------------------------------------------"""
    # use TransitionWindow instead of SineWindow
    # send MDCT and TransitionWindow the actual block lengths
    mdctTimeSamples_Left = TransitionWindow(dataLeft, codingParams.a,
                                            codingParams.b)
    mdctLinesLeft = MDCT(mdctTimeSamples_Left, codingParams.a,
                         codingParams.b)[:halfN]
    """------------------------------------END-EDIT--------------------------------------------------"""

    timeSamples_Right = dataRight
    """----------------------------------------EDIT--------------------------------------------------"""
    # use TransitionWindow instead of SineWindow
    # send MDCT and TransitionWindow the actual block lengths
    mdctTimeSamples_Right = TransitionWindow(dataRight, codingParams.a,
                                             codingParams.b)
    mdctLinesRight = MDCT(mdctTimeSamples_Right, codingParams.a,
                          codingParams.b)[:halfN]
    """------------------------------------END-EDIT--------------------------------------------------"""

    timeSamples_Mid = dataMid
    """----------------------------------------EDIT--------------------------------------------------"""
    # use TransitionWindow instead of SineWindow
    # send MDCT and TransitionWindow the actual block lengths
    mdctTimeSamples_Mid = TransitionWindow(dataMid, codingParams.a,
                                           codingParams.b)
    mdctLinesMid = MDCT(mdctTimeSamples_Mid, codingParams.a,
                        codingParams.b)[:halfN]
    """------------------------------------END-EDIT--------------------------------------------------"""

    timeSamples_Side = dataSide
    """----------------------------------------EDIT--------------------------------------------------"""
    # use TransitionWindow instead of SineWindow
    # send MDCT and TransitionWindow the actual block lengths
    mdctTimeSamples_Side = TransitionWindow(dataSide, codingParams.a,
                                            codingParams.b)
    mdctLinesSide = MDCT(mdctTimeSamples_Side, codingParams.a,
                         codingParams.b)[:halfN]
    """------------------------------------END-EDIT--------------------------------------------------"""
    ###

    # determine which bands to enable ms coding
    ms_switch = MSSwitchSFBands(mdctLinesLeft, mdctLinesRight, sfBands)

    ### compute scale factors for lr ms: this is the normalization stuff
    # compute overall scale factor for this block and boost mdctLines using it
    maxLine_Left = np.max(np.abs(mdctLinesLeft))
    overallScale_Left = ScaleFactor(
        maxLine_Left, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLinesLeft *= (1 << overallScale_Left)

    maxLine_Right = np.max(np.abs(mdctLinesRight))
    overallScale_Right = ScaleFactor(
        maxLine_Right, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLinesRight *= (1 << overallScale_Right)

    maxLine_Mid = np.max(np.abs(mdctLinesMid))
    overallScale_Mid = ScaleFactor(
        maxLine_Mid, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLinesMid *= (1 << overallScale_Mid)

    maxLine_Side = np.max(np.abs(mdctLinesSide))
    overallScale_Side = ScaleFactor(
        maxLine_Side, nScaleBits)  #leading zeroes don't depend on nMantBits
    mdctLinesSide *= (1 << overallScale_Side)

    scaleFactorsPack = []
    scaleFactorsPack.append(overallScale_Left)
    scaleFactorsPack.append(overallScale_Right)
    scaleFactorsPack.append(overallScale_Mid)
    scaleFactorsPack.append(overallScale_Side)

    ###

    ### Calculate the new thresholds for mid and side with the masking factors
    midThresh = getMaskedThreshold(timeSamples_Mid, mdctLinesMid,
                                   overallScale_Mid, codingParams.sampleRate,
                                   sfBands)
    sideThresh = getMaskedThreshold(timeSamples_Side, mdctLinesSide,
                                    overallScale_Side, codingParams.sampleRate,
                                    sfBands)

    lin = np.linspace(0, N - 1, N)
    freq = np.add(lin, 0.5)
    freq = np.multiply(freq, (codingParams.sampleRate) / N)
    freqtest = freq[0:N / 2]
    zVec = Bark(freqtest)

    new_threshs = StereoMaskingFactor(midThresh, sideThresh, sfBands, zVec)
    new_midThresh = new_threshs[0]
    new_sideThresh = new_threshs[1]

    ### Calculate all of the SMRs for all
    SMRs_Left = CalcSMRs(timeSamples_Left, mdctLinesLeft, overallScale_Left,
                         codingParams.sampleRate, sfBands)
    SMRs_Right = CalcSMRs(timeSamples_Right, mdctLinesRight,
                          overallScale_Right, codingParams.sampleRate, sfBands)
    SMRs_Mid = CalcSMRs(timeSamples_Mid, mdctLinesMid, overallScale_Mid,
                        codingParams.sampleRate, sfBands, 1, new_midThresh)
    SMRs_Side = CalcSMRs(timeSamples_Side, mdctLinesSide, overallScale_Side,
                         codingParams.sampleRate, sfBands, 1, new_sideThresh)
    (SMR1, SMR2) = OverallSMRs(SMRs_Left, SMRs_Right, SMRs_Mid, SMRs_Side,
                               sfBands, ms_switch)

    ###

    # perform bit allocation using SMR results
    #need to concatenate together, then split appart once the allocations have been made back into 2 channels
    nLines1 = sfBands.nLines
    nLinesPass = np.append(nLines1, nLines1)

    SMRsConcat = SMR1
    SMRsPass = np.append(SMRsConcat, SMR2)

    (bitAlloc, remaining_bits) = BitAlloc(bitBudget, maxMantBits,
                                          2 * sfBands.nBands, nLinesPass,
                                          SMRsPass)
    bitAlloc = bitAlloc.astype(int)

    bitAlloc1 = bitAlloc[0:sfBands.nBands]
    bitAlloc2 = bitAlloc[sfBands.nBands:]
    codingParams.bitReservoir = int(remaining_bits)

    # given the bit allocations, quantize the mdct lines in each band
    scaleFactor1 = np.empty(sfBands.nBands, dtype=np.int32)
    scaleFactor2 = np.empty(sfBands.nBands, dtype=np.int32)
    nMant = halfN

    #for the first bit allocation of the left and mid signals
    for iBand in range(sfBands.nBands):
        if not bitAlloc1[iBand]:
            nMant -= sfBands.nLines[
                iBand]  # account for mantissas not being transmitted
    mantissa1 = np.empty(nMant, dtype=np.int32)
    iMant = 0
    for iBand in range(sfBands.nBands):
        ms_band = ms_switch[iBand]
        lowLine = sfBands.lowerLine[iBand]
        highLine = sfBands.upperLine[
            iBand] + 1  # extra value is because slices don't include last value
        nLines = sfBands.nLines[iBand]

        if ms_band == 1:
            mdctLines = mdctLinesMid
        else:
            mdctLines = mdctLinesLeft

        scaleLine = np.max(np.abs(mdctLines[lowLine:highLine]))
        scaleFactor1[iBand] = ScaleFactor(scaleLine, nScaleBits,
                                          bitAlloc1[iBand])
        if bitAlloc1[iBand]:
            mantissa1[iMant:iMant + nLines] = vMantissa(
                mdctLines[lowLine:highLine], scaleFactor1[iBand], nScaleBits,
                bitAlloc1[iBand])
            iMant += nLines
    # end of loop over scale factor bands

    nMant = halfN
    #for the second bit allocation of the right and side signals
    for iBand in range(sfBands.nBands):
        if not bitAlloc2[iBand]:
            nMant -= sfBands.nLines[
                iBand]  # account for mantissas not being transmitted
    mantissa2 = np.empty(nMant, dtype=np.int32)
    iMant = 0
    for iBand in range(sfBands.nBands):
        ms_band = ms_switch[iBand]
        lowLine = sfBands.lowerLine[iBand]
        highLine = sfBands.upperLine[
            iBand] + 1  # extra value is because slices don't include last value
        nLines = sfBands.nLines[iBand]

        if ms_band == 1:
            mdctLines = mdctLinesSide
        else:
            mdctLines = mdctLinesRight

        scaleLine = np.max(np.abs(mdctLines[lowLine:highLine]))
        scaleFactor2[iBand] = ScaleFactor(scaleLine, nScaleBits,
                                          bitAlloc2[iBand])

        if bitAlloc2[iBand]:
            mantissa2[iMant:iMant + nLines] = vMantissa(
                mdctLines[lowLine:highLine], scaleFactor2[iBand], nScaleBits,
                bitAlloc2[iBand])
            iMant += nLines
    # end of loop over scale factor bands

    # return results

    scaleFactors = []
    bitAlloc = []
    mantissa = []

    scaleFactors.append(scaleFactor1)
    scaleFactors.append(scaleFactor2)
    bitAlloc.append(bitAlloc1)
    bitAlloc.append(bitAlloc2)
    mantissa.append(mantissa1)
    mantissa.append(mantissa2)

    return (scaleFactors, bitAlloc, mantissa, scaleFactorsPack, ms_switch)
示例#4
0
def EncodeDualChannel(data,codingParams,LRMS,huffman):
    """Encodes a single-channel block of signed-fraction data based on the parameters in a PACFile object"""

    # prepare various constants
    halfN = codingParams.nMDCTLines
    nScaleBits = codingParams.nScaleBits
    maxMantBits = (1<<codingParams.nMantSizeBits)  # 1 isn't an allowed bit allocation so n size bits counts up to 2^n
    if maxMantBits>16: maxMantBits = 16  # to make sure we don't ever overflow mantissa holders
    sfBands = codingParams.sfBands

    # compute target mantissa bit budget for this block of halfN MDCT mantissas
    bitBudget = codingParams.targetBitsPerSample * halfN  # this is overall target bit rate
    bitBudget -= nScaleBits*(sfBands.nBands +1)  # less scale factor bits (including overall scale factor)
    bitBudget -= codingParams.nMantSizeBits*sfBands.nBands  # less mantissa bit allocation bits
    '''Subtract the bits needed for the table ID'''
    bitBudget -= codingParams.nTableIDBits
    '''Get extra bits saved from Huffman encoding to do bit alloc'''
    codingParams.extraBits += huffman.withdrawBits()

    timeSamples=[]
    mdctTimeSamples=[]
    mdctLines=[]
    maxLine=[]
    overallScale=[]

    for iCh in range(codingParams.nChannels):
        # window data for side chain FFT and also window and compute MDCT
        timeSamples.append(data[iCh])
        mdctTimeSamples.append(SineWindow(data[iCh]))
        mdctLines.append(MDCT(mdctTimeSamples[iCh], halfN, halfN)[:halfN])

        # compute overall scale factor for this block and boost mdctLines using it
        maxLine.append(np.max( np.abs(mdctLines[iCh]) ) )
        overallScale.append(ScaleFactor(maxLine[iCh],nScaleBits) ) #leading zeroes don't depend on nMantBits
        mdctLines[iCh] *= (1<<overallScale[iCh])

    # compute the mantissa bit allocations
    # compute SMRs in side chain FFT
    (SMRs,LRMSmdctLines) = getStereoMaskThreshold(timeSamples, mdctLines, overallScale, codingParams.sampleRate, sfBands, LRMS, codingParams)

    bitAlloc=[]
    scaleFactor=[]
    mantissa=[]

    # perform bit allocation using SMR results
    for iCh in range(codingParams.nChannels):
        ba,bitDifference=BitAlloc(bitBudget, codingParams.extraBits, maxMantBits, sfBands.nBands, sfBands.nLines, SMRs[iCh], LRMS)
        bitAlloc.append(ba)
        codingParams.extraBits+=bitDifference

        # given the bit allocations, quantize the mdct lines in each band
        scaleFactor.append(np.empty(sfBands.nBands,dtype=np.int32))
        nMant=halfN
        for iBand in range(sfBands.nBands):
            if not bitAlloc[iCh][iBand]: nMant-= sfBands.nLines[iBand]  # account for mantissas not being transmitted
        mantissa.append(np.empty(nMant,dtype=np.int32))
        iMant=0
        for iBand in range(sfBands.nBands):
            lowLine = sfBands.lowerLine[iBand]
            highLine = sfBands.upperLine[iBand] + 1  # extra value is because slices don't include last value
            nLines= sfBands.nLines[iBand]
            scaleLine = np.max(np.abs( LRMSmdctLines[iCh][lowLine:highLine] ) )
            scaleFactor[iCh][iBand] = ScaleFactor(scaleLine, nScaleBits, bitAlloc[iCh][iBand])
            if bitAlloc[iCh][iBand]:
                mantissa[iCh][iMant:iMant+nLines] = vMantissa(LRMSmdctLines[iCh][lowLine:highLine],scaleFactor[iCh][iBand], nScaleBits, bitAlloc[iCh][iBand])
                iMant += nLines
        # end of loop over scale factor bands

    # return results
    return (scaleFactor, bitAlloc, mantissa, overallScale)