Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvspeex.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * Provides a WvEncoder abstraction for the Speex audio packet format. 00006 * suitable for encoding voice at low bitrates. 00007 * 00008 * Only monaural audio is supported for now. 00009 */ 00010 #include "wvspeex.h" 00011 #include <speex.h> 00012 #include <speex_header.h> 00013 00014 /** 00015 * Returns the SpeexMode to use for a given sampling rate. 00016 * "modeid" is the suggested mode 00017 * "samplingrate" is the sampling rate 00018 */ 00019 static SpeexMode *get_speex_mode(WvSpeex::CodecMode modeid, 00020 int samplingrate) 00021 { 00022 // use the suggested mode if it is valid 00023 if (modeid >= 0 && modeid < SPEEX_NB_MODES) 00024 return speex_mode_list[modeid]; 00025 00026 // otherwise determine a suitable default 00027 SpeexMode *mode; 00028 assert(samplingrate <= 48000 || ! "sampling rate too high"); 00029 assert(samplingrate >= 6000 || ! "sampling rate too low"); 00030 if (samplingrate > 25000) 00031 mode = & speex_uwb_mode; 00032 else if (samplingrate > 12500) 00033 mode = & speex_wb_mode; 00034 else 00035 mode = & speex_nb_mode; 00036 return mode; 00037 } 00038 00039 00040 00041 /***** WvSpeexEncoder *****/ 00042 00043 WvSpeexEncoder::WvSpeexEncoder( 00044 const WvSpeex::BitrateSpec &bitratespec, 00045 int samplingrate, unsigned int channels, WvSpeex::CodecMode modeid, 00046 int complexity) : 00047 spxstate(NULL), spxbits(NULL), spxmode(NULL), 00048 _channels(channels), _samplesperframe(0) 00049 { 00050 // init encoder 00051 spxmode = get_speex_mode(modeid, samplingrate); 00052 spxstate = speex_encoder_init(spxmode); 00053 if (! spxstate) 00054 { 00055 seterror("error during speex_encoder_init"); 00056 return; 00057 } 00058 spxbits = new SpeexBits; 00059 speex_bits_init(spxbits); 00060 00061 // set sampling rate 00062 speex_encoder_ctl(spxstate, SPEEX_SET_SAMPLING_RATE, &samplingrate); 00063 00064 // set the complexity 00065 if (complexity != WvSpeex::DEFAULT_COMPLEXITY) 00066 speex_encoder_ctl(spxstate, SPEEX_SET_COMPLEXITY, &complexity); 00067 00068 // init bitrate management 00069 switch (bitratespec.mode) 00070 { 00071 case WvSpeex::BitrateSpec::VBR_QUALITY: 00072 { 00073 int enable = 1; 00074 speex_encoder_ctl(spxstate, SPEEX_SET_VBR, &enable); 00075 float quality = bitratespec.quality_index * 10; 00076 speex_encoder_ctl(spxstate, SPEEX_SET_VBR_QUALITY, 00077 &quality); 00078 break; 00079 } 00080 00081 case WvSpeex::BitrateSpec::CBR_QUALITY: 00082 { 00083 int quality = int(bitratespec.quality_index * 10); 00084 speex_encoder_ctl(spxstate, SPEEX_SET_QUALITY, 00085 &quality); 00086 break; 00087 } 00088 00089 case WvSpeex::BitrateSpec::CBR_BITRATE: 00090 { 00091 int bitrate = bitratespec.nominal_bitrate; 00092 speex_encoder_ctl(spxstate, SPEEX_SET_BITRATE, 00093 &bitrate); 00094 break; 00095 } 00096 } 00097 00098 // cache frame size since we use it often 00099 speex_encoder_ctl(spxstate, SPEEX_GET_FRAME_SIZE, 00100 &_samplesperframe); 00101 } 00102 00103 00104 WvSpeexEncoder::~WvSpeexEncoder() 00105 { 00106 speex_encoder_destroy(spxstate); 00107 speex_bits_destroy(spxbits); 00108 delete spxbits; 00109 } 00110 00111 00112 bool WvSpeexEncoder::_typedencode(IBuffer &inbuf, OBuffer &outbuf, 00113 bool flush) 00114 { 00115 if (! flushspxbits(outbuf)) 00116 return false; 00117 for (;;) 00118 { 00119 size_t avail = inbuf.used(); 00120 if (avail == 0) 00121 return true; 00122 if (avail < size_t(_samplesperframe)) 00123 return ! flush; // not enough data 00124 speex_encode(spxstate, const_cast<float*>( 00125 inbuf.get(_samplesperframe)), spxbits); 00126 if (! flushspxbits(outbuf)) 00127 return false; 00128 if (! flush) 00129 return true; 00130 } 00131 } 00132 00133 00134 bool WvSpeexEncoder::_typedfinish(OBuffer &outbuf) 00135 { 00136 return flushspxbits(outbuf); 00137 } 00138 00139 00140 bool WvSpeexEncoder::flushspxbits(OBuffer &outbuf) 00141 { 00142 size_t needed = speex_bits_nbytes(spxbits); 00143 if (needed == 0) 00144 return true; 00145 00146 while (needed != 0) 00147 { 00148 size_t avail = outbuf.optallocable(); 00149 if (avail == 0) 00150 return false; 00151 if (avail > needed) 00152 avail = needed; 00153 speex_bits_write(spxbits, reinterpret_cast<char*>( 00154 outbuf.alloc(avail)), avail); 00155 needed -= avail; 00156 } 00157 // must reset before the next frame can be created 00158 speex_bits_reset(spxbits); 00159 return true; 00160 } 00161 00162 00163 int WvSpeexEncoder::samplingrate() const 00164 { 00165 int rate; 00166 speex_encoder_ctl(const_cast<void*>(spxstate), 00167 SPEEX_GET_SAMPLING_RATE, &rate); 00168 return rate; 00169 } 00170 00171 00172 WvSpeex::CodecMode WvSpeexEncoder::mode() const 00173 { 00174 return WvSpeex::CodecMode(spxmode->modeID); 00175 } 00176 00177 00178 bool WvSpeexEncoder::vbr() const 00179 { 00180 int enabled; 00181 speex_encoder_ctl(const_cast<void*>(spxstate), 00182 SPEEX_GET_VBR, &enabled); 00183 return enabled; 00184 } 00185 00186 00187 int WvSpeexEncoder::nominalbitrate() const 00188 { 00189 int bitrate; 00190 speex_encoder_ctl(const_cast<void*>(spxstate), 00191 SPEEX_GET_BITRATE, &bitrate); 00192 return bitrate; 00193 } 00194 00195 00196 00197 /***** WvSpeexDecoder *****/ 00198 00199 WvSpeexDecoder::WvSpeexDecoder(int samplingrate, unsigned int channels, 00200 WvSpeex::CodecMode modeid) : 00201 _samplingrate(samplingrate), _channels(channels), 00202 spxstate(NULL), spxbits(NULL), spxmode(NULL), 00203 _samplesperframe(0) 00204 { 00205 // init decoder 00206 spxmode = get_speex_mode(modeid, samplingrate); 00207 spxstate = speex_decoder_init(spxmode); 00208 if (! spxstate) 00209 { 00210 seterror("error during speex_decoder_init"); 00211 return; 00212 } 00213 spxbits = new SpeexBits; 00214 speex_bits_init(spxbits); 00215 00216 // set sampling rate 00217 speex_decoder_ctl(spxstate, SPEEX_SET_SAMPLING_RATE, 00218 & samplingrate); 00219 00220 // cache frame size since we use it often 00221 speex_decoder_ctl(spxstate, SPEEX_GET_FRAME_SIZE, 00222 &_samplesperframe); 00223 } 00224 00225 00226 WvSpeexDecoder::~WvSpeexDecoder() 00227 { 00228 speex_decoder_destroy(spxstate); 00229 speex_bits_destroy(spxbits); 00230 delete spxbits; 00231 } 00232 00233 00234 WvSpeex::CodecMode WvSpeexDecoder::mode() const 00235 { 00236 return WvSpeex::CodecMode(spxmode->modeID); 00237 } 00238 00239 00240 bool WvSpeexDecoder::postfilter() const 00241 { 00242 int enabled; 00243 speex_decoder_ctl(spxstate, SPEEX_GET_ENH, &enabled); 00244 return enabled; 00245 } 00246 00247 00248 void WvSpeexDecoder::setpostfilter(bool enable) 00249 { 00250 int enabled = enable ? 1 : 0; 00251 speex_decoder_ctl(spxstate, SPEEX_SET_ENH, &enabled); 00252 } 00253 00254 00255 bool WvSpeexDecoder::_typedencode(IBuffer &inbuf, OBuffer &outbuf, 00256 bool flush) 00257 { 00258 for (;;) 00259 { 00260 size_t avail = inbuf.used(); 00261 if (avail == 0) 00262 return true; 00263 if (outbuf.free() < size_t(_samplesperframe)) 00264 return false; // not enough room 00265 00266 size_t skip = 0; 00267 if (avail > MAX_BYTES_PER_FRAME) 00268 { 00269 // packet is too large but try to decode some audio anyhow 00270 skip = avail - MAX_BYTES_PER_FRAME; 00271 avail -= skip; 00272 } 00273 speex_bits_read_from(spxbits, const_cast<char*>( 00274 reinterpret_cast<const char*>(inbuf.get(avail))), avail); 00275 float *outsamples = outbuf.alloc(_samplesperframe); 00276 int retval = speex_decode(spxstate, spxbits, outsamples); 00277 inbuf.skip(skip); // skip over bad data 00278 if (retval != 0) 00279 return false; // signal bad data but don't stop on error 00280 if (! flush) 00281 return true; 00282 } 00283 } 00284 00285 00286 bool WvSpeexDecoder::_typedfinish(OBuffer &outbuf) 00287 { 00288 return true; 00289 } 00290 00291 00292 bool WvSpeexDecoder::missing(OBuffer &outbuf) 00293 { 00294 if (! isok() || isfinished()) 00295 return false; 00296 if (outbuf.free() < size_t(_samplesperframe)) 00297 return false; // not enough room 00298 speex_decode(spxstate, NULL, outbuf.alloc(_samplesperframe)); 00299 return true; 00300 }

Generated on Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7