Ejemplo n.º 1
0
/* Sect D.1 Step4b 
   A tone within the range (start -> end), must be 7.0 dB greater than
   all it's neighbours within +/- srange. Don't count its immediate neighbours. */
void psycho_3_tonal_label_range(FLOAT *power, int *tonelabel, int *maxima, FLOAT *Xtm, int start, int end, int srange) {
  int j,k;

  for (k=start;k<end;k++)  /* Search for all the maxima in this range */
    if (maxima[k] == 1) {
      tonelabel[k] = TONE; /* assume it's a TONE and then prove otherwise */
      for (j=-srange;j<=+srange;j++) /* Check the neighbours within +/- srange */
	if (abs(j) > 1) /* Don't count the immediate neighbours, or itself */
	  if ((power[k] - power[k+j]) < 7.0)
	    tonelabel[k] = 0; /* Not greater by 7dB, therefore not a tone */
      if (tonelabel[k] == TONE) {
	/* Calculate the sound pressure level for this tone by summing 
	   the adjacent spectral lines
	   Xtm[k] = 10 * log10( pow(10.0, 0.1*power[k-1]) + pow(10.0, 0.1*power[k]) 
	                      + pow(10.0, 0.1*power[k+1]) ); */
	double temp = psycho_3_add_db(power[k-1], power[k]);
	Xtm[k] = psycho_3_add_db(temp, power[k+1]);
	
	/* *ALL* spectral lines within +/- srange are set to -inf dB 
	   So that when we do the noise calculate, they are not counted */
	for (j=-srange;j<=+srange;j++)
	    power[k+j] = DBMIN;
      }
    }
}
Ejemplo n.º 2
0
/* D.1 Step 4.c Labelling non-tonal (noise) components 
   Sum the energies in each critical band (the tone energies have been removed 
   during the tone labelling).
   Find the "geometric mean" of these energies - i.e. find the best spot to put the
   sum of energies within this critical band. */
static void psycho_3_noise_label(psycho_3_mem * mem, FLOAT power[HBLKSIZE], FLOAT energy[BLKSIZE],
                                 int *tonelabel, int *noiselabel, FLOAT Xnm[HBLKSIZE])
{
    int i, j;
    int cbands = mem->cbands;
    int *cbandindex = mem->cbandindex;

    Xnm[0] = DBMIN;
    for (i = 0; i < cbands; i++) {
        /* for each critical band */
        FLOAT sum = DBMIN;
        FLOAT esum = 0;
        FLOAT centreweight = 0;
        int centre;
        for (j = cbandindex[i]; j < cbandindex[i + 1]; j++) {
            Xnm[j] = DBMIN;
            /* go through all the spectral lines within the critical band, adding the energies. The 
               tone energies have already been removed */
            if (power[j] != DBMIN) {
                /* Found a noise energy, add it to the sum */
                sum = psycho_3_add_db(mem, power[j], sum);

                /* calculations for the geometric mean FIXME MFC Feb 2003: Would it just be easier
                   to do the *whole* of psycho_1 in the energy domain rather than in the dB domain?
                   FIXME: This is just a lazy arsed arithmetic mean. Don't know if it's really going 
                   to make that much difference */
                esum += energy[j];  /* Calculate the sum of energies */
                centreweight += (j - cbandindex[i]) * energy[j];    /* And the energy moment */
            }
        }

        /* MEANX, crash on AMD64 without this hack. See
           https://sourceforge.net/tracker/?func=detail&atid=735435&aid=1453400&group_id=136040
           Probably a better way to do this */
        if (sum <= DBMIN || esum < 0.00001)
            /* If the energy sum is really small, just pretend the noise occurs in the centre
               frequency line */
            centre = (cbandindex[i] + cbandindex[i + 1]) / 2;
        else {
            /* Otherwise, work out the mean position of the noise, and put it there. */
            centre = cbandindex[i] + (int) (centreweight / esum);
        }
        // /MEANX
        Xnm[centre] = sum;
        noiselabel[centre] = NOISE;
    }
}
Ejemplo n.º 3
0
/* D.1 Step 4.c Labelling non-tonal (noise) components 
   Sum the energies in each critical band (the tone energies have been removed 
   during the tone labelling).
   Find the "geometric mean" of these energies - i.e. find the best spot to put the
   sum of energies within this critical band. */
void psycho_3_noise_label (FLOAT power[HBLKSIZE], FLOAT energy[BLKSIZE], int *tonelabel, int *noiselabel, FLOAT Xnm[HBLKSIZE]) {
  int i,j;
  
  Xnm[0] = DBMIN;
  for (i=0;i<cbands;i++) {
    /* for each critical band */
    double sum = DBMIN;
    double esum=0;
    double centreweight = 0;
    int centre;
    for (j=cbandindex[i]; j<cbandindex[i+1]; j++) {
      Xnm[j] = DBMIN;
      /* go through all the spectral lines within the critical band, 
	 adding the energies. The tone energies have already been removed */
      if (power[j] != DBMIN) {
	/* Found a noise energy, add it to the sum */
	sum = psycho_3_add_db(power[j], sum);
	
	/* calculations for the geometric mean 
	   FIXME MFC Feb 2003: Would it just be easier to
	   do the *whole* of psycho_1 in the energy domain rather than 
	   in the dB domain? 
	   FIXME: This is just a lazy arsed arithmetic mean. Don't know 
	   if it's really going to make that much difference */
	esum += energy[j]; /* Calculate the sum of energies */
	centreweight += (j - cbandindex[i]) * energy[j]; /* And the energy moment */
      }
    }

    if (sum<=DBMIN) 
      /* If the energy sum is really small, just pretend the noise occurs 
	 in the centre frequency line */
      centre = (cbandindex[i] + cbandindex[i+1])/2;
    else
      /* Otherwise, work out the mean position of the noise, and put it there. */
      centre = cbandindex[i] + (int)(centreweight/esum);

    Xnm[centre] = sum;
    noiselabel[centre] = NOISE;
  }
}
Ejemplo n.º 4
0
/* ISO11172 Sect D.1 Step 6
   Calculation of individual masking thresholds
   Work out how each of the tones&noises maskes other frequencies 
   NOTE: Only a subset of other frequencies is checked. According to the 
   standard different subbands are subsampled to different amounts.
   See psycho_3_init and freq_subset */
void psycho_3_threshold(FLOAT *LTg, int *tonelabel, FLOAT *Xtm, int *noiselabel, FLOAT *Xnm, FLOAT *bark, FLOAT *ath, int bit_rate, int *freq_subset) {
  int i,j,k;
  FLOAT LTtm[SUBSIZE];
  FLOAT LTnm[SUBSIZE];

  for (i=0;i<SUBSIZE;i++) {
    LTtm[i] = DBMIN;
    LTnm[i] = DBMIN;
  }
  /* Loop over the entire spectrum and find every noise and tone 
     And then with each noise/tone work out how it masks 
     the spectral lines around it */
  for (k=1;k<HBLKSIZE;k++) {
    /* Find every tone */
    if (tonelabel[k]==TONE) {
      for (j=0;j<SUBSIZE;j++) {
	/* figure out how it masks the levels around it */  
	FLOAT dz = bark[freq_subset[j]] - bark[k];     
	if (dz >= -3.0 && dz < 8.0) {
	  FLOAT vf;
	  FLOAT av = -1.525 - 0.275 * bark[k] - 4.5 + Xtm[k];
	  /* masking function for lower & upper slopes */
	  if (dz < -1)
	    vf = 17 * (dz + 1) - (0.4 * Xtm[k] + 6);
	  else if (dz < 0)
	    vf = (0.4 * Xtm[k] + 6) * dz;
	  else if (dz < 1)
	    vf = (-17 * dz);
	  else
	    vf = -(dz - 1) * (17 - 0.15 * Xtm[k]) - 17;
	  LTtm[j] = psycho_3_add_db (LTtm[j], av + vf);
	}    
      }
    }

    /* find every noise label */
    if (noiselabel[k]==NOISE) {
      for (j=0;j<SUBSIZE;j++) {
	/* figure out how it masks the levels around it */  
	FLOAT dz = bark[freq_subset[j]] - bark[k];     
	if (dz >= -3.0 && dz < 8.0) {
	  FLOAT vf;
	  FLOAT av = -1.525 - 0.175 * bark[k] - 0.5 + Xnm[k]; 
	  /* masking function for lower & upper slopes */
	  if (dz < -1)
	    vf = 17 * (dz + 1) - (0.4 * Xnm[k] + 6);
	  else if (dz < 0)
	    vf = (0.4 * Xnm[k] + 6) * dz;
	  else if (dz < 1)
	    vf = (-17 * dz);
	  else
	    vf = -(dz - 1) * (17 - 0.15 * Xnm[k]) - 17;
	  LTnm[j] = psycho_3_add_db (LTnm[j], av + vf);
	}    
      }
    }
  }

  /* ISO11172 D.1 Step 7
     Calculate the global masking threhold */
  for (i=0;i<SUBSIZE;i++) {
    LTg[i] = psycho_3_add_db(LTnm[i], LTtm[i]);
    if (bit_rate < 96)
      LTg[i] = psycho_3_add_db(ath[freq_subset[i]], LTg[i]);
    else
      LTg[i] = psycho_3_add_db(ath[freq_subset[i]]-12.0, LTg[i]);
  }
}