DSPRelated.com
Forums

Is there an easier way to calculate a frequency on a set of wav samples?

Started by SA Dev March 29, 2004
SA Dev wrote:

> Jon, > > >>sound effects at all, he just gets an audio feed. If I'm on the right > > track, I > >>think Jim's suggestion of a AGC based on a high-pass version of the audio > > is > >>right on the money. > > > Ok, I think I'm understanding at least what you are suggesting. If I create > a high-pass version of the audio (a version of the audio which cuts out the > lower frequencies leaving only the higher ones?), and run an AGC on this > higher version, it will determine a ratio I can use to alter the original > version of the audio? I'm guessing that the reason for the high-pass > version is because these are the sounds that are loudest to the ear and in a > sense I will be ignoring the low frequency rumbles that have been throwing > me off? > > If this is right, do you have any C code examples of producing a high pass > version (is this a low pass filter?), and/or AGC code? > > Thanks, > > SA Dev
Understand that AGC will flatten the dynamics of the individual tracks. It won't just make each of them the same volume as the others, it will make all parts of any one of them about the same volume of any other part. If that's OK, then the scheme is for you. Jerry -- Engineering is the art of making what you want from things you can get. �����������������������������������������������������������������������
Hi Jim,

Ok, I implemented the AGC, check it and let me know what errors you see.  I
didn't implement the DC because I didn't understand your formula and how it
would fit here.  My samples coming in are 16 bit signed integers.  This
produces sound that is very altered from the original (static).

INLINE INT16 calc_volumeM(int sample)
{
  static double gain,rect,envelope=0;
  static double attack=0.1,decay=0.1;
  static double too_weak=1000,too_strong=10000;
  static double min_gain=0.1,max_gain=10;

  //what is envelopes starting value

  rect=sample>0?sample:-sample; //rectify

  if (rect>envelope)    // if it's bigger than the envelope, attack
    envelope += (rect-envelope) * attack;
  else                  // the signal is smaller than envelope, so decay
    envelope *= decay;

  if (envelope<too_weak)
    gain=max_gain;
  else if (envelope>too_strong)
     gain=min_gain;
  else gain = min_gain+
((envelope-too_weak)/(too_strong-too_weak))*(max_gain-min_gain);

  return (int)(sample*gain);
}

Thanks,

SA Dev


"Jim Thomas" <jthomas@bittware.com> wrote in message
news:106j34bqnob6461@corp.supernews.com...
> SA Dev wrote: > > Ok, I think I'm understanding at least what you are suggesting. If I create > > a high-pass version of the audio (a version of the audio which cuts out the > > lower frequencies leaving only the higher ones?), and run an AGC on this > > higher version, it will determine a ratio I can use to alter the original > > version of the audio? > > Yes. > > > I'm guessing that the reason for the high-pass > > version is because these are the sounds that are loudest to the ear and in a > > sense I will be ignoring the low frequency rumbles that have been throwing > > me off? > > Well... kinda. The ear is completely deaf to DC, but a typical AGC > circuit is not. The high pass removes that. > >snip> > Finally, apply the gain to the signal. You can use either the original > signal, or the output of the high pass. I'd be inclined to use the > high-pass output - otherwise, you might clip: > > output = hp_out * gain;
I would use the original signal so you don't lose the low frequencies in the original. That way, only the volume of the signal is changed, not the frequency content/tone. Yes you may have to worry about clipping, but appropriate scaling should be able to solve it. (Thinking about this a bit more, if there really is significant DC content, then perhaps it might make sense to apply a 20Hz HP filter to the whole signal. An ideal might be a 20 Hz HP for the whole signal, and maybe an additional 100 Hz HP for the signal that controls the AGC (commonly called the side chain signal). But that's probably overkill for this particular application.)
SA Dev wrote:
> Hi Jim, > > Ok, I implemented the AGC, check it and let me know what errors you see. I > didn't implement the DC because I didn't understand your formula and how it > would fit here.
It's an exponential filter, which can be used to estimate DC. It's normally considered a high-pass filter, but since we're subtracting out the dc value, that ocnverts it to a high-pass filter. There are other ways of building high-pass filters, but this one is computationally simple. Try it with "a" = 0.95 - it'll converge after 20 samples.
> My samples coming in are 16 bit signed integers. This > produces sound that is very altered from the original (static). > > INLINE INT16 calc_volumeM(int sample) > { > static double gain,rect,envelope=0; > static double attack=0.1,decay=0.1;
decay needs to be a lot bigger than that. Try something more like 0.999, or even 0.99999.
> static double too_weak=1000,too_strong=10000; > static double min_gain=0.1,max_gain=10; > > //what is envelopes starting value
An initial value of zero for envelope should be fine. It's going to take a little time for it to adapt up, but that's just how it is. The most important thing is that (1-a)+a does not exceed 1.0 once a and (1-a) are quantized - rounding can kill you here. You can think about the exponential filter like this (repeating the formula): y[n] = a*y[n-1] + (1-a)*x Suppose a = 0.99. The next y is 99% of the previous value, and 1% of the new sample. So if the envelope has reached a steady state of say, 1000, and all the new samples going into it are 0, it will slowly bleed down. If all the new samples are 2000, it will ramp up until it meets 2000. When x == y, y won't change. It behaves a lot like a moving average. If you're more comfortable with a moving average, you could just implement that instead. The exponential filter doesn't require that you store a bunch of old values of x though. With a moving average, a lower cutoff frequency requires that you store more old samples. With the exponential filter, the storage requirements are decoupled from the cutoff freq. Just remember that once you have a good estimate ofthe DC component, you need to subtract it out. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (703) 779-7770 I'm Jim Thomas, and I approve this message.
Jim Thomas wrote:
> It's an exponential filter, which can be used to estimate DC. It's > normally considered a high-pass filter,
^^^^^^^^^ Oops! that should read low-pass. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (703) 779-7770 I'm Jim Thomas, and I approve this message.