Skip to content

Commit

Permalink
add buffersize setting and changed FA basic example slightly + versio…
Browse files Browse the repository at this point in the history
…n bump
  • Loading branch information
vincentsijben committed Apr 16, 2024
1 parent 1958989 commit 9610231
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 70 deletions.
1 change: 1 addition & 0 deletions FrequencyAnalyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ You can tweak the behaviour of this library with the following functions (you ca
* `.addMinim(minim)` mandatory to add the global minim object to the class.
* `.setFile("example.mp3")` to set the file for the audioplayer.
* `.setAudioInputMode(AudioInputMode.AUDIO_FILE)` to set the input mode to AudioInputMode.AUDIO_FILE. You can also set it to AudioInputMode.LINE_IN or AudioInputMode.MICROPHONE. Defaults to AudioInputMode.MICROPHONE.
* `.setAudioInputMode(AudioInputMode.AUDIO_FILE, n)` same as previous one, but you can also set the bufferSize. Needs to be a power of 2. A lower amount results in less audio resolution and decreases delay
* `.setAudioOutputMode(AudioOutputMode.STEREO)` to set the output mode to AudioOutputMode.STEREO. Defaults to AudioOutputMode.MONO. Use it to get access to both left and right channel analysis.
* `.showInfoPanel()` to show the infopanel.
* `.setInfoPanelY(n)` to offset the starting y-position of the infopanel by n pixels. Useful for when you have multiple infopanels to get them all lined up.
Expand Down
66 changes: 20 additions & 46 deletions examples/FrequencyAnalyzer/basics/basics.pde
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void setup() {
.addMinim(minim)
.setFile("https://github.com/vincentsijben/bpm-timings-for-processing/raw/main/assets/infraction_music_-_ritmo.mp3")
.setAudioInputMode(AudioInputMode.AUDIO_FILE)
//.setAudioInputMode(AudioInputMode.AUDIO_FILE, 128) // also set bufferSize, needs to be power of 2. Lower amount means less audio resolution and decreasing delay
//.setAudioInputMode(AudioInputMode.LINE_IN)
.setAudioOutputMode(AudioOutputMode.MONO)
;
Expand All @@ -26,13 +27,9 @@ void draw() {
background(0); // Clear the screen with a black background
noFill();

// Example visualization: Draw waveforms for left and right channels
//drawWaveform(fa.getLeftChannelBuffer(), 0, height / 4, width, height / 2, color(255, 0, 0)); // Red for left channel
//drawWaveform(fa.getRightChannelBuffer(), 0, 3 * height / 4, width, height / 2, color(0, 0, 255)); // Blue for right channel


// Example visualization: Draw the frequency spectrum using FFT analysis
// Only visible when MONO output (mixed fft)
//println(fa.specSize());
for (int i = 0; i < fa.specSize(); i++) {
// Calculate the amplitude and position for each frequency band
float amplitude = fa.getBand(i);
Expand All @@ -44,54 +41,17 @@ void draw() {

// Only visible when STEREO output (fftRight and fftLeft)
// Visualize the left channel
drawChannelFFT(fa.getFFTLeft(), color(255, 255, 0), 0, height / 2);
//drawChannelFFT(fa.getFFTLeft(), color(255, 255, 0), 0, height / 2);

// Visualize the right channel
drawChannelFFT(fa.getFFTRight(), color(0, 0, 255), height / 2, height);
//// Visualize the right channel
//drawChannelFFT(fa.getFFTRight(), color(0, 0, 255), height / 2, height);

fill(0, 200, 0);
circle(width/4*1, height/2, fa.getAvgRawRight(0)*30);
circle(width/4*2, height/2, fa.getAvgRaw(10)*30);
circle(width/4*3, height/2, fa.getAvgRaw(20)*30);

//}
//if (currentInputSource instanceof AudioFileInputSource) {

// AudioFileInputSource lineInInputSource = (AudioFileInputSource) currentInputSource;
// lineInInputSource.performFFT(); // Perform FFT on both channels

// // Visualize the left channel
// drawChannelFFT(lineInInputSource.fftLeft, color(255, 0, 0), 0, height / 2);

// // Visualize the right channel
// drawChannelFFT(lineInInputSource.fftRight, color(0, 0, 255), height / 2, height);
//}

// if (currentInputSource instanceof LineInInputSource) {

// LineInInputSource lineInInputSource = (LineInInputSource) currentInputSource;
// lineInInputSource.performFFT(); // Perform FFT on both channels

// // Visualize the left channel
// drawChannelFFT(lineInInputSource.fftLeft, color(255, 0, 0), 0, height / 2);

// // Visualize the right channel
// drawChannelFFT(lineInInputSource.fftRight, color(0, 0, 255), height / 2, height);
//}
}

void drawChannelFFT(FFT fft2, int color2, float startY, float endY) {
stroke(color2);
//println(fft2.specSize());
for (int i = 0; i < fft2.specSize(); i++) {
// Map the frequency band index to the x-coordinate
float x = map(i, 0, fft2.specSize(), 0, width);
// Map the amplitude to the y-coordinate, scaling by the height of the channel visualization area

float amplitude = fft2.getBand(i) * 5; // Scale factor for visual effect
float y = map(amplitude, 0, 100, endY, startY); // Invert direction for visual effect
line(x, endY, x, y);
}

}

void drawWaveform(float[] buffer, float x, float y, float w, float h, int strokeColor) {
Expand All @@ -105,3 +65,17 @@ void drawWaveform(float[] buffer, float x, float y, float w, float h, int stroke
}
endShape();
}

//void drawChannelFFT(FFT fft2, int color2, float startY, float endY) {
// stroke(color2);
// //println(fft2.specSize());
// for (int i = 0; i < fft2.specSize(); i++) {
// // Map the frequency band index to the x-coordinate
// float x = map(i, 0, fft2.specSize(), 0, width);
// // Map the amplitude to the y-coordinate, scaling by the height of the channel visualization area

// float amplitude = fft2.getBand(i) * 5; // Scale factor for visual effect
// float y = map(amplitude, 0, 100, endY, startY); // Invert direction for visual effect
// line(x, endY, x, y);
// }
//}
4 changes: 2 additions & 2 deletions resources/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,12 @@ source.repository=https://github.com/vincentsijben/bpm-tmings-for-processing.git
# This is used to compare different versions of the same Library, and check if
# an update is available.

library.version=16
library.version=17


# The version as the user will see it.

library.prettyVersion=1.2.2
library.prettyVersion=1.2.3


# The min and max revision of Processing compatible with your Library.
Expand Down
22 changes: 21 additions & 1 deletion src/bpm/library/arduinocontrols/ArduinoControls.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public ArduinoControls(PApplet parent) {

//https://github.com/benfry/processing4/wiki/Library-Basics
parent.registerMethod("draw", this);
parent.registerMethod("pre", this);
parent.registerMethod("post", this);
parent.registerMethod("keyEvent", this);
}
Expand Down Expand Up @@ -286,6 +287,12 @@ public ArduinoControls setInfoPanelKey(char keyboardKey) {
}

public void draw() {
// make sure everything in the main sketch is wrapped inside pushMatrix and popMatrix, so the infopanel is always shown top left, even in 3D mode
// pushMatrix in registermethod pre()
// popMatrix in registermethod draw()
this.parent.popMatrix();
this.parent.popStyle();
this.parent.hint(PConstants.DISABLE_DEPTH_TEST);
if (this.infoPanel.show) {
//System.out.println(""+this.infoPanel.x + this.infoPanel.y + this.infoPanel.w + this.infoPanel.h);
boolean portrait = false; //this.infoPanelLocation[2] < this.infoPanelLocation[3];
Expand All @@ -306,6 +313,7 @@ public void draw() {

this.parent.image(overlay, this.infoPanel.x, this.infoPanel.y, this.infoPanel.w, this.infoPanel.h); // Draw the overlay onto the main canvas
}
this.parent.hint(PConstants.ENABLE_DEPTH_TEST);
}


Expand All @@ -320,6 +328,18 @@ public void draw() {
public void post() {
// https://github.com/benfry/processing4/wiki/Library-Basics
// you cant draw in post() but its perfect for resetting the inputButtonsOnce array:
if (this.parent.frameCount != this.lastFrameCount) for (PushButton button : pushbuttons) button.pressedOnce = false;

}

public void pre() {

if (this.parent.frameCount != this.lastFrameCount) for (PushButton button : pushbuttons) button.pressedOnce = false;

// make sure everything in the main sketch is wrapped inside pushMatrix and popMatrix, so the infopanel is always shown top left, even in 3D mode
// pushMatrix in registermethod pre()
// popMatrix in registermethod draw()
this.parent.pushMatrix();
this.parent.pushStyle();
}
}

6 changes: 4 additions & 2 deletions src/bpm/library/frequencyanalyzer/AudioFileInputSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ class AudioFileInputSource implements AudioInputSource {
FFT fftLeft, fftRight, fftMixed;
AudioPlayer player;
String filePath;
int bufferSize = 1024; // Default setting

public AudioOutputMode channelOutput = AudioOutputMode.MONO; // Default setting

public void setAudioOutputMode(AudioOutputMode mode) {
this.channelOutput = mode;
}

public AudioFileInputSource(Minim minim, String filePath) {
public AudioFileInputSource(Minim minim, int size, String filePath) {
this.minim = minim;
this.filePath = filePath;
this.bufferSize = size;
}

@Override
public void init() {
this.player = minim.loadFile(filePath, 2048); // Load the file with a buffer size of 2048
this.player = minim.loadFile(filePath, this.bufferSize); // Load the file with a buffer size of 2048
this.fftLeft = new FFT(this.player.bufferSize(), this.player.sampleRate());
this.fftRight = new FFT(this.player.bufferSize(), this.player.sampleRate());
this.fftMixed = new FFT(this.player.bufferSize(), this.player.sampleRate());
Expand Down
47 changes: 35 additions & 12 deletions src/bpm/library/frequencyanalyzer/FrequencyAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,22 @@ public class FrequencyAnalyzer {
private float durationResetMaxValue;
private int startTime;
private float maxVal;
private int bufferSize;

public FrequencyAnalyzer(PApplet parent) {
this.parent = parent;
this.infoPanel = new InfoPanel(parent);


this.enableKeyPress = true;
this.keyPressedActionTaken = false;
this.durationResetMaxValue = 0.0f;
this.startTime = 0;
this.maxVal = 0.1f; //avoid NaN when using maxVal in map() in the first frame.
this.bufferSize = 1024;

parent.registerMethod("draw", this);
parent.registerMethod("pre", this);
parent.registerMethod("post", this);
parent.registerMethod("keyEvent", this);
parent.registerMethod("dispose", this);
Expand All @@ -47,8 +50,8 @@ public FrequencyAnalyzer(PApplet parent) {
public FrequencyAnalyzer addMinim(Minim minim) {
this.minim = minim;
this.setAudioInputMode(AudioInputMode.MICROPHONE);


return this;
}

Expand Down Expand Up @@ -79,7 +82,7 @@ public FrequencyAnalyzer setAudioOutputMode(AudioOutputMode mode) {
return this;
}

public FrequencyAnalyzer setAudioInputMode(AudioInputMode newMode) {
public FrequencyAnalyzer setAudioInputMode(AudioInputMode newMode, int size) {
if (newMode == this.currentInputMode) return this;
if (currentInputSource != null) {
currentInputSource.close();
Expand All @@ -89,18 +92,18 @@ public FrequencyAnalyzer setAudioInputMode(AudioInputMode newMode) {
// Initialize the new input source based on the selected mode
switch (newMode) {
case MICROPHONE:
currentInputSource = new MicrophoneInputSource(minim); // Assuming a MicrophoneSource class exists
currentInputSource = new MicrophoneInputSource(minim, size); // Assuming a MicrophoneSource class exists
break;
case LINE_IN:
currentInputSource = new LineInInputSource(minim);
currentInputSource = new LineInInputSource(minim, size);
break;
case AUDIO_FILE:
if (this.file == null) System.out.println("no audio file was set");
if (this.file == null) System.out.println("no audio file was set");

//currentInputSource = new AudioFileInputSource(minim, "https://github.com/vincentsijben/bpm-timings-for-processing/raw/main/assets/infraction_music_-_ritmo.mp3"); // Assuming an AudioFileSource class exists
currentInputSource = new AudioFileInputSource(minim, this.file); // Assuming an AudioFileSource class exists
currentInputSource = new AudioFileInputSource(minim, size, this.file); // Assuming an AudioFileSource class exists
//"stereotest.mp3"

break;
}

Expand All @@ -115,6 +118,10 @@ public FrequencyAnalyzer setAudioInputMode(AudioInputMode newMode) {
return this;
}

public FrequencyAnalyzer setAudioInputMode(AudioInputMode newMode) {
return setAudioInputMode(newMode, 1024);
}




Expand Down Expand Up @@ -212,9 +219,8 @@ public FrequencyAnalyzer disableKeyPress() {
private void toggleMuteOrMonitoring() {
if (currentInputSource.isMonitoring()) currentInputSource.disableMonitoring();
else currentInputSource.enableMonitoring();

//todo: add muted toggle?

}

public void keyEvent(KeyEvent event) {
Expand Down Expand Up @@ -288,6 +294,14 @@ public FrequencyAnalyzer setInfoPanelKey(char keyboardKey) {
}

public void draw() {
// make sure everything in the main sketch is wrapped inside pushMatrix and popMatrix, so the infopanel is always shown top left, even in 3D mode
// pushMatrix in registermethod pre()
// popMatrix in registermethod draw()
this.parent.popMatrix();
this.parent.popStyle();
this.parent.hint(PConstants.DISABLE_DEPTH_TEST);


if (this.infoPanel.show) {
PGraphics overlay = this.infoPanel.overlay;
overlay.beginDraw();
Expand Down Expand Up @@ -337,6 +351,7 @@ public void draw() {
overlay.endDraw();
this.parent.image(overlay, this.infoPanel.x, this.infoPanel.y, this.infoPanel.w, this.infoPanel.h); // Draw the overlay onto the main canvas
}
this.parent.hint(PConstants.ENABLE_DEPTH_TEST);
}


Expand All @@ -351,6 +366,9 @@ public void draw() {
public void post() {
// https://github.com/benfry/processing4/wiki/Library-Basics
// you cant draw in post() but its perfect for the fft analysis:
}

public void pre() {
if (this.minim != null) {
this.performFFT();

Expand All @@ -363,6 +381,11 @@ public void post() {
// }
//}
}
// make sure everything in the main sketch is wrapped inside pushMatrix and popMatrix, so the infopanel is always shown top left, even in 3D mode
// pushMatrix in registermethod pre()
// popMatrix in registermethod draw()
this.parent.pushMatrix();
this.parent.pushStyle();
}

public void dispose() {
Expand Down
9 changes: 5 additions & 4 deletions src/bpm/library/frequencyanalyzer/LineInInputSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ class LineInInputSource implements AudioInputSource {
Minim minim;
AudioInput lineIn;
FFT fftLeft, fftRight, fftMixed;
int bufferSize = 1024; //Default setting

private AudioOutputMode channelOutput = AudioOutputMode.MONO; // Default setting

public void setAudioOutputMode(AudioOutputMode mode) {
this.channelOutput = mode;
}

public LineInInputSource(Minim minim) {
public LineInInputSource(Minim minim, int size) {
this.minim = minim;
this.bufferSize = size;
}

@Override
public void init() {
// Assuming a stereo input for line-in
this.lineIn = this.minim.getLineIn(Minim.MONO);

this.lineIn = this.minim.getLineIn(Minim.MONO, this.bufferSize);
this.fftLeft = new FFT(this.lineIn.bufferSize(), this.lineIn.sampleRate());
this.fftRight = new FFT(this.lineIn.bufferSize(), this.lineIn.sampleRate());
this.fftMixed = new FFT(this.lineIn.bufferSize(), this.lineIn.sampleRate());
Expand All @@ -34,7 +35,7 @@ public void init() {
@Override
public void start() {
// Line-in starts automatically with getLineIn, but you might want to add logic here if needed
this.lineIn.enableMonitoring();
//this.lineIn.enableMonitoring();
}

@Override
Expand Down
Loading

0 comments on commit 9610231

Please sign in to comment.