Jamba C++ API  4.1.0
AudioBuffer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 pongasoft
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  *
16  * @author Yan Pujante
17  */
18 #pragma once
19 
20 #include <pluginterfaces/vst/ivstaudioprocessor.h>
21 #include <pongasoft/logging/logging.h>
22 #include <algorithm>
23 
24 #include "AudioUtils.h"
25 
26 namespace pongasoft {
27 namespace VST {
28 
29 using namespace Steinberg;
30 using namespace Steinberg::Vst;
31 
32 // defines the default setup channels (0 is left, 1 is right)
33 constexpr int32 DEFAULT_LEFT_CHANNEL = 0;
34 constexpr int32 DEFAULT_RIGHT_CHANNEL = 1;
35 
41 template<typename SampleType>
43 {
44 public:
49  {
50  void operator()(SampleType iSample)
51  {
52  fAbsoluteMax = std::max(fAbsoluteMax, iSample < 0 ? -iSample : iSample);
53  }
54 
55  SampleType fAbsoluteMax = 0;
56  };
57 
65  class Channel
66  {
67  public:
68  Channel(AudioBuffers &iBuffers, int32 iChannel) : fBuffers{iBuffers}, fChannel{iChannel}
69  {
70  }
71 
75  inline int32 getNumSamples() const
76  {
77  return fBuffers.getNumSamples();
78  }
79 
91  inline SampleType *getBuffer()
92  {
93  return fChannel < fBuffers.getNumChannels() ? fBuffers.getBuffer()[fChannel] : nullptr;
94  }
95 
107  inline SampleType const *getBuffer() const
108  {
109  return fChannel < fBuffers.getNumChannels() ? fBuffers.getBuffer()[fChannel] : nullptr;
110  }
111 
115  inline bool isSilent() const { return fBuffers.isSilent(fChannel); }
116 
120  inline void setSilenceFlag(bool iSilent)
121  {
122  fBuffers.setSilenceFlag(fChannel, iSilent);
123  }
124 
128  inline bool isActive() const
129  {
130  return fChannel < fBuffers.getNumChannels() && getBuffer() != nullptr;
131  }
132 
136  inline tresult copyTo(Channel &toChannel) const { return toChannel.copyFrom(*this); };
137 
141  tresult copyFrom(Channel const &fromChannel)
142  {
143  int32 numSamples = std::min(getNumSamples(), fromChannel.getNumSamples());
144 
145  auto ptrFrom = fromChannel.getBuffer();
146  auto ptrTo = getBuffer();
147 
148  // sanity check
149  if(!ptrFrom || !ptrTo)
150  return kResultFalse;
151 
152  std::copy(ptrFrom, ptrFrom + numSamples, ptrTo);
153 
154  return kResultOk;
155  }
156 
160  inline SampleType absoluteMax() const
161  {
162  return forEachSample(AbsoluteMaxOp()).fAbsoluteMax;
163  }
164 
167  inline void clear()
168  {
169  auto buffer = getBuffer();
170 
171  // sanity check
172  if(!buffer)
173  return;
174 
175  std::fill(buffer, buffer + getNumSamples(), 0);
176 
177  setSilenceFlag(true);
178  }
179 
192  template<typename UnaryFunction>
193  inline UnaryFunction forEachSample(UnaryFunction f)
194  {
195  auto buffer = getBuffer();
196 
197  if(buffer)
198  {
199  return std::for_each(buffer, buffer + getNumSamples(), f);
200  }
201  else
202  return f;
203  }
204 
217  template<typename UnaryFunction>
218  inline UnaryFunction forEachSample(UnaryFunction f) const
219  {
220  auto buffer = getBuffer();
221 
222  if(buffer)
223  {
224  return std::for_each(buffer, buffer + getNumSamples(), f);
225  }
226  else
227  return f;
228  }
229 
250  template<typename UnaryOperation>
251  inline UnaryOperation copyFrom(Channel const &iFromChannel, UnaryOperation f)
252  {
253  auto outputBuffer = getBuffer();
254  auto inputBuffer = iFromChannel.getBuffer();
255 
256  if(outputBuffer && inputBuffer)
257  {
258  int32 const numSamples = std::min(getNumSamples(), iFromChannel.getNumSamples());
259 
260  // implementation note: adding 'UnaryOperation &' as the template type forces f to be passed
261  // by reference otherwise it would be copied which would loose the state (ex: for functors).
262  std::transform<decltype(inputBuffer), decltype(outputBuffer), UnaryOperation &>(inputBuffer, inputBuffer + numSamples, outputBuffer, f);
263  }
264 
265  return f;
266  }
267 
271  template<typename UnaryOperation>
272  inline UnaryOperation copyTo(Channel &oToChannel, UnaryOperation f) const
273  {
274  return oToChannel.copyFrom(*this, f);
275  }
276 
277  private:
279  int32 fChannel;
280  };
281 
283 
284 
285 public:
286  AudioBuffers(AudioBusBuffers &buffer, int32 numSamples) : fBuffer(buffer), fNumSamples(numSamples)
287  {}
288 
289  // returns true if the buffer is silent (meaning all channels are silent => set to 1) (according to silenceFlags)
290  inline bool isSilent() const
291  {
292  return fBuffer.numChannels == 0 || fBuffer.silenceFlags == (static_cast<uint64>(1) << fBuffer.numChannels) - 1;
293  }
294 
299  inline bool adjustSilenceFlags()
300  {
301  uint64 silenceFlags = 0;
302 
303  auto buffer = getBuffer();
304 
305  for(int32 channel = 0; channel < getNumChannels(); channel++)
306  {
307  bool silent = true;
308 
309  auto ptr = buffer[channel];
310 
311  if(!ptr)
312  continue;
313 
314  for(int j = 0; j < getNumSamples(); ++j, ptr++)
315  {
316  auto sample = *ptr;
317 
318  if(silent && !pongasoft::VST::isSilent(sample))
319  silent = false;
320  }
321 
322  if(silent)
323  BIT_SET(silenceFlags, channel);
324  }
325 
326  fBuffer.silenceFlags = silenceFlags;
327 
328  return isSilent();
329  }
330 
331  // getSilenceFlags
332  inline uint64 getSilenceFlags() const { return fBuffer.silenceFlags; }
333 
334  // setSilenceFlags
335  inline void setSilenceFlags(uint64 iFlags) const { fBuffer.silenceFlags = iFlags; }
336 
340  inline void setSilenceFlag(int32 iChannel, bool iSilent)
341  {
342  if(iChannel < getNumChannels())
343  {
344  if(iSilent)
345  BIT_SET(fBuffer.silenceFlags, iChannel);
346  else
347  BIT_CLEAR(fBuffer.silenceFlags, iChannel);
348  }
349  }
350 
354  inline bool isSilent(int32 iChannel) const
355  {
356  if(iChannel < getNumChannels())
357  {
358  return BIT_TEST(fBuffer.silenceFlags, iChannel);
359  }
360  return true;
361  }
362 
369  inline Channel getAudioChannel(int32 iChannel)
370  {
371  return Channel{*this, iChannel};
372  }
373 
380  inline const Channel getAudioChannel(int32 iChannel) const
381  {
382  // implementation note: removing const since Channel accepts only non const
383  return Channel{*const_cast<class_type *>(this), iChannel};
384  }
385 
389  inline Channel getLeftChannel() { return getAudioChannel(DEFAULT_LEFT_CHANNEL); }
390 
394  inline const Channel getLeftChannel() const { return getAudioChannel(DEFAULT_LEFT_CHANNEL); }
395 
399  inline Channel getRightChannel() { return getAudioChannel(DEFAULT_RIGHT_CHANNEL); }
400 
404  inline const Channel getRightChannel() const { return getAudioChannel(DEFAULT_RIGHT_CHANNEL); }
405 
406  // returns the underlying buffer
407  inline SampleType **getBuffer();
408 
409  // returns the underlying buffer
410  inline SampleType const * const *getBuffer() const;
411 
415  inline int32 getNumChannels() const { return fBuffer.numChannels; }
416 
420  inline int32 getNumSamples() const { return fNumSamples; }
421 
434  template<typename UnaryFunction>
435  inline UnaryFunction forEachSample(UnaryFunction f)
436  {
437  for(int32 channel = 0; channel < getNumChannels(); channel++)
438  {
439  f = getAudioChannel(channel).forEachSample(f);
440  }
441 
442  return f;
443  }
444 
457  template<typename UnaryFunction>
458  inline UnaryFunction forEachSample(UnaryFunction f) const
459  {
460  for(int32 channel = 0; channel < getNumChannels(); channel++)
461  {
462  f = getAudioChannel(channel).forEachSample(f);
463  }
464 
465  return f;
466  }
467 
471  inline tresult copyTo(class_type &toBuffer) const { return toBuffer.copyFrom(*this); };
472 
476  tresult copyFrom(class_type const &fromBuffer)
477  {
478  auto fromSamples = fromBuffer.getBuffer();
479  auto toSamples = getBuffer();
480 
481  // there are cases when the 2 buffers could be identical.. no need to copy
482  if(fromSamples == toSamples)
483  return kResultOk;
484 
485  // sanity check
486  if(!fromSamples || !toSamples)
487  return kResultFalse;
488 
489  int32 numChannels = std::min(getNumChannels(), fromBuffer.getNumChannels());
490  int32 numSamples = std::min(getNumSamples(), fromBuffer.getNumSamples());
491 
492  for(int32 channel = 0; channel < numChannels; channel++)
493  {
494  auto ptrFrom = fromSamples[channel];
495  auto ptrTo = toSamples[channel];
496 
497  // sanity check
498  if(!ptrFrom || !ptrTo)
499  continue;
500 
501  std::copy(ptrFrom, ptrFrom + numSamples, ptrTo);
502  }
503 
504  return kResultOk;
505  }
506 
525  template<typename UnaryOperation>
526  inline UnaryOperation copyFrom(class_type const &iFromBuffer, UnaryOperation f)
527  {
528  int32 numChannels = std::min(getNumChannels(), iFromBuffer.getNumChannels());
529 
530  for(int32 channel = 0; channel < numChannels; channel++)
531  {
532  f = getAudioChannel(channel).copyFrom(iFromBuffer.getAudioChannel(channel), f);
533  }
534 
535  return f;
536  }
537 
541  template<typename UnaryOperation>
542  inline UnaryOperation copyTo(class_type &iToBuffer, UnaryOperation f) const { return iToBuffer.copyFrom(*this, f); };
543 
547  inline SampleType absoluteMax() const
548  {
549  return forEachSample(AbsoluteMaxOp()).fAbsoluteMax;
550  }
551 
554  inline tresult clear()
555  {
556  for(int32 channel = 0; channel < getNumChannels(); channel++)
557  {
558  getAudioChannel(channel).clear();
559  }
560 
561  return kResultOk;
562  }
563 
564 private:
565  AudioBusBuffers &fBuffer;
566  const int32 fNumSamples;
567 };
568 
569 template<>
570 inline Sample32 const * const *AudioBuffers<Sample32>::getBuffer() const { return fBuffer.channelBuffers32; }
571 
572 template<>
573 inline Sample64 const * const *AudioBuffers<Sample64>::getBuffer() const { return fBuffer.channelBuffers64; }
574 
575 template<>
576 inline Sample32 **AudioBuffers<Sample32>::getBuffer() { return fBuffer.channelBuffers32; }
577 
578 template<>
579 inline Sample64 **AudioBuffers<Sample64>::getBuffer() { return fBuffer.channelBuffers64; }
580 
583 
584 }
585 }
Represents all the buffers (example for a stereo channel there is 2 underlying sample buffers)
Definition: AudioBuffer.h:42
UnaryOperation copyFrom(class_type const &iFromBuffer, UnaryOperation f)
Copy iFromBuffer to this buffer, applying f to each sample for each channel or in other words,...
Definition: AudioBuffer.h:526
AudioBusBuffers & fBuffer
Definition: AudioBuffer.h:565
Unary operator adapter for computing the absolute max.
Definition: AudioBuffer.h:48
Channel getRightChannel()
Definition: AudioBuffer.h:399
constexpr int32 DEFAULT_RIGHT_CHANNEL
Definition: AudioBuffer.h:34
AudioBuffers< Sample32 > AudioBuffers32
Definition: AudioBuffer.h:581
UnaryOperation copyTo(class_type &iToBuffer, UnaryOperation f) const
Same as copyFrom with the roles reversed.
Definition: AudioBuffer.h:542
Represents a single channel (for example left audio channel).
Definition: AudioBuffer.h:65
AudioBuffers< SampleType > class_type
Definition: AudioBuffer.h:282
const Channel getAudioChannel(int32 iChannel) const
Return the audio channel for the provided channel.
Definition: AudioBuffer.h:380
void setSilenceFlag(int32 iChannel, bool iSilent)
Sets a single channel silence flag.
Definition: AudioBuffer.h:340
Definition: Clock.h:22
const int32 fNumSamples
Definition: AudioBuffer.h:566
SampleType const * getBuffer() const
Note that this pointer is NOT guaranteed to be not null as demonstrated by this piece of logic in the...
Definition: AudioBuffer.h:107
tresult clear()
Clears the buffer (and sets the silence flag)
Definition: AudioBuffer.h:554
AudioBuffers(AudioBusBuffers &buffer, int32 numSamples)
Definition: AudioBuffer.h:286
SampleType absoluteMax() const
Definition: AudioBuffer.h:547
const Channel getLeftChannel() const
Definition: AudioBuffer.h:394
int32 getNumSamples() const
Definition: AudioBuffer.h:75
Channel getLeftChannel()
Definition: AudioBuffer.h:389
UnaryOperation copyTo(Channel &oToChannel, UnaryOperation f) const
Same as copyFrom with the roles reversed.
Definition: AudioBuffer.h:272
UnaryFunction forEachSample(UnaryFunction f) const
Applies the provided unary function to each sample (if the channel is active).
Definition: AudioBuffer.h:218
bool isActive() const
Definition: AudioBuffer.h:128
int32 getNumChannels() const
Definition: AudioBuffer.h:415
AudioBuffers & fBuffers
Definition: AudioBuffer.h:278
void operator()(SampleType iSample)
Definition: AudioBuffer.h:50
bool isSilent() const
Definition: AudioBuffer.h:115
bool adjustSilenceFlags()
Computes and adjust the silence flags.
Definition: AudioBuffer.h:299
AudioBuffers< Sample64 > AudioBuffers64
Definition: AudioBuffer.h:582
void setSilenceFlags(uint64 iFlags) const
Definition: AudioBuffer.h:335
UnaryFunction forEachSample(UnaryFunction f) const
Applies the provided unary function to each sample of each channel.
Definition: AudioBuffer.h:458
#define BIT_CLEAR(a, b)
Definition: AudioUtils.h:31
bool isSilent(int32 iChannel) const
Definition: AudioBuffer.h:354
UnaryOperation copyFrom(Channel const &iFromChannel, UnaryOperation f)
Copy iFromChannel to this channel, applying f to each sample or in other words, for each sample.
Definition: AudioBuffer.h:251
UnaryFunction forEachSample(UnaryFunction f)
Applies the provided unary function to each sample of each channel.
Definition: AudioBuffer.h:435
constexpr int32 DEFAULT_LEFT_CHANNEL
Definition: AudioBuffer.h:33
Channel getAudioChannel(int32 iChannel)
Return the audio channel for the provided channel.
Definition: AudioBuffer.h:369
bool isSilent(Sample32 value)
Definition: AudioUtils.h:49
Channel(AudioBuffers &iBuffers, int32 iChannel)
Definition: AudioBuffer.h:68
int32 fChannel
Definition: AudioBuffer.h:279
#define BIT_TEST(a, b)
Definition: AudioUtils.h:32
bool isSilent() const
Definition: AudioBuffer.h:290
SampleType absoluteMax() const
Definition: AudioBuffer.h:160
tresult copyTo(class_type &toBuffer) const
Copy the content of THIS buffer to the provided buffer (up to num samples)
Definition: AudioBuffer.h:471
tresult copyTo(Channel &toChannel) const
Copy the content of THIS channel to the provided channel (up to num samples)
Definition: AudioBuffer.h:136
SampleType * getBuffer()
Note that this pointer is NOT guaranteed to be not null as demonstrated by this piece of logic in the...
Definition: AudioBuffer.h:91
int32 getNumSamples() const
Definition: AudioBuffer.h:420
uint64 getSilenceFlags() const
Definition: AudioBuffer.h:332
#define BIT_SET(a, b)
Definition: AudioUtils.h:30
tresult copyFrom(class_type const &fromBuffer)
Copy the content of the provided buffer to THIS buffer (up to num samples)
Definition: AudioBuffer.h:476
const Channel getRightChannel() const
Definition: AudioBuffer.h:404
void setSilenceFlag(bool iSilent)
Sets a single channel silence flag.
Definition: AudioBuffer.h:120
tresult copyFrom(Channel const &fromChannel)
Copy the content of the provided channel to THIS channel (up to num samples)
Definition: AudioBuffer.h:141
void clear()
Clears the channel (and sets the silence flag)
Definition: AudioBuffer.h:167
UnaryFunction forEachSample(UnaryFunction f)
Applies the provided unary function to each sample (if the channel is active).
Definition: AudioBuffer.h:193