| /* $Id$ */ |
| /* |
| * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| * |
| * 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| #ifndef __PJMEDIA_STEREO_H__ |
| #define __PJMEDIA_STEREO_H__ |
| |
| /** |
| * @file stereo.h |
| * @brief Monochannel and multichannel converter. |
| */ |
| |
| #include <pjmedia/errno.h> |
| #include <pjmedia/port.h> |
| #include <pjmedia/types.h> |
| #include <pj/assert.h> |
| |
| |
| /** |
| * @defgroup PJMEDIA_STEREO Monochannel and multichannel audio frame converter |
| * @ingroup PJMEDIA_FRAME_OP |
| * @brief Mono - multi-channels audio conversion |
| * @{ |
| * |
| */ |
| |
| PJ_BEGIN_DECL |
| |
| |
| /** |
| * Multichannel to monochannel conversion mixes samples from all channels |
| * into the monochannel. |
| */ |
| #define PJMEDIA_STEREO_MIX PJ_TRUE |
| |
| |
| |
| /** |
| * Multichannel to monochannel conversion, it has two operation mode specified |
| * by param options, @see pjmedia_stereo_options. This function can work safely |
| * using the same buffer (in place conversion). |
| * |
| * @param mono Output buffer to store the mono frame extracted |
| * from the multichannels frame. |
| * @param multi Input frame containing multichannels audio. |
| * @param channel_count Number of channels in the input frame. |
| * @param samples_per_frame Number of samples in the input frame. |
| * @param mix If the value is PJ_TRUE then the input channels |
| * will be mixed to produce output frame, otherwise |
| * only frame from channel_src will be copied to the |
| * output frame. |
| * @param channel_src When mixing is disabled, the mono output frame |
| * will be copied from this channel number. |
| * |
| * @return PJ_SUCCESS on success; |
| */ |
| PJ_INLINE(pj_status_t) pjmedia_convert_channel_nto1(pj_int16_t mono[], |
| const pj_int16_t multi[], |
| unsigned channel_count, |
| unsigned samples_per_frame, |
| pj_bool_t mix, |
| unsigned channel_src) |
| { |
| unsigned i; |
| |
| PJ_ASSERT_RETURN(mono && multi && channel_count && samples_per_frame && |
| channel_src < channel_count, PJ_EINVAL); |
| |
| if (mix==PJ_FALSE) { |
| for (i = channel_src; i < samples_per_frame; i += channel_count) { |
| *mono = multi[i]; |
| ++mono; |
| } |
| } else { |
| unsigned j; |
| for (i = 0; i < samples_per_frame; i += channel_count) { |
| int tmp = 0; |
| for(j = 0; j < channel_count; ++j) |
| tmp += multi[i+j]; |
| |
| if (tmp > 32767) tmp = 32767; |
| else if (tmp < -32768) tmp = -32768; |
| *mono = (pj_int16_t) tmp; |
| ++mono; |
| } |
| } |
| |
| return PJ_SUCCESS; |
| } |
| |
| |
| /** |
| * Monochannel to multichannel conversion, it will just duplicate the samples |
| * from monochannel frame to all channels in the multichannel frame. |
| * This function can work safely using the same buffer (in place conversion) |
| * as long as the buffer is big enough for the multichannel samples. |
| * |
| * @param multi Output buffer to store the multichannels frame |
| * mixed from the mono frame. |
| * @param mono The input monochannel audio frame. |
| * @param channel_count Desired number of channels in the output frame. |
| * @param samples_per_frame Number of samples in the input frame. |
| * @param options Options for conversion, currently must be zero. |
| * |
| * @return PJ_SUCCESS on success; |
| */ |
| PJ_INLINE(pj_status_t) pjmedia_convert_channel_1ton(pj_int16_t multi[], |
| const pj_int16_t mono[], |
| unsigned channel_count, |
| unsigned samples_per_frame, |
| unsigned options) |
| { |
| const pj_int16_t *src; |
| |
| PJ_ASSERT_RETURN(mono && multi && channel_count && samples_per_frame, |
| PJ_EINVAL); |
| PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); |
| |
| PJ_UNUSED_ARG(options); |
| |
| src = mono + samples_per_frame - 1; |
| samples_per_frame *= channel_count; |
| while (samples_per_frame) { |
| unsigned i; |
| for (i=1; i<=channel_count; ++i) |
| multi[samples_per_frame-i] = *src; |
| samples_per_frame -= channel_count; |
| --src; |
| } |
| |
| return PJ_SUCCESS; |
| } |
| |
| |
| /** |
| * Options for channel converter port. The #pjmedia_stereo_options is also |
| * valid for this port options. |
| */ |
| typedef enum pjmedia_stereo_port_options |
| { |
| /** |
| * Specifies whether this port should not destroy downstream port when |
| * this port is destroyed. |
| */ |
| PJMEDIA_STEREO_DONT_DESTROY_DN = 4 |
| } pjmedia_stereo_port_options; |
| |
| |
| /** |
| * Create a mono-multi channel converter port. This creates a converter session, |
| * which will adjust the samples of audio frame to a different channel count |
| * when the port's get_frame() and put_frame() is called. |
| * |
| * When the port's get_frame() is called, this port will get a frame from |
| * the downstream port and convert the frame to the target channel count before |
| * returning it to the caller. |
| * |
| * When the port's put_frame() is called, this port will convert the frame |
| * to the downstream port's channel count before giving the frame to the |
| * downstream port. |
| * |
| * @param pool Pool to allocate the structure and buffers. |
| * @param dn_port The downstream port, which channel count is to |
| * be converted to the target channel count. |
| * @param channel_count This port channel count. |
| * @param options Bitmask flags from #pjmedia_stereo_port_options |
| * and also application may add PJMEDIA_STEREO_MIX |
| * to mix channels. |
| * When this flag is zero, the default behavior |
| * is to use simple N-to-1 channel converter and |
| * to destroy downstream port when this port is |
| * destroyed. |
| * @param p_port Pointer to receive the stereo port instance. |
| * |
| * @return PJ_SUCCESS on success. |
| */ |
| PJ_DECL(pj_status_t) pjmedia_stereo_port_create( pj_pool_t *pool, |
| pjmedia_port *dn_port, |
| unsigned channel_count, |
| unsigned options, |
| pjmedia_port **p_port ); |
| |
| PJ_END_DECL |
| |
| /** |
| * @} |
| */ |
| |
| |
| #endif /* __PJMEDIA_STEREO_H__ */ |
| |