配置分离

This commit is contained in:
loliball 2024-09-07 23:50:23 +08:00
parent 285fb3108c
commit ebb362edc1
7 changed files with 95 additions and 56 deletions

1
.idea/gradle.xml generated
View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

2
.idea/kotlinc.xml generated
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="KotlinJpsPluginSettings"> <component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.23" /> <option name="version" value="2.0.20" />
</component> </component>
</project> </project>

View File

@ -1,6 +1,7 @@
plugins { plugins {
kotlin("jvm") version "1.9.23" kotlin("jvm") version "2.0.20"
id("com.github.johnrengelman.shadow") version "8.1.1" id("com.github.johnrengelman.shadow") version "8.1.1"
id("org.jetbrains.kotlin.plugin.serialization") version "2.0.20"
} }
group = "loli.ball" group = "loli.ball"
@ -11,9 +12,9 @@ repositories {
} }
dependencies { dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0-RC.2")
implementation("io.github.jaredmdobson:concentus:1.0.2") implementation("io.github.jaredmdobson:concentus:1.0.2")
testImplementation(kotlin("test")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0-RC.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2")
} }
tasks.jar { tasks.jar {

View File

@ -1,3 +1,6 @@
import io.github.jaredmdobson.concentus.OpusDecoder
import io.github.jaredmdobson.concentus.OpusEncoder
import java.util.concurrent.atomic.AtomicInteger
import javax.sound.sampled.AudioFormat import javax.sound.sampled.AudioFormat
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -73,3 +76,39 @@ object AudioConvert {
} }
} }
// 下面是统计用的
val compressRateOpus = AtomicInteger()
val compressRatePcm = AtomicInteger()
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 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) {
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) }

View File

@ -1,4 +1,3 @@
import java.io.Serializable
/** /**
* Created by LoliBall on 2024/8/31 23:02. * Created by LoliBall on 2024/8/31 23:02.
@ -7,4 +6,14 @@ import java.io.Serializable
data class DataPack( data class DataPack(
val timestamp: Long, val timestamp: Long,
val opus: ByteArray, val opus: ByteArray,
) : Serializable ) : java.io.Serializable
@kotlinx.serialization.Serializable
data class Config(
val SERVER: Boolean = false,
val CLIENT: Boolean = true,
val SERVER_HOST: String = "127.0.0.1",
val SERVER_PORT: Int = 7860,
val ECHO_CANCELLATION: Boolean = true,
val STATISTICS: Boolean = false,
)

View File

@ -1,7 +1,8 @@
import io.github.jaredmdobson.concentus.* import io.github.jaredmdobson.concentus.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicInteger import kotlinx.serialization.json.Json
import javax.print.Doc import kotlinx.serialization.json.encodeToJsonElement
import java.io.File
import kotlin.concurrent.fixedRateTimer import kotlin.concurrent.fixedRateTimer
/** /**
@ -9,10 +10,10 @@ import kotlin.concurrent.fixedRateTimer
* https://github.com/WhichWho * https://github.com/WhichWho
*/ */
//val SERVER_HOST = "zedo.top" var SERVER_HOST = "127.0.0.1"
val SERVER_HOST = "127.0.0.1" var SERVER_PORT = 7860
val SERVER_PORT = 7860 var ECHO_CANCELLATION = false // 回声消除
val ECHO_CANCELLATION = false // 回声消除
val RAW_PCM_PASS = false // 不进行opus压缩pcm直传 val RAW_PCM_PASS = false // 不进行opus压缩pcm直传
// 2.5, 5, 10, 20, 40, 60 ms // 2.5, 5, 10, 20, 40, 60 ms
@ -28,53 +29,33 @@ val OPUS_COMPLEXITY = 10 // 0: 快,质量差 10: 慢,质量好
val OPUS_SIGNAL_TYPE = OpusSignal.OPUS_SIGNAL_VOICE val OPUS_SIGNAL_TYPE = OpusSignal.OPUS_SIGNAL_VOICE
val OPUS_MODE = OpusMode.MODE_HYBRID val OPUS_MODE = OpusMode.MODE_HYBRID
// 下面是统计用的
val compressRateOpus = AtomicInteger()
val compressRatePcm = AtomicInteger()
fun main(args: Array<String>) { fun main(args: Array<String>) {
val scope = CoroutineScope(Dispatchers.IO) val scope = CoroutineScope(Dispatchers.IO)
val conf = Json.decodeFromString<Config>(File("vc.conf").readText()).also {
SERVER_HOST = it.SERVER_HOST
SERVER_PORT = it.SERVER_PORT
ECHO_CANCELLATION = it.ECHO_CANCELLATION
}
val jobServer = if (conf.SERVER) {
scope.launch { scope.launch {
Server.main(emptyArray()) Server.main(emptyArray())
} }
} else null
val jobClient = if (conf.CLIENT) {
scope.launch { scope.launch {
delay(1000) // 等服务器起来 if (conf.SERVER) delay(1000) // 等服务器起来
Client.main(emptyArray()) Client.main(emptyArray())
} }
} else null
if (conf.STATISTICS) {
fixedRateTimer(period = 1000) { fixedRateTimer(period = 1000) {
"compress rate: %.2f%%".format(compressRateOpus.get() * 100f / compressRatePcm.get()).loge() "compress rate: %.2f%%".format(compressRateOpus.get() * 100f / compressRatePcm.get()).loge()
compressRateOpus.set(0) compressRateOpus.set(0)
compressRatePcm.set(0) compressRatePcm.set(0)
} }
} }
runBlocking {
val encodeOpusBuffer = mutableMapOf<OpusEncoder, ByteArray>() jobServer?.join()
val encodePcmShortBuffer = mutableMapOf<OpusEncoder, ShortArray>() jobClient?.join()
// 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 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) {
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) }

8
vc.conf Normal file
View File

@ -0,0 +1,8 @@
{
"SERVER": true,
"CLIENT": true,
"SERVER_HOST": "127.0.0.1",
"SERVER_PORT": 7860,
"ECHO_CANCELLATION": false,
"STATISTICS": true
}