# Partitioning the frequency axis with shifting resolution

I am calculating the sum of the signal energy in different frequency bands for music in Matlab. At the moment I have calculated the FFT for a music signal and then split this frequency vector in N partitions. This gives me the sum of the energy for N parts which is all good.

The problem with this is that music most often is concentrated around some frequencies and since my partitions are of uniform length this does not give a good representation of the original signal.

What I would like to do is to be able to give a frequency value f0 and the number of partitions N. This should then give me N partitions but where the partition lengths are shorther around f0 and increasingly longer when farther away from f0. How could one do this?

My idea is that the end result would be a normalized length vector.

Any help would be appreciated.

• Is $N$ the FFT length?
– Deve
Dec 7, 2015 at 12:33
• No, N is how many parts the frequency axis is divided in. So if N = 2, my frequency axis would be divided into [0 12 000]hz and [12 001 24 000]hz, since my sample freq is 48kHz. Dec 7, 2015 at 12:40
• Then I guess doing a non-uniform partitioning into N frequency bands would be a simple approach? Maybe I don't get the question ;)
– Deve
Dec 7, 2015 at 13:10
• Maybe your question is how to weight the sums in order to get a normalized result? What about dividing each sum by the number of bins it contains?
– Deve
Dec 7, 2015 at 13:12
• Use a logarithmic scale and experiment with different bases. Octaves are important in music, so maybe a base $2$ scale would be appropriate. Dec 7, 2015 at 17:53

After some thinking I managed to create an answer that works for my problem. It does not center around the frequency f0 automatically but there is 4 design parameters that you can tinker with. My plan is to run the design parameters through an optimizer. So I can find the parameters that minimize the difference between the sum of the energy in each partition.

N_partition = 20;                                   % number of partitions
N_switch = -2;                                      % switches how how many partitions there are in
% the lower vs the upper part of the signal
N_lower = N_partition/2 + N_switch;                 % number of partitions in the lower part of the signal
N_upper = N_partition/2 - N_switch;                 % number of partitions in the upper part of the signal
diff_lower_upper = 0.05;                            % design value that decides how big the first partition in the signal is
a_upper = 25;                                       % design value that decides the slope appearance for the lower part of the signal
a_lower = 2;                                        % design value that decides the slope appearance for the upper part of the signal
vec_u = 0:1/N_upper:1;                              % vector for the lower part
vec_l = 0:1/N_lower:1;                              % vector for the upper part

part_upper = ((a_upper.^vec_u-1)/(a_upper-1));      % the change vector for the upper part of the vector, exponential
part_lower = ((a_lower.^vec_l-1)/(a_lower-1));      % the change vector for the lower part of the vector, exponential
part_lower = fliplr(part_lower).*diff_lower_upper;  % the change vector but corrected for the diff_lower_upper design value

change_vec = [part_lower(1:end-1) part_upper(2:end)]; % the change vector, removes the zero value from part_upper and part_lower

nl = change_vec./sum(change_vec);                   % normalize the change vector, this is our normalized length vector


For my case, this creates the following accumulated frequency/partition. I wanted high "resolution" around my f0 that is 1000Hz and then the partitions should grow in size the farther away they come from f0 which they do. Thanks to everyone that commented!