📄 manual.lyx
字号:
is the number of bytes actually written to \emph onbyte_ptr\emph default (the encoded size in bytes). Before calling speex_bits_write, it is possible to find the number of bytes that need to be written by calling \family typewriterspeex_bits_nbytes(&bits)\family default, which returns a number of bytes.\end_layout\begin_layout StandardIt is still possible to use the \emph onspeex_encode()\emph default function, which takes a \emph on(float *)\emph default for the audio. However, this would make an eventual port to an FPU-less platform (like ARM) more complicated. Internally, \emph onspeex_encode() \emph defaultand\emph on speex_encode_int()\emph default are processed in the same way. Whether the encoder uses the fixed-point version is only decided by the compile-time flags, not at the API level.\end_layout\begin_layout StandardAfter you're done with the encoding, free all resources with:\end_layout\begin_layout LyX-Codespeex_bits_destroy(&bits);\end_layout\begin_layout LyX-Codespeex_encoder_destroy(enc_state);\end_layout\begin_layout StandardThat's about it for the encoder. \end_layout\begin_layout SectionDecoding\begin_inset LatexCommand \label{sub:Decoding}\end_inset\end_layout\begin_layout StandardIn order to decode speech using Speex, you first need to:\end_layout\begin_layout LyX-Code#include <speex/speex.h>\end_layout\begin_layout StandardYou also need to declare a Speex bit-packing struct\end_layout\begin_layout LyX-CodeSpeexBits bits;\end_layout\begin_layout Standardand a Speex decoder state\end_layout\begin_layout LyX-Codevoid *dec_state;\end_layout\begin_layout StandardThe two are initialized by:\end_layout\begin_layout LyX-Codespeex_bits_init(&bits);\end_layout\begin_layout LyX-Codedec_state = speex_decoder_init(&speex_nb_mode);\end_layout\begin_layout StandardFor wideband decoding, \emph onspeex_nb_mode\emph default will be replaced by \emph onspeex_wb_mode\emph default. If you need to obtain the size of the frames that will be used by the decoder, you can get that value in the \emph onframe_size\emph default variable with:\end_layout\begin_layout LyX-Codespeex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &frame_size); \end_layout\begin_layout StandardThere is also a parameter that can be set for the decoder: whether or not to use a perceptual enhancer. This can be set by: \end_layout\begin_layout LyX-Codespeex_decoder_ctl(dec_state, SPEEX_SET_ENH, &enh); \end_layout\begin_layout Standardwhere \emph onenh\emph default is an int with value 0 to have the enhancer disabled and 1 to have it enabled. As of 1.2-beta1, the default is now to enable the enhancer.\end_layout\begin_layout StandardAgain, once the decoder initialization is done, for every input frame:\end_layout\begin_layout LyX-Codespeex_bits_read_from(&bits, input_bytes, nbBytes);\end_layout\begin_layout LyX-Codespeex_decode_int(dec_state, &bits, output_frame);\end_layout\begin_layout Standardwhere input_bytes is a \emph on(char *)\emph default containing the bit-stream data received for a frame, \emph onnbBytes\emph default is the size (in bytes) of that bit-stream, and \emph onoutput_frame\emph default is a \emph on(short *)\emph default and points to the area where the decoded speech frame will be written. A NULL value as the first argument indicates that we don't have the bits for the current frame. When a frame is lost, the Speex decoder will do its best to "guess" the correct signal.\end_layout\begin_layout StandardAs for the encoder, the \emph onspeex_decode()\emph default function can still be used, with a \emph on(float *)\emph default as the output for the audio.\end_layout\begin_layout StandardAfter you're done with the decoding, free all resources with:\end_layout\begin_layout LyX-Codespeex_bits_destroy(&bits);\end_layout\begin_layout LyX-Codespeex_decoder_destroy(dec_state);\end_layout\begin_layout SectionPreprocessor\begin_inset LatexCommand \label{sub:Preprocessor}\end_inset\end_layout\begin_layout StandardIn order to use the Speex preprocessor\begin_inset LatexCommand \index{preprocessor}\end_inset, you first need to:\end_layout\begin_layout LyX-Code#include <speex/speex_preprocess.h>\end_layout\begin_layout StandardThen, a preprocessor state can be created as:\end_layout\begin_layout LyX-CodeSpeexPreprocessState *preprocess_state = speex_preprocess_state_init(frame_size, sampling_rate);\end_layout\begin_layout StandardIt is recommended to use the same value for \family typewriterframe_size\family default as is used by the encoder (20 \emph onms\emph default).\end_layout\begin_layout StandardFor each input frame, you need to call:\end_layout\begin_layout LyX-Codespeex_preprocess_run(preprocess_state, audio_frame);\end_layout\begin_layout Standardwhere \family typewriteraudio_frame\family default is used both as input and output.\end_layout\begin_layout StandardIn cases where the output audio is not useful for a certain frame, it is possible to use instead:\end_layout\begin_layout LyX-Codespeex_preprocess_estimate_update(preprocess_state, audio_frame);\end_layout\begin_layout StandardThis call will update all the preprocessor internal state variables without computing the output audio, thus saving some CPU cycles.\end_layout\begin_layout StandardThe behaviour of the preprocessor can be changed using:\end_layout\begin_layout LyX-Codespeex_preprocess_ctl(preprocess_state, request, ptr);\end_layout\begin_layout Standardwhich is used in the same way as the encoder and decoder equivalent. Options are listed in Section .\end_layout\begin_layout StandardThe preprocessor state can be destroyed using:\end_layout\begin_layout LyX-Codespeex_preprocess_state_destroy(preprocess_state);\end_layout\begin_layout SectionEcho Cancellation\begin_inset LatexCommand \label{sub:Echo-Cancellation}\end_inset\end_layout\begin_layout StandardThe Speex library now includes an echo cancellation\begin_inset LatexCommand \index{echo cancellation}\end_inset algorithm suitable for Acoustic Echo Cancellation\begin_inset LatexCommand \index{acoustic echo cancellation}\end_inset (AEC). In order to use the echo canceller, you first need to\end_layout\begin_layout LyX-Code#include <speex/speex_echo.h>\end_layout\begin_layout StandardThen, an echo canceller state can be created by:\end_layout\begin_layout LyX-CodeSpeexEchoState *echo_state = speex_echo_state_init(frame_size, filter_length);\end_layout\begin_layout Standardwhere \family typewriterframe_size\family default is the amount of data (in samples) you want to process at once and \family typewriterfilter_length\family default is the length (in samples) of the echo cancelling filter you want to use (also known as \shape italictail length\shape default\begin_inset LatexCommand \index{tail length}\end_inset). It is recommended to use a frame size in the order of 20 ms (or equal to the codec frame size) and make sure it is easy to perform an FFT of that size (powers of two are better than prime sizes). The recommended tail length is approximately the third of the room reverberation time. For example, in a small room, reverberation time is in the order of 300 ms, so a tail length of 100 ms is a good choice (800 samples at 8000 Hz sampling rate).\end_layout\begin_layout StandardOnce the echo canceller state is created, audio can be processed by:\end_layout\begin_layout LyX-Codespeex_echo_cancellation(echo_state, input_frame, echo_frame, output_frame);\end_layout\begin_layout Standardwhere \family typewriterinput_frame\family default is the audio as captured by the microphone, \family typewriterecho_frame\family default is the signal that was played in the speaker (and needs to be removed) and \family typewriteroutput_frame\family default is the signal with echo removed. \end_layout\begin_layout StandardOne important thing to keep in mind is the relationship between \family typewriterinput_frame\family default and \family typewriterecho_frame\family default. It is important that, at any time, any echo that is present in the input has already been sent to the echo canceller as \family typewriterecho_frame\family default. In other words, the echo canceller cannot remove a signal that it hasn't yet received. On the other hand, the delay between the input signal and the echo signal must be small enough because otherwise part of the echo cancellation filter is inefficient. In the ideal case, you code would look like:\end_layout\begin_layout LyX-Codewrite_to_soundcard(echo_frame, frame_size);\end_layout\begin_layout LyX-Coderead_from_soundcard(input_frame, frame_size);\end_layout\begin_layout LyX-Codespeex_echo_cancellation(echo_state, input_frame, echo_frame, output_frame);\end_layout\begin_layout StandardIf you wish to further reduce the echo present in the signal, you can do so by \family typewriterassociating the echo canceller to the preprocessor\family default (see Section \begin_inset LatexCommand \ref{sub:Preprocessor}\end_inset). This is done by calling:\end_layout\begin_layout LyX-Codespeex_preprocess_ctl(preprocess_state, SPEEX_PREPROCESS_SET_ECHO_STATE, echo_state);\end_layout\begin_layout Standardin the initialisation.\end_layout\begin_layout StandardAs of version 1.2-beta2, there is an alternative, simpler API that can be used instead of \emph onspeex_echo_cancellation()\emph default. When audio capture and playback are handled asynchronously (e.g. in different threads or using the \emph onpoll()\emph default or \emph onselect()\emph default system call), it can be difficult to keep track of what input_frame comes with what echo_frame. Instead, the playback comtext/thread can simply call:\end_layout\begin_layout LyX-Codespeex_echo_playback(echo_state, echo_frame);\end_layout\begin_layout Standardevery time an audio frame is played. Then, the capture context/thread calls:\end_layout\begin_layout LyX-Codespeex_echo_capture(echo_state, input_frame, output_frame);\end_layout\begin_layout Standardfor every frame captured. Internally, \emph onspeex_echo_playback()\emph default simply buffers the playback frame so it can be used by \emph onspeex_echo_capture()\emph default to call \emph onspeex_echo_cancel()\emph default. A side effect of using this alternate API is that the playback audio is delayed by two frames, which is the normal delay caused by the soundcard. When capture and playback are already synchronised, \emph onspeex_echo_cancellation()\emph default is preferable since it gives better control on the exact input/echo timing.\end_layout\begin_layout StandardThe echo cancellation state can be destroyed with:\end_layout\begin_layout LyX-Codespeex_echo_state_destroy(echo_state);\end_layout\begin_layout StandardIt is also possible to reset the state of the echo canceller so it can be reused without the need to create another state with:\end_layout\begin_layout LyX-Codespeex_echo_state_reset(echo_state);\end_layout\begin_layout SubsectionTroubleshooting\end_layout\begin_layout StandardThere are several things that may prevent the echo canceller from working properly. One of them is a bug (or something suboptimal) in the code, but there are many others you should consider first\end_layout\begin_layout ItemizeUsing a different soundcard to do the capture and plaback will *not* work, regardless of what you may think. The only exception to that is if the two cards can be made to have their sampling clock \begin_inset Quotes eld\end_insetlocked\begin_inset Quotes erd\end_inset on the same clock source.\end_layout\begin_layout ItemizeThe delay between the record and playback signals must be minimal. Any signal played has to \begin_inset Quotes eld\end_insetappear\begin_inset Quotes erd\end_inset on the playback (far end) signal slightly before the echo canceller \begin_inset Quotes eld\end_insetsees\begin_inset Quotes erd\end_inset it in the near end signal, but excessive delay means that part of the filter length is wasted. In the worst situations, the delay is such that it is longer than the filter length, in which case, no echo can be cancelled.\end_layout\begin_layout ItemizeWhen it comes to echo tail length (filter length), longer is *not* better. Actually, the longer the tail length, the longer it takes for the filter to adapt. Of course, a tail length that is too short will not cancel enough echo, but the most common problem seen is that people set a very long tail length and then wonder why no echo is being cancelled.\end_layout\begin_layout ItemizeNon-linear distortion cannot (by definition) be modeled by the linear adaptive filter used in the echo canceller and thus cannot be cancelled. Use good audio gear and avoid saturation/clipping.\end_layout\begin_layout StandardAlso useful is reading \emph onEcho Cancellation Demystified\emph default by Alexey Frunze\begin_inset Footstatus collapsed\begin_layout Standardhttp://www.embeddedstar.com/articles/2003/7/article20030720-1.html\end_layout\end_inset, which explains the fundamental principles of echo cancellation. The details of the algorithm described in the article are different, but the general ideas of echo cancellation through adaptive filters are the same.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -