samplerateconverter.cpp 3.61 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
4
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
5
 *
6 7 8 9 10 11 12 13
 *  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.
14
 *
15 16 17
 *  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.
18 19 20 21 22 23 24 25 26 27 28
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
29 30 31
 */

#include "samplerateconverter.h"
32
#include "manager.h"
33
#include <cassert>
34
#include "logger.h"
35

36 37
SamplerateConverter::SamplerateConverter(int freq) : floatBufferIn_(0),
    floatBufferOut_(0), samples_(0), maxFreq_(freq), src_state_(0)
Julien Bonjean's avatar
Julien Bonjean committed
38
{
Rafaël Carré's avatar
Rafaël Carré committed
39
    int err;
40
    src_state_ = src_new(SRC_LINEAR, 1, &err);
41

42
    samples_ = (freq * 20) / 1000; // start with 20 ms buffers
43

44 45
    floatBufferIn_ = new float[samples_];
    floatBufferOut_ = new float[samples_];
46 47
}

48
SamplerateConverter::~SamplerateConverter()
Rafaël Carré's avatar
Rafaël Carré committed
49
{
50 51
    delete [] floatBufferIn_;
    delete [] floatBufferOut_;
Rafaël Carré's avatar
Rafaël Carré committed
52

53
    src_delete(src_state_);
Rafaël Carré's avatar
Rafaël Carré committed
54 55
}

Emmanuel Milou's avatar
Emmanuel Milou committed
56
void
57
SamplerateConverter::Short2FloatArray(const short *in, float *out, int len)
Julien Bonjean's avatar
Julien Bonjean committed
58
{
Emmanuel Milou's avatar
Emmanuel Milou committed
59 60
    // factor is 1/(2^15), used to rescale the short int range to the
    // [-1.0 - 1.0] float range.
61

Rafaël Carré's avatar
Rafaël Carré committed
62 63
    while (len--)
        out[len] = (float) in[len] * .000030517578125f;
64 65
}

66
void SamplerateConverter::resample(SFLDataFormat *dataIn,
67 68 69
                                   SFLDataFormat *dataOut,
                                   size_t dataOutSize, int inputFreq,
                                   int outputFreq, size_t nbSamples)
Julien Bonjean's avatar
Julien Bonjean committed
70
{
71
    double sampleFactor = (double) outputFreq / inputFreq;
72

73
    if (sampleFactor == 1.0)
74
        return;
Rafaël Carré's avatar
Rafaël Carré committed
75

76
    size_t outSamples = nbSamples * sampleFactor;
77
    const unsigned int maxSamples = std::max(outSamples, nbSamples);
78

79
    if (maxSamples > samples_) {
80
        /* grow buffer if needed */
81 82 83 84 85
        samples_ = maxSamples;
        delete [] floatBufferIn_;
        delete [] floatBufferOut_;
        floatBufferIn_ = new float[samples_];
        floatBufferOut_ = new float[samples_];
86 87
    }

88
    SRC_DATA src_data;
89 90
    src_data.data_in = floatBufferIn_;
    src_data.data_out = floatBufferOut_;
91 92 93 94
    src_data.input_frames = nbSamples;
    src_data.output_frames = outSamples;
    src_data.src_ratio = sampleFactor;
    src_data.end_of_input = 0; // More data will come
Rafaël Carré's avatar
Rafaël Carré committed
95

96
    Short2FloatArray(dataIn, floatBufferIn_, nbSamples);
97
    src_process(src_state_, &src_data);
Rafaël Carré's avatar
Rafaël Carré committed
98

99 100 101 102 103
    if (outSamples > dataOutSize) {
        ERROR("Outsamples exceeds output buffer size, clamping to %u", dataOutSize);
        outSamples = dataOutSize;
    }
    src_float_to_short_array(floatBufferOut_, dataOut, outSamples);
104
}