2013-03-19 2 views
1

Мне нужно получить доступ к нескольким аудио входам в 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? Правильно ли я использую его?

Вот краткий обзор того, что я получил:

wave plot

Я также загрузил проект затмения 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.

Любые подсказки о том, как я могу продолжить?

+0

Я немного смущен, на этот раз, почему вы все еще используете обработку вообще? Почему бы просто не использовать обычную старую Java?Что вам действительно нужно делать? (то есть, что означает «доступ к нескольким аудиовходам»?) –

+0

нечего путать, простой java будет делать. Я просто просто иллюстрировал идею построения графики, используя функции обработки для простоты. Любые мысли о PortAudio? –

+0

ах. к сожалению, не играл с этим (в прошлый раз, когда я делал аудио, Java по-прежнему занималась обработкой изображений и аудиопроектом). Комментирует, потому что я работаю над Processing.js и пишу много кода обработки =) –

ответ

0

Конечная цель - получить доступ к нескольким аудиовходам, и этот маршрут в данный момент времени никуда не ведет.

Простейшее решение, которое я тестировал на 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()); 
    } 

} 

Это работает для меня на данном этапе во времени так, действительный ответ пока кто разделит простой способ использовать jpab/jportaudio на ОС Windows для построения формы волны с входа.

 Смежные вопросы

  • Нет связанных вопросов^_^