Мне нужно получить доступ к нескольким аудио входам в Java, поэтому сначала проверил SO и нашел this answer и предложил использовать привязки Java PortAudio(). К сожалению, я нашел мало и устарел documentation.Как построить форму волны с помощью PortAudio в Java (jpab с обработкой)?
С того, что я нашел, что я попробовал в затмении это с помощью Processing:
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;
}
}
Я начал с микрофонным 1, и я думаю, что я получаю близко, как я могу показаться несколько значений, но я не на 100% уверен, что я правильно перехожу на вход ByteBuffer.
Каков правильный способ доступа к значениям и построение формы сигнала с аудиовхода с помощью jpab?
Я обновил код немного, и мне удалось приблизиться к сюжету, но я все еще в темноте. Каковы правильные диапазоны min/max для поплавков, считанных с входного ByteBuffer? Правильно ли я использую его?
Вот краткий обзор того, что я получил:
Я также загрузил проект затмения 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.
Любые подсказки о том, как я могу продолжить?
Я немного смущен, на этот раз, почему вы все еще используете обработку вообще? Почему бы просто не использовать обычную старую Java?Что вам действительно нужно делать? (то есть, что означает «доступ к нескольким аудиовходам»?) –
нечего путать, простой java будет делать. Я просто просто иллюстрировал идею построения графики, используя функции обработки для простоты. Любые мысли о PortAudio? –
ах. к сожалению, не играл с этим (в прошлый раз, когда я делал аудио, Java по-прежнему занималась обработкой изображений и аудиопроектом). Комментирует, потому что я работаю над Processing.js и пишу много кода обработки =) –