java socket 音频_WebSocket接收音频,并推送到声卡上

/******************************************************************************

* Compilation: javac StdAudio.java

* Execution: java StdAudio

* Dependencies: none

*

* Simple library for reading, writing, and manipulating .wav files.

*

*

* Limitations

* -----------

* - Assumes the audio is monaural, little endian, with sampling rate

* of 44,100

* - check when reading .wav files from a .jar file ?

*

******************************************************************************/

importjavax.sound.sampled.AudioFileFormat;importjavax.sound.sampled.AudioFormat;importjavax.sound.sampled.AudioInputStream;importjavax.sound.sampled.AudioSystem;importjavax.sound.sampled.Clip;importjavax.sound.sampled.DataLine;importjavax.sound.sampled.LineUnavailableException;importjavax.sound.sampled.SourceDataLine;importjavax.sound.sampled.UnsupportedAudioFileException;importjava.io.ByteArrayInputStream;importjava.io.File;importjava.io.IOException;importjava.io.InputStream;/*** Standard audio. This class provides a basic capability for

* creating, reading, and saving audio.

*

* The audio format uses a sampling rate of 44,100 Hz, 16-bit, monaural.

*

*

* For additional documentation, see Section 1.5 of

* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.

*

*@authorRobert Sedgewick

*@authorKevin Wayne*/

public final classStdAudio {/*** The sample rate: 44,100 Hz for CD quality audio.*/

public static final int SAMPLE_RATE = 16000;//44100;

private static final int BYTES_PER_SAMPLE = 2; //16-bit audio

private static final int BITS_PER_SAMPLE = 16; //16-bit audio

private static final double MAX_16_BIT = 32768;private static final int SAMPLE_BUFFER_SIZE = 4096;private static final int MONO = 1;private static final int STEREO = 2;private static final boolean LITTLE_ENDIAN = false;private static final boolean BIG_ENDIAN = true;private static final boolean SIGNED = true;private static final boolean UNSIGNED = false;private static SourceDataLine line; //to play the sound

private static byte[] buffer; //our internal buffer

private static int bufferSize = 0; //number of samples currently in internal buffer

privateStdAudio() {//can not instantiate

}//static initializer

static{

init();

}//open up an audio stream

private static voidinit() {try{//44,100 Hz, 16-bit audio, mono, signed PCM, little endian

AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, MONO, SIGNED, LITTLE_ENDIAN);

DataLine.Info info= new DataLine.Info(SourceDataLine.class, format);

line=(SourceDataLine) AudioSystem.getLine(info);

line.open(format, SAMPLE_BUFFER_SIZE*BYTES_PER_SAMPLE);//the internal buffer is a fraction of the actual buffer size, this choice is arbitrary//it gets divided because we can't expect the buffered data to line up exactly with when//the sound card decides to push out its samples.

buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];

}catch(LineUnavailableException e) {

System.out.println(e.getMessage());

}//no sound gets made before this call

line.start();

}//get an AudioInputStream object from a file

private staticAudioInputStream getAudioInputStreamFromFile(String filename) {if (filename == null) {throw new IllegalArgumentException("filename is null");

}try{//first try to read file from local file system

File file = newFile(filename);if(file.exists()) {returnAudioSystem.getAudioInputStream(file);

}//resource relative to .class file

InputStream is1 = StdAudio.class.getResourceAsStream(filename);if (is1 != null) {returnAudioSystem.getAudioInputStream(is1);

}//resource relative to classloader root

InputStream is2 = StdAudio.class.getClassLoader().getResourceAsStream(filename);if (is2 != null) {returnAudioSystem.getAudioInputStream(is2);

}//give up

else{throw new IllegalArgumentException("could not read '" + filename + "'");

}

}catch(IOException e) {throw new IllegalArgumentException("could not read '" + filename + "'", e);

}catch(UnsupportedAudioFileException e) {throw new IllegalArgumentException("file of unsupported audio format: '" + filename + "'", e);

}

}/*** Closes standard audio.*/

public static voidclose() {

line.drain();

line.stop();

}/*** Writes one sample (between -1.0 and +1.0) to standard audio.

* If the sample is outside the range, it will be clipped.

*

*@paramsample the sample to play

*@throwsIllegalArgumentException if the sample is {@codeDouble.NaN}*/

public static void play(doublesample) {if (Double.isNaN(sample)) throw new IllegalArgumentException("sample is NaN");//clip if outside [-1, +1]

if (sample < -1.0) sample = -1.0;if (sample > +1.0) sample = +1.0;//convert to bytes

short s = (short) (MAX_16_BIT *sample);if (sample == 1.0) s = Short.MAX_VALUE; //special case since 32768 not a short

buffer[bufferSize++] = (byte) s;

buffer[bufferSize++] = (byte) (s >> 8); //little endian//send to sound card if buffer is full

if (bufferSize >=buffer.length) {

line.write(buffer,0, buffer.length);

bufferSize= 0;

}

}public static void play(byte[] samples)

{for (int i = 0; i < samples.length; i++) {

play(samples[i]);

}

}public static void play(bytesample) {

buffer[bufferSize++] =sample;//send to sound card if buffer is full

if (bufferSize >=buffer.length) {

line.write(buffer,0, buffer.length);

bufferSize= 0;

}

}/*** Writes the array of samples (between -1.0 and +1.0) to standard audio.

* If a sample is outside the range, it will be clipped.

*

*@paramsamples the array of samples to play

*@throwsIllegalArgumentException if any sample is {@codeDouble.NaN}

*@throwsIllegalArgumentException if {@codesamples} is {@codenull}*/

public static void play(double[] samples) {if (samples == null) throw new IllegalArgumentException("argument to play() is null");for (int i = 0; i < samples.length; i++) {

play(samples[i]);

}

}/*** Reads audio samples from a file (in .wav or .au format) and returns

* them as a double array with values between -1.0 and +1.0.

* The audio file must be 16-bit with a sampling rate of 44,100.

* It can be mono or stereo.

*

*@paramfilename the name of the audio file

*@returnthe array of samples*/

public static double[] read(String filename) {//make sure that AudioFormat is 16-bit, 44,100 Hz, little endian

final AudioInputStream ais =getAudioInputStreamFromFile(filename);

AudioFormat audioFormat=ais.getFormat();//require sampling rate = 44,100 Hz

if (audioFormat.getSampleRate() !=SAMPLE_RATE) {throw new IllegalArgumentException("StdAudio.read() currently supports only a sample rate of " + SAMPLE_RATE + " Hz\n"

+ "audio format: " +audioFormat);

}//require 16-bit audio

if (audioFormat.getSampleSizeInBits() !=BITS_PER_SAMPLE) {throw new IllegalArgumentException("StdAudio.read() currently supports only " + BITS_PER_SAMPLE + "-bit audio\n"

+ "audio format: " +audioFormat);

}//require little endian

if(audioFormat.isBigEndian()) {throw new IllegalArgumentException("StdAudio.read() currently supports only audio stored using little endian\n"

+ "audio format: " +audioFormat);

}byte[] bytes = null;try{int bytesToRead =ais.available();

bytes= new byte[bytesToRead];int bytesRead =ais.read(bytes);if (bytesToRead !=bytesRead) {throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes");

}

}catch(IOException ioe) {throw new IllegalArgumentException("could not read '" + filename + "'", ioe);

}int n =bytes.length;//little endian, mono

if (audioFormat.getChannels() ==MONO) {double[] data = new double[n/2];for (int i = 0; i < n/2; i++) {//little endian, mono

data[i] = ((short) (((bytes[2*i+1] & 0xFF) << 8) | (bytes[2*i] & 0xFF))) / ((double) MAX_16_BIT);

}returndata;

}//little endian, stereo

else if (audioFormat.getChannels() ==STEREO) {double[] data = new double[n/4];for (int i = 0; i < n/4; i++) {double left = ((short) (((bytes[4*i+1] & 0xFF) << 8) | (bytes[4*i + 0] & 0xFF))) / ((double) MAX_16_BIT);double right = ((short) (((bytes[4*i+3] & 0xFF) << 8) | (bytes[4*i + 2] & 0xFF))) / ((double) MAX_16_BIT);

data[i]= (left + right) / 2.0;

}returndata;

}//TODO: handle big endian (or other formats)

else throw new IllegalStateException("audio format is neither mono or stereo");

}/*** Saves the double array as an audio file (using .wav or .au format).

*

*@paramfilename the name of the audio file

*@paramsamples the array of samples

*@throwsIllegalArgumentException if unable to save {@codefilename}

*@throwsIllegalArgumentException if {@codesamples} is {@codenull}

*@throwsIllegalArgumentException if {@codefilename} is {@codenull}

*@throwsIllegalArgumentException if {@codefilename} extension is not {@code.wav}

* or {@code.au}*/

public static void save(String filename, double[] samples) {if (filename == null) {throw new IllegalArgumentException("filenameis null");

}if (samples == null) {throw new IllegalArgumentException("samples[] is null");

}//assumes 16-bit samples with sample rate = 44,100 Hz//use 16-bit audio, mono, signed PCM, little Endian

AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, MONO, SIGNED, LITTLE_ENDIAN);byte[] data = new byte[2 *samples.length];for (int i = 0; i < samples.length; i++) {int temp = (short) (samples[i] *MAX_16_BIT);if (samples[i] == 1.0) temp = Short.MAX_VALUE; //special case since 32768 not a short

data[2*i + 0] = (byte) temp;

data[2*i + 1] = (byte) (temp >> 8); //little endian

}//now save the file

try{

ByteArrayInputStream bais= newByteArrayInputStream(data);

AudioInputStream ais= newAudioInputStream(bais, format, samples.length);if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {

AudioSystem.write(ais, AudioFileFormat.Type.WAVE,newFile(filename));

}else if (filename.endsWith(".au") || filename.endsWith(".AU")) {

AudioSystem.write(ais, AudioFileFormat.Type.AU,newFile(filename));

}else{throw new IllegalArgumentException("file type for saving must be .wav or .au");

}

}catch(IOException ioe) {throw new IllegalArgumentException("unable to save file '" + filename + "'", ioe);

}

}/*** Plays an audio file (in .wav, .mid, or .au format) in a background thread.

*

*@paramfilename the name of the audio file

*@throwsIllegalArgumentException if unable to play {@codefilename}

*@throwsIllegalArgumentException if {@codefilename} is {@codenull}*/

public static synchronized void play(finalString filename) {new Thread(newRunnable() {public voidrun() {

AudioInputStream ais=getAudioInputStreamFromFile(filename);

stream(ais);

}

}).start();

}// https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html

//play a wav or aif file//javax.sound.sampled.Clip fails for long clips (on some systems), perhaps because//JVM closes (see remedy in loop)

private static voidstream(AudioInputStream ais) {

SourceDataLine line= null;int BUFFER_SIZE = 4096; //4K buffer

try{

AudioFormat audioFormat=ais.getFormat();

DataLine.Info info= new DataLine.Info(SourceDataLine.class, audioFormat);

line=(SourceDataLine) AudioSystem.getLine(info);

line.open(audioFormat);

line.start();byte[] samples = new byte[BUFFER_SIZE];int count = 0;while ((count = ais.read(samples, 0, BUFFER_SIZE)) != -1) {

line.write(samples,0, count);

}

}catch(IOException e) {

e.printStackTrace();

}catch(LineUnavailableException e) {

e.printStackTrace();

}finally{if (line != null) {

line.drain();

line.close();

}

}

}/*** Loops an audio file (in .wav, .mid, or .au format) in a background thread.

*

*@paramfilename the name of the audio file

*@throwsIllegalArgumentException if {@codefilename} is {@codenull}*/

public static synchronized voidloop(String filename) {if (filename == null) throw newIllegalArgumentException();final AudioInputStream ais =getAudioInputStreamFromFile(filename);try{

Clip clip=AudioSystem.getClip();//Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));

clip.open(ais);

clip.loop(Clip.LOOP_CONTINUOUSLY);

}catch(LineUnavailableException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}//keep JVM open

new Thread(newRunnable() {public voidrun() {while (true) {try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

}/***************************************************************************

* Unit tests {@codeStdAudio}.

***************************************************************************/

//create a note (sine wave) of the given frequency (Hz), for the given//duration (seconds) scaled to the given volume (amplitude)

private static double[] note(double hz, double duration, doubleamplitude) {int n = (int) (StdAudio.SAMPLE_RATE *duration);double[] a = new double[n+1];for (int i = 0; i <= n; i++)

a[i]= amplitude * Math.sin(2 * Math.PI * i * hz /StdAudio.SAMPLE_RATE);returna;

}/*** Test client - play an A major scale to standard audio.

*

*@paramargs the command-line arguments*/

/*** Test client - play an A major scale to standard audio.

*

*@paramargs the command-line arguments*/

public static voidmain(String[] args) {//440 Hz for 1 sec

double freq = 440.0;for (int i = 0; i <= StdAudio.SAMPLE_RATE; i++) {

StdAudio.play(0.5 * Math.sin(2*Math.PI * freq * i /StdAudio.SAMPLE_RATE));

}//scale increments

int[] steps = { 0, 2, 4, 5, 7, 9, 11, 12};for (int i = 0; i < steps.length; i++) {double hz = 440.0 * Math.pow(2, steps[i] / 12.0);

StdAudio.play(note(hz,1.0, 0.5));

}//need to call this in non-interactive stuff so the program doesn't terminate//until all the sound leaves the speaker.

StdAudio.close();

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java可以使用Java-WebSocket库来编写多个WebSocket实例。在使用Java-WebSocket库时,需要创建多个WebSocketServer实例,并为每个实例指定不同的端口号。每个WebSocketServer实例都可以处理多个WebSocket连接。在处理WebSocket连接时,可以使用WebSocket类的onOpen、onClose、onMessage和onError方法来处理WebSocket连接的打开、关闭、消息和错误事件。此外,还可以使用WebSocket类的send方法向客户端发送消息。下面是一个简单的Java-WebSocket多个WebSocket实例的示例代码: ``` import java.net.InetSocketAddress; import java.util.concurrent.CopyOnWriteArrayList; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.server.WebSocketServer; public class MultiWebSocketServer { private CopyOnWriteArrayList<WebSocket> webSockets = new CopyOnWriteArrayList<>(); public MultiWebSocketServer(int... ports) { for (int port : ports) { WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) { @Override public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) { webSockets.add(webSocket); System.out.println("WebSocket opened: " + webSocket.getRemoteSocketAddress()); } @Override public void onClose(WebSocket webSocket, int i, String s, boolean b) { webSockets.remove(webSocket); System.out.println("WebSocket closed: " + webSocket.getRemoteSocketAddress()); } @Override public void onMessage(WebSocket webSocket, String s) { System.out.println("WebSocket message received: " + s); } @Override public void onError(WebSocket webSocket, Exception e) { System.out.println("WebSocket error: " + e.getMessage()); } }; server.start(); System.out.println("WebSocket server started on port " + port); } } public void broadcast(String message) { for (WebSocket webSocket : webSockets) { webSocket.send(message); } } public static void main(String[] args) { MultiWebSocketServer server = new MultiWebSocketServer(8080, 8081); server.broadcast("Hello, world!"); } } ``` 此代码创建了两个WebSocketServer实例,分别监听8080和8081端口。在每个WebSocketServer实例的onOpen、onClose、onMessage和onError方法,分别处理WebSocket连接的打开、关闭、消息和错误事件。在broadcast方法,使用WebSocket类的send方法向所有客户端发送消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值