全部测试
This commit is contained in:
parent
7845e171fa
commit
2bd2c98e7b
16
.idea/checkstyle-idea.xml
generated
Normal file
16
.idea/checkstyle-idea.xml
generated
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CheckStyle-IDEA" serialisationVersion="2">
|
||||||
|
<checkstyleVersion>10.18.0</checkstyleVersion>
|
||||||
|
<scanScope>JavaOnly</scanScope>
|
||||||
|
<copyLibs>true</copyLibs>
|
||||||
|
<option name="thirdPartyClasspath" />
|
||||||
|
<option name="activeLocationIds" />
|
||||||
|
<option name="locations">
|
||||||
|
<list>
|
||||||
|
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
|
||||||
|
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,9 +1,18 @@
|
|||||||
import javax.sound.sampled.AudioFormat;
|
import javax.sound.sampled.AudioFormat
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
public class AudioConvert {
|
object AudioConvert {
|
||||||
|
fun getAudioFormat(sampleRate: Int, channels: Int): AudioFormat {
|
||||||
public static AudioFormat getAudioFormat(int sampleRate, int channels) {
|
return AudioFormat(
|
||||||
return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sampleRate, 16, channels, channels * 2, sampleRate, false);
|
AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
sampleRate.toFloat(),
|
||||||
|
16,
|
||||||
|
channels,
|
||||||
|
channels * 2,
|
||||||
|
sampleRate.toFloat(),
|
||||||
|
false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,21 +21,19 @@ public class AudioConvert {
|
|||||||
* @param input 输入的 float[] 数据
|
* @param input 输入的 float[] 数据
|
||||||
* @param output 转换后的 byte[] 数据
|
* @param output 转换后的 byte[] 数据
|
||||||
*/
|
*/
|
||||||
public static void convertFloatToShortByte(float[] input, byte[] output) {
|
fun convertFloatToShortByte(input: FloatArray, output: ByteArray) {
|
||||||
if (input.length * 2 != output.length) {
|
require(input.size * 2 == output.size) { "output byte array length must be twice the length of the input float array." }
|
||||||
throw new IllegalArgumentException("output byte array length must be twice the length of the input float array.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < input.length; i++) {
|
for (i in input.indices) {
|
||||||
// 将 float 值限制在 -1.0 到 1.0 之间
|
// 将 float 值限制在 -1.0 到 1.0 之间
|
||||||
float sample = Math.min(Math.max(input[i], -1.0f), 1.0f);
|
val sample = min(max(input[i].toDouble(), -1.0), 1.0).toFloat()
|
||||||
|
|
||||||
// 将 float 值转换为 short
|
// 将 float 值转换为 short
|
||||||
short shortSample = (short) (sample * 32767);
|
val shortSample = (sample * 32767).toInt().toShort()
|
||||||
|
|
||||||
// 将 short 值转换为两个字节,并存储在 lineBuffer 中
|
// 将 short 值转换为两个字节,并存储在 lineBuffer 中
|
||||||
output[i * 2] = (byte) (shortSample & 0xFF); // 低位字节
|
output[i * 2] = (shortSample.toInt() and 0xFF).toByte() // 低位字节
|
||||||
output[i * 2 + 1] = (byte) ((shortSample >> 8) & 0xFF); // 高位字节
|
output[i * 2 + 1] = ((shortSample.toInt() shr 8) and 0xFF).toByte() // 高位字节
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,20 +43,17 @@ public class AudioConvert {
|
|||||||
* @param input 输入的 byte[] 数据(每两个字节表示一个 short)
|
* @param input 输入的 byte[] 数据(每两个字节表示一个 short)
|
||||||
* @param output 转换后的 float[] 数据
|
* @param output 转换后的 float[] 数据
|
||||||
*/
|
*/
|
||||||
public static void convertShortByteToFloat(byte[] input, float[] output) {
|
fun convertShortByteToFloat(input: ByteArray, output: FloatArray) {
|
||||||
if (input.length != output.length * 2) {
|
require(input.size == output.size * 2) { "Input byte array length must be twice the length of the output float array." }
|
||||||
throw new IllegalArgumentException("Input byte array length must be twice the length of the output float array.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < output.length; i++) {
|
for (i in output.indices) {
|
||||||
// 将两个字节转换为 short
|
// 将两个字节转换为 short
|
||||||
int low = input[i * 2] & 0xFF;
|
val low = input[i * 2].toInt() and 0xFF
|
||||||
int high = input[i * 2 + 1] & 0xFF;
|
val high = input[i * 2 + 1].toInt() and 0xFF
|
||||||
short shortSample = (short) ((high << 8) | low);
|
val shortSample = ((high shl 8) or low).toShort()
|
||||||
|
|
||||||
// 将 short 值转换为 float
|
// 将 short 值转换为 float
|
||||||
output[i] = shortSample / 32768.0f;
|
output[i] = shortSample / 32768.0f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,70 +1,71 @@
|
|||||||
import javax.sound.sampled.AudioFormat;
|
import java.io.IOException
|
||||||
import javax.sound.sampled.AudioSystem;
|
import java.io.InputStream
|
||||||
import javax.sound.sampled.SourceDataLine;
|
import java.io.OutputStream
|
||||||
import javax.sound.sampled.TargetDataLine;
|
import java.net.Socket
|
||||||
import java.io.IOException;
|
import javax.sound.sampled.AudioFormat
|
||||||
import java.io.InputStream;
|
import javax.sound.sampled.AudioSystem
|
||||||
import java.io.OutputStream;
|
import javax.sound.sampled.SourceDataLine
|
||||||
import java.net.Socket;
|
import javax.sound.sampled.TargetDataLine
|
||||||
|
|
||||||
public class Client {
|
object Client {
|
||||||
public static InputStream in;
|
var `in`: InputStream? = null
|
||||||
public static OutputStream out;
|
var out: OutputStream? = null
|
||||||
public static SourceDataLine sourceDataLine;
|
var sourceDataLine: SourceDataLine? = null
|
||||||
public static TargetDataLine targetDataLine;
|
var targetDataLine: TargetDataLine? = null
|
||||||
public static byte[] bufferOut;
|
var bufferOut: ByteArray
|
||||||
public static byte[] bufferIn;
|
var bufferIn: ByteArray
|
||||||
public static float[] sample;
|
var sample: FloatArray
|
||||||
public static int SAMPLE_RATE = 48000;
|
var SAMPLE_RATE: Int = 48000
|
||||||
public static int CHANNELS = 1;
|
var CHANNELS: Int = 1
|
||||||
public static AudioFormat format = AudioConvert.getAudioFormat(SAMPLE_RATE, CHANNELS);
|
var format: AudioFormat = AudioConvert.getAudioFormat(SAMPLE_RATE, CHANNELS)
|
||||||
public static Socket socket;
|
var socket: Socket? = null
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
@Throws(Exception::class)
|
||||||
socket = new Socket("127.0.0.1", 7860);
|
@JvmStatic
|
||||||
in = socket.getInputStream();
|
fun main(args: Array<String>) {
|
||||||
out = socket.getOutputStream();
|
socket = Socket("127.0.0.1", 7860)
|
||||||
sample = new float[Server.BUFFER_SIZE];
|
`in` = socket!!.getInputStream()
|
||||||
bufferIn = new byte[sample.length * 2];
|
out = socket!!.getOutputStream()
|
||||||
bufferOut = new byte[sample.length * 2];
|
sample = FloatArray(Server.BUFFER_SIZE)
|
||||||
|
bufferIn = ByteArray(sample.size * 2)
|
||||||
|
bufferOut = ByteArray(sample.size * 2)
|
||||||
|
|
||||||
targetDataLine = AudioSystem.getTargetDataLine(format);
|
targetDataLine = AudioSystem.getTargetDataLine(format)
|
||||||
targetDataLine.open(format, bufferIn.length);
|
targetDataLine.open(format, bufferIn.size)
|
||||||
targetDataLine.start();
|
targetDataLine.start()
|
||||||
|
|
||||||
|
|
||||||
sourceDataLine = AudioSystem.getSourceDataLine(format);
|
sourceDataLine = AudioSystem.getSourceDataLine(format)
|
||||||
sourceDataLine.open(format, bufferIn.length);
|
sourceDataLine.open(format, bufferIn.size)
|
||||||
sourceDataLine.start();
|
sourceDataLine.start()
|
||||||
|
|
||||||
|
|
||||||
new Thread(() -> {
|
Thread {
|
||||||
while (true) {
|
while (true) {
|
||||||
//Arrays.fill(bufferOut, (byte) 0);
|
//Arrays.fill(bufferOut, (byte) 0);
|
||||||
targetDataLine.read(bufferOut, 0, bufferOut.length);
|
targetDataLine.read(bufferOut, 0, bufferOut.size)
|
||||||
try {
|
try {
|
||||||
out.write(bufferOut, 0, bufferOut.length);
|
out.write(bufferOut, 0, bufferOut.size)
|
||||||
out.flush();
|
out.flush()
|
||||||
} catch (Exception e) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace();
|
e.printStackTrace()
|
||||||
System.exit(0);
|
System.exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}.start()
|
||||||
|
|
||||||
|
|
||||||
new Thread(() -> {
|
Thread {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
in.read(bufferIn, 0, bufferIn.length);
|
`in`.read(bufferIn, 0, bufferIn.size)
|
||||||
sourceDataLine.write(bufferIn, 0, bufferIn.length);
|
sourceDataLine.write(bufferIn, 0, bufferIn.size)
|
||||||
} catch (IOException e) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace();
|
e.printStackTrace()
|
||||||
System.exit(0);
|
System.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}).start();
|
}.start()
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
117
src/Server.kt
117
src/Server.kt
@ -1,98 +1,95 @@
|
|||||||
import java.io.IOException;
|
import java.io.IOException
|
||||||
import java.io.InputStream;
|
import java.io.InputStream
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket
|
||||||
import java.net.Socket;
|
import java.net.Socket
|
||||||
import java.util.Arrays;
|
import java.util.*
|
||||||
import java.util.List;
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
|
|
||||||
public class Server {
|
object Server {
|
||||||
|
var clientAudios: MutableList<ClientAudio> = CopyOnWriteArrayList()
|
||||||
|
@kotlin.jvm.JvmField
|
||||||
|
var BUFFER_SIZE: Int = 2048 * Client.CHANNELS
|
||||||
|
var mixSample: FloatArray = FloatArray(BUFFER_SIZE)
|
||||||
|
var buffer: ByteArray = ByteArray(BUFFER_SIZE * 2)
|
||||||
|
|
||||||
public static List<ClientAudio> clientAudios = new CopyOnWriteArrayList<>();
|
@kotlin.Throws(Exception::class)
|
||||||
public static int BUFFER_SIZE = 2048 * Client.CHANNELS;
|
@kotlin.jvm.JvmStatic
|
||||||
public static float[] mixSample = new float[BUFFER_SIZE];
|
fun main(args: Array<String>) {
|
||||||
public static byte[] buffer = new byte[BUFFER_SIZE * 2];
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
//混音
|
//混音
|
||||||
new Thread(() -> {
|
Thread {
|
||||||
while (true) {
|
while (true) {
|
||||||
for (var client : clientAudios) {
|
for (client in clientAudios) {
|
||||||
if (!client.isConnected()) {
|
if (!client.isConnected) {
|
||||||
clientAudios.remove(client);
|
clientAudios.remove(client)
|
||||||
System.out.println("现在是: "+clientAudios);
|
println("现在是: " + clientAudios)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
client.read();
|
client.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (var client : clientAudios) {
|
for (client in clientAudios) {
|
||||||
Arrays.fill(mixSample, 0);
|
Arrays.fill(mixSample, 0f)
|
||||||
for (var audio : clientAudios) {
|
for (audio in clientAudios) {
|
||||||
//if (audio != client)
|
//if (audio != client)
|
||||||
audio.mix(mixSample);
|
audio.mix(mixSample)
|
||||||
}
|
}
|
||||||
AudioConvert.convertFloatToShortByte(mixSample, buffer);
|
AudioConvert.convertFloatToShortByte(mixSample, buffer)
|
||||||
client.send(buffer);
|
client.send(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println("混音");
|
//System.out.println("混音");
|
||||||
}
|
}
|
||||||
}).start();
|
}.start()
|
||||||
|
|
||||||
ServerSocket sever = new ServerSocket(7860);
|
val sever = ServerSocket(7860)
|
||||||
while (true) {
|
while (true) {
|
||||||
Socket socket = sever.accept();
|
val socket = sever.accept()
|
||||||
System.out.println("Accepted connection from " + socket.getRemoteSocketAddress());
|
println("Accepted connection from " + socket.remoteSocketAddress)
|
||||||
clientAudios.add(new ClientAudio(socket));
|
clientAudios.add(ClientAudio(socket))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ClientAudio {
|
class ClientAudio(var socket: Socket) {
|
||||||
Socket socket;
|
var `in`: InputStream? = null
|
||||||
InputStream in;
|
var out: OutputStream? = null
|
||||||
OutputStream out;
|
var buffer: ByteArray = ByteArray(BUFFER_SIZE * 2)
|
||||||
byte[] buffer = new byte[BUFFER_SIZE * 2];
|
var sample: FloatArray = FloatArray(BUFFER_SIZE)
|
||||||
float[] sample = new float[BUFFER_SIZE];
|
|
||||||
|
|
||||||
public ClientAudio(Socket socket) {
|
init {
|
||||||
this.socket = socket;
|
|
||||||
try {
|
try {
|
||||||
in = socket.getInputStream();
|
`in` = socket.getInputStream()
|
||||||
out = socket.getOutputStream();
|
out = socket.getOutputStream()
|
||||||
|
} catch (e: IOException) {
|
||||||
} catch (IOException e) {
|
throw RuntimeException(e)
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
val isConnected: Boolean
|
||||||
return socket.isConnected();
|
get() = socket.isConnected
|
||||||
}
|
|
||||||
|
|
||||||
public void send(byte[] buffer) {
|
fun send(buffer: ByteArray) {
|
||||||
try {
|
try {
|
||||||
out.write(buffer);
|
out!!.write(buffer)
|
||||||
out.flush();
|
out!!.flush()
|
||||||
} catch (IOException e) {
|
} catch (e: IOException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void read() {
|
fun read() {
|
||||||
try {
|
try {
|
||||||
in.read(buffer);
|
`in`!!.read(buffer)
|
||||||
AudioConvert.convertShortByteToFloat(buffer, sample);
|
AudioConvert.convertShortByteToFloat(buffer, sample)
|
||||||
} catch (IOException e) {
|
} catch (e: IOException) {
|
||||||
//throw new RuntimeException(e);
|
//throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mix(float[] sample) {
|
fun mix(sample: FloatArray) {
|
||||||
for (int i = 0; i < sample.length; i++) {
|
for (i in sample.indices) {
|
||||||
sample[i] += this.sample[i];
|
sample[i] += this.sample[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user