silk-python 0.2.7__cp313-cp313-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pysilk/__init__.py +22 -0
- pysilk/backends/__init__.py +3 -0
- pysilk/backends/cffi/__init__.py +264 -0
- pysilk/backends/cffi/_silk.pyd +0 -0
- pysilk/backends/cffi/build.py +97 -0
- pysilk/backends/cython/__init__.py +4 -0
- pysilk/backends/cython/_silk.c +13503 -0
- pysilk/backends/cython/_silk.pyd +0 -0
- pysilk/backends/cython/_silk.pyi +27 -0
- pysilk/backends/cython/_silk.pyx +275 -0
- pysilk/backends/cython/silk.pxd +72 -0
- silk_python-0.2.7.dist-info/METADATA +108 -0
- silk_python-0.2.7.dist-info/RECORD +15 -0
- silk_python-0.2.7.dist-info/WHEEL +5 -0
- silk_python-0.2.7.dist-info/top_level.txt +1 -0
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import Any, BinaryIO
|
|
2
|
+
|
|
3
|
+
class SilkError(Exception):
|
|
4
|
+
def __init__(self, code) -> Any: ...
|
|
5
|
+
|
|
6
|
+
def encode(
|
|
7
|
+
input: BinaryIO,
|
|
8
|
+
output: BinaryIO,
|
|
9
|
+
sample_rate: int,
|
|
10
|
+
bit_rate: int,
|
|
11
|
+
max_internal_sample_rate: int = 24000,
|
|
12
|
+
packet_loss_percentage: int = 0,
|
|
13
|
+
complexity: int = 2,
|
|
14
|
+
use_inband_fec: bool = False,
|
|
15
|
+
use_dtx: bool = False,
|
|
16
|
+
tencent: bool = True,
|
|
17
|
+
) -> bytes: ...
|
|
18
|
+
def decode(
|
|
19
|
+
input: BinaryIO,
|
|
20
|
+
output: BinaryIO,
|
|
21
|
+
sample_rate: int,
|
|
22
|
+
frame_size: int = 0,
|
|
23
|
+
frames_per_packet: int = 1,
|
|
24
|
+
more_internal_decoder_frames: bool = False,
|
|
25
|
+
in_band_fec_offset: int = 0,
|
|
26
|
+
loss: bool = False,
|
|
27
|
+
) -> bytes: ...
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# cython: language_level=3
|
|
2
|
+
# cython: cdivision=True
|
|
3
|
+
from cpython.bytes cimport (PyBytes_AS_STRING, PyBytes_Check,
|
|
4
|
+
PyBytes_FromStringAndSize, PyBytes_Size)
|
|
5
|
+
from cpython.mem cimport PyMem_Free, PyMem_Malloc
|
|
6
|
+
from cpython.object cimport PyObject, PyObject_HasAttrString
|
|
7
|
+
from libc.stdint cimport int16_t, int32_t, uint8_t
|
|
8
|
+
|
|
9
|
+
from pysilk.backends.cython.silk cimport (SHOULD_SWAP,
|
|
10
|
+
SKP_SILK_SDK_DecControlStruct,
|
|
11
|
+
SKP_Silk_SDK_Decode,
|
|
12
|
+
SKP_SILK_SDK_EncControlStruct,
|
|
13
|
+
SKP_Silk_SDK_Encode,
|
|
14
|
+
SKP_Silk_SDK_Get_Decoder_Size,
|
|
15
|
+
SKP_Silk_SDK_Get_Encoder_Size,
|
|
16
|
+
SKP_Silk_SDK_InitDecoder,
|
|
17
|
+
SKP_Silk_SDK_InitEncoder, swap_i16)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SilkError(Exception):
|
|
21
|
+
def __init__(self, code):
|
|
22
|
+
self.code = code
|
|
23
|
+
|
|
24
|
+
def __str__(self):
|
|
25
|
+
if isinstance(self.code, int):
|
|
26
|
+
if self.code == -1:
|
|
27
|
+
return "ENC_INPUT_INVALID_NO_OF_SAMPLES"
|
|
28
|
+
elif self.code == -2:
|
|
29
|
+
return "ENC_FS_NOT_SUPPORTED"
|
|
30
|
+
elif self.code == -3:
|
|
31
|
+
return "ENC_PACKET_SIZE_NOT_SUPPORTED"
|
|
32
|
+
elif self.code == -4:
|
|
33
|
+
return "ENC_PAYLOAD_BUF_TOO_SHORT"
|
|
34
|
+
elif self.code == -5:
|
|
35
|
+
return "ENC_INVALID_LOSS_RATE"
|
|
36
|
+
elif self.code == -6:
|
|
37
|
+
return "ENC_INVALID_COMPLEXITY_SETTING"
|
|
38
|
+
elif self.code == -7:
|
|
39
|
+
return "ENC_INVALID_INBAND_FEC_SETTING"
|
|
40
|
+
elif self.code == -8:
|
|
41
|
+
return "ENC_INVALID_DTX_SETTING"
|
|
42
|
+
elif self.code == -9:
|
|
43
|
+
return "ENC_INTERNAL_ERROR"
|
|
44
|
+
elif self.code == -10:
|
|
45
|
+
return "DEC_INVALID_SAMPLING_FREQUENCY"
|
|
46
|
+
elif self.code == -11:
|
|
47
|
+
return "DEC_PAYLOAD_TOO_LARGE"
|
|
48
|
+
elif self.code == -12:
|
|
49
|
+
return "DEC_PAYLOAD_ERROR"
|
|
50
|
+
else:
|
|
51
|
+
return "Other error"
|
|
52
|
+
else:
|
|
53
|
+
return str(self.code)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
cdef inline bytes i16_to_bytes(int16_t data):
|
|
57
|
+
cdef:
|
|
58
|
+
uint8_t * p = <uint8_t *> &data
|
|
59
|
+
bytes bt = PyBytes_FromStringAndSize(NULL, 2)
|
|
60
|
+
if <PyObject*>bt == NULL:
|
|
61
|
+
raise MemoryError
|
|
62
|
+
cdef uint8_t* buf = <uint8_t*>PyBytes_AS_STRING(bt)
|
|
63
|
+
buf[0] = p[0]
|
|
64
|
+
buf[1] = p[1]
|
|
65
|
+
return bt
|
|
66
|
+
|
|
67
|
+
cdef inline int16_t bytes_to_i16(bytes data):
|
|
68
|
+
cdef int16_t buf = 0
|
|
69
|
+
cdef uint8_t *p = <uint8_t *> &buf
|
|
70
|
+
p[0] = <uint8_t> data[0]
|
|
71
|
+
p[1] = <uint8_t> data[1]
|
|
72
|
+
return buf
|
|
73
|
+
|
|
74
|
+
cdef inline void write_i16_le(object output, int16_t data):
|
|
75
|
+
if SHOULD_SWAP:
|
|
76
|
+
data = swap_i16(data)
|
|
77
|
+
output.write(i16_to_bytes(data))
|
|
78
|
+
|
|
79
|
+
cdef inline int16_t read_i16_le(object input):
|
|
80
|
+
chunk = input.read(2) # type: bytes
|
|
81
|
+
cdef int16_t data = bytes_to_i16(chunk)
|
|
82
|
+
if SHOULD_SWAP:
|
|
83
|
+
data = swap_i16(data)
|
|
84
|
+
return data
|
|
85
|
+
|
|
86
|
+
cdef inline uint8_t PyFile_Check(object file):
|
|
87
|
+
if PyObject_HasAttrString(file, "read") and PyObject_HasAttrString(file, "write"): # should we check seek method?
|
|
88
|
+
return 1
|
|
89
|
+
return 0
|
|
90
|
+
|
|
91
|
+
def encode(object input,
|
|
92
|
+
object output,
|
|
93
|
+
int32_t sample_rate,
|
|
94
|
+
int32_t bit_rate,
|
|
95
|
+
int32_t max_internal_sample_rate = 24000,
|
|
96
|
+
int32_t packet_loss_percentage = 0,
|
|
97
|
+
int32_t complexity = 2,
|
|
98
|
+
bint use_inband_fec = False,
|
|
99
|
+
bint use_dtx = False,
|
|
100
|
+
bint tencent = True):
|
|
101
|
+
"""encode(input: BinaryIO, output: BinaryIO, sample_rate: int, bit_rate: int, max_internal_sample_rate: int = 24000, packet_loss_percentage: int = 0, complexity: int = 2, use_inband_fec: bool = False, use_dtx: bool = False, tencent: bool = True) -> bytes
|
|
102
|
+
|
|
103
|
+
encode pcm to silk
|
|
104
|
+
:param input: BytesIO or an openfile with "rb" mode
|
|
105
|
+
:param output: BytesIO or an openfile with "wb" mode
|
|
106
|
+
:param sample_rate:
|
|
107
|
+
:param bit_rate:
|
|
108
|
+
:param max_internal_sample_rate:
|
|
109
|
+
:param packet_loss_percentage:
|
|
110
|
+
:param complexity:
|
|
111
|
+
:param use_inband_fec:
|
|
112
|
+
:param use_dtx:
|
|
113
|
+
:param tencent: Tencent's special tag
|
|
114
|
+
:return: None
|
|
115
|
+
"""
|
|
116
|
+
if not PyFile_Check(input):
|
|
117
|
+
raise TypeError("input except a file-like object, got %s" % type(input).__name__)
|
|
118
|
+
if not PyFile_Check(output):
|
|
119
|
+
raise TypeError("output except a file-like object, got %s" % type(output).__name__)
|
|
120
|
+
|
|
121
|
+
cdef SKP_SILK_SDK_EncControlStruct enc_control
|
|
122
|
+
enc_control.API_sampleRate = sample_rate
|
|
123
|
+
enc_control.maxInternalSampleRate = max_internal_sample_rate
|
|
124
|
+
enc_control.packetSize = (20 * sample_rate) / 1000
|
|
125
|
+
enc_control.bitRate = bit_rate
|
|
126
|
+
enc_control.packetLossPercentage = packet_loss_percentage
|
|
127
|
+
enc_control.complexity = complexity
|
|
128
|
+
enc_control.useInBandFEC = use_inband_fec
|
|
129
|
+
enc_control.useDTX = use_dtx
|
|
130
|
+
|
|
131
|
+
cdef SKP_SILK_SDK_EncControlStruct enc_status
|
|
132
|
+
enc_status.API_sampleRate = 0
|
|
133
|
+
enc_status.maxInternalSampleRate = 0
|
|
134
|
+
enc_status.packetSize = 0
|
|
135
|
+
enc_status.bitRate = 0
|
|
136
|
+
enc_status.packetLossPercentage = 0
|
|
137
|
+
enc_status.complexity = 0
|
|
138
|
+
enc_status.useInBandFEC = 0
|
|
139
|
+
enc_status.useDTX = 0
|
|
140
|
+
|
|
141
|
+
cdef int32_t enc_size_bytes = 0
|
|
142
|
+
cdef int32_t code = SKP_Silk_SDK_Get_Encoder_Size(&enc_size_bytes)
|
|
143
|
+
if code != 0:
|
|
144
|
+
raise SilkError(code)
|
|
145
|
+
cdef void * enc = PyMem_Malloc(<size_t> enc_size_bytes)
|
|
146
|
+
if enc == NULL:
|
|
147
|
+
raise MemoryError
|
|
148
|
+
code = SKP_Silk_SDK_InitEncoder(enc, &enc_status)
|
|
149
|
+
if code != 0:
|
|
150
|
+
PyMem_Free(enc)
|
|
151
|
+
raise SilkError(code)
|
|
152
|
+
cdef int32_t frame_size = sample_rate / 1000 * 40
|
|
153
|
+
if tencent:
|
|
154
|
+
output.write(b"\x02#!SILK_V3")
|
|
155
|
+
else:
|
|
156
|
+
output.write(b"#!SILK_V3")
|
|
157
|
+
cdef int16_t n_bytes = 1250
|
|
158
|
+
cdef uint8_t payload[1250]
|
|
159
|
+
cdef int16_t* chunk_ptr
|
|
160
|
+
cdef int32_t chunk_size
|
|
161
|
+
try:
|
|
162
|
+
while True:
|
|
163
|
+
chunk = input.read(frame_size) # type: bytes
|
|
164
|
+
if not PyBytes_Check(chunk):
|
|
165
|
+
raise TypeError(f"input must be a file-like rb object, got {type(input).__name__}")
|
|
166
|
+
|
|
167
|
+
n_bytes = 1250
|
|
168
|
+
if <int32_t> PyBytes_Size(chunk) < frame_size:
|
|
169
|
+
break
|
|
170
|
+
chunk_ptr = <int16_t *> PyBytes_AS_STRING(chunk)
|
|
171
|
+
chunk_size = <int32_t> (PyBytes_Size(chunk) / 2)
|
|
172
|
+
with nogil:
|
|
173
|
+
code = SKP_Silk_SDK_Encode(enc,
|
|
174
|
+
&enc_control,
|
|
175
|
+
chunk_ptr,
|
|
176
|
+
chunk_size,
|
|
177
|
+
payload,
|
|
178
|
+
&n_bytes)
|
|
179
|
+
if code != 0:
|
|
180
|
+
raise SilkError(code)
|
|
181
|
+
|
|
182
|
+
write_i16_le(output, n_bytes)
|
|
183
|
+
output.write(<bytes> payload[0:n_bytes])
|
|
184
|
+
finally:
|
|
185
|
+
PyMem_Free(enc)
|
|
186
|
+
|
|
187
|
+
def decode(object input,
|
|
188
|
+
object output,
|
|
189
|
+
int32_t sample_rate,
|
|
190
|
+
int32_t frame_size=0,
|
|
191
|
+
int32_t frames_per_packet=1,
|
|
192
|
+
bint more_internal_decoder_frames=False,
|
|
193
|
+
int32_t in_band_fec_offset=0,
|
|
194
|
+
bint loss=False):
|
|
195
|
+
"""decode(input: BinaryIO, output: BinaryIO, sample_rate: int, frame_size: int = 0, frames_per_packet: int = 1, more_internal_decoder_frames: bool = False, in_band_fec_offset: int = 0, loss: bool = False) -> bytes
|
|
196
|
+
|
|
197
|
+
decode silk to pcm
|
|
198
|
+
:param input:
|
|
199
|
+
:param output:
|
|
200
|
+
:param sample_rate:
|
|
201
|
+
:param frame_size:
|
|
202
|
+
:param frames_per_packet:
|
|
203
|
+
:param more_internal_decoder_frames:
|
|
204
|
+
:param in_band_fec_offset:
|
|
205
|
+
:param loss:
|
|
206
|
+
:return:
|
|
207
|
+
"""
|
|
208
|
+
if not PyFile_Check(input):
|
|
209
|
+
raise TypeError("input except a file-like object, got %s" % type(input).__name__)
|
|
210
|
+
if not PyFile_Check(output):
|
|
211
|
+
raise TypeError("output except a file-like object, got %s" % type(output).__name__)
|
|
212
|
+
|
|
213
|
+
chunk = input.read(9) # type: bytes
|
|
214
|
+
if not PyBytes_Check(chunk):
|
|
215
|
+
raise TypeError(f"input must be a file-like rb object, got {type(input).__name__}")
|
|
216
|
+
if chunk != b"#!SILK_V3" and chunk != b"\x02#!SILK_V":
|
|
217
|
+
raise SilkError("INVALID")
|
|
218
|
+
elif chunk == b"\x02#!SILK_V":
|
|
219
|
+
chunk = input.read(1)
|
|
220
|
+
if chunk != b"3":
|
|
221
|
+
raise SilkError("INVALID")
|
|
222
|
+
|
|
223
|
+
cdef SKP_SILK_SDK_DecControlStruct dec_control
|
|
224
|
+
dec_control.API_sampleRate = sample_rate
|
|
225
|
+
dec_control.frameSize = frame_size
|
|
226
|
+
dec_control.framesPerPacket = frames_per_packet
|
|
227
|
+
dec_control.moreInternalDecoderFrames = more_internal_decoder_frames
|
|
228
|
+
dec_control.inBandFECOffset = in_band_fec_offset
|
|
229
|
+
cdef int32_t dec_size = 0
|
|
230
|
+
cdef int32_t code = SKP_Silk_SDK_Get_Decoder_Size(&dec_size)
|
|
231
|
+
if code != 0:
|
|
232
|
+
raise SilkError(code)
|
|
233
|
+
cdef void *dec = PyMem_Malloc(dec_size)
|
|
234
|
+
if dec == NULL:
|
|
235
|
+
raise MemoryError
|
|
236
|
+
code = SKP_Silk_SDK_InitDecoder(dec)
|
|
237
|
+
if code != 0:
|
|
238
|
+
PyMem_Free(dec)
|
|
239
|
+
raise SilkError(code)
|
|
240
|
+
frame_size = sample_rate / 1000 * 40
|
|
241
|
+
# cdef uint8_t buf[frame_size] # otherwise need malloc
|
|
242
|
+
cdef uint8_t *buf = <uint8_t *> PyMem_Malloc(frame_size)
|
|
243
|
+
if buf == NULL:
|
|
244
|
+
PyMem_Free(dec)
|
|
245
|
+
raise MemoryError
|
|
246
|
+
cdef int16_t n_bytes
|
|
247
|
+
cdef const uint8_t *chunk_ptr
|
|
248
|
+
try:
|
|
249
|
+
while True:
|
|
250
|
+
chunk = input.read(2)
|
|
251
|
+
if PyBytes_Size(chunk) < 2:
|
|
252
|
+
break
|
|
253
|
+
n_bytes = bytes_to_i16(chunk)
|
|
254
|
+
if SHOULD_SWAP:
|
|
255
|
+
n_bytes = swap_i16(n_bytes)
|
|
256
|
+
if n_bytes > <int16_t> frame_size:
|
|
257
|
+
raise SilkError("INVALID")
|
|
258
|
+
chunk = input.read(n_bytes) # type: bytes
|
|
259
|
+
if <int16_t> PyBytes_Size(chunk) < n_bytes: # not enough data
|
|
260
|
+
raise SilkError("INVALID")
|
|
261
|
+
chunk_ptr = <const uint8_t *> PyBytes_AS_STRING(chunk)
|
|
262
|
+
with nogil:
|
|
263
|
+
code = SKP_Silk_SDK_Decode(dec,
|
|
264
|
+
&dec_control,
|
|
265
|
+
loss,
|
|
266
|
+
chunk_ptr,
|
|
267
|
+
<const int32_t> n_bytes,
|
|
268
|
+
<int16_t *> buf,
|
|
269
|
+
&n_bytes)
|
|
270
|
+
if code != 0:
|
|
271
|
+
raise SilkError(code)
|
|
272
|
+
output.write(<bytes> buf[:n_bytes * 2])
|
|
273
|
+
finally:
|
|
274
|
+
PyMem_Free(buf)
|
|
275
|
+
PyMem_Free(dec)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# cython: language_level=3
|
|
2
|
+
# cython: cdivision=True
|
|
3
|
+
from libc.stdint cimport int16_t, int32_t, uint8_t
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
cdef extern from "SKP_Silk_control.h" nogil:
|
|
7
|
+
ctypedef struct SKP_SILK_SDK_EncControlStruct:
|
|
8
|
+
int32_t API_sampleRate
|
|
9
|
+
int32_t maxInternalSampleRate
|
|
10
|
+
int32_t packetSize
|
|
11
|
+
int32_t bitRate
|
|
12
|
+
int32_t packetLossPercentage
|
|
13
|
+
int32_t complexity
|
|
14
|
+
int32_t useInBandFEC
|
|
15
|
+
int32_t useDTX
|
|
16
|
+
ctypedef struct SKP_SILK_SDK_DecControlStruct:
|
|
17
|
+
int32_t API_sampleRate
|
|
18
|
+
int32_t frameSize
|
|
19
|
+
int32_t framesPerPacket
|
|
20
|
+
int32_t moreInternalDecoderFrames
|
|
21
|
+
int32_t inBandFECOffset
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
cdef extern from "SKP_Silk_SDK_API.h" nogil:
|
|
25
|
+
int32_t SKP_Silk_SDK_Get_Encoder_Size(int32_t *encSizeBytes)
|
|
26
|
+
int32_t SKP_Silk_SDK_InitEncoder(void *encState, SKP_SILK_SDK_EncControlStruct *encStatus)
|
|
27
|
+
int32_t SKP_Silk_SDK_Encode(void *encState,
|
|
28
|
+
const SKP_SILK_SDK_EncControlStruct *encControl,
|
|
29
|
+
const int16_t *samplesIn,
|
|
30
|
+
int32_t nSamplesIn,
|
|
31
|
+
uint8_t *outData,
|
|
32
|
+
int16_t *nBytesOut)
|
|
33
|
+
int32_t SKP_Silk_SDK_Get_Decoder_Size(int32_t *decSizeBytes)
|
|
34
|
+
int32_t SKP_Silk_SDK_InitDecoder(void *decState)
|
|
35
|
+
int32_t SKP_Silk_SDK_Decode(void * decState,
|
|
36
|
+
SKP_SILK_SDK_DecControlStruct *decControl,
|
|
37
|
+
int32_t lostFlag,
|
|
38
|
+
const uint8_t *inData,
|
|
39
|
+
const int32_t nBytesIn,
|
|
40
|
+
int16_t *samplesOut,
|
|
41
|
+
int16_t *nSamplesOut)
|
|
42
|
+
|
|
43
|
+
cdef extern from * nogil:
|
|
44
|
+
"""
|
|
45
|
+
/*
|
|
46
|
+
void swap_i16(int16_t *data)
|
|
47
|
+
{
|
|
48
|
+
int8_t *p = (int8_t *)data;
|
|
49
|
+
int8_t tmp = p[0];
|
|
50
|
+
p[0] = p[1];
|
|
51
|
+
p[1] = tmp;
|
|
52
|
+
}
|
|
53
|
+
*/
|
|
54
|
+
uint8_t is_le()
|
|
55
|
+
{
|
|
56
|
+
uint16_t data=1;
|
|
57
|
+
return *(uint8_t*)&data;
|
|
58
|
+
}
|
|
59
|
+
#if defined(_WIN64) || defined(_WIN32)
|
|
60
|
+
#define swap_i16 _byteswap_ushort
|
|
61
|
+
#else
|
|
62
|
+
#define swap_i16 __builtin_bswap16
|
|
63
|
+
#endif /* _WIN32 */
|
|
64
|
+
#ifdef WORDS_BIGENDIAN
|
|
65
|
+
#define SHOULD_SWAP 1
|
|
66
|
+
#else
|
|
67
|
+
#define SHOULD_SWAP 0
|
|
68
|
+
#endif
|
|
69
|
+
"""
|
|
70
|
+
int16_t swap_i16(int16_t data)
|
|
71
|
+
uint8_t is_le()
|
|
72
|
+
int SHOULD_SWAP
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: silk-python
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: silk encode and decode
|
|
5
|
+
Home-page: https://github.com/synodriver/pysilk
|
|
6
|
+
Author: synodriver
|
|
7
|
+
Author-email: diguohuangjiajinweijun@gmail.com
|
|
8
|
+
License: BSD
|
|
9
|
+
Keywords: silk,encode,decode,pcm,audio
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
14
|
+
Classifier: Programming Language :: C
|
|
15
|
+
Classifier: Programming Language :: Cython
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
|
+
Requires-Python: >=3.6
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Requires-Dist: cffi>=1.0.0
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
39
|
+
|
|
40
|
+
<h1 align="center"><i>✨ pysilk ✨ </i></h1>
|
|
41
|
+
|
|
42
|
+
<h3 align="center">The python binding for <a href="https://github.com/kn007/silk-v3-decoder">silk-v3-decoder</a> </h3>
|
|
43
|
+
|
|
44
|
+
[](https://pypi.org/project/silk-python/)
|
|
45
|
+

|
|
46
|
+

|
|
47
|
+

|
|
48
|
+

|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
## 安装
|
|
52
|
+
```bash
|
|
53
|
+
pip install silk-python
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
## 使用
|
|
58
|
+
- encode
|
|
59
|
+
```python
|
|
60
|
+
import pysilk
|
|
61
|
+
|
|
62
|
+
with open("verybiginput.pcm", "rb") as pcm, open("output.silk", "wb") as silk:
|
|
63
|
+
pysilk.encode(pcm, silk, 24000, 24000)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- decode
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import pysilk
|
|
70
|
+
|
|
71
|
+
with open("verybiginput.silk", "rb") as silk, open("output.pcm", "wb") as pcm:
|
|
72
|
+
pysilk.decode(silk, pcm, 24000)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 支持功能
|
|
76
|
+
- 接受任何二进制的```file-like object```,比如```BytesIO```,可以流式解码大文件
|
|
77
|
+
- 包装了silk的全部C接口的参数,当然他们都有合理的默认值
|
|
78
|
+
- 基于```Cython```, [关键部位](https://github.com/synodriver/pysilk/blob/stream/pysilk/silk.pxd#L43-L65) 内联C函数,高性能
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## 公开函数
|
|
82
|
+
```python
|
|
83
|
+
from typing import BinaryIO
|
|
84
|
+
|
|
85
|
+
def encode(input: BinaryIO, output: BinaryIO, sample_rate: int, bit_rate: int, max_internal_sample_rate: int = 24000, packet_loss_percentage: int = 0, complexity: int = 2, use_inband_fec: bool = False, use_dtx: bool = False, tencent: bool = True) -> None: ...
|
|
86
|
+
def decode(input: BinaryIO, output: BinaryIO, sample_rate: int, frame_size: int = 0, frames_per_packet: int = 1, more_internal_decoder_frames: bool = False, in_band_fec_offset: int = 0, loss: bool = False) -> None: ...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 公开异常
|
|
90
|
+
```python
|
|
91
|
+
class SilkError(Exception):
|
|
92
|
+
pass
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### ✨v0.2.0✨
|
|
96
|
+
合并了[CFFI](https://github.com/synodriver/pysilk-cffi) 的工作
|
|
97
|
+
|
|
98
|
+
### 本机编译
|
|
99
|
+
```
|
|
100
|
+
python -m pip install setuptools wheel cython cffi
|
|
101
|
+
git clone https://github.com/synodriver/pysilk
|
|
102
|
+
cd pysilk
|
|
103
|
+
git submodule update --init --recursive
|
|
104
|
+
python setup.py bdist_wheel --use-cython --use-cffi
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 后端选择
|
|
108
|
+
默认由py实现决定,在cpython上自动选择cython后端,在pypy上自动选择cffi后端,使用```SILK_USE_CFFI```环境变量可以强制选择cffi
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
pysilk/__init__.py,sha256=51ILaDOKD4UUQk0w6FjBXTjTSF8kqkOyxXNleBoUTqw,417
|
|
2
|
+
pysilk/backends/__init__.py,sha256=XywP1BY8lg5-vwoQw0cKnqhB-lP27C5UiVRg25FP64c,69
|
|
3
|
+
pysilk/backends/cffi/__init__.py,sha256=MDJqE3f01r8ahQFQH_8MFmMtHD89yhDeTmbhUuUx6Lw,8977
|
|
4
|
+
pysilk/backends/cffi/_silk.pyd,sha256=YHwyjEPCxW_TrePYy1Hn0kyRzEVimbLt0spiF3iVu8I,139776
|
|
5
|
+
pysilk/backends/cffi/build.py,sha256=dWh6JFs02S4du75NQyIGdzAmCO4uRCbh-rgKf4FdXjQ,3690
|
|
6
|
+
pysilk/backends/cython/__init__.py,sha256=6TA0vr_27_mdZ22s5_ZEJR0M7HcJUzPVrcMyIPRcFQ0,113
|
|
7
|
+
pysilk/backends/cython/_silk.c,sha256=ixNIgNj2JjwxfB9RvX-IyIiZaKdeN0MJmBzLykyevKk,571618
|
|
8
|
+
pysilk/backends/cython/_silk.pyd,sha256=VSo4QKHBhueuFsF7akuC9Ka63DbG5ARCGZND0utGR8Q,181248
|
|
9
|
+
pysilk/backends/cython/_silk.pyi,sha256=3Y39NJhDIe4ehO0HHzu9P8y0cCVC5aTUbDCgxFKks1k,690
|
|
10
|
+
pysilk/backends/cython/_silk.pyx,sha256=6mJ1MrKjVcKabWg-YDrNiawhKa9hzBVBC76Xt0Hn6AU,10705
|
|
11
|
+
pysilk/backends/cython/silk.pxd,sha256=9SKUDcJeDDIeTsScrerq1rtwSWqZLP_yaWp_N2HEOUE,2328
|
|
12
|
+
silk_python-0.2.7.dist-info/METADATA,sha256=pCACDqPqLMlWUiXGRTFccl8S4gbRUG_ANYmrr8m5vo4,3869
|
|
13
|
+
silk_python-0.2.7.dist-info/WHEEL,sha256=0ABLuJ37exXk5N_efmYNs2NU9NK1K2Qlod_6bYkofEA,97
|
|
14
|
+
silk_python-0.2.7.dist-info/top_level.txt,sha256=tcB-cCbL6OMj8uspHFAz4kJ8ObWLz--nuLQ1wVc0GRY,7
|
|
15
|
+
silk_python-0.2.7.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pysilk
|