Compare commits

..

No commits in common. "01573626a27ab7b38afecb5376cc47f8bfe233e1" and "24ee4f1388b2e1fa2cc94744c71666342df7d41b" have entirely different histories.

2 changed files with 59 additions and 51 deletions

View File

@ -6,30 +6,27 @@ 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
val SAMPLE_RATE = 48000 var SAMPLE_RATE: Int = 48000
val CHANNELS = 1 var CHANNELS: Int = 1
val BUFFER_SIZE = PACKET_SAMPLES * CHANNELS var BUFFER_SIZE: Int = 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)
val bufferOut = ByteArray(BUFFER_SIZE * 2) var `in`: ObjectInputStream? = null
val bufferIn = ByteArray(BUFFER_SIZE * 2) var out: ObjectOutputStream? = null
val format = AudioConvert.getAudioFormat(SAMPLE_RATE, CHANNELS)
val decoder = OpusDecoder(SAMPLE_RATE, CHANNELS)
val encoder = OpusEncoder(SAMPLE_RATE, CHANNELS, 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
@ -44,31 +41,43 @@ data class DataPack(
) : Serializable ) : Serializable
fun mainClient() = runBlocking { fun mainClient() = runBlocking {
val socket = Socket()
val t = measureTimeMillis { val t = measureTimeMillis {
// socket.connect(InetSocketAddress("zedo.top", SERVER_PORT)) // socket = Socket("zedo.top", 7860)
socket.connect(InetSocketAddress("127.0.0.1", SERVER_PORT)) socket = Socket("127.0.0.1", 17860)
} }
println("connect time $t") println("connect done! $t")
out = ObjectOutputStream(socket!!.getOutputStream())
`in` = ObjectInputStream(socket!!.getInputStream())
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.writeObject(encoder.encode(bufferOut)) // out!!.write(bufferOut, 0, bufferOut.size)
out.flush() // println(Arrays.toString(bufferOut))
// 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)
@ -84,7 +93,7 @@ fun mainClient() = runBlocking {
// println("丢弃") // println("丢弃")
// } // }
// `in`!!.read(bufferIn, 0, bufferIn.size) // `in`!!.read(bufferIn, 0, bufferIn.size)
val dataPack = inp.readObject() as DataPack val dataPack = `in`!!.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) {

View File

@ -10,7 +10,7 @@ import java.net.Socket
import java.util.* import java.util.*
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
val clientAudios = CopyOnWriteArrayList<ClientAudio>() var clientAudios: MutableList<ClientAudio> = CopyOnWriteArrayList()
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 -= client clientAudios.remove(client)
continue continue
} }
client.read() client.read()
@ -34,9 +34,8 @@ 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 || !ECHO_CANCELLATION) { // if (audio != client)
client.mix(audio.sample) client.mix(audio.sample)
}
} }
client.send() client.send()
} }
@ -44,43 +43,40 @@ fun mainServer() = runBlocking {
} }
} }
val sever = ServerSocket(SERVER_PORT) val sever = ServerSocket(17860)
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 += ClientAudio(socket) clientAudios.add(ClientAudio(socket))
} }
} }
class ClientAudio(val socket: Socket) { class ClientAudio(var 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(BUFFER_SIZE * 2) val buffer: ByteArray = ByteArray(BUFFER_SIZE * 2)
val sample = FloatArray(BUFFER_SIZE) val sample: FloatArray = FloatArray(BUFFER_SIZE)
val mixSample = FloatArray(BUFFER_SIZE) val mixSample: FloatArray = FloatArray(BUFFER_SIZE)
val mixBuffer = ByteArray(BUFFER_SIZE * 2) var mixBuffer: ByteArray = 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) {
@ -89,7 +85,10 @@ class ClientAudio(val 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)