Ejemplo n.º 1
0
def SimpleMDCTEncoding(approx ,  
                   targetBitrate , 
                   Q=7 , 
                   encodeCoeffs=True,                     
                   encodeIndexes=True , 
                   subsampling = 1, 
                   TsPenalty=False, 
                   saveOutputFilePath=None,
                   outputAllIndexes=False):
    """ Simple encoder of a sparse approximation 
    
    Arguments:
    
        - `approx`: a :class:`.pymp_Approx` object containing atoms from the decomposition
        
        - `targetBitrate`: a float indicating the target bitrate. Atoms are considered in decreasing amplitude order. 
        The encoding will stop either when the target Bitrate it reached or when all atoms of `approx` have been considered
        
        - `Q`: The number of midtread quantizer steps. Default is 7, increase this number for higher bitrates
        
        - `TsPenalty`: a boolean indicating whether LOMP algorithm has been used, and addition time-shift parameters must be encoded
        
    Returns:
    
        - `SNR`: The achieved Signal to Noise Ratio 
        
        - `Bitrate`: The achieved bitrate, not necessarily equal to the given target 
        
        - `quantizedApprox`: a :class:`.pymp_Approx` object containing the quantized atoms
    
    """ 
    # determine the fixed cost (in bits) of an atom's index 
    indexcost = log(approx.length*len(approx.dico.sizes)/subsampling,2)    
    
    # determine the fixed cost (in bits) of an atom's weight 
    Coeffcost = Q;
        
    # instantiate the quantized approximation
    quantizedApprox = pymp_Approx.pymp_Approx(approx.dico, 
                                               [], 
                                               approx.originalSignal, 
                                               approx.length, 
                                               approx.samplingFrequency)

    
    total = 0
    TsCosts = 0    

    # First loop to evaluate the max of atom's weight and 
    maxValue = 0
    for atom in approx.atoms:
        if abs(atom.mdct_value) > abs(maxValue):
                maxValue = atom.mdct_value

    # deduce the Quantizer step width
    quantizerWidth = maxValue/float(2**(Q-1))
    
    if quantizerWidth == 0:
        raise ValueError('zero found for quantizer step width...')
    
    if approx.atomNumber <= 0:
        raise ValueError('approx object has an empty list of atoms')
    
    # second loop: atom after atom    
    for atom in approx.atoms:
                
        value = atom.mdct_value;
            
        # Quantize the atom's weight        
        quantizedValue =  ceil((value - quantizerWidth/2) / quantizerWidth)*quantizerWidth

        # If quantized value is 0, no need to include it
        if quantizedValue == 0:
            # If one is 100% sure atom's weights are in decreasing order, we could stop right here
            # But in the general case, we're not...
            continue
        
        else:
            total += 1

        # instantiate the quantized atom        
        quantizedAtom = pymp_MDCTAtom.pymp_MDCTAtom(atom.length , 
                                                    atom.amplitude , 
                                                    atom.timePosition , 
                                                    atom.frequencyBin , 
                                                    atom.samplingFrequency,                                                         
                                                    mdctCoeff = quantizedValue)    
            
        # recompute true waveform        
        quantizedAtom.frame = atom.frame  
        quantizedAtom.waveform = atom.waveform*(sqrt((quantizedAtom.mdct_value**2)/(atom.mdct_value**2)))

        # add atom to quantized Approx                
        quantizedApprox.addAtom(quantizedAtom)
        
         
        # All time-shift optimal parameters live in an interval of length L/2 where
        # L is the atom scale 
        if TsPenalty:
                TsCosts += log(atom.length/2, 2);
                
        # estimate current bitrate: Each atom coding cost is fixed!!
        nbBitsSoFar = (total *( indexcost + Coeffcost)) + TsCosts;
        br = float(nbBitsSoFar)/(float(approx.length)/float(approx.samplingFrequency))
                
        if br >= targetBitrate:
            break;

    # Evaluate True Bitrate            
    bitrate = float(nbBitsSoFar)/(float(approx.length)/float(approx.samplingFrequency))
        
    approxEnergy = sum(quantizedApprox.recomposedSignal.dataVec**2)
    resEnergy = sum((approx.originalSignal.dataVec - quantizedApprox.recomposedSignal.dataVec)**2)
    
    # Evaluate distorsion 
    SNR = 10.0*log( approxEnergy / resEnergy , 10)
                                
    return SNR , bitrate, quantizedApprox
Ejemplo n.º 2
0
mpl.rcParams['text.usetex'] = True;

from Classes import pymp_Signal, pymp_Approx;
from Classes.mdct import *


atomShort = pymp_MDCTAtom.pymp_MDCTAtom(32, 1, 1024, 4, 8000, 1);
atomMid = pymp_MDCTAtom.pymp_MDCTAtom(256, 1, 256, 10, 8000, 1);
atomLong = pymp_MDCTAtom.pymp_MDCTAtom(2048, 1, 0, 40, 8000, 1);

atomShort.synthesize();
atomMid.synthesize();
atomLong.synthesize();

# Initialize empty approximant
approx  = pymp_Approx.pymp_Approx(None, [], None, atomLong.length, atomLong.samplingFrequency)

# add atoms
approx.addAtom(atomShort)
approx.addAtom(atomMid)
approx.addAtom(atomLong)

timeVec = np.arange(approx.length)/float(approx.samplingFrequency);

# Plot the recomposed Signal, both in time domain and Time-Frequency
plt.figure()
plt.subplot(211)
plt.plot(timeVec,approx.recomposedSignal.dataVec)
plt.xlim([0,float(approx.length)/float(approx.samplingFrequency)])
plt.grid()
plt.subplot(212)