/src/pjsip/pjmedia/include/pjmedia/stereo.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
3 | | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | | */ |
19 | | #ifndef __PJMEDIA_STEREO_H__ |
20 | | #define __PJMEDIA_STEREO_H__ |
21 | | |
22 | | /** |
23 | | * @file stereo.h |
24 | | * @brief Monochannel and multichannel converter. |
25 | | */ |
26 | | |
27 | | #include <pjmedia/errno.h> |
28 | | #include <pjmedia/port.h> |
29 | | #include <pjmedia/types.h> |
30 | | #include <pj/assert.h> |
31 | | |
32 | | |
33 | | /** |
34 | | * @defgroup PJMEDIA_STEREO Monochannel and multichannel audio frame converter |
35 | | * @ingroup PJMEDIA_FRAME_OP |
36 | | * @brief Mono - multi-channels audio conversion |
37 | | * @{ |
38 | | * |
39 | | */ |
40 | | |
41 | | PJ_BEGIN_DECL |
42 | | |
43 | | |
44 | | /** |
45 | | * Multichannel to monochannel conversion mixes samples from all channels |
46 | | * into the monochannel. |
47 | | */ |
48 | | #define PJMEDIA_STEREO_MIX PJ_TRUE |
49 | | |
50 | | |
51 | | |
52 | | /** |
53 | | * Multichannel to monochannel conversion. This function can work safely |
54 | | * using the same buffer (in place conversion). |
55 | | * |
56 | | * @param mono Output buffer to store the mono frame extracted |
57 | | * from the multichannels frame. |
58 | | * @param multi Input frame containing multichannels audio. |
59 | | * @param channel_count Number of channels in the input frame. |
60 | | * @param samples_per_frame Number of samples in the input frame. |
61 | | * @param mix If the value is PJ_TRUE then the input channels |
62 | | * will be mixed to produce output frame, otherwise |
63 | | * only frame from channel_src will be copied to the |
64 | | * output frame. |
65 | | * @param channel_src When mixing is disabled, the mono output frame |
66 | | * will be copied from this channel number. |
67 | | * |
68 | | * @return PJ_SUCCESS on success; |
69 | | */ |
70 | | PJ_INLINE(pj_status_t) pjmedia_convert_channel_nto1(pj_int16_t mono[], |
71 | | const pj_int16_t multi[], |
72 | | unsigned channel_count, |
73 | | unsigned samples_per_frame, |
74 | | pj_bool_t mix, |
75 | | unsigned channel_src) |
76 | 0 | { |
77 | 0 | unsigned i; |
78 | 0 |
|
79 | 0 | PJ_ASSERT_RETURN(mono && multi && channel_count && samples_per_frame && |
80 | 0 | channel_src < channel_count, PJ_EINVAL); |
81 | 0 |
|
82 | 0 | if (mix==PJ_FALSE) { |
83 | 0 | for (i = channel_src; i < samples_per_frame; i += channel_count) { |
84 | 0 | *mono = multi[i]; |
85 | 0 | ++mono; |
86 | 0 | } |
87 | 0 | } else { |
88 | 0 | unsigned j; |
89 | 0 | for (i = 0; i < samples_per_frame; i += channel_count) { |
90 | 0 | int tmp = 0; |
91 | 0 | for(j = 0; j < channel_count; ++j) |
92 | 0 | tmp += multi[i+j]; |
93 | 0 |
|
94 | 0 | if (tmp > 32767) tmp = 32767; |
95 | 0 | else if (tmp < -32768) tmp = -32768; |
96 | 0 | *mono = (pj_int16_t) tmp; |
97 | 0 | ++mono; |
98 | 0 | } |
99 | 0 | } |
100 | 0 |
|
101 | 0 | return PJ_SUCCESS; |
102 | 0 | } |
103 | | |
104 | | |
105 | | /** |
106 | | * Monochannel to multichannel conversion, it will just duplicate the samples |
107 | | * from monochannel frame to all channels in the multichannel frame. |
108 | | * This function can work safely using the same buffer (in place conversion) |
109 | | * as long as the buffer is big enough for the multichannel samples. |
110 | | * |
111 | | * @param multi Output buffer to store the multichannels frame |
112 | | * mixed from the mono frame. |
113 | | * @param mono The input monochannel audio frame. |
114 | | * @param channel_count Desired number of channels in the output frame. |
115 | | * @param samples_per_frame Number of samples in the input frame. |
116 | | * @param options Options for conversion, currently must be zero. |
117 | | * |
118 | | * @return PJ_SUCCESS on success; |
119 | | */ |
120 | | PJ_INLINE(pj_status_t) pjmedia_convert_channel_1ton(pj_int16_t multi[], |
121 | | const pj_int16_t mono[], |
122 | | unsigned channel_count, |
123 | | unsigned samples_per_frame, |
124 | | unsigned options) |
125 | 0 | { |
126 | 0 | const pj_int16_t *src; |
127 | 0 |
|
128 | 0 | PJ_ASSERT_RETURN(mono && multi && channel_count && samples_per_frame, |
129 | 0 | PJ_EINVAL); |
130 | 0 | PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); |
131 | 0 |
|
132 | 0 | PJ_UNUSED_ARG(options); |
133 | 0 |
|
134 | 0 | src = mono + samples_per_frame - 1; |
135 | 0 | samples_per_frame *= channel_count; |
136 | 0 | while (samples_per_frame) { |
137 | 0 | unsigned i; |
138 | 0 | for (i=1; i<=channel_count; ++i) |
139 | 0 | multi[samples_per_frame-i] = *src; |
140 | 0 | samples_per_frame -= channel_count; |
141 | 0 | --src; |
142 | 0 | } |
143 | 0 |
|
144 | 0 | return PJ_SUCCESS; |
145 | 0 | } |
146 | | |
147 | | |
148 | | /** |
149 | | * Options for channel converter port. |
150 | | */ |
151 | | typedef enum pjmedia_stereo_port_options |
152 | | { |
153 | | /** |
154 | | * Specifies whether this port should not destroy downstream port when |
155 | | * this port is destroyed. |
156 | | */ |
157 | | PJMEDIA_STEREO_DONT_DESTROY_DN = 4 |
158 | | } pjmedia_stereo_port_options; |
159 | | |
160 | | |
161 | | /** |
162 | | * Create a mono-multi channel converter port. This creates a converter session, |
163 | | * which will adjust the samples of audio frame to a different channel count |
164 | | * when the port's get_frame() and put_frame() is called. |
165 | | * |
166 | | * When the port's get_frame() is called, this port will get a frame from |
167 | | * the downstream port and convert the frame to the target channel count before |
168 | | * returning it to the caller. |
169 | | * |
170 | | * When the port's put_frame() is called, this port will convert the frame |
171 | | * to the downstream port's channel count before giving the frame to the |
172 | | * downstream port. |
173 | | * |
174 | | * @param pool Pool to allocate the structure and buffers. |
175 | | * @param dn_port The downstream port, which channel count is to |
176 | | * be converted to the target channel count. |
177 | | * @param channel_count This port channel count. |
178 | | * @param options Bitmask flags from #pjmedia_stereo_port_options |
179 | | * and also application may add PJMEDIA_STEREO_MIX |
180 | | * to mix channels. |
181 | | * When this flag is zero, the default behavior |
182 | | * is to use simple N-to-1 channel converter and |
183 | | * to destroy downstream port when this port is |
184 | | * destroyed. |
185 | | * @param p_port Pointer to receive the stereo port instance. |
186 | | * |
187 | | * @return PJ_SUCCESS on success. |
188 | | */ |
189 | | PJ_DECL(pj_status_t) pjmedia_stereo_port_create( pj_pool_t *pool, |
190 | | pjmedia_port *dn_port, |
191 | | unsigned channel_count, |
192 | | unsigned options, |
193 | | pjmedia_port **p_port ); |
194 | | |
195 | | PJ_END_DECL |
196 | | |
197 | | /** |
198 | | * @} |
199 | | */ |
200 | | |
201 | | |
202 | | #endif /* __PJMEDIA_STEREO_H__ */ |
203 | | |