speexcodec_ub.cpp 5.12 KB
Newer Older
Alexandre Savard's avatar
Alexandre Savard committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 *  Copyright (C) 2007-2009 Savoir-Faire Linux inc.
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "audiocodec.h"
#include <cstdio>
#include <speex/speex.h>
#include <speex/speex_preprocess.h>

26
27
28
class Speex : public AudioCodec
{

Alexandre Savard's avatar
Alexandre Savard committed
29
    public:
30
31
32
33
34
35
36
37
38
39
        Speex (int payload=0)
                : AudioCodec (payload, "speex"),
                _speexModePtr (NULL),
                _speex_dec_bits(),
                _speex_enc_bits(),
                _speex_dec_state(),
                _speex_enc_state(),
                _speex_frame_size(),
                _preprocess_state() {
            _clockRate = 32000;
40
            _frameSize = 640; // 20 ms at 32 kHz
41
42
43
44
45
46
47
48
49
50
51
52
            _channel = 1;
            _bitrate = 0;
            _bandwidth = 0;
            initSpeex();
        }

        Speex (const Speex&);
        Speex& operator= (const Speex&);

        void initSpeex() {

            // int _samplingRate = 32000;
Alexandre Savard's avatar
Alexandre Savard committed
53
54
55

            // 8000 HZ --> Narrow-band mode
            // TODO Manage the other modes
56
57
            _speexModePtr = &speex_wb_mode;
            // _speexModePtr = &speex_wb_mode;
Alexandre Savard's avatar
Alexandre Savard committed
58
59

            // Init the decoder struct
60
61
            speex_bits_init (&_speex_dec_bits);
            _speex_dec_state = speex_decoder_init (_speexModePtr);
Alexandre Savard's avatar
Alexandre Savard committed
62
63

            // Init the encoder struct
64
65
66
67
            speex_bits_init (&_speex_enc_bits);
            _speex_enc_state = speex_encoder_init (_speexModePtr);

            speex_encoder_ctl (_speex_enc_state,SPEEX_SET_SAMPLING_RATE,&_clockRate);
Alexandre Savard's avatar
Alexandre Savard committed
68

69
            speex_decoder_ctl (_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_speex_frame_size);
Alexandre Savard's avatar
Alexandre Savard committed
70
71
72
73
74
75
76

#ifdef HAVE_SPEEXDSP_LIB

            int enable = 1;
            int complex = 10;
            int attenuation = -10;

77
78
            speex_encoder_ctl (_speex_enc_state, SPEEX_SET_VAD, &enable);
            speex_encoder_ctl (_speex_enc_state, SPEEX_SET_DTX, &enable);
Alexandre Savard's avatar
Alexandre Savard committed
79
            // speex_encoder_ctl(_speex_enc_state, SPEEX_SET_VBR_QUALITY, &quality);
80
            speex_encoder_ctl (_speex_enc_state, SPEEX_SET_COMPLEXITY, &complex);
Alexandre Savard's avatar
Alexandre Savard committed
81
82

            // Init the decoder struct
83
            speex_decoder_ctl (_speex_dec_state, SPEEX_GET_FRAME_SIZE, &_frameSize);
Alexandre Savard's avatar
Alexandre Savard committed
84
85

            // Init the preprocess struct
86
            _preprocess_state = speex_preprocess_state_init (_frameSize,_clockRate);
87
88
89
90
            speex_preprocess_ctl (_preprocess_state, SPEEX_PREPROCESS_SET_DENOISE, &enable);
            speex_preprocess_ctl (_preprocess_state, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &attenuation);
            speex_preprocess_ctl (_preprocess_state, SPEEX_PREPROCESS_SET_VAD, &enable);
            speex_preprocess_ctl (_preprocess_state, SPEEX_PREPROCESS_SET_AGC, &enable);
Alexandre Savard's avatar
Alexandre Savard committed
91
#endif
92

Alexandre Savard's avatar
Alexandre Savard committed
93
94
        }

95
        ~Speex() {
Alexandre Savard's avatar
Alexandre Savard committed
96
97
98
99
100
            terminateSpeex();
        }

        void terminateSpeex() {
            // Destroy the decoder struct
101
102
            speex_bits_destroy (&_speex_dec_bits);
            speex_decoder_destroy (_speex_dec_state);
Alexandre Savard's avatar
Alexandre Savard committed
103
104
105
            _speex_dec_state = 0;

            // Destroy the encoder struct
106
107
            speex_bits_destroy (&_speex_enc_bits);
            speex_encoder_destroy (_speex_enc_state);
Alexandre Savard's avatar
Alexandre Savard committed
108
109
110
            _speex_enc_state = 0;
        }

111
112
113
114
115
        virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) {

            // int ratio = 320 / _speex_frame_size;
            speex_bits_read_from (&_speex_dec_bits, (char*) src, size);
            speex_decode_int (_speex_dec_state, &_speex_dec_bits, dst);
116

117
            // return the nuber of byte, not the number of sample
118
            return _frameSize * 2;
Alexandre Savard's avatar
Alexandre Savard committed
119
120
        }

121
122
        virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) {
            speex_bits_reset (&_speex_enc_bits);
Alexandre Savard's avatar
Alexandre Savard committed
123
124

#ifdef HAVE_SPEEXDSP_LIB
125

126
127
128
129
130
131
132
            speex_preprocess_run (_preprocess_state, src);
#endif


            speex_encode_int (_speex_enc_state, src, &_speex_enc_bits);
            speex_bits_nbytes (&_speex_enc_bits);
            int nbBytes = speex_bits_write (&_speex_enc_bits, (char*) dst, size);
133

Alexandre Savard's avatar
Alexandre Savard committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
            return nbBytes;
        }

    private:
        const SpeexMode* _speexModePtr;
        SpeexBits  _speex_dec_bits;
        SpeexBits  _speex_enc_bits;
        void *_speex_dec_state;
        void *_speex_enc_state;
        int _speex_frame_size;
        SpeexPreprocessState *_preprocess_state;
};

// the class factories
148
149
150
extern "C" AudioCodec* create()
{
    return new Speex (112);
Alexandre Savard's avatar
Alexandre Savard committed
151
152
}

153
154
extern "C" void destroy (AudioCodec* a)
{
Alexandre Savard's avatar
Alexandre Savard committed
155
156
157
    delete a;
}