如何用minim库制作左右声道的两个FFT对象进行处理
how to make two FFT objects for the left and right channel with the minim library for processing
我有以下代码从音频文件创建 FFT 对象
请参阅下面的代码:
import ddf.minim.*;
import ddf.minim.analysis.*;
Minim minim;
AudioPlayer player;
FFT fft;
void setup(){
minim = new Minim(this);
player = minim.loadFile("audio.mp3");
fft = new FFT( player.bufferSize(), player.sampleRate() );
fft.logAverages(86, 1);
fft.window(FFT.HAMMING);
numZones = fft.avgSize();
}
但现在我想为左右声道创建两个 FFT 对象。所以最后我想要一个 fftLeft = new FFT(audio.left)
和一个 fftRight = new FFT(audio.right)
我试过方法.getChannel(player.LEFT)
,但是没用。有人对如何执行此操作有提示或建议吗?
当你 运行 FFT 的 forward() 方法时你可以传递你想要的通道。
像这样:
//in setup()
fftLeft = new FFT( player.bufferSize(), player.sampleRate() );
fftRight = new FFT( player.bufferSize(), player.sampleRate() );
//in draw()
fftLeft.forward(player.left);
fftRight.forward(player.right);
这是 minim 附带的 SoundSpectrum 示例的调整版本:
/**
* An FFT object is used to convert an audio signal into its frequency domain representation. This representation
* lets you see how much of each frequency is contained in an audio signal. Sometimes you might not want to
* work with the entire spectrum, so it's possible to have the FFT object calculate average frequency bands by
* simply averaging the values of adjacent frequency bands in the full spectrum. There are two different ways
* these can be calculated: <b>Linearly</b>, by grouping equal numbers of adjacent frequency bands, or
* <b>Logarithmically</b>, by grouping frequency bands by <i>octave</i>, which is more akin to how humans hear sound.
* <br/>
* This sketch illustrates the difference between viewing the full spectrum,
* linearly spaced averaged bands, and logarithmically spaced averaged bands.
* <p>
* From top to bottom:
* <ul>
* <li>The full spectrum.</li>
* <li>The spectrum grouped into 30 linearly spaced averages.</li>
* <li>The spectrum grouped logarithmically into 10 octaves, each split into 3 bands.</li>
* </ul>
*
* Moving the mouse across the sketch will highlight a band in each spectrum and display what the center
* frequency of that band is. The averaged bands are drawn so that they line up with full spectrum bands they
* are averages of. In this way, you can clearly see how logarithmic averages differ from linear averages.
* <p>
* For more information about Minim and additional features, visit http://code.compartmental.net/minim/
*/
import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer jingle;
FFT fftLogLeft,fftLogRight;
float height3;
float height23;
float spectrumScale = 4;
float centerFrequency;
PFont font;
void setup()
{
size(512, 480);
height3 = height/3;
height23 = 2*height/3;
minim = new Minim(this);
jingle = minim.loadFile("jingle.mp3", 1024);
// loop the file
jingle.loop();
// create an FFT object for calculating logarithmically spaced averages
// left channel
fftLogLeft = new FFT( jingle.bufferSize(), jingle.sampleRate() );
fftLogLeft.logAverages( 22, 3 );
fftLogRight = new FFT( jingle.bufferSize(), jingle.sampleRate() );
fftLogRight.logAverages( 22, 3 );
rectMode(CORNERS);
}
void draw()
{
background(0);
//run FFT on left channel
fftLogLeft.forward( jingle.left );
//run FFT on left channel
fftLogRight.forward( jingle.right );
plotFFT(fftLogLeft,height-50,"Left Channel");
plotFFT(fftLogRight,height,"Right Channel");
}
void plotFFT(FFT fft,float y,String prefix){
// draw the logarithmic averages
{
// since logarithmically spaced averages are not equally spaced
// we can't precompute the width for all averages
for(int i = 0; i < fft.avgSize(); i++)
{
centerFrequency = fft.getAverageCenterFrequency(i);
// how wide is this average in Hz?
float averageWidth = fft.getAverageBandWidth(i);
// we calculate the lowest and highest frequencies
// contained in this average using the center frequency
// and bandwidth of this average.
float lowFreq = centerFrequency - averageWidth/2;
float highFreq = centerFrequency + averageWidth/2;
// freqToIndex converts a frequency in Hz to a spectrum band index
// that can be passed to getBand. in this case, we simply use the
// index as coordinates for the rectangle we draw to represent
// the average.
int xl = (int)fft.freqToIndex(lowFreq);
int xr = (int)fft.freqToIndex(highFreq);
// if the mouse is inside of this average's rectangle
// print the center frequency and set the fill color to red
if ( mouseX >= xl && mouseX < xr )
{
fill(255, 128);
text(prefix + "Logarithmic Average Center Frequency: " + centerFrequency, 5, y - 25);
fill(255, 0, 0);
}
else
{
fill(255);
}
// draw a rectangle for each average, multiply the value by spectrumScale so we can see it better
rect( xl, y, xr, y - fft.getAvg(i)*spectrumScale );
}
}
}
备注:
- 您需要在 运行 之前将 .mp3 文件放到草图上。将其命名为 "jingle.mp3" 或将调用更改为
loadFile()
以使用正确的文件名
- 我以对数平均值为例。它们对于可视化比线性或根本没有平均值更有用。有关 Processing 中声音可视化的 FFT 的更多有用技巧,请参阅 this answer and Dan Ellis' Music Signal Processing course 在哥伦比亚大学教授(因为一些实践使用 Processing 的 minim 库)
我有以下代码从音频文件创建 FFT 对象 请参阅下面的代码:
import ddf.minim.*;
import ddf.minim.analysis.*;
Minim minim;
AudioPlayer player;
FFT fft;
void setup(){
minim = new Minim(this);
player = minim.loadFile("audio.mp3");
fft = new FFT( player.bufferSize(), player.sampleRate() );
fft.logAverages(86, 1);
fft.window(FFT.HAMMING);
numZones = fft.avgSize();
}
但现在我想为左右声道创建两个 FFT 对象。所以最后我想要一个 fftLeft = new FFT(audio.left) 和一个 fftRight = new FFT(audio.right)
我试过方法.getChannel(player.LEFT)
,但是没用。有人对如何执行此操作有提示或建议吗?
当你 运行 FFT 的 forward() 方法时你可以传递你想要的通道。
像这样:
//in setup()
fftLeft = new FFT( player.bufferSize(), player.sampleRate() );
fftRight = new FFT( player.bufferSize(), player.sampleRate() );
//in draw()
fftLeft.forward(player.left);
fftRight.forward(player.right);
这是 minim 附带的 SoundSpectrum 示例的调整版本:
/**
* An FFT object is used to convert an audio signal into its frequency domain representation. This representation
* lets you see how much of each frequency is contained in an audio signal. Sometimes you might not want to
* work with the entire spectrum, so it's possible to have the FFT object calculate average frequency bands by
* simply averaging the values of adjacent frequency bands in the full spectrum. There are two different ways
* these can be calculated: <b>Linearly</b>, by grouping equal numbers of adjacent frequency bands, or
* <b>Logarithmically</b>, by grouping frequency bands by <i>octave</i>, which is more akin to how humans hear sound.
* <br/>
* This sketch illustrates the difference between viewing the full spectrum,
* linearly spaced averaged bands, and logarithmically spaced averaged bands.
* <p>
* From top to bottom:
* <ul>
* <li>The full spectrum.</li>
* <li>The spectrum grouped into 30 linearly spaced averages.</li>
* <li>The spectrum grouped logarithmically into 10 octaves, each split into 3 bands.</li>
* </ul>
*
* Moving the mouse across the sketch will highlight a band in each spectrum and display what the center
* frequency of that band is. The averaged bands are drawn so that they line up with full spectrum bands they
* are averages of. In this way, you can clearly see how logarithmic averages differ from linear averages.
* <p>
* For more information about Minim and additional features, visit http://code.compartmental.net/minim/
*/
import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer jingle;
FFT fftLogLeft,fftLogRight;
float height3;
float height23;
float spectrumScale = 4;
float centerFrequency;
PFont font;
void setup()
{
size(512, 480);
height3 = height/3;
height23 = 2*height/3;
minim = new Minim(this);
jingle = minim.loadFile("jingle.mp3", 1024);
// loop the file
jingle.loop();
// create an FFT object for calculating logarithmically spaced averages
// left channel
fftLogLeft = new FFT( jingle.bufferSize(), jingle.sampleRate() );
fftLogLeft.logAverages( 22, 3 );
fftLogRight = new FFT( jingle.bufferSize(), jingle.sampleRate() );
fftLogRight.logAverages( 22, 3 );
rectMode(CORNERS);
}
void draw()
{
background(0);
//run FFT on left channel
fftLogLeft.forward( jingle.left );
//run FFT on left channel
fftLogRight.forward( jingle.right );
plotFFT(fftLogLeft,height-50,"Left Channel");
plotFFT(fftLogRight,height,"Right Channel");
}
void plotFFT(FFT fft,float y,String prefix){
// draw the logarithmic averages
{
// since logarithmically spaced averages are not equally spaced
// we can't precompute the width for all averages
for(int i = 0; i < fft.avgSize(); i++)
{
centerFrequency = fft.getAverageCenterFrequency(i);
// how wide is this average in Hz?
float averageWidth = fft.getAverageBandWidth(i);
// we calculate the lowest and highest frequencies
// contained in this average using the center frequency
// and bandwidth of this average.
float lowFreq = centerFrequency - averageWidth/2;
float highFreq = centerFrequency + averageWidth/2;
// freqToIndex converts a frequency in Hz to a spectrum band index
// that can be passed to getBand. in this case, we simply use the
// index as coordinates for the rectangle we draw to represent
// the average.
int xl = (int)fft.freqToIndex(lowFreq);
int xr = (int)fft.freqToIndex(highFreq);
// if the mouse is inside of this average's rectangle
// print the center frequency and set the fill color to red
if ( mouseX >= xl && mouseX < xr )
{
fill(255, 128);
text(prefix + "Logarithmic Average Center Frequency: " + centerFrequency, 5, y - 25);
fill(255, 0, 0);
}
else
{
fill(255);
}
// draw a rectangle for each average, multiply the value by spectrumScale so we can see it better
rect( xl, y, xr, y - fft.getAvg(i)*spectrumScale );
}
}
}
备注:
- 您需要在 运行 之前将 .mp3 文件放到草图上。将其命名为 "jingle.mp3" 或将调用更改为
loadFile()
以使用正确的文件名 - 我以对数平均值为例。它们对于可视化比线性或根本没有平均值更有用。有关 Processing 中声音可视化的 FFT 的更多有用技巧,请参阅 this answer and Dan Ellis' Music Signal Processing course 在哥伦比亚大学教授(因为一些实践使用 Processing 的 minim 库)