1
/* $Id: resample_libsamplerate.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pjmedia/resample.h>
21
#include <pjmedia/errno.h>
22
#include <pj/assert.h>
27
* HOW TO ACTIVATE LIBSAMPLERATE (a.k.a SRC/Secret Rabbit Code) AS
28
* PJMEDIA'S SAMPLE RATE CONVERSION BACKEND
30
* See README.txt in third_party/samplerate directory.
34
#if PJMEDIA_RESAMPLE_IMP==PJMEDIA_RESAMPLE_LIBSAMPLERATE
36
#include "../../third_party/libsamplerate/src/samplerate.h"
38
#define THIS_FILE "resample_libsamplerate.c"
42
# pragma comment( lib, "../../third_party/lib/libsamplerate-i386-win32-vc-debug.lib")
44
# pragma comment( lib, "../../third_party/lib/libsamplerate-i386-win32-vc-release.lib")
49
struct pjmedia_resample
54
float *frame_in, *frame_out;
55
unsigned in_extra, out_extra;
60
PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool,
61
pj_bool_t high_quality,
62
pj_bool_t large_filter,
63
unsigned channel_count,
66
unsigned samples_per_frame,
67
pjmedia_resample **p_resample)
69
pjmedia_resample *resample;
72
PJ_ASSERT_RETURN(pool && p_resample && rate_in &&
73
rate_out && samples_per_frame, PJ_EINVAL);
75
resample = PJ_POOL_ZALLOC_T(pool, pjmedia_resample);
76
PJ_ASSERT_RETURN(resample, PJ_ENOMEM);
78
/* Select conversion type */
80
type = large_filter ? SRC_SINC_BEST_QUALITY : SRC_SINC_MEDIUM_QUALITY;
82
type = large_filter ? SRC_SINC_FASTEST : SRC_LINEAR;
85
/* Create converter */
86
resample->state = src_new(type, channel_count, &err);
87
if (resample->state == NULL) {
88
PJ_LOG(4,(THIS_FILE, "Error creating resample: %s",
94
resample->ratio = rate_out * 1.0 / rate_in;
96
/* Calculate number of samples for input and output */
97
resample->in_samples = samples_per_frame;
98
resample->out_samples = rate_out / (rate_in / samples_per_frame);
100
resample->frame_in = (float*)
102
resample->in_samples + 8,
105
resample->frame_out = (float*)
107
resample->out_samples + 8,
110
/* Set the converter ratio */
111
err = src_set_ratio(resample->state, resample->ratio);
113
PJ_LOG(4,(THIS_FILE, "Error creating resample: %s",
115
return PJMEDIA_ERROR;
121
"Resample using libsamplerate %s, type=%s (%s), "
122
"ch=%d, in/out rate=%d/%d",
124
src_get_name(type), src_get_description(type),
125
channel_count, rate_in, rate_out));
127
*p_resample = resample;
133
PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample,
134
const pj_int16_t *input,
139
/* Convert samples to float */
140
src_short_to_float_array(input, resample->frame_in,
141
resample->in_samples);
143
if (resample->in_extra) {
146
for (i=0; i<resample->in_extra; ++i)
147
resample->frame_in[resample->in_samples+i] =
148
resample->frame_in[resample->in_samples-1];
151
/* Prepare SRC_DATA */
152
pj_bzero(&src_data, sizeof(src_data));
153
src_data.data_in = resample->frame_in;
154
src_data.data_out = resample->frame_out;
155
src_data.input_frames = resample->in_samples + resample->in_extra;
156
src_data.output_frames = resample->out_samples + resample->out_extra;
157
src_data.src_ratio = resample->ratio;
160
src_process(resample->state, &src_data);
162
/* Convert output back to short */
163
src_float_to_short_array(resample->frame_out, output,
164
src_data.output_frames_gen);
166
/* Replay last sample if conversion couldn't fill up the whole
167
* frame. This could happen for example with 22050 to 16000 conversion.
169
if (src_data.output_frames_gen < (int)resample->out_samples) {
172
if (resample->in_extra < 4)
173
resample->in_extra++;
175
for (i=src_data.output_frames_gen;
176
i<resample->out_samples; ++i)
178
output[i] = output[src_data.output_frames_gen-1];
184
PJ_DEF(unsigned) pjmedia_resample_get_input_size(pjmedia_resample *resample)
186
PJ_ASSERT_RETURN(resample != NULL, 0);
187
return resample->in_samples;
191
PJ_DEF(void) pjmedia_resample_destroy(pjmedia_resample *resample)
193
PJ_ASSERT_ON_FAIL(resample, return);
194
if (resample->state) {
195
src_delete(resample->state);
196
resample->state = NULL;
198
PJ_LOG(5,(THIS_FILE, "Resample destroyed"));
202
#else /* PJMEDIA_RESAMPLE_IMP==PJMEDIA_RESAMPLE_LIBSAMPLERATE */
204
int pjmedia_libsamplerate_excluded;
206
#endif /* PJMEDIA_RESAMPLE_IMP==PJMEDIA_RESAMPLE_LIBSAMPLERATE */