Twitch SDK (Internal)
resampleoperator.h
Go to the documentation of this file.
1 /********************************************************************************************
2  * Twitch Broadcasting SDK
3  *
4  * This software is supplied under the terms of a license agreement with Twitch Interactive, Inc. and
5  * may not be copied or used except in accordance with the terms of that agreement
6  * Copyright (c) 2012-2017 Twitch Interactive, Inc.
7  *
8  *********************************************************************************************/
9 
10 #pragma once
11 
14 
15 #include <ratio>
16 
17 namespace ttv
18 {
33  template <typename InputSource, size_t OutputSampleRate, typename ContextType>
35  {
36  public:
37  ResampleOperator(ContextType& context)
38  : mInputSource(context)
39  {
40  mGainNormalization = 0.0;
41  for (size_t i = 0; i < TapCount; i++)
42  {
44  }
45  }
46 
47  using SampleType = typename InputSource::SampleType;
48  static_assert(std::is_signed<SampleType>::value, "Input sample type must be floating point.");
49 
50  static constexpr size_t InputSampleRate = InputSource::SampleRate;
51  static constexpr size_t SampleRate = OutputSampleRate;
52 
53  using FilterOptions = typename ContextType::FilterOptions;
54 
55  static constexpr size_t TapCount = FilterOptions::TapCount;
56  using OutputToInputRatio = std::ratio<OutputSampleRate, InputSampleRate>;
57 
58 
59  InputSource& GetInputSource()
60  {
61  return mInputSource;
62  }
63 
64  void Unbind()
65  {
66  SampleRange inputRange = mInputSource.GetSampleRange();
67 
68  // Make sure to populate the cache with the last samples before unbinding.
69  size_t inputIndex = inputRange.startIndex + inputRange.sampleCount - TapCount;
70  mSampleCache.Populate(inputIndex, [this](size_t index)
71  {
72  return mInputSource[index];
73  });
74  }
75 
76 
78  {
79  SampleRange sampleRange = ExtendSampleRange(mInputSource.GetSampleRange(), mSampleCache.GetRange());
80 
81  size_t inputIndex = sampleRange.startIndex;
82  size_t inputLength = sampleRange.sampleCount;
83  inputLength -= TapCount;
84 
85  size_t subdivisionIndex = inputIndex * OutputToInputRatio::num;
86 
87  size_t outputIndex = subdivisionIndex / OutputToInputRatio::den;
88  if (subdivisionIndex % OutputToInputRatio::den != 0)
89  {
90  outputIndex++;
91  }
92 
93  size_t lastInputIndex = inputIndex + inputLength;
94 
95  size_t lastSubdivisionIndex = lastInputIndex * OutputToInputRatio::num;
96  size_t lastOutputIndex = lastSubdivisionIndex / OutputToInputRatio::den;
97 
98  if ((OutputToInputRatio::den - (lastSubdivisionIndex % OutputToInputRatio::den) < OutputToInputRatio::num))
99  {
100  lastOutputIndex++;
101  }
102 
103  size_t outputLength = lastOutputIndex - outputIndex;
104 
105  return {outputIndex, outputLength};
106  }
107 
108 
109  SampleType operator[](size_t index) const
110  {
111  assert(index >= GetSampleRange().startIndex);
112  assert(index < GetSampleRange().startIndex + GetSampleRange().sampleCount);
113 
114  size_t outputSubdivisionIndex = index * OutputToInputRatio::den;
115 
116  size_t inputIndex = outputSubdivisionIndex / OutputToInputRatio::num;
117  size_t inputPhase = outputSubdivisionIndex % OutputToInputRatio::num;
118 
119  if (inputPhase != 0)
120  {
121  inputIndex++;
122  inputPhase = OutputToInputRatio::num - inputPhase;
123  }
124 
125  size_t coefficientIndex = TapCount * inputPhase;
126 
127  mSampleCache.Populate(inputIndex, [this](size_t index)
128  {
129  return mInputSource[index];
130  });
131 
132  double value = 0.0;
133 
134  for (size_t i = 0; i < TapCount; i++)
135  {
136  double coefficient = mCoefficients[coefficientIndex + i];
137  value += coefficient * mSampleCache[inputIndex + i];
138  };
139 
140 
141  // Unity gain normalization.
142  value /= mGainNormalization;
143 
144  return ClampAndCastSample<SampleType>(value);
145  }
146 
147  private:
148  InputSource mInputSource;
149 
151  {
152  static constexpr double Cutoff = FilterOptions::Cutoff * static_cast<double>(OutputToInputRatio::num) / static_cast<double>(OutputToInputRatio::den);
153  static constexpr double Range = static_cast<double>(TapCount);
154  };
155 
157 
158  using WindowFunction = typename FilterOptions::WindowFunction;
159 
161  static constexpr size_t CoefficientPhaseSubdivisions = OutputToInputRatio::num * TapCount;
162 
164 
166 
169  };
170 }
SampleRange ExtendSampleRange(SampleRange range, SampleRange extension)
Definition: dsputilities.h:106
SampleCache< double, TapCount > mSampleCache
Definition: resampleoperator.h:167
Definition: resampleoperator.h:34
double mGainNormalization
Definition: resampleoperator.h:168
static constexpr size_t CoefficientPhaseSubdivisions
Definition: resampleoperator.h:161
SampleRange GetSampleRange() const
Definition: resampleoperator.h:77
InputSource mInputSource
Definition: resampleoperator.h:148
Definition: dsputilities.h:202
static constexpr size_t InputSampleRate
Definition: resampleoperator.h:50
size_t sampleCount
Definition: dsputilities.h:80
static constexpr double Cutoff
Definition: resampleoperator.h:152
Definition: dsputilities.h:259
JSON (JavaScript Object Notation).
Definition: adsapi.h:16
#define assert(expr)
Definition: assertion.h:47
void Unbind()
Definition: resampleoperator.h:64
Definition: dsputilities.h:60
Definition: dsputilities.h:240
typename ContextType::FilterOptions FilterOptions
Definition: resampleoperator.h:53
static constexpr double Range
Definition: resampleoperator.h:153
InputSource & GetInputSource()
Definition: resampleoperator.h:59
size_t startIndex
Definition: dsputilities.h:75
Definition: dsputilities.h:280
LookupTable< CycledCoefficientFunction, CoefficientPhaseSubdivisions > mCoefficients
Definition: resampleoperator.h:165
ResampleOperator(ContextType &context)
Definition: resampleoperator.h:37
static constexpr size_t SampleRate
Definition: resampleoperator.h:51
typename InputSource::SampleType SampleType
Definition: resampleoperator.h:47
void Populate(size_t startIndex, PopulatorType &&populator)
Definition: samplecache.h:71
static constexpr size_t TapCount
Definition: resampleoperator.h:55
Definition: resampleoperator.h:150
SampleRange GetRange() const
Definition: samplecache.h:54
typename FilterOptions::WindowFunction WindowFunction
Definition: resampleoperator.h:158
SampleType operator[](size_t index) const
Definition: resampleoperator.h:109
std::ratio< OutputSampleRate, InputSampleRate > OutputToInputRatio
Definition: resampleoperator.h:56