I'm using the Aubio librar开发者_JS百科y; I can't find this anywhere in the docs at aubio.org or on the internet. When doing processing (specifically pitch detection with aubio_pitch_detect
in my case) does Aubio do anything to the incoming audio arrays in terms of windowing, or do I have to implement that myself?
If I need to add it, a simple windowing code sample (or link) would be welcome.
This is more of a question than an answer, but I can't comment other answers due to newbie-status.
Regarding the answers of Flavien Volken and buildsucceeded, they both state the same in terms of the Hamming coefficients:
0.54 or 0.53836, and 0.46 or 0.46164.
Both answers have a "-" in between them: 0.54 - 0.46.
So far, so good. Now look at this:
(1) Johns Hopkins University says: 0.54 + 0.46
(2) University of California says: 0.54 - 0.46
(3) A book on DSP says: 0.54 + 0.46
(4) Wikipedia says: 0.54 + 0.46
(5) mathworks says: 0.54 - 0.46
(6) A forum user says: 1.07672 - 0.92328
Totally confused, how do we know what is really correct now?
Here are the links (can't post more than 2 real links because of newbie-status here):
(1): www.jhu.edu/signals/phasors/hpfs7.htm
(2): www.ece.uci.edu/docs/hspice/hspice_2001_2-220.html
(3): books.google.de/books?id=ytuUKKVeR88C&pg=PT442&lpg=PT442&dq=hamming%20window%200.54%200.46&source=bl&ots=ecdP7pU8-w&sig=yv9QiCvuWv8vShO-6CjZATx37lA&hl=en&sa=X&ei=M4IJUfvBLsTFtAbQ54GwCw&ved=0CDAQ6AEwATgK
(4): de.wikipedia.org/wiki/Hamming-Fenster#Hamming-Fenster
(5): www.mathworks.de/de/help/signal/ref/hamming.html
(6): forums.oracle.com/forums/message.jspa?messageID=9244422#9244422
Found this in Performous:
// Hamming window
for (size_t i=0; i < FFT_N; i++) {
m_window[i] = 0.53836 - 0.46164 * std::cos(2.0 * M_PI * i / (FFT_N - 1));
}
Edit: To address the "omg is it + or - or what" question, you need to look a little further to see whether you're multiplying by sin or cos of π*i/FFT_N
. Because sin(0) = 0 and cos(0) = 1, you are looking at the difference between a window that looks (approximately!) like this:
or like this:
Note that if you put one after the other, they both look like this:
So while the specific processing you want to do on the signal after you window it might affect which windowing option you choose they are not in fact fundamentally opposed, just aligned differently.
aubio_pitch_do
takes a vector of audio samples as input, and will do the windowing needed.
The documentation can be found in the header files. In this case, check out the pitch.h
file.
If you need to create a window, you can do it with new_aubio_window ( size, type )
.
For example:
fvec_t * my_new_window = new_aubio_window ( 1024, "hanningz" );
Here is the list of window types available so far:
/** Window types */
typedef enum
{
aubio_win_rectangle,
aubio_win_hamming,
aubio_win_hanning,
aubio_win_hanningz,
aubio_win_blackman,
aubio_win_blackman_harris,
aubio_win_gaussian,
aubio_win_welch,
aubio_win_parzen,
aubio_win_default = aubio_win_hanningz,
} aubio_window_type;
Here is my port of several windowing methods to init a windowing vector.
include <math.h>
enum {
WINDOW_RECTANGULAR,
WINDOW_HANN,
WINDOW_HAMMING,
WINDOW_COSINE,
WINDOW_LANCZOS,
WINDOW_TRIANGULAR,
WINDOW_BARTLETT,
WINDOW_GAUSSIAN,
WINDOW_BARTLETT_HANN,
WINDOW_BLACKMAN,
WINDOW_NUTALL,
WINDOW_BLACKMAN_HARRIS,
WINDOW_BLACKMAN_NUTALL,
WINDOW_FLATTOP,
WINDOW_NB
};
template <class T_Real>
void computeWindow(T_Real*buffer, int length, int type)
{
switch (type)
{
case WINDOW_RECTANGULAR :
for (int n = 0; n < length; n++){ buffer[n] = 1.0; } break;
case WINDOW_HANN :
for (int n = 0; n < length; n++){ buffer[n] = 0.5*(1.0 - cos(M_PI*2.0*n/(length-1))); } break;
case WINDOW_HAMMING :
for (int n = 0; n < length; n++){ buffer[n] = 0.54-0.46*cos(M_PI*2.0*n/(length-1)); } break;
case WINDOW_COSINE :
for (int n = 0; n < length; n++){ buffer[n] = sin(M_PI*n/(length-1)); } break;
case WINDOW_LANCZOS :
for (int n = 0; n < length; n++){ double x = (2.0*n/(length-1)-1.0); buffer[n] = sin(M_PI*x)/(x*M_PI); } break;
case WINDOW_TRIANGULAR :
for (int n = 0; n < length; n++){ buffer[n] = (2.0/(length+1))*((0.5*(length-1.0))-fabs(n-0.5*(length-1.0))) ; } break;
case WINDOW_BARTLETT :
for (int n = 0; n < length; n++){ buffer[n] = (2.0/(length-1))*((0.5*(length-1.0))-fabs(n-0.5*(length-1.0))) ; } break;
case WINDOW_GAUSSIAN :
{
double fi = 0.5;
for (int n = 0; n < length; n++)
{
double inner = (n-0.5*(length-1))/(0.5*fi*(length-1));
double indice = -0.5*inner*inner;
buffer[n] = exp(indice);
}
break;
}
case WINDOW_BARTLETT_HANN :
for (int n = 0; n < length; n++){ buffer[n] = 0.62-0.48*fabs((double)n/(length-1.0)-0.5)-0.48*cos(M_PI*2.0*n/(length-1));} break;
case WINDOW_BLACKMAN :
{
double alpha = 0.16;
double a0 = 0.5*(1.0-alpha);
double a1 = 0.5;
double a2 = 0.5*alpha;
for (int n = 0; n < length; n++){ buffer[n] = a0 - a1*cos(M_PI*2.0*n/(length-1)) + a2*cos(M_PI*4.0*n/(length-1));} break;
}
case WINDOW_NUTALL :
{
double a0 = 0.355768;
double a1 = 0.487396;
double a2 = 0.144232;
double a3 = 0.012604;
for (int n = 0; n < length; n++){ buffer[n] = a0 - a1*cos(M_PI*2.0*n/(length-1)) + a2*cos(M_PI*4.0*n/(length-1)) - a3*cos(M_PI*6.0*n/(length-1));} break;
}
case WINDOW_BLACKMAN_HARRIS :
{
double a0 = 0.35875;
double a1 = 0.48829;
double a2 = 0.14128;
double a3 = 0.01168;
for (int n = 0; n < length; n++){ buffer[n] = a0 - a1*cos(M_PI*2.0*n/(length-1)) + a2*cos(M_PI*4.0*n/(length-1)) - a3*cos(M_PI*6.0*n/(length-1));} break;
}
case WINDOW_BLACKMAN_NUTALL :
{
double a0 = 0.3635819;
double a1 = 0.4891775;
double a2 = 0.1365995;
double a3 = 0.0106411;
for (int n = 0; n < length; n++){ buffer[n] = a0 - a1*cos(M_PI*2.0*n/(length-1)) + a2*cos(M_PI*4.0*n/(length-1)) - a3*cos(M_PI*6.0*n/(length-1));} break;
}
case WINDOW_FLATTOP :
{
double a0 = 1.0;
double a1 = 1.93;
double a2 = 1.29;
double a3 = 0.388;
double a4 = 0.032;
for (int n = 0; n < length; n++)
{ buffer[n] =
a0 - a1*cos(M_PI*2.0*n/(length-1)) +
a2*cos(M_PI*4.0*n/(length-1)) -
a3*cos(M_PI*6.0*n/(length-1)) +
a4*cos(M_PI*8.0*n/(length-1));
} break;
}
default: break;
}
}
Example usage:
computeWindow<float>(myFloatWindowBuffer, windowLength, WINDOW_NUTALL);
精彩评论