source: roaraudio/libroardsp/transcode_speex.c @ 2305:d0b7c9a6b499

Last change on this file since 2305:d0b7c9a6b499 was 2305:d0b7c9a6b499, checked in by phi, 15 years ago

added support for stereo Speex

File size: 6.2 KB
Line 
1//transcode_speex.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
5 *
6 *  This file is part of libroardsp a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroardsp is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "libroardsp.h"
26
27#ifdef ROAR_HAVE_LIBSPEEX
28
29#define _16BIT (16/8)
30#define _SIZE_LEN 2
31
32int roar_xcoder_speex_init       (struct roar_xcoder * state) {
33 struct roar_xcoder_speex * self = malloc(sizeof(struct roar_xcoder_speex));
34 struct roar_audio_info  * info = &(state->info.pcm);
35 int tmp;
36
37 if ( self == NULL )
38  return -1;
39
40 // curruntly only 16 bit mode is supported
41 if ( info->bits != 16 ) {
42  free(self);
43  return -1;
44 }
45
46 // only mono/stereo mode is supported
47 switch (info->channels) {
48  case 1: self->stereo = 0; break;
49  case 2: self->stereo = 1; break;
50  default:
51    free(self);
52    return -1;
53 }
54
55 memset(self, 0, sizeof(struct roar_xcoder_speex));
56
57 state->inst = self;
58
59 self->mode  = ROAR_SPEEX_MODE_UWB;
60
61 if (state->encode) {
62  switch (self->mode) {
63   case ROAR_SPEEX_MODE_NB:  self->xcoder = speex_encoder_init(&speex_nb_mode);  break;
64   case ROAR_SPEEX_MODE_WB:  self->xcoder = speex_encoder_init(&speex_wb_mode);  break;
65   case ROAR_SPEEX_MODE_UWB: self->xcoder = speex_encoder_init(&speex_uwb_mode); break;
66  }
67  tmp = 8;
68  speex_encoder_ctl(self->xcoder, SPEEX_SET_QUALITY,       &tmp);
69  tmp = info->rate;
70  speex_encoder_ctl(self->xcoder, SPEEX_SET_SAMPLING_RATE, &tmp);
71  speex_encoder_ctl(self->xcoder, SPEEX_GET_FRAME_SIZE,    &(self->frame_size));
72 } else {
73  self->xcoder = NULL;
74 }
75
76 speex_bits_init(&(self->bits));
77
78 return 0;
79}
80
81int roar_xcoder_speex_uninit     (struct roar_xcoder * state) {
82 struct roar_xcoder_speex * self = state->inst;
83
84 if ( self->xcoder != NULL ) {
85  if (state->encode) {
86   speex_encoder_destroy(self->xcoder);
87  } else {
88   speex_decoder_destroy(self->xcoder);
89  }
90 }
91
92 speex_bits_destroy(&(self->bits));
93
94 free(self);
95
96 return 0;
97}
98
99int roar_xcoder_speex_packet_size(struct roar_xcoder * state, int samples) {
100 struct roar_xcoder_speex * self = state->inst;
101
102 if (!state->encode)
103  if (state->stage != ROAR_XCODER_STAGE_OPENED)
104   return -1;
105
106 return _16BIT * self->frame_size * (self->stereo ? 2 : 1);
107}
108
109int roar_xcoder_speex_encode     (struct roar_xcoder * state, void * buf, size_t len) {
110 struct roar_xcoder_speex * self = state->inst;
111 uint16_t tmp_net;
112 int pkg_len;
113
114 if (!state->encode)
115  return -1;
116
117 ROAR_DBG("roar_xcoder_speex_encode(*): Encoding...");
118
119 if ( state->stage == ROAR_XCODER_STAGE_INITED ) {
120  if ( roar_vio_write(state->backend, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) != ROAR_SPEEX_MAGIC_LEN )
121   return -1;
122  state->stage = ROAR_XCODER_STAGE_MAGIC;
123  ROAR_DBG("roar_xcoder_speex_encode(*): Wrote MAGIC");
124
125  state->stage = ROAR_XCODER_STAGE_OPENING;
126
127  tmp_net = ROAR_HOST2NET16(self->mode);
128  if ( roar_vio_write(state->backend, &tmp_net, 2) != 2 )
129   return -1;
130
131  state->stage = ROAR_XCODER_STAGE_OPENED;
132 }
133
134 speex_bits_reset(&(self->bits));
135
136 if ( self->stereo )
137  speex_encode_stereo_int((spx_int16_t *) buf, self->frame_size, &(self->bits));
138
139 speex_encode_int(self->xcoder, (spx_int16_t *) buf, &(self->bits));
140
141 pkg_len = speex_bits_write(&(self->bits), self->cc, ROAR_SPEEX_MAX_CC);
142
143 tmp_net = ROAR_HOST2NET16(pkg_len);
144
145 if ( roar_vio_write(state->backend, &tmp_net, 2) != 2 )
146  return -1;
147
148 if ( roar_vio_write(state->backend, self->cc, pkg_len) != pkg_len )
149   return -1;
150
151 return 0;
152}
153
154// TODO: move all the init thingys into a seperate function
155int roar_xcoder_speex_decode     (struct roar_xcoder * state, void * buf, size_t len) {
156 struct roar_xcoder_speex * self = state->inst;
157 char magic[ROAR_SPEEX_MAGIC_LEN];
158 uint16_t tmp_net;
159 int pkg_len;
160 int tmp;
161 SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
162 SpeexCallback callback;
163
164 if ( state->stage == ROAR_XCODER_STAGE_INITED ) {
165  if ( roar_vio_read(state->backend, magic, ROAR_SPEEX_MAGIC_LEN) != ROAR_SPEEX_MAGIC_LEN )
166   return -1;
167
168  if ( memcmp(magic, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) != 0 )
169   return -1;
170
171  state->stage = ROAR_XCODER_STAGE_MAGIC;
172
173  if ( roar_vio_read(state->backend, &tmp_net, 2) != 2 )
174   return -1;
175
176  self->mode = ROAR_NET2HOST16(tmp_net);
177
178  state->stage = ROAR_XCODER_STAGE_OPENING;
179
180  switch (self->mode) {
181   case ROAR_SPEEX_MODE_NB:  self->xcoder = speex_decoder_init(&speex_nb_mode);  break;
182   case ROAR_SPEEX_MODE_WB:  self->xcoder = speex_decoder_init(&speex_wb_mode);  break;
183   case ROAR_SPEEX_MODE_UWB: self->xcoder = speex_decoder_init(&speex_uwb_mode); break;
184   default:
185     return -1;
186    break;
187  }
188
189  tmp=1;
190  speex_decoder_ctl(self->xcoder, SPEEX_SET_ENH, &tmp);
191  tmp = state->info.pcm.rate;
192  speex_encoder_ctl(self->xcoder, SPEEX_SET_SAMPLING_RATE, &tmp);
193  speex_decoder_ctl(self->xcoder, SPEEX_GET_FRAME_SIZE, &(self->frame_size));
194
195  if ( self->stereo ) {
196   memcpy(&(self->stereo_state), &stereo, sizeof(self->stereo_state));
197
198   callback.callback_id = SPEEX_INBAND_STEREO;
199   callback.func = speex_std_stereo_request_handler;
200   callback.data = &(self->stereo_state);
201
202   speex_decoder_ctl(self->xcoder, SPEEX_SET_HANDLER, &callback);
203  }
204
205  state->stage = ROAR_XCODER_STAGE_OPENED;
206 }
207
208 if ( roar_vio_read(state->backend, &tmp_net, 2) != 2 )
209  return -1;
210
211 pkg_len = ROAR_NET2HOST16(tmp_net);
212
213 if ( pkg_len > ROAR_SPEEX_MAX_CC )
214  return -1;
215
216 if ( roar_vio_read(state->backend, self->cc, pkg_len) != pkg_len )
217  return -1;
218
219 speex_bits_read_from(&(self->bits), self->cc, pkg_len);
220
221 speex_decode_int(self->xcoder, &(self->bits), buf);
222
223 if ( self->stereo ) {
224  speex_decode_stereo_int(buf, self->frame_size, &(self->stereo_state));
225 }
226
227 return 0;
228}
229
230#endif
231
232//ll
Note: See TracBrowser for help on using the repository browser.