0

I'm trying to output my computer microphone input to the speakers output using Minim in Processing. The aim of the project is to analyze an input (the microphone, a sound file, etc), make some alterations to its frequency spectrum, and finally output it to the speakers or save the stuff on a file (I still don't know how to implement this last feature).

I referred to mots' answer in this post https://forum.processing.org/beta/num_1256413038.html to make it, but I can't let it work: nothing is being played through the speakers.

This is the code I'm using:

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);
  }
}

EDIT 31 December 2021

This is the code I have written down: it runs with no errors, but as you can see in the OUT section a lot of frequencies along the entire spectrum bring up and make noise to the output. I think it's caused by the discontinuities between the samples.

The code:

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);
  }
}

Any reply is accepted,

Simone

Simone Scala
  • 1
  • 1
  • 2
  • To get you started please see if you can run this demo: http://code.compartmental.net/minim/audiooutput_class_audiooutput.html . Should be able to see waveforms and change them by using keyboard 1-5. – apodidae Dec 29 '21 at 21:10
  • Yes, it works. I imagine the problem would be the fft, but I can't demonstrate it. Thanks for the reply. – Simone Scala Dec 30 '21 at 09:31
  • When I run your posted code, the problem seems to start with 'output.addSignal()' which then affects the code below. Also fftOut = fftIn = new FFT() doesn't look right to me. Please check out the following demo which uses another technique to route microphone input to the speakers: https://discourse.processing.org/t/minim-audioinput-nullpointerexception/3557 . The example that you posted is several years old. – apodidae Dec 30 '21 at 17:50
  • I've posted a new code which analyzes the in and out sound. – Simone Scala Jan 07 '22 at 13:42

1 Answers1

0

I debugged the code that you posted and it should now run without error. I'm not sure how the demo actually works, but it does produce a scratchy output from my macOS speakers, which is consistent with comments by the original author. Note that the 'println' calls indicate that 'fftIn' is indeed equal to 'fftOut'. output.AddSignal() had to be moved down a couple of lines because it relies upon values for fftIn and fftOut. It was also necessary to separate 'fftIn' from 'fftOut', even though they are equal. Revisions are notated in the source code. An empty draw() was added in order to get it to run (won't run without it).

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() {  
}

apodidae
  • 1,988
  • 2
  • 5
  • 9