• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..29-Jun-2021-

HyperbolicCosineWindow.hH A D29-Jun-20211.9 KiB6930

IntegerRatio.cppH A D29-Jun-20211.6 KiB5127

IntegerRatio.hH A D29-Jun-20211.2 KiB5321

KaiserWindow.hH A D29-Jun-20212.4 KiB8848

LinearResampler.cppH A D29-Jun-20211.5 KiB4321

LinearResampler.hH A D29-Jun-20211.2 KiB4518

MultiChannelResampler.cppH A D29-Jun-20216.2 KiB172130

MultiChannelResampler.hH A D29-Jun-20217.5 KiB272131

PolyphaseResampler.cppH A D29-Jun-20212.3 KiB6332

PolyphaseResampler.hH A D29-Jun-20211.4 KiB5218

PolyphaseResamplerMono.cppH A D29-Jun-20212.1 KiB6432

PolyphaseResamplerMono.hH A D29-Jun-20211.1 KiB4015

PolyphaseResamplerStereo.cppH A D29-Jun-20212.6 KiB8045

PolyphaseResamplerStereo.hH A D29-Jun-20211.1 KiB4015

README.mdH A D29-Jun-20214 KiB10268

SincResampler.cppH A D29-Jun-20212.9 KiB7849

SincResampler.hH A D29-Jun-20211.3 KiB4819

SincResamplerStereo.cppH A D29-Jun-20212.9 KiB8250

SincResamplerStereo.hH A D29-Jun-20211.1 KiB4015

README.md

1# Sample Rate Converter
2
3This folder contains a sample rate converter, or "resampler".
4
5The converter is based on a sinc function that has been windowed by a hyperbolic cosine.
6We found this had fewer artifacts than the more traditional Kaiser window.
7
8## Building the Resampler
9
10It is part of [Oboe](https://github.com/google/oboe) but has no dependencies on Oboe.
11So the contents of this folder can be used outside of Oboe.
12
13To build it for use outside of Oboe:
14
151. Copy the "resampler" folder to a folder in your project that is in the include path.
162. Add all of the \*.cpp files in the resampler folder to your project IDE or Makefile.
17
18## Creating a Resampler
19
20Include the [main header](MultiChannelResampler.h) for the resampler.
21
22    #include "resampler/MultiChannelResampler.h"
23
24Here is an example of creating a stereo resampler that will convert from 44100 to 48000 Hz.
25Only do this once, when you open your stream. Then use the sample resampler to process multiple buffers.
26
27    MultiChannelResampler *resampler = MultiChannelResampler::make(
28            2, // channel count
29            44100, // input sampleRate
30            48000, // output sampleRate
31            MultiChannelResampler::Quality::Medium); // conversion quality
32
33Possible values for quality include { Fastest, Low, Medium, High, Best }.
34Higher quality levels will sound better but consume more CPU because they have more taps in the filter.
35
36## Fractional Frame Counts
37
38Note that the number of output frames generated for a given number of input frames can vary.
39
40For example, suppose you are converting from 44100 Hz to 48000 Hz and using an input buffer with 960 frames. If you calculate the number of output frames you get:
41
42    960 * 48000 * 44100 = 1044.897959...
43
44You cannot generate a fractional number of frames. So the resampler will sometimes generate 1044 frames and sometimes 1045 frames. On average it will generate 1044.897959 frames. The resampler stores the fraction internally and keeps track of when to consume or generate a frame.
45
46You can either use a fixed number of input frames or a fixed number of output frames. The other frame count will vary.
47
48## Calling the Resampler with a fixed number of OUTPUT frames
49
50In this example, suppose we have a fixed number of output frames and a variable number of input frames.
51
52Assume you start with these variables and a method that returns the next input frame:
53
54    float *outputBuffer;     // multi-channel buffer to be filled
55    int    numOutputFrames;  // number of frames of output
56
57The resampler has a method isWriteNeeded() that tells you whether to write to or read from the resampler.
58
59    int outputFramesLeft = numOutputFrames;
60    while (outputFramesLeft > 0) {
61        if(resampler->isWriteNeeded()) {
62            const float *frame = getNextInputFrame(); // you provide this
63            resampler->writeNextFrame(frame);
64        } else {
65            resampler->readNextFrame(outputBuffer);
66            outputBuffer += channelCount;
67            outputFramesLeft--;
68        }
69    }
70
71## Calling the Resampler with a fixed number of INPUT frames
72
73In this example, suppose we have a fixed number of input frames and a variable number of output frames.
74
75Assume you start with these variables:
76
77    float *inputBuffer;     // multi-channel buffer to be consumed
78    float *outputBuffer;    // multi-channel buffer to be filled
79    int    numInputFrames;  // number of frames of input
80    int    numOutputFrames = 0;
81    int    channelCount;    // 1 for mono, 2 for stereo
82
83    int inputFramesLeft = numInputFrames;
84    while (inputFramesLeft > 0) {
85        if(resampler->isWriteNeeded()) {
86            resampler->writeNextFrame(inputBuffer);
87            inputBuffer += channelCount;
88            inputFramesLeft--;
89        } else {
90            resampler->readNextFrame(outputBuffer);
91            outputBuffer += channelCount;
92            numOutputFrames++;
93        }
94    }
95
96## Deleting the Resampler
97
98When you are done, you should delete the Resampler to avoid a memory leak.
99
100    delete resampler;
101
102