使用信息

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory; @Slf4j
public class WebSocketTTS extends WebSocketClient { //https://github.com/alumae/kaldi-gstreamer-server
//https://realpython.com/python-speech-recognition/
public static String WS_URL = "ws://xxx.xxx.xxx.xxx/service"; private boolean isWsClosed = false; Queue<byte[]> audioQueue = new LinkedBlockingQueue<>(); ExecutorService exec = Executors.newFixedThreadPool(1,
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
}); public WebSocketTTS(URI serverURI) {
super(serverURI, new Draft_6455());
exec.execute(this::play);
} public WebSocketTTS(URI serverURI, Draft draft) {
super(serverURI, draft);
} @Override
public void onClose(int code, String reason, boolean remote) { System.out.println("code = " + code + "; reason = " + reason);
System.out.println("Connection closed by " + (remote ? "remote peer" : "us"));
isWsClosed = true;
System.out.println("已关闭连接");
} @Override
public void onError(Exception arg0) {
System.out.println("made mistakes");
} @Override
public void onMessage(ByteBuffer bytes) {
audioQueue.add(bytes.array());
log.info("接收到:{}字节,音频时长:{}秒", bytes.capacity(),bytes.capacity()/16000.0f);
} public void play() {
while (true) {
byte[] data = audioQueue.poll();
if (data != null) {
StdAudio.play(data);
} else if (isWsClosed) {
break;
}
}
} @Override
public void onMessage(String message) { String json = StringEscapeUtils.unescapeJava(message);
System.out.println(json);
} @Override
public void onOpen(ServerHandshake arg0) {
System.out.println("已经连接到websocket接口");
} public static void main(String[] args) throws URISyntaxException, InterruptedException, IOException { WebSocketTTS websocket = new WebSocketTTS(new URI(WS_URL));
if (!websocket.connectBlocking()) {
System.err.println("Could not connect to the server.");
return;
} List<String> lines = Files.readAllLines(Paths.get("d:/测试文本.txt"), Charset.forName("UTF-8")); for (String line : lines) {
ObjectMapper objectMapper = new ObjectMapper();
ImmutableMap<String, Object> immutableMap = ImmutableMap.of("text", line, "param", "value");
String json = objectMapper.writeValueAsString(immutableMap);
websocket.send(json);
}
websocket.send("<eos>"); while (!(websocket.isWsClosed&&websocket.audioQueue.isEmpty()))
{
Thread.sleep(5000);
log.info("正在等待服务退出");
} } }

StdAudio.java

/******************************************************************************
* 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 ?
*
******************************************************************************/ import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream; /**
* <i>Standard audio</i>. This class provides a basic capability for
* creating, reading, and saving audio.
* <p>
* The audio format uses a sampling rate of 44,100 Hz, 16-bit, monaural.
*
* <p>
* For additional documentation, see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <i>Computer Science: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class StdAudio { /**
* 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 private StdAudio() {
// can not instantiate
} // static initializer
static {
init();
} // open up an audio stream
private static void init() {
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 static AudioInputStream getAudioInputStreamFromFile(String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename is null");
} try {
// first try to read file from local file system
File file = new File(filename);
if (file.exists()) {
return AudioSystem.getAudioInputStream(file);
} // resource relative to .class file
InputStream is1 = StdAudio.class.getResourceAsStream(filename);
if (is1 != null) {
return AudioSystem.getAudioInputStream(is1);
} // resource relative to classloader root
InputStream is2 = StdAudio.class.getClassLoader().getResourceAsStream(filename);
if (is2 != null) {
return AudioSystem.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 void close() {
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.
*
* @param sample the sample to play
* @throws IllegalArgumentException if the sample is {@code Double.NaN}
*/
public static void play(double sample) {
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(byte sample) {
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.
*
* @param samples the array of samples to play
* @throws IllegalArgumentException if any sample is {@code Double.NaN}
* @throws IllegalArgumentException if {@code samples} is {@code null}
*/
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.
*
* @param filename the name of the audio file
* @return the 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);
}
return data;
} // 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;
}
return data;
} // 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).
*
* @param filename the name of the audio file
* @param samples the array of samples
* @throws IllegalArgumentException if unable to save {@code filename}
* @throws IllegalArgumentException if {@code samples} is {@code null}
* @throws IllegalArgumentException if {@code filename} is {@code null}
* @throws IllegalArgumentException if {@code filename} 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 = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais, format, samples.length);
if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));
}
else if (filename.endsWith(".au") || filename.endsWith(".AU")) {
AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(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.
*
* @param filename the name of the audio file
* @throws IllegalArgumentException if unable to play {@code filename}
* @throws IllegalArgumentException if {@code filename} is {@code null}
*/
public static synchronized void play(final String filename) {
new Thread(new Runnable() {
public void run() {
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 void stream(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.
*
* @param filename the name of the audio file
* @throws IllegalArgumentException if {@code filename} is {@code null}
*/
public static synchronized void loop(String filename) {
if (filename == null) throw new IllegalArgumentException(); 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(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
} /***************************************************************************
* Unit tests {@code StdAudio}.
***************************************************************************/ // 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, double amplitude) {
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);
return a;
} /**
* Test client - play an A major scale to standard audio.
*
* @param args the command-line arguments
*/
/**
* Test client - play an A major scale to standard audio.
*
* @param args the command-line arguments
*/
public static void main(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();
}
}

WebSocket接收音频,并推送到声卡上的更多相关文章

  1. springboot整合websocket实现一对一消息推送和广播消息推送

    maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  2. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

  3. 基于 WebSocket 的 MQTT 移动推送方案

    WebSphere MQ Telemetry Transport 简介 WebSphere MQ Telemetry Transport (MQTT) 是一项异步消息传输协议,是 IBM 在分析了他们 ...

  4. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

  5. Android APP切换到后台接收不到推送消息

    1.   Android端进程被杀死后,目前自带的保护后台接收消息活跃机制.暂时没有什么好的机制保持任何情况下都活跃 android原生系统用home键杀进程可以起来,如果是强行停止就只能用户自己手动 ...

  6. 将本地的项目推送到github上

    好像还是不能用git在本地直接建一个repository,然后推送到github,这是把本地项目推送到github上已经建好的裤 …or create a new repository on the ...

  7. 怎么把宿主机上的镜像推送到hub上

    怎么把宿主机上的镜像推送到hub上: 1.查看系统中存在的镜像: [root@izuf63bjp8ts8nkl13pxh1z devicemapper]# docker imagesREPOSITOR ...

  8. 数据测试002:利用Jmeter推送测试数据(上)

    数据测试002:利用Jmeter推送测试数据(上) 刚才用Jmeter配置一下MySQL数据库花了点时间,好在最后都解决了,注意下面几个问题: 1)没有配置  “Cannot load JDBC dr ...

  9. WebSocket(4)---实现定时推送比特币交易信息

    实现定时推送比特币交易信息 实现功能:跟虚拟币交易所一样,时时更新当前比特币的价格,最高价,最低价,买一价等等...... 提示:(1)本篇博客是在上一遍基础上搭建,上一篇博客地址:[WebSocke ...

随机推荐

  1. kth-largest-element

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  2. [C++11]C++可变参数模板

    可变参数模板 原文链接: http://blog.csdn.net/xiaohu2022/article/details/69076281 普通模板只可以采取固定数量的模板参数.然而,有时候我们希望模 ...

  3. cube.js 学习(三)cube.js data schema

    cube.js的 data schema 类似graphql 的type 定义,但是cube.js 的data schema 更偏向于dsl, 其中抽象了进行数据分析应用开发中的东西,自己提炼了mea ...

  4. AtCoder Grand Contest 009 题解

    传送门 为啥这场题目少一点啊-- \(A\) 易知增加的数前面肯定比后面大,那么我们倒着做,然后维护一下最小要加多少就可以了 typedef long long ll; const int N=1e5 ...

  5. 洛谷P3124被困在haybales

    题目 按理来说是可以二分的,但是发现其实直接暴力然后注意细节就可以了. 先找到牛所在的起点,然后分别向右找和向左找. 第一次查找从\(r\)点冲到\(l\)点时,突破不了\(l\),从\(l\)点冲到 ...

  6. 微信小程序微信登录

    开发接口 登录 wx.login wx.checkSession 签名加密 小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 登录流程时序 ...

  7. Java中的读文件,文件的创建,写文件

    前言 大家好,我是 Vic,今天给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 示意图 读文件 public static void read(String path,Strin ...

  8. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  9. Large-Scale Oil Palm Tree Detection from High-Resolution Satellite Images Using Two-Stage Convolutional Neural Networks(worldview油棕树检测)

    不是目标检测也不是语义分割,两步CNN指的是,采集的数据是一堆点,以点为中心的65*65和17*17图像范围大小来判断这个点是否是油棕树.第一步就是判断65*65的范围是否为(油棕树植被群,其他植被/ ...

  10. [SDOI2009][BZOJ 1876]SuperGCD

    Description Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比 赛计算GCD.有一天Sheng bill很嚣张地找到了你,并 ...