2015-11-16 8 views
15

SocketからのAudioInputStreamの作成に問題があります。ソケットからの "Endless" AudioInputStream

AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), 100000); 

それは後にのみサウンドを再生しますが、私はこのコードを使用する場合しかしながら、

AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream()); 

public class SoundStream extends Thread { 
    private int port; 
    private String IP; 
    private Socket socket; 

    private SoundObject soundObject; 

    private OpenAL openAL; 
    private Source source; 

    private boolean run = true; 

    public SoundStream(int port, String IP, SoundObject soundObject) { 
     this.soundObject = soundObject; 
     this.port = port; 
     this.IP = IP; 
    } 

    public void run() { 
     try { 
      this.socket = new Socket(this.IP, this.port); 
      this.openAL = new OpenAL(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     this.mainCycleMethod(); 
    } 

    private void mainCycleMethod() { 
     while (run) { 
      this.soundObject.blockAndWait(); 
      switch (this.soundObject.getAndResetEvent()) { 
       case 0: 
        this.run = false; 
        this.close(); 
        break; 
       case 1: 
        this.setPitch(); 
        break; 
       case 2: 
        this.closeSource(); 
        this.play(); 
        break; 
       case 3: 
        this.pause(true); 
        break; 
       case 4: 
        this.pause(false); 
        break; 
      } 
     } 
    } 

    private BufferedInputStream getInputStream() throws Exception { 
     return new BufferedInputStream(socket.getInputStream()); 
    } 

    private void setPitch() { 
     if(this.source != null) { 
      try { 
       this.source.setPitch(this.soundObject.getPitch()); 
      } catch (ALException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private void play() { 
     try { 
      AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), AudioSystem.NOT_SPECIFIED); 
//   AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream()); 
//   AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(this.soundObject.getAudioFormat(), audioInputStream_tmp); 
      this.source = openAL.createSource(audioInputStream); 
      this.source.setGain(1f); 
      this.source.play(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    private void close() { 
     this.closeSource(); 
     this.openAL.close(); 
     try { 
      this.socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void closeSource() { 
     if(this.source!=null) { 
      this.source.close(); 
     } 
    } 

    private void pause(boolean pause) { 
     if(this.source != null) { 
      try { 
       if (pause) { 
        this.source.pause(); 
       } else { 
        this.source.play(); 
       } 
      } catch (ALException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 


public class SoundObject extends AbstractEventObject { 
    public AudioFormat getAudioFormat() { 
     boolean signed = false; 
     //true,false 
     boolean bigEndian = false; 
     //true,false 
     return new AudioFormat(this.frequency, this.bits, this.channels, signed, bigEndian); 
    } 
. 
. 
. 
. 
} 

このコードは、この行でUnsupportedAudioFileExceptionがスローされます。 はここで重要な部分ですそれらの100000サンプルフレームをオーディオ入力ストリームにロードします。 100000フレームすべてを再生した後、終了します。

最初のAudioInputStream入力時にパラメータとしてAudioFormatを直接渡すことができますが、これは可能ではないようですが、この問題を解決すると思います。 サーバーからオーディオ形式仕様を受け取りました。

私はAudioInputStreamコンストラクタにパラメータとして渡すことができるデータラインを作成することが1つの可能な解決策だと思います。しかし、私はソケットから直接データラインにデータを取得する方法がわかりません。私は無限ループを使用するソリューションを知っています。無限ループでは、データを読み込んでデータラインに書き込みます。しかし、それは無駄であるようです。より直接的なアプローチはありますか?

私は速度を変更する必要があるので、java-openALライブラリを使用して解決することができますし、私はそれを自分で行う必要はないことを願っています。

ありがとうございました

+1

最初の手順として、 'AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(this、this.soundObject.getAudioFormat()、AudioSystem.NOT_SPECIFIED); 'を試し、何が起こるかを見てみましょう。 – Roman

+0

openAL.createSource(audioInputStream)メソッドでブロックされるので、私の問題は解決しません。おそらく、InputStream全体が終了するのを待つでしょう。ありがとうございます –

+0

'openAL'とは何ですか?完全なソースコード(おそらく[mcve])を表示できますか? – Roman

答えて

2

私はついにこの問題を解決しました。 java-openALにはストリーミングサポートが組み込まれていることが判明しましたが、GitHubのドキュメントにはありませんでしたので、最初は気づいていませんでした。 Sourceクラスには、OutputStreamを返すcreateOutputStreamメソッドがあります。バイトをOutputStreamに直接書き込むことができます。ここで

は私のコードです:このスニペットで

私はOpenALのを初期化します。ここでは

public void run() { 
    try { 
     this.socket = new Socket(this.IP, this.port); 
     this.openAL = new OpenAL(); 
    } catch (Exception ex) { 
     Log.severe(ex.toString()); 
    } 
    this.mainCycleMethod(); 
} 

は、入力ストリームが使用可能になったときに呼び出され、私のプレイ方法である:

private void play() { 
    try { 
     this.source = openAL.createSource(); 
     this.outputWriter = new OutputWriter(this.socket.getInputStream(), this.source, this.soundObject.getAudioFormat()); 
     this.source.setGain(1f); 
     this.outputWriter.start(); 
    } catch (Exception ex) { 
     Log.severe(ex.toString()); 
    } 
} 

あなたが持っていますパラメータなしでcreateSourceメソッドを使用するには、Sourceの新しいインスタンスを返します。 sourceのplayメソッドを呼び出さないでください。このメソッドは、createOutputStreamメソッドによって返されるSourceOutputStreamクラスによって処理されます。手動でplayメソッドを呼び出すことには何も問題はありませんが、バッファが空のときに私は悪い経験をしていました。基本的には、データをOpenALにストリーミングするときに、後で再生を開始しません。

package cz.speechtech.sound; 

import org.urish.openal.ALException; 
import org.urish.openal.Source; 

import javax.sound.sampled.AudioFormat; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

/** 
* Created by honza on 16.12.15. 
*/ 
public class OutputWriter extends Thread { 
    private InputStream inputStream; 
    private OutputStream outputStream; 

    private int STREAMING_BUFFER_SIZE = 24000; 
    private int NUMBER_OF_BUFFERS = 4; 

    private boolean run = true; 

    public OutputWriter(InputStream inputStream, Source source, AudioFormat audioFormat) { 
     this.inputStream = inputStream; 
     try { 
      this.outputStream = source.createOutputStream(audioFormat, this.NUMBER_OF_BUFFERS, 1024); 
     } catch (ALException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void run() { 
     byte[] buffer = new byte[this.STREAMING_BUFFER_SIZE]; 
     int i; 
     try { 
      Thread.sleep(1000); // Might cause problems 
      while (this.run) { 
       i = this.inputStream.read(buffer); 
       if (i == -1) break; 
       outputStream.write(buffer, 0, i); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public synchronized void stopRunning() { 
     this.run = false; 
     try { 
      this.outputStream.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

素敵な一日を:ここで

はOutputStreamにのInputStreamからバイトを渡すの世話をする私のOutputWriterコードです。

関連する問題