grrrr/nsgt

Q-factor too high for frequencies

ivanmkc opened this issue · 3 comments

Hi,

Many thanks for this great package. I'm using it for musical note analysis and thus I'm putting in the minimum frequency as midi2hz(21) and the maximum as midi2hz(108). 21 and 108 are the lowest and highest notes on a piano respectively, in midi format, and midi2hz converts midi values to Hertz.

My code is thus:

Ls = len(segmentWindow)
numBins = int(np.ceil(108 - 21))
scl = LogScale(midi2hz(21), midi2hz(108), numBins)
nsgt = NSGT(scl, samplingRate, Ls, real=True, matrixform=True)

I'm getting the following warning:
UserWarning: Q-factor too high for frequencies 27.50,29.10,30.78,32.57,34.46,36.46,38.58,40.82,43.19,45.69,48.35,51.15,54.12,57.26,60.59,64.10,67.82,71.76,75.92,80.33,84.99,89.93,95.15,100.67,106.51,112.69,119.23,126.15,133.48,141.22,149.42,158.09,167.27,176.98,187.25 warn("Q-factor too high for frequencies %s"%",".join("%.2f"%fi for fi in f[q >= qneeded]))

  1. Do you know why this is?
  2. How would you recommend fixing this?

Thanks

grrrr commented

Hi Ivan, high Q factors (high spectral resolution) need large frame sizes
aka time support in mathematical terms. I need to formalize this sometime,
it's a reoccurring question. Obviously your "segment length" is about a
factor 6 or so too small to resolve your low frequency bins.

Am 31.07.2016 um 19:42 schrieb Ivan Cheung notifications@github.com:

Hi,

Many thanks for this great package. I'm using it for musical note analysis
and thus I'm putting in the minimum frequency as midi2hz(21) and the
maximum as midi2hz(108). 21 and 108 are the lowest and highest notes on a
piano respectively, in midi format, and midi2hz converts midi values to
Hertz.

My code is thus:
`
Ls = len(segmentWindow)

numBins = int(np.ceil(108 - 21))
scl = LogScale(midi2hz(21), midi2hz(108), numBins)
nsgt = NSGT(scl, samplingRate, Ls, real=True, matrixform=True)
`

I'm getting the following warning:
UserWarning: Q-factor too high for frequencies
27.50,29.10,30.78,32.57,34.46,36.46,38.58,40.82,43.19,45.69,48.35,51.15,54.12,57.26,60.59,64.10,67.82,71.76,75.92,80.33,84.99,89.93,95.15,100.67,106.51,112.69,119.23,126.15,133.48,141.22,149.42,158.09,167.27,176.98,187.25
warn("Q-factor too high for frequencies %s"%",".join("%.2f"%fi for fi in
f[q >= qneeded]))

  1. Do you know why this is?
  2. How would you recommend fixing this?

Thanks


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#18, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAJ-JvFi4mBhUEZAYqS6tLqYcYi4C7eeks5qbN6HgaJpZM4JZFLA
.

Hi Thomas,

Thanks for responding. I understand the need for more samples to support
more spectral resolution.

  1. I'm wondering if there's anything I can change besides reducing the number
    of bins. I tried reducing the number of bins by a factor of 4 and it worked to remove the warning, but it took 3 times longer to compute which was counter-intuitive for me. Shouldn't it take less time for less bins?
  2. How do I reduce the q factor? Can I set this?
  3. Also, in nsfgwin, there is the line of code:

qneeded = f_(Ls/(8._sr))

Where does the 8 come from? Is it kind of arbitrary right now?

Thanks

On Sun, Jul 31, 2016 at 3:47 PM, Thomas Grill notifications@github.com
wrote:

Hi Ivan, high Q factors (high spectral resolution) need large frame sizes
aka time support in mathematical terms. I need to formalize this sometime,
it's a reoccurring question. Obviously your "segment length" is about a
factor 6 or so too small to resolve your low frequency bins.

Am 31.07.2016 um 19:42 schrieb Ivan Cheung notifications@github.com:

Hi,

Many thanks for this great package. I'm using it for musical note analysis
and thus I'm putting in the minimum frequency as midi2hz(21) and the
maximum as midi2hz(108). 21 and 108 are the lowest and highest notes on a
piano respectively, in midi format, and midi2hz converts midi values to
Hertz.

My code is thus:
`
Ls = len(segmentWindow)

numBins = int(np.ceil(108 - 21))
scl = LogScale(midi2hz(21), midi2hz(108), numBins)
nsgt = NSGT(scl, samplingRate, Ls, real=True, matrixform=True)
`

I'm getting the following warning:
UserWarning: Q-factor too high for frequencies

27.50,29.10,30.78,32.57,34.46,36.46,38.58,40.82,43.19,45.69,48.35,51.15,54.12,57.26,60.59,64.10,67.82,71.76,75.92,80.33,84.99,89.93,95.15,100.67,106.51,112.69,119.23,126.15,133.48,141.22,149.42,158.09,167.27,176.98,187.25
warn("Q-factor too high for frequencies %s"%",".join("%.2f"%fi for fi in
f[q >= qneeded]))

  1. Do you know why this is?
  2. How would you recommend fixing this?

Thanks


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#18, or mute the thread
<
https://github.com/notifications/unsubscribe-auth/AAJ-JvFi4mBhUEZAYqS6tLqYcYi4C7eeks5qbN6HgaJpZM4JZFLA

.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#18 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABgzgQWXhx9p5d7agyZZr7zRpdWUM02fks5qbPvngaJpZM4JZFLA
.

@grrrr what do you think of adding the following code to the nsgt Scale class - I can submit the PR

class Scale:
    dbnd = 1.e-8

    def __init__(self, bnds):
        self.bnds = bnds

    def __len__(self):
        return self.bnds

    def Q(self, bnd=None):
        # numerical differentiation (if self.Q not defined by sub-class)
        if bnd is None:
            bnd = np.arange(self.bnds)
        return self.F(bnd)*self.dbnd/(self.F(bnd+self.dbnd)-self.F(bnd-self.dbnd))

    def __call__(self):
        f = np.array([self.F(b) for b in range(self.bnds)],dtype=float)
        q = np.array([self.Q(b) for b in range(self.bnds)],dtype=float)
        return f,q

    def suggested_sllen(self, sr):
        f,q = self()

        Ls = int(np.ceil(max((q*8.*sr)/f)))

        # make sure its divisible by 4
        Ls = Ls + -Ls % 4

        return Ls

The way to use it is to get the suggested sllen that supports your desired frequencies and Q factors (from which you can get trlen for slicq) - the same should apply for the length argument to the non-sliced transform:

scl = LogScale(fmin, fs/2, fbins)

# use slice length required to support desired frequency scale/q factors
sllen = scl.suggested_sllen(fs)

# optional trlen for sliced-q, otherwise Ls=sllen
trlen = sllen//4
trlen = trlen + -trlen % 2 # make trlen divisible by 2