]> git.mxchange.org Git - flightgear.git/blob - 3rdparty/iaxclient/lib/codec_speex.c
VS2015 compatability fixes.
[flightgear.git] / 3rdparty / iaxclient / lib / codec_speex.c
1 /*
2  * iaxclient: a cross-platform IAX softphone library
3  *
4  * Copyrights:
5  * Copyright (C) 2003-2004, Horizon Wimba, Inc.
6  * Copyright (C) 2007, Wimba, Inc.
7  *
8  * Contributors:
9  * Steve Kann <stevek@stevek.com>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU Lesser (Library) General Public License.
13  */
14
15 #include "codec_speex.h"
16 #include "iaxclient_lib.h"
17 #include "speex/speex.h"
18
19 struct State
20 {
21         void *state;
22         int frame_size;
23         SpeexBits bits;
24 };
25
26
27 static void destroy ( struct iaxc_audio_codec *c)
28 {
29         struct State * encstate = (struct State *) c->encstate;
30         struct State * decstate = (struct State *) c->decstate;
31
32         speex_bits_destroy(&encstate->bits);
33         speex_bits_destroy(&decstate->bits);
34         speex_encoder_destroy(encstate->state);
35         speex_decoder_destroy(decstate->state);
36
37         free(c->encstate);
38         free(c->decstate);
39
40         free(c);
41 }
42
43
44 static int decode( struct iaxc_audio_codec *c,
45                 int *inlen, unsigned char *in, int *outlen, short *out )
46 {
47         struct State * decstate = (struct State *) c->decstate;
48
49         if ( *inlen == 0 )
50         {
51                 speex_decode_int(decstate->state, NULL, out);
52                 *outlen -= decstate->frame_size;
53                 return 0;
54         }
55
56         speex_bits_read_from(&decstate->bits, (char *) in, *inlen);
57         *inlen = 0;
58
59         while ( speex_bits_remaining(&decstate->bits) &&
60                         *outlen >= decstate->frame_size )
61         {
62                 int ret = speex_decode_int(decstate->state, &decstate->bits, out);
63
64                 // from speex/speex.h, speex_decode returns:
65                 // @return return status (0 for no error, -1 for end of stream, -2 other)
66                 if (ret == 0)
67                 {
68                         /* one frame of output */
69                         *outlen -= decstate->frame_size;
70                         out += decstate->frame_size;
71                 } else if (ret == -1)
72                 {
73                         /* at end of stream, or just a terminator */
74                         int bits_left = speex_bits_remaining(&decstate->bits) % 8;
75                         if(bits_left >= 5)
76                                 speex_bits_advance(&decstate->bits, bits_left);
77                         else
78                                 break;
79                 } else
80                 {
81                         /* maybe there's not a whole frame somehow? */
82                         fprintf(stderr, "decode_int returned non-zero => %d\n",ret);
83                         break;
84                 }
85         }
86         return 0;
87 }
88
89 static int encode( struct iaxc_audio_codec *c,
90                 int *inlen, short *in, int *outlen, unsigned char *out )
91 {
92         int bytes;
93         struct State * encstate = (struct State *) c->encstate;
94
95         /* need to encode minimum of encstate->frame_size samples */
96
97         /*  only add terminator at end of bits */
98         speex_bits_reset(&encstate->bits);
99
100         /* need to encode minimum of encstate->frame_size samples */
101         while(*inlen >= encstate->frame_size)
102         {
103                 //fprintf(stderr, "encode: inlen=%d outlen=%d\n", *inlen, *outlen);
104                 speex_encode_int(encstate->state, in, &encstate->bits);
105                 *inlen -= encstate->frame_size;
106                 in += encstate->frame_size;
107         }
108
109         /* add terminator */
110         speex_bits_pack(&encstate->bits, 15, 5);
111
112         bytes = speex_bits_write(&encstate->bits, (char *) out, *outlen);
113
114         /* can an error happen here?  no bytes? */
115         *outlen -= bytes;
116
117         return 0;
118 }
119
120 struct iaxc_audio_codec *codec_audio_speex_new(struct iaxc_speex_settings *set)
121 {
122         struct State * encstate;
123         struct State * decstate;
124         struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(sizeof(struct iaxc_audio_codec),1);
125         const SpeexMode *sm;
126
127         if(!c)
128                 return c;
129
130         strcpy(c->name,"speex");
131         c->format = IAXC_FORMAT_SPEEX;
132         c->encode = encode;
133         c->decode = decode;
134         c->destroy = destroy;
135
136         c->encstate = calloc(sizeof(struct State),1);
137         c->decstate = calloc(sizeof(struct State),1);
138
139         /* leaks a bit on no-memory */
140         if(!(c->encstate && c->decstate))
141                 return NULL;
142
143         encstate = (struct State *) c->encstate;
144         decstate = (struct State *) c->decstate;
145
146         sm = speex_lib_get_mode(SPEEX_MODEID_NB);
147
148         encstate->state = speex_encoder_init(sm);
149         decstate->state = speex_decoder_init(sm);
150         speex_bits_init(&encstate->bits);
151         speex_bits_init(&decstate->bits);
152         speex_bits_reset(&encstate->bits);
153         speex_bits_reset(&decstate->bits);
154
155         speex_decoder_ctl(decstate->state, SPEEX_SET_ENH, &set->decode_enhance);
156
157         speex_encoder_ctl(encstate->state, SPEEX_SET_COMPLEXITY, &set->complexity);
158
159         if(set->quality >= 0) {
160                 if(set->vbr) {
161                         speex_encoder_ctl(encstate->state, SPEEX_SET_VBR_QUALITY, &set->quality);
162                 } else {
163                         int quality = (int)set->quality;
164                         speex_encoder_ctl(encstate->state, SPEEX_SET_QUALITY, &quality);
165                 }
166         }
167         if(set->bitrate >= 0)
168                 speex_encoder_ctl(encstate->state, SPEEX_SET_BITRATE, &set->bitrate);
169         if(set->vbr)
170                 speex_encoder_ctl(encstate->state, SPEEX_SET_VBR, &set->vbr);
171         if(set->abr)
172                 speex_encoder_ctl(encstate->state, SPEEX_SET_ABR, &set->abr);
173
174         /* set up frame sizes (normally, this is 20ms worth) */
175         speex_encoder_ctl(encstate->state,SPEEX_GET_FRAME_SIZE,&encstate->frame_size);
176         speex_decoder_ctl(decstate->state,SPEEX_GET_FRAME_SIZE,&decstate->frame_size);
177
178         c->minimum_frame_size = 160;
179
180         if(encstate->frame_size > c->minimum_frame_size)
181                 c->minimum_frame_size = encstate->frame_size;
182         if(decstate->frame_size > c->minimum_frame_size)
183                 c->minimum_frame_size = decstate->frame_size;
184
185         if(!(encstate->state && decstate->state))
186                 return NULL;
187
188         return c;
189 }
190