首次推送

This commit is contained in:
sansen
2026-07-20 19:01:03 +08:00
parent ea01b9cf99
commit ef1bf61f9f
4484 changed files with 937163 additions and 1 deletions
@@ -0,0 +1,109 @@
//go:build android
package teamspeak
/*
#cgo CFLAGS: -I${SRCDIR}/../../android/app/src/main/cpp/third_party/opus/include
#cgo android,arm64 LDFLAGS: -L${SRCDIR}/.opus/lib/arm64-v8a -l:libopus.a -lm
#cgo android,arm LDFLAGS: -L${SRCDIR}/.opus/lib/armeabi-v7a -l:libopus.a -lm
#cgo android,386 LDFLAGS: -L${SRCDIR}/.opus/lib/x86 -l:libopus.a -lm
#cgo android,amd64 LDFLAGS: -L${SRCDIR}/.opus/lib/x86_64 -l:libopus.a -lm
#include "opus.h"
#include <stdlib.h>
*/
import "C"
import (
"errors"
"fmt"
"runtime"
"sync"
"unsafe"
)
var errOpusDecoderReleased = errors.New("opus decoder has been released")
type opusVoiceDecoderFactory struct{}
type opusVoiceDecoder struct {
mu sync.Mutex
decoder *C.OpusDecoder
channels int
}
func newPlatformVoiceDecoderFactory() voiceDecoderFactory { return opusVoiceDecoderFactory{} }
func (opusVoiceDecoderFactory) NewvoiceDecoder(_ int, codec int) (voiceDecoder, error) {
if codec != 4 && codec != 5 {
return nil, fmt.Errorf("unsupported TeamSpeak voice codec %d", codec)
}
channels := voiceCodecChannels(codec)
var opusErr C.int
decoder := C.opus_decoder_create(C.opus_int32(receiveSampleRate), C.int(channels), &opusErr)
if decoder == nil || opusErr != C.OPUS_OK {
return nil, fmt.Errorf("opus_decoder_create: %d", int(opusErr))
}
return &opusVoiceDecoder{decoder: decoder, channels: channels}, nil
}
func (d *opusVoiceDecoder) Decode(packet []byte) ([]int16, error) {
if len(packet) == 0 {
return nil, errors.New("empty Opus packet")
}
d.mu.Lock()
defer d.mu.Unlock()
if d.decoder == nil {
return nil, errOpusDecoderReleased
}
pcm := make([]int16, receiveMaxDecodeSamplesPerChannel*d.channels)
decoded := C.opus_decode(
d.decoder,
(*C.uchar)(unsafe.Pointer(&packet[0])),
C.opus_int32(len(packet)),
(*C.opus_int16)(unsafe.Pointer(&pcm[0])),
C.int(receiveMaxDecodeSamplesPerChannel),
0,
)
runtime.KeepAlive(packet)
return decodedPCM(pcm, decoded, d.channels)
}
func (d *opusVoiceDecoder) DecodeLost() ([]int16, error) {
d.mu.Lock()
defer d.mu.Unlock()
if d.decoder == nil {
return nil, errOpusDecoderReleased
}
pcm := make([]int16, receiveMaxDecodeSamplesPerChannel*d.channels)
decoded := C.opus_decode(
d.decoder,
nil,
0,
(*C.opus_int16)(unsafe.Pointer(&pcm[0])),
C.int(receiveMaxDecodeSamplesPerChannel),
0,
)
return decodedPCM(pcm, decoded, d.channels)
}
func (d *opusVoiceDecoder) Release() {
d.mu.Lock()
decoder := d.decoder
d.decoder = nil
d.mu.Unlock()
if decoder != nil {
C.opus_decoder_destroy(decoder)
}
}
func decodedPCM(pcm []int16, decoded C.int, channels int) ([]int16, error) {
if decoded < 0 {
return nil, fmt.Errorf("opus_decode: %d", int(decoded))
}
perChannel := int(decoded)
decodedSamples := perChannel * channels
if perChannel > receiveMaxDecodeSamplesPerChannel || decodedSamples > len(pcm) {
return nil, fmt.Errorf("opus_decode returned %d samples/channel, buffer has %d samples for %d channels", perChannel, len(pcm), channels)
}
return normalizeDecodedPCM(pcm[:decodedSamples], channels), nil
}