Twitch SDK (Internal)
audioconvertpipeline.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 
24 
25 #include <tuple>
26 
27 namespace ttv
28 {
39  template <typename InputBufferFormat, typename OutputBufferFormat, typename ContextType>
41  {
42  public:
43  static_assert((InputBufferFormat::ChannelCount == OutputBufferFormat::ChannelCount) || (InputBufferFormat::ChannelCount == 1), "Multiple input channels not matching multiple output channels.");
44  static constexpr size_t InputChannelCount = InputBufferFormat::ChannelCount;
45  static constexpr size_t OutputChannelCount = OutputBufferFormat::ChannelCount;
46 
47  using InputSampleType = typename InputBufferFormat::SampleType;
48  using OutputSampleType = typename OutputBufferFormat::SampleType;
49 
50  AudioConvertPipeline(ContextType& context)
51  : mOperatorChains(MakeOperatorTuple<OperatorChainTuple>(context))
52  {}
53 
54  void BindInputBuffer(const InputSampleType* buffer, SampleRange range)
55  {
56  BindOperatorChains<>(buffer, range);
57  }
58 
60  {
61  return std::get<0>(mOperatorChains).GetSampleRange();
62  }
63 
65  {
66  SampleRange rangeToIterate = IntersectSampleRanges(range, std::get<0>(mOperatorChains).GetSampleRange());
67 
68  size_t bufferIndex = (rangeToIterate.startIndex - range.startIndex) * OutputChannelCount;
69  for (size_t index = rangeToIterate.startIndex; index < rangeToIterate.startIndex + rangeToIterate.sampleCount; index++)
70  {
71  TransferSamples<>(buffer + bufferIndex, index);
72  bufferIndex += OutputChannelCount;
73  }
74  return rangeToIterate;
75  }
76 
78  {
79  UnbindOperatorChains<>();
80  }
81 
82  private:
84 
86 
87  template <size_t Index = 0>
88  std::enable_if_t<Index < std::tuple_size<OperatorChainTuple>::value> BindOperatorChains(const InputSampleType* buffer, SampleRange range)
89  {
90  using OperatorChainToBind = std::tuple_element_t<Index, OperatorChainTuple>;
91  RecursiveBinder<OperatorChainToBind>::RecurseAndBind(std::get<Index>(mOperatorChains), buffer, range);
92 
93  BindOperatorChains<Index + 1>(buffer, range);
94  }
95 
96  template <size_t Index = 0>
97  std::enable_if_t<Index >= std::tuple_size<OperatorChainTuple>::value> BindOperatorChains(const InputSampleType* buffer, SampleRange range)
98  {
99  }
100 
101  template <typename Operator, typename Enable = void>
102  struct Binder
103  {
104  static void BindOperator(Operator& op, const InputSampleType* buffer, SampleRange range)
105  {
106  }
107  };
108 
109  template <typename Operator>
110  struct Binder<Operator, VoidType<decltype(std::declval<Operator>().Bind(nullptr, {}))>>
111  {
112  static void BindOperator(Operator& op, const InputSampleType* buffer, SampleRange range)
113  {
114  op.Bind(buffer, range);
115  }
116  };
117 
118  template <typename Operator, typename Enable = void>
120  {
121  static void RecurseAndBind(Operator& op, const InputSampleType* buffer, SampleRange range)
122  {
123  Binder<Operator>::BindOperator(op, buffer, range);
124  }
125  };
126 
127 
128  template <typename Operator>
129  struct RecursiveBinder<Operator, VoidType<decltype(std::declval<Operator>().GetInputSource())>>
130  {
131  static void RecurseAndBind(Operator& op, const InputSampleType* buffer, SampleRange range)
132  {
133  Binder<Operator>::BindOperator(op, buffer, range);
134 
135  using InputSourceType = std::remove_reference_t<decltype(op.GetInputSource())>;
136  RecursiveBinder<InputSourceType>::RecurseAndBind(op.GetInputSource(), buffer, range);
137  }
138  };
139 
140 
141  template <size_t Index = 0>
142  std::enable_if_t<(Index < std::tuple_size<OperatorChainTuple>::value) && (std::tuple_size<OperatorChainTuple>::value == 1)> TransferSamples(OutputSampleType* buffer, size_t inputIndex)
143  {
144  // If we have a mono input, just duplicate it across all output channels.
145  OutputSampleType value = std::get<0>(mOperatorChains)[inputIndex];
146  for (size_t i = 0; i < OutputChannelCount; i++)
147  {
148  buffer[i] = value;
149  }
150  }
151 
152  template <size_t Index = 0>
153  std::enable_if_t<(Index < std::tuple_size<OperatorChainTuple>::value) && (std::tuple_size<OperatorChainTuple>::value > 1)> TransferSamples(OutputSampleType* buffer, size_t inputIndex)
154  {
155  buffer[Index] = std::get<Index>(mOperatorChains)[inputIndex];
156  TransferSamples<Index + 1>(buffer, inputIndex);
157  }
158 
159 
160  template <size_t Index = 0>
161  std::enable_if_t<Index >= std::tuple_size<OperatorChainTuple>::value> TransferSamples(OutputSampleType* buffer, size_t inputIndex)
162  {
163  }
164 
165  template <size_t Index = 0>
166  std::enable_if_t<Index < std::tuple_size<OperatorChainTuple>::value> UnbindOperatorChains()
167  {
168  using OperatorChainToUnbind = std::tuple_element_t<Index, OperatorChainTuple>;
169  RecursiveUnbinder<OperatorChainToUnbind>::RecurseAndUnbind(std::get<Index>(mOperatorChains));
170 
171  UnbindOperatorChains<Index + 1>();
172  }
173 
174 
175  template <size_t Index = 0>
176  std::enable_if_t<Index >= std::tuple_size<OperatorChainTuple>::value> UnbindOperatorChains()
177  {
178  }
179 
180  template <typename Operator, typename Enable = void>
181  struct Unbinder
182  {
183  static void UnbindOperator(Operator& op)
184  {
185  }
186  };
187 
188  template <typename Operator>
189  struct Unbinder<Operator, std::enable_if_t<std::is_void<decltype(std::declval<Operator>().Unbind())>::value>>
190  {
191  static void UnbindOperator(Operator& op)
192  {
193  op.Unbind();
194  }
195  };
196 
197  template <typename Operator, typename Enable = void>
199  {
200  static void RecurseAndUnbind(Operator& op)
201  {
202  Unbinder<Operator>::UnbindOperator(op);
203  }
204  };
205 
206  template <typename Operator>
207  struct RecursiveUnbinder<Operator, VoidType<decltype(std::declval<Operator>().GetInputSource())>>
208  {
209  static void RecurseAndUnbind(Operator& op)
210  {
211  Unbinder<Operator>::UnbindOperator(op);
212 
213  using InputSourceType = std::remove_reference_t<decltype(op.GetInputSource())>;
215  }
216  };
217  };
218 
219 
220  template <typename InputBufferFormat, typename OutputBufferFormat, typename ContextType>
221  auto MakeAudioConvertPipeline(ContextType& context)
222  {
224  }
225 }
typename OperatorChainTupleBuilder< ContextType, InputBufferFormat, OutputBufferFormat, InputBufferFormat::ChannelCount >::Type BuildOperatorChainTuple
Definition: operatorchainbuilder.h:263
SampleRange GetOutputSampleRange() const
Definition: audioconvertpipeline.h:59
Definition: audioconvertpipeline.h:119
BuildOperatorChainTuple< AudioConvertContext< AudioConvertOptions >, InputBufferFormat, OutputBufferFormat > OperatorChainTuple
Definition: audioconvertpipeline.h:83
AudioConvertPipeline(ContextType &context)
Definition: audioconvertpipeline.h:50
Definition: cpp11transition.h:22
static constexpr size_t OutputChannelCount
Definition: audioconvertpipeline.h:45
static void BindOperator(Operator &op, const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:112
size_t sampleCount
Definition: dsputilities.h:80
Definition: audioconvertpipeline.h:198
std::enable_if_t<(Index< std::tuple_size< OperatorChainTuple >::value) &&(std::tuple_size< OperatorChainTuple >::value > 1)> TransferSamples(OutputSampleType *buffer, size_t inputIndex)
Definition: audioconvertpipeline.h:153
JSON (JavaScript Object Notation).
Definition: adsapi.h:16
OperatorChainTuple mOperatorChains
Definition: audioconvertpipeline.h:85
typename InputBufferFormat::SampleType InputSampleType
Definition: audioconvertpipeline.h:47
typename OutputBufferFormat::SampleType OutputSampleType
Definition: audioconvertpipeline.h:48
Definition: dsputilities.h:60
static constexpr size_t InputChannelCount
Definition: audioconvertpipeline.h:44
static void RecurseAndBind(Operator &op, const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:121
void BindInputBuffer(const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:54
size_t startIndex
Definition: dsputilities.h:75
auto MakeAudioConvertPipeline(ContextType &context)
Definition: audioconvertpipeline.h:221
static void RecurseAndUnbind(Operator &op)
Definition: audioconvertpipeline.h:200
SampleRange IntersectSampleRanges(SampleRange firstRange, SampleRange secondRange)
Definition: dsputilities.h:87
std::enable_if_t<(Index< std::tuple_size< OperatorChainTuple >::value) &&(std::tuple_size< OperatorChainTuple >::value==1)> TransferSamples(OutputSampleType *buffer, size_t inputIndex)
Definition: audioconvertpipeline.h:142
static void BindOperator(Operator &op, const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:104
std::enable_if_t< Index< std::tuple_size< OperatorChainTuple >::value > BindOperatorChains(const InputSampleType *buffer, SampleRange range) { using OperatorChainToBind=std::tuple_element_t< Index, OperatorChainTuple >;RecursiveBinder< OperatorChainToBind >::RecurseAndBind(std::get< Index >mOperatorChains), buffer, range);BindOperatorChains< Index+1 >buffer, range);} template< size_t Index=0 > std::enable_if_t< Index >=std::tuple_size< OperatorChainTuple >::value > BindOperatorChains(const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:97
Definition: audioconvertpipeline.h:40
typename MakeVoid< Arg >::Type VoidType
Definition: coreutilities.h:175
Definition: audioconvertpipeline.h:102
SampleRange TransferToOutputBuffer(OutputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:64
void UnbindInputBuffer()
Definition: audioconvertpipeline.h:77
static void RecurseAndBind(Operator &op, const InputSampleType *buffer, SampleRange range)
Definition: audioconvertpipeline.h:131