nb1
This commit is contained in:
parent
24ee4f1388
commit
6a2faf0520
@ -6,27 +6,30 @@ import java.io.IOException
|
|||||||
import java.io.ObjectInputStream
|
import java.io.ObjectInputStream
|
||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.net.InetSocketAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.util.*
|
|
||||||
import javax.sound.sampled.AudioFormat
|
import javax.sound.sampled.AudioFormat
|
||||||
import javax.sound.sampled.AudioSystem
|
import javax.sound.sampled.AudioSystem
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
val SERVER_PORT = 7890
|
||||||
|
val ECHO_CANCELLATION = true
|
||||||
val PACKET_SAMPLES = 2880
|
val PACKET_SAMPLES = 2880
|
||||||
var SAMPLE_RATE: Int = 48000
|
val SAMPLE_RATE = 48000
|
||||||
var CHANNELS: Int = 1
|
val CHANNELS = 1
|
||||||
var BUFFER_SIZE: Int = PACKET_SAMPLES * CHANNELS
|
val BUFFER_SIZE = PACKET_SAMPLES * CHANNELS
|
||||||
var sample = FloatArray(BUFFER_SIZE)
|
|
||||||
var bufferOut = ByteArray(sample.size * 2)
|
|
||||||
var bufferIn = ByteArray(sample.size * 2)
|
|
||||||
var format: AudioFormat = AudioConvert.getAudioFormat(SAMPLE_RATE, CHANNELS)
|
|
||||||
var socket: Socket? = null
|
|
||||||
var targetDataLine = AudioSystem.getTargetDataLine(format)
|
|
||||||
var sourceDataLine = AudioSystem.getSourceDataLine(format)
|
|
||||||
|
|
||||||
var `in`: ObjectInputStream? = null
|
val bufferOut = ByteArray(BUFFER_SIZE * 2)
|
||||||
var out: ObjectOutputStream? = null
|
val bufferIn = ByteArray(BUFFER_SIZE * 2)
|
||||||
|
val format = AudioConvert.getAudioFormat(SAMPLE_RATE, CHANNELS)
|
||||||
|
|
||||||
|
val decoder = OpusDecoder(48000, 1)
|
||||||
|
val encoder = OpusEncoder(48000, 1, OpusApplication.OPUS_APPLICATION_AUDIO).also {
|
||||||
|
it.bitrate = 96000
|
||||||
|
it.forceMode = OpusMode.MODE_CELT_ONLY
|
||||||
|
it.signalType = OpusSignal.OPUS_SIGNAL_MUSIC
|
||||||
|
it.complexity = 0
|
||||||
|
}
|
||||||
|
|
||||||
object Client {
|
object Client {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -41,43 +44,31 @@ data class DataPack(
|
|||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
||||||
fun mainClient() = runBlocking {
|
fun mainClient() = runBlocking {
|
||||||
val t = measureTimeMillis {
|
val socket = Socket()
|
||||||
// socket = Socket("zedo.top", 7860)
|
|
||||||
socket = Socket("127.0.0.1", 17860)
|
|
||||||
}
|
|
||||||
println("connect done! $t")
|
|
||||||
out = ObjectOutputStream(socket!!.getOutputStream())
|
|
||||||
`in` = ObjectInputStream(socket!!.getInputStream())
|
|
||||||
|
|
||||||
|
val t = measureTimeMillis {
|
||||||
|
// socket.connect(InetSocketAddress("zedo.top", SERVER_PORT))
|
||||||
|
socket.connect(InetSocketAddress("127.0.0.1", SERVER_PORT))
|
||||||
|
}
|
||||||
|
println("connect time $t")
|
||||||
|
|
||||||
|
val out = ObjectOutputStream(socket.getOutputStream())
|
||||||
|
val inp = ObjectInputStream(socket.getInputStream())
|
||||||
|
|
||||||
|
val targetDataLine = AudioSystem.getTargetDataLine(format)
|
||||||
targetDataLine.open(format, bufferIn.size)
|
targetDataLine.open(format, bufferIn.size)
|
||||||
targetDataLine.start()
|
targetDataLine.start()
|
||||||
|
|
||||||
|
val sourceDataLine = AudioSystem.getSourceDataLine(format)
|
||||||
sourceDataLine.open(format, bufferIn.size)
|
sourceDataLine.open(format, bufferIn.size)
|
||||||
sourceDataLine.start()
|
sourceDataLine.start()
|
||||||
|
|
||||||
var encoder = OpusEncoder(48000, 1, OpusApplication.OPUS_APPLICATION_AUDIO).also {
|
|
||||||
it.bitrate = 96000
|
|
||||||
it.forceMode = OpusMode.MODE_CELT_ONLY
|
|
||||||
it.signalType = OpusSignal.OPUS_SIGNAL_MUSIC
|
|
||||||
it.complexity = 0
|
|
||||||
}
|
|
||||||
var decoder: OpusDecoder = OpusDecoder(48000, 1)
|
|
||||||
|
|
||||||
// val opus = ByteArray(sample.size * 2)
|
|
||||||
|
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
while (true) {
|
while (true) {
|
||||||
//Arrays.fill(bufferOut, (byte) 0);
|
|
||||||
targetDataLine.read(bufferOut, 0, bufferOut.size)
|
targetDataLine.read(bufferOut, 0, bufferOut.size)
|
||||||
try {
|
try {
|
||||||
// out!!.write(bufferOut, 0, bufferOut.size)
|
out.writeObject(encoder.encode(bufferOut))
|
||||||
// println(Arrays.toString(bufferOut))
|
out.flush()
|
||||||
// println("aaa: " + Arrays.toString(bufferOut))
|
|
||||||
// val pcm = Program.BytesToShorts(bufferOut, 0, bufferOut.size)
|
|
||||||
// val bytesEncoded = encoder.encode(pcm, 0, PACKET_SAMPLES, opus, 0, opus.size)
|
|
||||||
// out!!.writeObject(DataPack(System.currentTimeMillis(), opus.sliceArray(0..<bytesEncoded)))
|
|
||||||
out!!.writeObject(encoder.encode(bufferOut))
|
|
||||||
out!!.flush()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
System.exit(0)
|
System.exit(0)
|
||||||
@ -93,7 +84,7 @@ fun mainClient() = runBlocking {
|
|||||||
// println("丢弃")
|
// println("丢弃")
|
||||||
// }
|
// }
|
||||||
// `in`!!.read(bufferIn, 0, bufferIn.size)
|
// `in`!!.read(bufferIn, 0, bufferIn.size)
|
||||||
val dataPack = `in`!!.readObject() as DataPack
|
val dataPack = inp.readObject() as DataPack
|
||||||
decoder.decode(dataPack, bufferIn)
|
decoder.decode(dataPack, bufferIn)
|
||||||
sourceDataLine.write(bufferIn, 0, bufferIn.size)
|
sourceDataLine.write(bufferIn, 0, bufferIn.size)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
@ -10,7 +10,7 @@ import java.net.Socket
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|
||||||
var clientAudios: MutableList<ClientAudio> = CopyOnWriteArrayList()
|
val clientAudios = CopyOnWriteArrayList<ClientAudio>()
|
||||||
|
|
||||||
object Server {
|
object Server {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -25,7 +25,7 @@ fun mainServer() = runBlocking {
|
|||||||
while (true) {
|
while (true) {
|
||||||
for (client in clientAudios) {
|
for (client in clientAudios) {
|
||||||
if (!client.isConnected) {
|
if (!client.isConnected) {
|
||||||
clientAudios.remove(client)
|
clientAudios -= client
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
client.read()
|
client.read()
|
||||||
@ -34,8 +34,9 @@ fun mainServer() = runBlocking {
|
|||||||
for (client in clientAudios) {
|
for (client in clientAudios) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
for (audio in clientAudios) {
|
for (audio in clientAudios) {
|
||||||
// if (audio != client)
|
if (audio != client || !ECHO_CANCELLATION) {
|
||||||
client.mix(audio.sample)
|
client.mix(audio.sample)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.send()
|
client.send()
|
||||||
}
|
}
|
||||||
@ -43,40 +44,43 @@ fun mainServer() = runBlocking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sever = ServerSocket(17860)
|
val sever = ServerSocket(SERVER_PORT)
|
||||||
while (true) {
|
while (true) {
|
||||||
val socket = sever.accept()
|
val socket = sever.accept()
|
||||||
println("Accepted connection from " + socket.remoteSocketAddress)
|
println("Accepted connection from " + socket.remoteSocketAddress)
|
||||||
clientAudios.add(ClientAudio(socket))
|
clientAudios += ClientAudio(socket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientAudio(var socket: Socket) {
|
class ClientAudio(val socket: Socket) {
|
||||||
|
|
||||||
val inp = ObjectInputStream(socket.getInputStream())
|
val inp = ObjectInputStream(socket.getInputStream())
|
||||||
val out = ObjectOutputStream(socket.getOutputStream())
|
val out = ObjectOutputStream(socket.getOutputStream())
|
||||||
val buffer: ByteArray = ByteArray(BUFFER_SIZE * 2)
|
val buffer = ByteArray(BUFFER_SIZE * 2)
|
||||||
val sample: FloatArray = FloatArray(BUFFER_SIZE)
|
val sample = FloatArray(BUFFER_SIZE)
|
||||||
val mixSample: FloatArray = FloatArray(BUFFER_SIZE)
|
val mixSample = FloatArray(BUFFER_SIZE)
|
||||||
var mixBuffer: ByteArray = ByteArray(BUFFER_SIZE * 2)
|
val mixBuffer = ByteArray(BUFFER_SIZE * 2)
|
||||||
|
|
||||||
|
val decoder = OpusDecoder(48000, 1)
|
||||||
|
val encoder = OpusEncoder(48000, 1, OpusApplication.OPUS_APPLICATION_AUDIO).also {
|
||||||
|
it.bitrate = 96000
|
||||||
|
it.forceMode = OpusMode.MODE_CELT_ONLY
|
||||||
|
it.signalType = OpusSignal.OPUS_SIGNAL_MUSIC
|
||||||
|
it.complexity = 0
|
||||||
|
}
|
||||||
|
|
||||||
var isConnected = true
|
var isConnected = true
|
||||||
|
|
||||||
fun send() {
|
fun send() {
|
||||||
try {
|
try {
|
||||||
AudioConvert.convertFloatToShortByte(mixSample, mixBuffer)
|
AudioConvert.convertFloatToShortByte(mixSample, mixBuffer)
|
||||||
out.writeObject(encoder.encode(mixBuffer))
|
out.writeObject(encoder.encode(mixBuffer))
|
||||||
// out.write(mixBuffer)
|
|
||||||
out.flush()
|
out.flush()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
isConnected = false
|
isConnected = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var decoder: OpusDecoder = OpusDecoder(48000, 1)
|
|
||||||
var encoder = OpusEncoder(48000, 1, OpusApplication.OPUS_APPLICATION_AUDIO).also {
|
|
||||||
it.bitrate = 96000
|
|
||||||
it.forceMode = OpusMode.MODE_CELT_ONLY
|
|
||||||
it.signalType = OpusSignal.OPUS_SIGNAL_MUSIC
|
|
||||||
it.complexity = 0
|
|
||||||
}
|
|
||||||
fun read() {
|
fun read() {
|
||||||
try {
|
try {
|
||||||
// if (`in`!!.available() > bufferIn.size * 2) {
|
// if (`in`!!.available() > bufferIn.size * 2) {
|
||||||
@ -85,10 +89,7 @@ class ClientAudio(var socket: Socket) {
|
|||||||
// }
|
// }
|
||||||
// `in`.read(buffer)
|
// `in`.read(buffer)
|
||||||
val pack = inp.readObject() as DataPack
|
val pack = inp.readObject() as DataPack
|
||||||
|
|
||||||
// opus.copyInto(buffer)
|
|
||||||
// println("延迟: ${System.currentTimeMillis() - timestamp}ms")
|
// println("延迟: ${System.currentTimeMillis() - timestamp}ms")
|
||||||
// println(Arrays.toString(opus))
|
|
||||||
decoder.decode(pack, buffer)
|
decoder.decode(pack, buffer)
|
||||||
AudioConvert.convertShortByteToFloat(buffer, sample)
|
AudioConvert.convertShortByteToFloat(buffer, sample)
|
||||||
Arrays.fill(mixSample, 0f)
|
Arrays.fill(mixSample, 0f)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user