Browse code

silk: added support for SILK codec (8-24kHz).

Raphael Coeffic authored on 06/03/2012 10:22:23
Showing 4 changed files
... ...
@@ -19,4 +19,5 @@ sems-logfile-callextract
19 19
 cscope.out
20 20
 cscope.files
21 21
 semantic.cache
22
-apps/rtmp/flash_phone/*.swf
23 22
\ No newline at end of file
23
+apps/rtmp/flash_phone/*.swf
24
+core/plug-in/silk/SILK_SDK_*
24 25
\ No newline at end of file
... ...
@@ -78,4 +78,9 @@
78 78
 
79 79
 #define CODEC_SPEEX_WB 26
80 80
 
81
+#define CODEC_SILK_NB 27
82
+#define CODEC_SILK_MB 28
83
+#define CODEC_SILK_WB 29
84
+#define CODEC_SILK_UB 30
85
+
81 86
 #endif
82 87
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+plug_in_name = silk
2
+COREPATH =../..
3
+
4
+SILK_DIR=SILK_SDK_SRC_v1.0.8/SILK_SDK_SRC_FIX_v1.0.8
5
+SILK_INC=$(SILK_DIR)/interface
6
+SILK_LIB = $(SILK_DIR)/libSKP_SILK_SDK.a
7
+
8
+module_cflags = -I $(SILK_INC)
9
+module_extra_objs = $(SILK_LIB)
10
+extra_clean = clean_silk
11
+
12
+include ../Makefile.audio_module
13
+
14
+$(SILK_LIB):
15
+	$(MAKE) -C $(SILK_DIR) lib
16
+
17
+.PHONY: clean_silk
18
+clean_silk:
19
+	$(MAKE) -C $(SILK_DIR) clean
0 20
new file mode 100644
... ...
@@ -0,0 +1,281 @@
1
+/*
2
+  This is a simple interface to the SILK SDK for SEMS.
3
+  Copyright (C) 2012 Raphael Coeffic
4
+
5
+  This code is free software; you can redistribute it and/or
6
+  modify it under the terms of the GNU Lesser General Public
7
+  License as published by the Free Software Foundation.
8
+  
9
+  This code is distributed in the hope that it will be useful,
10
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+  Lesser General Public License for more details.
13
+  
14
+  You should have received a copy of the GNU Lesser General Public
15
+  License along with this library; if not, write to the Free Software
16
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+*/
18
+
19
+#include "amci.h"
20
+#include "codecs.h"
21
+#include "SKP_Silk_SDK_API.h"
22
+#include "../../log.h"
23
+
24
+#include <string.h>
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+
28
+// TODO:
29
+//  - use integrated PLC (without FEC)
30
+//  - set 'useinbandfec=0' in SDP
31
+
32
+
33
+int Pcm16_2_SILK( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
34
+		  unsigned int channels, unsigned int rate, long h_codec );
35
+int SILK_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
36
+		  unsigned int channels, unsigned int rate, long h_codec );
37
+
38
+long SILK_NB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
39
+long SILK_MB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
40
+long SILK_WB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
41
+long SILK_UB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
42
+void SILK_destroy(long handle);
43
+
44
+static unsigned int SILK_bytes2samples(long, unsigned int);
45
+static unsigned int SILK_samples2bytes(long, unsigned int);
46
+
47
+BEGIN_EXPORTS("silk", AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY)
48
+
49
+BEGIN_CODECS
50
+#if SYSTEM_SAMPLECLOCK_RATE >=24000
51
+CODEC(CODEC_SILK_UB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, 
52
+      SILK_UB_create, SILK_destroy, 
53
+      SILK_bytes2samples, SILK_samples2bytes)
54
+#endif
55
+#if SYSTEM_SAMPLECLOCK_RATE >=16000
56
+CODEC(CODEC_SILK_WB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, 
57
+      SILK_WB_create, SILK_destroy, 
58
+      SILK_bytes2samples, SILK_samples2bytes)
59
+#endif
60
+#if SYSTEM_SAMPLECLOCK_RATE >=12000
61
+CODEC(CODEC_SILK_MB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, 
62
+      SILK_MB_create, SILK_destroy, 
63
+      SILK_bytes2samples, SILK_samples2bytes)
64
+#endif
65
+CODEC(CODEC_SILK_NB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, 
66
+      SILK_NB_create, SILK_destroy, 
67
+      SILK_bytes2samples, SILK_samples2bytes)
68
+END_CODECS
69
+  
70
+BEGIN_PAYLOADS
71
+#if SYSTEM_SAMPLECLOCK_RATE >=24000
72
+PAYLOAD(-1, "SILK", 24000, 24000, 1, CODEC_SILK_UB, AMCI_PT_AUDIO_FRAME)
73
+#endif
74
+#if SYSTEM_SAMPLECLOCK_RATE >=16000
75
+PAYLOAD(-1, "SILK", 16000, 16000, 1, CODEC_SILK_WB, AMCI_PT_AUDIO_FRAME)
76
+#endif
77
+#if SYSTEM_SAMPLECLOCK_RATE >=12000
78
+PAYLOAD(-1, "SILK", 12000, 12000, 1, CODEC_SILK_MB, AMCI_PT_AUDIO_FRAME)
79
+#endif
80
+PAYLOAD(-1, "SILK", 8000, 8000, 1, CODEC_SILK_NB, AMCI_PT_AUDIO_FRAME)
81
+END_PAYLOADS
82
+  
83
+BEGIN_FILE_FORMATS
84
+END_FILE_FORMATS
85
+
86
+END_EXPORTS
87
+
88
+typedef struct
89
+{
90
+  SKP_SILK_SDK_EncControlStruct encControl;
91
+  void* psEnc;
92
+
93
+  SKP_SILK_SDK_DecControlStruct decControl;
94
+  void* psDec;
95
+} SILK_state;
96
+
97
+
98
+static int create_SILK_encoder(SILK_state* st, 
99
+			       unsigned int rtp_Hz,
100
+			       unsigned int avg_bit_rate)
101
+{
102
+  SKP_int32 ret,encSizeBytes;
103
+
104
+  /* Create Encoder */
105
+  ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
106
+  if( ret ) {
107
+    ERROR( "SKP_Silk_create_encoder returned %d", ret );
108
+    return ret;
109
+  }
110
+
111
+  st->psEnc = malloc( encSizeBytes );
112
+  if(st->psEnc == NULL) {
113
+    ERROR( "could not allocate SILK encoder state" );
114
+    return -1;
115
+  }
116
+  
117
+  /* Reset Encoder */
118
+  ret = SKP_Silk_SDK_InitEncoder( st->psEnc, &st->encControl );
119
+  if( ret ) {
120
+    ERROR( "SKP_Silk_SDK_InitEncoder returned %d", ret );
121
+    return ret;
122
+  }
123
+  
124
+  /* Set Encoder parameters */
125
+  st->encControl.API_sampleRate        = rtp_Hz;
126
+  st->encControl.maxInternalSampleRate = rtp_Hz;
127
+  st->encControl.packetSize            = ( 20 * rtp_Hz ) / 1000;
128
+  st->encControl.packetLossPercentage  = 0;
129
+  st->encControl.useInBandFEC          = 0;
130
+  st->encControl.useDTX                = 0;
131
+  st->encControl.complexity            = 2;
132
+  st->encControl.bitRate               = avg_bit_rate;
133
+  
134
+  return 0;
135
+}
136
+
137
+static int create_SILK_decoder(SILK_state* st, 
138
+			       unsigned int rtp_Hz)
139
+{
140
+  SKP_int32 ret, decSizeBytes;
141
+
142
+  /* Set the samplingrate that is requested for the output */
143
+  st->decControl.API_sampleRate = rtp_Hz;
144
+
145
+  /* Initialize to one frame per packet, for proper concealment before first packet arrives */
146
+  st->decControl.framesPerPacket = 1;
147
+
148
+  /* Create decoder */
149
+  ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
150
+  if( ret ) {
151
+    ERROR( "SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
152
+    return ret;
153
+  }
154
+
155
+  st->psDec = malloc( decSizeBytes );
156
+  if(st->psDec == NULL) {
157
+    ERROR( "could not allocate SILK decoder state" );
158
+    return -1;
159
+  }
160
+
161
+  /* Reset decoder */
162
+  ret = SKP_Silk_SDK_InitDecoder( st->psDec );
163
+  if( ret ) {
164
+    ERROR( "SKP_Silk_InitDecoder returned %d", ret );
165
+    return ret;
166
+  }
167
+
168
+  return 0;
169
+}
170
+
171
+static long SILK_create(unsigned int rtp_Hz,
172
+			unsigned int avg_bit_rate,
173
+			const char* format_parameters, 
174
+			amci_codec_fmt_info_t* format_description)
175
+{
176
+  SILK_state* st = malloc(sizeof(SILK_state));
177
+  if(st == NULL) {
178
+    ERROR("could not allocate SILK state\n");
179
+    return 0;
180
+  }
181
+
182
+  if(create_SILK_encoder(st,rtp_Hz,avg_bit_rate))
183
+    goto error;
184
+
185
+  if(create_SILK_decoder(st,rtp_Hz))
186
+    goto error;
187
+
188
+  return (long)st;
189
+
190
+ error:
191
+  if(st->psEnc) free(st->psEnc);
192
+  if(st->psDec) free(st->psDec);
193
+  free(st);
194
+
195
+  return 0;
196
+}
197
+
198
+long SILK_NB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description)
199
+{
200
+  return SILK_create(8000,20000,format_parameters,format_description);
201
+}
202
+
203
+long SILK_MB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description)
204
+{
205
+  return SILK_create(12000,25000,format_parameters,format_description);
206
+}
207
+
208
+long SILK_WB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description)
209
+{
210
+  return SILK_create(16000,30000,format_parameters,format_description);
211
+}
212
+
213
+long SILK_UB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description)
214
+{
215
+  return SILK_create(24000,40000,format_parameters,format_description);
216
+}
217
+
218
+void SILK_destroy(long handle)
219
+{
220
+  SILK_state* st = (SILK_state*)handle;
221
+  if(st->psEnc) free(st->psEnc);
222
+  if(st->psDec) free(st->psDec);
223
+  free(st);  
224
+}
225
+
226
+static unsigned int SILK_bytes2samples(long h_codec, unsigned int num_bytes) {
227
+  return num_bytes / 2;
228
+}
229
+
230
+static unsigned int SILK_samples2bytes(long h_codec, unsigned int num_samples) {
231
+  return num_samples * 2;
232
+}
233
+
234
+int Pcm16_2_SILK( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
235
+		  unsigned int channels, unsigned int rate, long h_codec )
236
+{
237
+  SILK_state* st = (SILK_state*)h_codec;
238
+  SKP_int16 ret;
239
+
240
+  /* max payload size */
241
+  SKP_int16 nBytes = AUDIO_BUFFER_SIZE;
242
+
243
+  /* Silk Encoder */
244
+  ret = SKP_Silk_SDK_Encode( st->psEnc, &st->encControl, (SKP_int16*)in_buf, 
245
+			     (SKP_int16)size/2, out_buf, &nBytes );
246
+  if( ret ) {
247
+    ERROR( "SKP_Silk_Encode returned %d (size=%u)\n", ret, size );
248
+    return -1;
249
+  }
250
+
251
+  return nBytes;
252
+}
253
+
254
+int SILK_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
255
+		  unsigned int channels, unsigned int rate, long h_codec )
256
+{
257
+  SILK_state* st = (SILK_state*)h_codec;
258
+  SKP_int16 ret, len, *outPtr = (SKP_int16*)out_buf;
259
+
260
+  do {
261
+    /* Decode 20 ms */
262
+    ret = SKP_Silk_SDK_Decode( st->psDec, &st->decControl, 0/*lost*/,
263
+			       in_buf, size, outPtr, &len );
264
+    if( ret ) {
265
+      ERROR( "SKP_Silk_SDK_Decode returned %d\n", ret );
266
+      return ret;
267
+    }
268
+
269
+    outPtr += len;
270
+
271
+    if( (unsigned char*)outPtr - out_buf > AUDIO_BUFFER_SIZE ) {
272
+      /* Oooops!!! buffer overflow !!! */
273
+      ERROR("Buffer overflow (size=%li)\n",
274
+	    (unsigned char*)outPtr - out_buf);
275
+      return -1; // TODO
276
+    }
277
+    /* Until last 20 ms frame of packet has been decoded */
278
+  } while( st->decControl.moreInternalDecoderFrames );
279
+
280
+  return (unsigned char*)outPtr - out_buf;
281
+}