处理最小值中的逆 FFT

Posted

技术标签:

【中文标题】处理最小值中的逆 FFT【英文标题】:Inverse FFT in Processing Minim 【发布时间】:2022-01-20 15:01:23 【问题描述】:

我正在尝试使用 Minim in Processing 将我的计算机麦克风输入输出到扬声器输出。该项目的目的是分析输入(麦克风,声音文件等),对其频谱进行一些更改,最后将其输出到扬声器或将内容保存在文件中(我仍然不知道如何实现最后一个功能)。

我在这篇帖子 https://forum.processing.org/beta/num_1256413038.html 中提到了 mots 的回答来实现它,但我不能让它起作用:扬声器没有播放任何内容。

这是我正在使用的代码:

import ddf.minim.*;
import ddf.minim.analysis.*;


private FFT fftIn, fftOut;
private AudioInput input;
private AudioOutput output;
private Minim minim;

void setup() 
  size(300, 200);

  minim = new Minim(this);

  input = minim.getLineIn();
  input.addListener(new Listener());

  output = minim.getLineOut();
  output.addSignal(new Signal());
  
  fftOut = fftIn = new FFT(input.bufferSize(), input.sampleRate());


class Listener implements AudioListener 
  public void  samples(float[] sample) 
    fftIn.forward(sample);
  
  public void samples(float[] left, float[] right) 
    samples(left);
  



private class Signal implements Audiosignal 
  public void generate(float[] sample) 
    boolean mode = false;
    
    if (mode) 
      fftIn.inverse(sample);
     else 
      for (int i = 0; i < input.bufferSize() / 2; i++) 
        fftOut.setBand(i, fftIn.getBand(i));
                      
      fftOut.inverse(sample);
    
  

  public void generate(float[] left, float[] right) 
    generate(right);
  

2021 年 12 月 31 日编辑

这是我写下的代码:它运行时没有错误,但正如您在OUT 部分中看到的那样,整个频谱中的许多频率都会引起输出并产生噪音。我认为这是由于样本之间的不连续性造成的。

代码:

import ddf.minim.*;
import ddf.minim.analysis.*;


Minim minim;
AudioInput mic;
AudioOutput out;
FFT drawfft, testfft;

PGraphics IN, OUT;

float scale = 8, barWidth;


public void settings() 
  size(1200, 960);


void setup() 
  surface.setResizable(false);

  init();
  
  IN = createGraphics(1200, 480);
  OUT = createGraphics(1200, 480);


void draw() 
  drawSpectrum(IN, -1);
  image(IN, 0, 0);
  drawSpectrum(OUT, 1);
  image(OUT, 0, height - OUT.height);


void drawSpectrum(PGraphics pg, int channel) 
  if(channel == -1) drawfft.forward(mic.mix);
  else if(channel == 1) drawfft.forward(out.mix);
  
  int W = width;
  int H = (height - 5) / 2;
  
  pg.beginDraw();

  pg.background(0);

  barWidth = W / float(drawfft.specSize());
  
  pg.fill(255);
  pg.textAlign(RIGHT, TOP);
  pg.textSize(13);
  if(channel == -1) pg.text("IN", pg.width - 8, 8);
  else if(channel == 1) pg.text("OUT", pg.width - 8, 8);

  
  for(int i = 0; i < drawfft.specSize(); i++) 
    pg.strokeWeight(1);
    pg.fill(255, 0, 0);
    pg.stroke(255, 0, 0);
    pg.rect(i * barWidth, H, barWidth, -constrain(dB(drawfft.getBand(i)) * scale, 0, H));
  
  
  pg.endDraw();


void init() 
  minim = new Minim(this);
  minim.debugOn();
  
  mic = minim.getLineIn(Minim.MONO);
  out = minim.getLineOut(Minim.MONO);
  
  testfft = new FFT(mic.bufferSize(), mic.sampleRate());

  mic.addListener(new InEvent());
  out.addSignal(new OutEvent());

  drawfft = new FFT(mic.bufferSize(), mic.sampleRate());


float dB(float amp)  return 20 * (log(amp) / log(10)); 


class InEvent implements AudioListener 
  synchronized void samples(float[] samp) 
    testfft.forward(samp);
  
  
  synchronized void samples(float[] sampL, float[] sampR) 
    samples(sampL);
  


class OutEvent implements AudioSignal 
  synchronized void generate(float[] samp) 
    testfft.inverse(samp);
  
 
  synchronized void generate(float[] left, float[] right) 
    generate(left);
  

接受任何回复,

西蒙娜

【问题讨论】:

为了让你开始,请看看你是否可以运行这个演示:code.compartmental.net/minim/audiooutput_class_audiooutput.html。应该能够看到波形并使用键盘 1-5 更改它们。 是的,它有效。我想问题是fft,但我无法证明它。感谢您的回复。 当我运行您发布的代码时,问题似乎从“output.addSignal()”开始,然后影响下面的代码。另外 fftOut = fftIn = new FFT() 在我看来也不合适。请查看以下演示,该演示使用另一种技术将麦克风输入路由到扬声器:discourse.processing.org/t/…。您发布的示例已有几年历史了。 我发布了一个分析输入输出声音的新代码。 【参考方案1】:

我调试了您发布的代码,它现在应该可以正常运行了。我不确定演示实际上是如何工作的,但它确实从我的 macOS 扬声器中产生了沙哑的输出,这与原作者的 cmets 一致。请注意,“println”调用表明“fftIn”确实等于“fftOut”。 output.AddSignal() 必须向下移动几行,因为它依赖于 fftIn 和 fftOut 的值。也有必要将 'fftIn' 与 'fftOut' 分开,即使它们是相等的。修订在源代码中注明。添加了一个空的 draw() 以使其运行(没有它就无法运行)。

import ddf.minim.*;
import ddf.minim.analysis.*;

private FFT fftIn, fftOut;
private AudioInput input;
private AudioOutput output;
private Minim minim;

void setup() 
  size(300, 200);
  minim = new Minim(this);
  // Added Minim.MONO
  input = minim.getLineIn(Minim.MONO);
  input.addListener(new Listener());
  output = minim.getLineOut();
  // Separated fftIn from fftOut
  fftIn = new FFT(input.bufferSize(), input.sampleRate());
  println("fftIn =",fftIn);
  fftOut = fftIn;
  // moved this down here because it needs fftIn, fftOut
  output.addSignal(new Signal());


class Listener implements AudioListener 
  public void  samples(float[] sample) 
    fftIn.forward(sample);
  
  public void samples(float[] left, float[] right) 
    samples(left);
  


private class Signal implements AudioSignal 
  public void generate(float[] sample) 
    boolean mode = false;
    println("fftOut =",fftOut);
    if (mode) 
      fftIn.inverse(sample);
     else 
      for (int i = 0; i < input.bufferSize() / 2; i++) 
        fftOut.setBand(i, fftIn.getBand(i));
                      
      fftOut.inverse(sample);
    
  

  public void generate(float[] left, float[] right) 
    generate(right);
  


// Won't run without adding this
void draw()   


【讨论】:

以上是关于处理最小值中的逆 FFT的主要内容,如果未能解决你的问题,请参考以下文章

如何从 MySQL 列中缺失的有序值中获取最小值? [复制]

在 numpy 数组中取每个条目的最小值 +- 10 行

Crystal Reports,从下一条记录的最小值中减去当前记录的最大值

使用SQL查找多列行中的最小值

如何找到 ArrayList 的最小值?

从输入的值中获取最大值和最小值,输入0后结束(利用do_while boolean isRight来标识用户输入)