配置分离
This commit is contained in:
parent
285fb3108c
commit
ebb362edc1
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -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
2
.idea/kotlinc.xml
generated
@ -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>
|
@ -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 {
|
||||||
|
@ -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) }
|
@ -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,
|
||||||
|
)
|
@ -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) }
|
|
Loading…
x
Reference in New Issue
Block a user