代码格式整理
This commit is contained in:
parent
25805cd556
commit
33d1fb0006
@ -56,4 +56,20 @@ object AudioConvert {
|
||||
output[i] = shortSample / 32768.0f
|
||||
}
|
||||
}
|
||||
|
||||
fun bytes2shorts(input: ByteArray, output: ShortArray) {
|
||||
for (c in output.indices) {
|
||||
val low = input[(c * 2)].toInt() and 0xFF
|
||||
val high = input[(c * 2) + 1].toInt() shl 8
|
||||
output[c] = (low or high).toShort()
|
||||
}
|
||||
}
|
||||
|
||||
fun shorts2bytes(input: ShortArray, output: ByteArray) {
|
||||
for (c in input.indices) {
|
||||
output[c * 2] = (input[c].toInt() and 0xFF).toByte()
|
||||
output[c * 2 + 1] = ((input[c].toInt() shr 8) and 0xFF).toByte()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import io.github.jaredmdobson.concentus.OpusEncoder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.IOException
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
@ -41,10 +42,9 @@ class Client {
|
||||
it.complexity = OPUS_COMPLEXITY
|
||||
}
|
||||
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
fun mainClient() {
|
||||
val socket = Socket()
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
val t = measureTimeMillis {
|
||||
socket.connect(InetSocketAddress(SERVER_HOST, SERVER_PORT))
|
||||
@ -54,7 +54,7 @@ class Client {
|
||||
val out = ObjectOutputStream(socket.getOutputStream())
|
||||
val inp = ObjectInputStream(socket.getInputStream())
|
||||
|
||||
scope.launch {
|
||||
val recordJob = scope.launch {
|
||||
while (true) {
|
||||
targetDataLine.read(bufferOut, 0, bufferOut.size)
|
||||
try {
|
||||
@ -67,7 +67,7 @@ class Client {
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val playJob = scope.launch {
|
||||
while (true) {
|
||||
try {
|
||||
// if (`in`!!.available() > bufferIn.size * 2) {
|
||||
@ -84,5 +84,10 @@ class Client {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
recordJob.join()
|
||||
playJob.join()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
src/Main.kt
48
src/Main.kt
@ -1,5 +1,8 @@
|
||||
import io.github.jaredmdobson.concentus.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.print.Doc
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
/**
|
||||
* Created by LoliBall on 2024/8/31 5:26.
|
||||
@ -9,7 +12,8 @@ import kotlinx.coroutines.*
|
||||
//val SERVER_HOST = "zedo.top"
|
||||
val SERVER_HOST = "127.0.0.1"
|
||||
val SERVER_PORT = 7860
|
||||
val ECHO_CANCELLATION = true // 回声消除
|
||||
val ECHO_CANCELLATION = false // 回声消除
|
||||
val RAW_PCM_PASS = true // 不进行opus压缩pcm直传
|
||||
|
||||
// 2.5, 5, 10, 20, 40, 60 ms
|
||||
// 120, 240, 480, 960, 1920, 2880
|
||||
@ -24,27 +28,53 @@ val OPUS_COMPLEXITY = 10 // 0: 快,质量差 10: 慢,质量好
|
||||
val OPUS_SIGNAL_TYPE = OpusSignal.OPUS_SIGNAL_VOICE
|
||||
val OPUS_MODE = OpusMode.MODE_HYBRID
|
||||
|
||||
fun main() = runBlocking {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
||||
// 下面是统计用的
|
||||
val compressRateOpus = AtomicInteger()
|
||||
val compressRatePcm = AtomicInteger()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
scope.launch {
|
||||
Server.main(emptyArray())
|
||||
}
|
||||
delay(1000)
|
||||
Client.main(emptyArray())
|
||||
delay(Long.MAX_VALUE)
|
||||
scope.launch {
|
||||
delay(1000) // 等服务器起来
|
||||
Client.main(emptyArray())
|
||||
}
|
||||
fixedRateTimer(period = 1000) {
|
||||
"compress rate: %.2f%%".format(compressRateOpus.get() * 100f / compressRatePcm.get()).loge()
|
||||
compressRateOpus.set(0)
|
||||
compressRatePcm.set(0)
|
||||
}
|
||||
}
|
||||
|
||||
val encodeOpusBuffer = mutableMapOf<OpusEncoder, ByteArray>()
|
||||
val encodePcmShortBuffer = mutableMapOf<OpusEncoder, ShortArray>()
|
||||
|
||||
// 1275是opus单帧包最大值
|
||||
fun OpusEncoder.encode(pcm: ByteArray): DataPack {
|
||||
if (RAW_PCM_PASS) {
|
||||
return DataPack(System.currentTimeMillis(), pcm.copyOf())
|
||||
}
|
||||
val opusBuffer = encodeOpusBuffer[this] ?: ByteArray(1275).also { encodeOpusBuffer[this] = it }
|
||||
val bytesEncoded = encode(pcm, 0, PACKET_SAMPLES, opusBuffer, 0, opusBuffer.size)
|
||||
"compress rate: %.2f%%".format(bytesEncoded / pcm.size.toFloat() * 100).loge()
|
||||
val shortBuffer = encodePcmShortBuffer[this] ?: ShortArray(pcm.size / 2).also { encodePcmShortBuffer[this] = it }
|
||||
AudioConvert.bytes2shorts(pcm, shortBuffer)
|
||||
val bytesEncoded = encode(shortBuffer, 0, PACKET_SAMPLES, opusBuffer, 0, opusBuffer.size)
|
||||
compressRatePcm.addAndGet(pcm.size)
|
||||
compressRateOpus.addAndGet(bytesEncoded)
|
||||
return DataPack(System.currentTimeMillis(), opusBuffer.sliceArray(0..<bytesEncoded))
|
||||
}
|
||||
|
||||
val decodePcmShortBuffer = mutableMapOf<OpusDecoder, ShortArray>()
|
||||
fun OpusDecoder.decode(pack: DataPack, pcm: ByteArray) {
|
||||
decode(pack.opus, 0, pack.opus.size, pcm, 0, PACKET_SAMPLES, false)
|
||||
if (RAW_PCM_PASS) {
|
||||
pack.opus.copyInto(pcm)
|
||||
return
|
||||
}
|
||||
val shortBuffer = decodePcmShortBuffer[this] ?: ShortArray(pcm.size / 2).also { decodePcmShortBuffer[this] = it }
|
||||
decode(pack.opus, 0, pack.opus.size, shortBuffer, 0, PACKET_SAMPLES, false)
|
||||
AudioConvert.shorts2bytes(shortBuffer, pcm)
|
||||
}
|
||||
|
||||
fun <T> T.loge() = also { println(this) }
|
@ -23,7 +23,8 @@ object Server {
|
||||
|
||||
fun mainServer() {
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
scope.launch {
|
||||
while (true) {
|
||||
for (client in clientAudios) {
|
||||
if (!client.isConnected) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user