全部测试

This commit is contained in:
zedoCN 2024-08-31 03:19:00 +08:00
parent 7845e171fa
commit 2bd2c98e7b
4 changed files with 151 additions and 133 deletions

16
.idea/checkstyle-idea.xml generated Normal file
View 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>

View File

@ -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
} }
} }
} }

View File

@ -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()
/* /*

View File

@ -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]
} }
} }
} }