kwave  18.07.70
RateConverter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  RateConverter.cpp - single channel sample rate converter
3  -------------------
4  begin : Sat Jul 11 2009
5  copyright : (C) 2009 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <math.h>
21 
22 #include "libkwave/Utils.h"
24 
25 //***************************************************************************
27  :Kwave::SampleSource(), m_ratio(1.0), m_converter(Q_NULLPTR),
28  m_converter_in(), m_converter_out()
29 {
30  int error = 0;
31  m_converter = src_new(SRC_SINC_MEDIUM_QUALITY, 1, &error);
32  Q_ASSERT(m_converter);
33  if (!m_converter) qWarning("creating converter failed: '%s",
34  src_strerror(error));
35 }
36 
37 //***************************************************************************
39 {
40  if (m_converter) src_delete(m_converter);
41 }
42 
43 //***************************************************************************
45 {
46 }
47 
48 //***************************************************************************
50 {
51  // shortcut for ratio == 1:1
52  if ((m_ratio == 1.0) || data.isEmpty()) {
53  emit output(data);
54  return;
55  }
56 
57  // normal processing
58  Kwave::SampleArray samples_out;
59  const unsigned int in_len = data.size();
60 
61  // convert the input buffer into an array of floats
62  m_converter_in.resize(in_len);
63  float *f_in = m_converter_in.data();
64  const sample_t *s_in = data.constData();
65  Q_ASSERT(f_in);
66  Q_ASSERT(s_in);
67 
68  // work blockwise to allow loop unrolling
69  unsigned int remaining = in_len;
70  const unsigned int block_size = 16;
71  while (remaining >= block_size) {
72  for (unsigned int i = 0; i < block_size; i++)
73  f_in[i] = sample2float(s_in[i]);
74  f_in += block_size;
75  s_in += block_size;
76  remaining -= block_size;
77  }
78  for (; remaining; remaining--)
79  (*f_in++) = sample2float(*(s_in++));
80 
81  // prepare the output buffer (estimated size, rounded up)
82  // worst case would be factor 2, which means that there was a 100%
83  // leftover remaining from the previous pass
84  // just for safety we limit the extra output space to some
85  // (hopefully) reasonable range between 4096 and 16384
86  const unsigned int out_len = Kwave::toUint(
87  ceil(static_cast<double>(in_len) * m_ratio)
88  );
89  const unsigned int extra = qBound<unsigned int>(4096, out_len, 16384);
90  m_converter_out.resize(out_len + extra);
91 
92  // set up the sample rate converter input
93  SRC_DATA src;
94  src.data_in = m_converter_in.data();
95  src.data_out = m_converter_out.data();
96  src.input_frames = in_len;
97  src.output_frames = out_len + extra;
98  src.input_frames_used = 0;
99  src.output_frames_gen = 0;
100  src.end_of_input = (in_len == 0) ? 1 : 0;
101  src.src_ratio = m_ratio;
102 
103  // let the converter run...
104  int error = src_process(m_converter, &src);
105  if (error) qWarning("SRC error: '%s'", src_strerror(error));
106  Q_ASSERT(!error);
107 
108  // convert the result back from floats to sample_t
109  unsigned int gen = Kwave::toUint(src.output_frames_gen);
110  Kwave::SampleArray out(gen);
111  const float *f_out = src.data_out;
112  sample_t *s_out = out.data();
113 
114  // work blockwise to allow loop unrolling
115  remaining = gen;
116  while (remaining >= block_size) {
117  for (unsigned int i = 0; i < block_size; ++i)
118  s_out[i] = float2sample(f_out[i]);
119  s_out += block_size;
120  f_out += block_size;
121  remaining -= block_size;
122  }
123  for (; remaining; remaining--, ++s_out, ++f_out)
124  *s_out = float2sample(*f_out);
125 
126  emit output(out);
127 }
128 
129 //***************************************************************************
130 void Kwave::RateConverter::setRatio(const QVariant ratio)
131 {
132  m_ratio = QVariant(ratio).toDouble();
133 }
134 
135 //***************************************************************************
136 //***************************************************************************
Definition: App.h:33
void setRatio(const QVariant r)
SRC_STATE * m_converter
Definition: RateConverter.h:71
QVarLengthArray< float, 65536 > m_converter_out
Definition: RateConverter.h:77
QVarLengthArray< float, 65536 > m_converter_in
Definition: RateConverter.h:74
void output(Kwave::SampleArray data)
bool isEmpty() const
Definition: SampleArray.h:118
static float sample2float(const sample_t s)
Definition: Sample.h:65
void input(Kwave::SampleArray data)
const sample_t * constData() const
Definition: SampleArray.h:54
unsigned int size() const
virtual void goOn() Q_DECL_OVERRIDE
unsigned int toUint(T x)
Definition: Utils.h:109
sample_t * data()
Definition: SampleArray.h:62
static sample_t float2sample(const float f)
Definition: Sample.h:57
virtual ~RateConverter() Q_DECL_OVERRIDE
qint32 sample_t
Definition: Sample.h:37