Jamba C++ API  6.3.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 
355  inline void clearSilentFlag()
356  {
357  fBuffer.silenceFlags = 0;
358  }
359 
363  inline bool isSilent(int32 iChannel) const
364  {
365  if(iChannel < getNumChannels())
366  {
367  return BIT_TEST(fBuffer.silenceFlags, iChannel);
368  }
369  return true;
370  }
371 
378  inline Channel getAudioChannel(int32 iChannel)
379  {
380  return Channel{*this, iChannel};
381  }
382 
389  inline const Channel getAudioChannel(int32 iChannel) const
390  {
391  // implementation note: removing const since Channel accepts only non const
392  return Channel{*const_cast<class_type *>(this), iChannel};
393  }
394 
398  inline Channel getLeftChannel() { return getAudioChannel(DEFAULT_LEFT_CHANNEL); }
399 
403  inline const Channel getLeftChannel() const { return getAudioChannel(DEFAULT_LEFT_CHANNEL); }
404 
408  inline Channel getRightChannel() { return getAudioChannel(DEFAULT_RIGHT_CHANNEL); }
409 
413  inline const Channel getRightChannel() const { return getAudioChannel(DEFAULT_RIGHT_CHANNEL); }
414 
416  inline SampleType **getBuffer();
417 
418  // returns the underlying (sample) buffer (const version)
419  inline SampleType const * const *getBuffer() const;
420 
422  inline AudioBusBuffers &getAudioBusBuffers() { return fBuffer; }
423 
425  inline AudioBusBuffers const &getAudioBusBuffers() const { return fBuffer; }
426 
430  inline int32 getNumChannels() const { return fBuffer.numChannels; }
431 
435  inline int32 getNumSamples() const { return fNumSamples; }
436 
449  template<typename UnaryFunction>
450  inline UnaryFunction forEachSample(UnaryFunction f)
451  {
452  for(int32 channel = 0; channel < getNumChannels(); channel++)
453  {
454  f = getAudioChannel(channel).forEachSample(f);
455  }
456 
457  return f;
458  }
459 
472  template<typename UnaryFunction>
473  inline UnaryFunction forEachSample(UnaryFunction f) const
474  {
475  for(int32 channel = 0; channel < getNumChannels(); channel++)
476  {
477  f = getAudioChannel(channel).forEachSample(f);
478  }
479 
480  return f;
481  }
482 
486  inline tresult copyTo(class_type &toBuffer) const { return toBuffer.copyFrom(*this); };
487 
491  tresult copyFrom(class_type const &fromBuffer)
492  {
493  auto fromSamples = fromBuffer.getBuffer();
494  auto toSamples = getBuffer();
495 
496  // there are cases when the 2 buffers could be identical.. no need to copy
497  if(fromSamples == toSamples)
498  return kResultOk;
499 
500  // sanity check
501  if(!fromSamples || !toSamples)
502  return kResultFalse;
503 
504  int32 numChannels = std::min(getNumChannels(), fromBuffer.getNumChannels());
505  int32 numSamples = std::min(getNumSamples(), fromBuffer.getNumSamples());
506 
507  for(int32 channel = 0; channel < numChannels; channel++)
508  {
509  auto ptrFrom = fromSamples[channel];
510  auto ptrTo = toSamples[channel];
511 
512  // sanity check
513  if(!ptrFrom || !ptrTo)
514  continue;
515 
516  std::copy(ptrFrom, ptrFrom + numSamples, ptrTo);
517  }
518 
519  return kResultOk;
520  }
521 
540  template<typename UnaryOperation>
541  inline UnaryOperation copyFrom(class_type const &iFromBuffer, UnaryOperation f)
542  {
543  int32 numChannels = std::min(getNumChannels(), iFromBuffer.getNumChannels());
544 
545  for(int32 channel = 0; channel < numChannels; channel++)
546  {
547  f = getAudioChannel(channel).copyFrom(iFromBuffer.getAudioChannel(channel), f);
548  }
549 
550  return f;
551  }
552 
556  template<typename UnaryOperation>
557  inline UnaryOperation copyTo(class_type &iToBuffer, UnaryOperation f) const { return iToBuffer.copyFrom(*this, f); };
558 
562  inline SampleType absoluteMax() const
563  {
564  return forEachSample(AbsoluteMaxOp()).fAbsoluteMax;
565  }
566 
569  inline tresult clear()
570  {
571  for(int32 channel = 0; channel < getNumChannels(); channel++)
572  {
573  getAudioChannel(channel).clear();
574  }
575 
576  return kResultOk;
577  }
578 
579 private:
580  AudioBusBuffers &fBuffer;
581  const int32 fNumSamples;
582 };
583 
584 template<>
585 inline Sample32 const * const *AudioBuffers<Sample32>::getBuffer() const { return fBuffer.channelBuffers32; }
586 
587 template<>
588 inline Sample64 const * const *AudioBuffers<Sample64>::getBuffer() const { return fBuffer.channelBuffers64; }
589 
590 template<>
591 inline Sample32 **AudioBuffers<Sample32>::getBuffer() { return fBuffer.channelBuffers32; }
592 
593 template<>
594 inline Sample64 **AudioBuffers<Sample64>::getBuffer() { return fBuffer.channelBuffers64; }
595 
598 
599 }
600 }
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:541
AudioBusBuffers & fBuffer
Definition: AudioBuffer.h:580
Unary operator adapter for computing the absolute max.
Definition: AudioBuffer.h:48
Channel getRightChannel()
Definition: AudioBuffer.h:408
constexpr int32 DEFAULT_RIGHT_CHANNEL
Definition: AudioBuffer.h:34
AudioBuffers< Sample32 > AudioBuffers32
Definition: AudioBuffer.h:596
UnaryOperation copyTo(class_type &iToBuffer, UnaryOperation f) const
Same as copyFrom with the roles reversed.
Definition: AudioBuffer.h:557
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:389
void setSilenceFlag(int32 iChannel, bool iSilent)
Sets a single channel silence flag.
Definition: AudioBuffer.h:340
Definition: Clock.h:22
AudioBusBuffers & getAudioBusBuffers()
Returns the AudioBusBuffers original buffer.
Definition: AudioBuffer.h:422
const int32 fNumSamples
Definition: AudioBuffer.h:581
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:569
AudioBuffers(AudioBusBuffers &buffer, int32 numSamples)
Definition: AudioBuffer.h:286
SampleType absoluteMax() const
Definition: AudioBuffer.h:562
const Channel getLeftChannel() const
Definition: AudioBuffer.h:403
int32 getNumSamples() const
Definition: AudioBuffer.h:75
Channel getLeftChannel()
Definition: AudioBuffer.h:398
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
void clearSilentFlag()
Makes the buffer NON silent (by setting the flag to 0).
Definition: AudioBuffer.h:355
bool isActive() const
Definition: AudioBuffer.h:128
int32 getNumChannels() const
Definition: AudioBuffer.h:430
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:597
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:473
#define BIT_CLEAR(a, b)
Definition: AudioUtils.h:32
bool isSilent(int32 iChannel) const
Definition: AudioBuffer.h:363
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:450
constexpr int32 DEFAULT_LEFT_CHANNEL
Definition: AudioBuffer.h:33
Channel getAudioChannel(int32 iChannel)
Return the audio channel for the provided channel.
Definition: AudioBuffer.h:378
bool isSilent(Sample32 value)
Definition: AudioUtils.h:62
Channel(AudioBuffers &iBuffers, int32 iChannel)
Definition: AudioBuffer.h:68
int32 fChannel
Definition: AudioBuffer.h:279
#define BIT_TEST(a, b)
Definition: AudioUtils.h:33
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:486
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:435
uint64 getSilenceFlags() const
Definition: AudioBuffer.h:332
#define BIT_SET(a, b)
Definition: AudioUtils.h:31
tresult copyFrom(class_type const &fromBuffer)
Copy the content of the provided buffer to THIS buffer (up to num samples)
Definition: AudioBuffer.h:491
AudioBusBuffers const & getAudioBusBuffers() const
Returns the AudioBusBuffers original buffer (const version)
Definition: AudioBuffer.h:425
const Channel getRightChannel() const
Definition: AudioBuffer.h:413
void setSilenceFlag(bool iSilent)
Sets a single channel silence flag.
Definition: AudioBuffer.h:120
SampleType ** getBuffer()
Returns the underlying (sample) buffer.
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