gpt4 book ai didi

java - 如何在 Java 中使用 PortAudio 绘制波形(带有处理功能的 jpab)?

转载 作者:行者123 更新时间:2023-12-01 04:47:56 25 4
gpt4 key购买 nike

我需要在Java中访问多个音频输入,所以首先咨询了SO并发现this answer并设置为使用 PortAudio Java 绑定(bind) ( jpab )。不幸的是我发现很少而且过时的documentation .

根据我发现的内容,我尝试使用 Processing在 eclipse 中:

import java.nio.ByteBuffer;

import org.jpab.Callback;
import org.jpab.Device;
import org.jpab.PortAudio;
import org.jpab.PortAudioException;
import org.jpab.Stream;
import org.jpab.StreamConfiguration;
import org.jpab.StreamConfiguration.Mode;
import org.jpab.StreamConfiguration.SampleFormat;


import processing.core.PApplet;


public class PortAudioPlot extends PApplet implements Callback {

float min = 1000000,max = 0;

public void setup(){
try {
PortAudio.initialize();
for(Device d : PortAudio.getDevices()) println(d);

Device d = PortAudio.getDevices().get(1);// Microphone (Realtek High Definition Audio)
if(d.getMaxInputChannels() > 0){
println(d.getName());
StreamConfiguration sc = new StreamConfiguration();
sc.setInputDevice(d);
sc.setInputFormat(SampleFormat.SIGNED_INTEGER_16);
sc.setMode(Mode.INPUT_ONLY);
sc.setSampleRate(44100);
sc.setInputChannels(d.getMaxInputChannels());
PortAudio.createStream(sc, this, new Runnable() {
public void run() {
try {
PortAudio.terminate();
} catch (PortAudioException ignore) { ignore.printStackTrace(); }
}
}).start();
}
} catch (PortAudioException e) {
e.printStackTrace();
}
}
public void draw(){
if(keyPressed && key == 's') saveFrame(dataPath("frame-####.jpg"));
}
public void stop(){
try {
PortAudio.terminate();
} catch (PortAudioException e) {
e.printStackTrace();
}
super.stop();
}

public static void main(String[] args) {
PApplet.main(PortAudioPlot.class.getSimpleName());
}
@Override
public State callback(ByteBuffer in, ByteBuffer out) {
int size = in.capacity();
println("in size: " + size + " min: " + min + " max: " + max);
background(255);
beginShape(LINES);
for (int i = 0; i < size; i++) {
float v = in.getFloat(i);
if(!Float.isNaN(v) && v != Float.POSITIVE_INFINITY && v != Float.NEGATIVE_INFINITY){
float x = (float)i/size * width;
float y = (height * .5f) + (v * .5f);
if(v < min) min = v;
if(v > max) max = v;
vertex(x,y);
}
}
endShape();
return State.ABORTED;
}

}

我从第一个麦克风开始,我想我已经接近了,因为我可以看到一些值,但我不能 100% 确定我正确地遍历了输入 ByteBuffer。

使用 jpab 从音频输入访问值并绘制波形的正确方法是什么?

我已经更新了一点点代码,并设法让一些东西更接近情节,但我仍然一无所知。从输入 ByteBuffer 读取的 float 的正确最小/最大范围是多少?我是否以正确的方式使用它?

以下是我所拥有内容的快速预览:

wave plot

我还上传了 eclipse 项目 here 。它使用 prebuilt Windows x86 PortAudio binaries .

另一个更新:有人建议我这些值应该从 -1.0 到 1.0 并为此调整我的代码以进行映射/钳制,但我不确定这是否属实。这是一个更新的示例:

import java.nio.ByteBuffer;
import java.util.Arrays;

import org.jpab.Callback;
import org.jpab.Device;
import org.jpab.PortAudio;
import org.jpab.PortAudioException;
import org.jpab.Stream;
import org.jpab.StreamConfiguration;
import org.jpab.StreamConfiguration.Mode;
import org.jpab.StreamConfiguration.SampleFormat;


import processing.core.PApplet;


public class PortAudioPlot extends PApplet implements Callback {

int[] pix;
int hh;//half height
int py;//y for each channel plot
int numChannels;
int pad = 5;

public void setup(){
try {
colorMode(HSB,360,100,100);
hh = height/2;
pix = new int[width*height];
PortAudio.initialize();
for(Device d : PortAudio.getDevices()) println(d);

Device d = PortAudio.getDevices().get(1);// Microphone (Realtek High Definition Audio)
numChannels = d.getMaxInputChannels();
py = height / numChannels;
if(numChannels > 0){
println(d.getName()+" sr:" + d.getDefaultSampleRate());
StreamConfiguration sc = new StreamConfiguration();
sc.setInputLatency(d.getDefaultLowInputLatency());
sc.setInputDevice(d);
sc.setInputFormat(SampleFormat.SIGNED_INTEGER_16);
sc.setMode(Mode.INPUT_ONLY);
sc.setSampleRate(d.getDefaultSampleRate());
sc.setInputChannels(numChannels);
PortAudio.createStream(sc, this, new Runnable() {
public void run() {
try {
PortAudio.terminate();
} catch (PortAudioException ignore) { ignore.printStackTrace(); }
}
}).start();
}
} catch (PortAudioException e) {
e.printStackTrace();
}
}
public void draw(){
loadPixels();
arrayCopy(pix, pixels);
updatePixels();
if(keyPressed && key == 's') saveFrame(dataPath("frame-####.jpg"));
}
public void stop(){
try {
PortAudio.terminate();
} catch (PortAudioException e) {
e.printStackTrace();
}
super.stop();
}

public static void main(String[] args) {
PApplet.main(PortAudioPlot.class.getSimpleName());
}
@Override
public State callback(ByteBuffer in, ByteBuffer out) {
int size = in.capacity();
println("in size: " + size);
Arrays.fill(pix, color(0,0,100));
for (int i = 0; i < width; i++) {
int ch = i%numChannels;//channel id
int sy = py * ch;//channel plot y starting position
int minY = sy+pad;//min y for min input value
int maxY = (sy*2)-pad;//min y for min input value
int buffIndex = i * size / width;//map i(x pixel index) to buffer index
float v = in.getFloat(buffIndex);
if(!Float.isNaN(v) && v != Float.POSITIVE_INFINITY && v != Float.NEGATIVE_INFINITY){
int vOffset = constrain((int)map(v,-1.0f,1.0f,minY,maxY),minY,maxY);
pix[vOffset * height + i] = color(map(ch,0,numChannels,0,360),100,50);
}
}
return State.RUNNING;
}

}

我还注意到,当我设置延迟时,输入 ByteBuffer 计数会发生变化。

我注意到的另一个令人困惑的事情是:JPAB 与 jportaudio 不同,尽管大多数 API 都很相似,但 createStream(jpab)/openStream(jportaudio) 除外。到目前为止,我还没有找到 jportaudio 的编译版本,也没有自己在 Windows 上编译它。

有关于我如何继续的线索吗?

最佳答案

最终目标是访问多个音频输入,但目前这条路线似乎没有通向任何地方。

我在 Windows 和 OSX 上测试过的最简单的解决方案很容易设置,并且可以在纯 Java 中工作,但在处理中也非常好用 Beads可以连接到JACK 。看这个thread了解更多细节,特别是后面关于 JNAJack 的部分(JJack 不再维护)。我用过这个版本的Beads (下载链接)和JNA (下载链接)。

这是我用来测试的基本代码示例:

import java.util.Arrays;

import org.jaudiolibs.beads.AudioServerIO;

import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.AudioIO;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.beads.ugens.Gain;
import processing.core.PApplet;


public class BeadsJNA extends PApplet {

AudioContext ac;

public void setup(){
ac = new AudioContext(new AudioServerIO.Jack(),512,AudioContext.defaultAudioFormat(4,2));//control number of ins(4) and outs(2)

UGen microphoneIn = ac.getAudioInput();
Gain g = new Gain(ac, 1, 0.5f);
g.addInput(microphoneIn);
ac.out.addInput(g);

println("no. of inputs: " + ac.getAudioInput().getOuts());

ac.start();
}
public void draw(){
loadPixels();
Arrays.fill(pixels, color(0));

for(int i = 0; i < width; i++)
{
int buffIndex = i * ac.getBufferSize() / width;
int vOffset = (int)((1 + ac.out.getValue(0, buffIndex)) * height / 2);
pixels[vOffset * height + i] = color(255);
}
updatePixels();
}

public static void main(String[] args) {
PApplet.main(BeadsJNA.class.getSimpleName());
}

}

这在现阶段对我有用,所以是一个有效的答案直到有人分享在 Windows 上使用 jpab/jportaudio 的简单方法绘制输入波形。

关于java - 如何在 Java 中使用 PortAudio 绘制波形(带有处理功能的 jpab)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15511851/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com