HephAudio v3.0.6
A cross-platform C++ library for recording, playing, and processing audio on Windows, Android, Linux, iOS, and macOS.
Loading...
Searching...
No Matches
BufferOperators.h
Go to the documentation of this file.
1#pragma once
2#include "HephShared.h"
3#include "BufferBase.h"
4#include "HephTypeTraits.h"
5#include "Event.h"
7
10namespace Heph
11{
12#pragma region Event
17 template<typename Lhs, typename Rhs>
19 {
20 const Lhs& lhs;
21 const Rhs& rhs;
22 Lhs& result;
23 BufferOperatorResultCreatedEventArgs(const Lhs& lhs, const Rhs& rhs, Lhs& result) : lhs(lhs), rhs(rhs), result(result) {}
24 };
25
26 template<typename Lhs, typename Rhs>
28 {
33 static inline Event OnResultCreated = Event();
34 };
35#pragma endregion
36#pragma region Addition
41 template<class Lhs, typename LhsData, typename Rhs = LhsData, typename RhsData = Rhs>
43 {
44 static constexpr bool DEFINE_RHS_LHS_OPERATOR = !has_addition_operator<Rhs, Lhs, Lhs>::value && !has_addition_operator<Rhs, Lhs, Rhs>::value;
45
46 public:
48 {
49 static_assert(std::is_default_constructible<Lhs>::value, "Lhs must have a default constructor");
50 static_assert(std::is_base_of<BufferBase<Lhs, LhsData>, Lhs>::value, "Lhs must derive from BufferBase<Lhs, LhsData>");
51 static_assert(
52 std::is_base_of<BufferBase<Rhs, RhsData>, Rhs>::value || std::is_same<Rhs, RhsData>::value,
53 "Rhs must derive from BufferBase<Rhs, RhsData> or RhsData must be the same type as Rhs"
54 );
55 static_assert(
56 has_addition_operator<LhsData, RhsData>::value && has_addition_assignment_operator<LhsData, RhsData>::value,
57 "LhsData must have operator+(RhsData) and operator+=(RhsData)"
58 );
59 }
61 BufferAdditionOperator& operator=(const BufferAdditionOperator&) = delete;
62
63 public:
64 friend inline Lhs operator+(const Lhs& lhs, const Rhs& rhs)
65 {
66 return Impl<Rhs, RhsData>(lhs, rhs);
67 }
68
69 friend inline Lhs& operator+=(Lhs& lhs, const Rhs& rhs)
70 {
71 return ImplAssign<Rhs, RhsData>(lhs, rhs);
72 }
73
74 template<typename Ret = Lhs>
75 friend inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR, Ret>::type operator+(const Rhs& rhs, const Lhs& lhs)
76 {
77 return lhs + rhs;
78 }
79
80 template<typename Ret>
81 friend inline typename std::enable_if<!DEFINE_RHS_LHS_OPERATOR, Ret>::type operator+(const Rhs& rhs, const Lhs& lhs);
82
83 private:
84 template<typename U = Rhs, typename V = RhsData>
85 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
86 {
87 Lhs result{};
90 {
91 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
92 }
94
95 const size_t size = lhs.Size();
96 for (size_t i = 0; i < size; ++i)
97 {
98 result.begin()[i] = lhs.begin()[i] + rhs;
99 }
100 return result;
101 }
102
103 template<typename U = Rhs, typename V = RhsData>
104 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
105 {
106 const size_t size = lhs.Size();
107 for (size_t i = 0; i < size; ++i)
108 {
109 lhs.begin()[i] += rhs;
110 }
111 return lhs;
112 }
113
114 template<typename U = Rhs, typename V = RhsData>
115 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
116 {
117 if (lhs.Size() != rhs.Size())
118 {
119 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
120 }
121
122 Lhs result{};
125 {
127 "BufferOperatorEvents::OnResultCreated event must be handled"));
128 }
130
131 const size_t size = lhs.Size();
132 for (size_t i = 0; i < size; ++i)
133 {
134 result.begin()[i] = lhs.begin()[i] + rhs.begin()[i];
135 }
136 return result;
137 }
138
139 template<typename U = Rhs, typename V = RhsData>
140 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
141 {
142 const size_t minSize = HEPH_MATH_MIN(lhs.Size(), rhs.Size());
143 for (size_t i = 0; i < minSize; ++i)
144 {
145 lhs.begin()[i] += rhs.begin()[i];
146 }
147 return lhs;
148 }
149 };
150#pragma endregion
151#pragma region Subtraction
156 template<class Lhs, typename LhsData, typename Rhs = LhsData, typename RhsData = Rhs>
158 {
159 static constexpr bool DEFINE_RHS_LHS_OPERATOR = !has_subtraction_operator<Rhs, Lhs, Lhs>::value && !has_subtraction_operator<Rhs, Lhs, Rhs>::value;
160
161 public:
163 {
164 static_assert(std::is_default_constructible<Lhs>::value, "Lhs must have a default constructor");
165 static_assert(std::is_base_of<BufferBase<Lhs, LhsData>, Lhs>::value, "Lhs must derive from BufferBase<Lhs, LhsData>");
166 static_assert(
167 std::is_base_of<BufferBase<Rhs, RhsData>, Rhs>::value || std::is_same<Rhs, RhsData>::value,
168 "Rhs must derive from BufferBase<Rhs, RhsData> or RhsData must be the same type as Rhs"
169 );
170 static_assert(
171 has_subtraction_operator<LhsData, RhsData>::value && has_subtraction_assignment_operator<LhsData, RhsData>::value,
172 "LhsData must have operator-(RhsData) and operator-=(RhsData)"
173 );
174 }
176 BufferSubtractionOperator& operator=(const BufferSubtractionOperator&) = delete;
177
178 public:
179 friend inline Lhs operator-(const Lhs& lhs, const Rhs& rhs)
180 {
181 return Impl<Rhs, RhsData>(lhs, rhs);
182 }
183
184 friend inline Lhs& operator-=(Lhs& lhs, const Rhs& rhs)
185 {
186 return ImplAssign<Rhs, RhsData>(lhs, rhs);
187 }
188
189 template<typename Ret = Lhs>
190 friend inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR, Ret>::type operator-(const Rhs& rhs, const Lhs& lhs)
191 {
192 return ImplRhs<Rhs, RhsData>(rhs, lhs);
193 }
194
195 template<typename Ret>
196 friend inline typename std::enable_if<!DEFINE_RHS_LHS_OPERATOR, Ret>::type operator-(const Rhs& rhs, const Lhs& lhs);
197
198 private:
199 template<typename U = Rhs, typename V = RhsData>
200 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
201 {
202 Lhs result{};
205 {
206 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
207 }
209
210 const size_t size = lhs.Size();
211 for (size_t i = 0; i < size; ++i)
212 {
213 result.begin()[i] = lhs.begin()[i] - rhs;
214 }
215 return result;
216 }
217
218 template<typename U = Rhs, typename V = RhsData>
219 static inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR&& std::is_same<U, V>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs)
220 {
221 Lhs result{};
224 {
225 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
226 }
228
229 const size_t size = lhs.Size();
230 for (size_t i = 0; i < size; ++i)
231 {
232 result.begin()[i] = rhs - lhs.begin()[i];
233 }
234 return result;
235 }
236
237 template<typename U = Rhs, typename V = RhsData>
238 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
239 {
240 const size_t size = lhs.Size();
241 for (size_t i = 0; i < size; ++i)
242 {
243 lhs.begin()[i] -= rhs;
244 }
245 return lhs;
246 }
247
248 template<typename U = Rhs, typename V = RhsData>
249 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
250 {
251 if (lhs.Size() != rhs.Size())
252 {
253 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
254 }
255
256 Lhs result{};
259 {
261 "BufferOperatorEvents::OnResultCreated event must be handled"));
262 }
264
265 const size_t size = lhs.Size();
266 for (size_t i = 0; i < size; ++i)
267 {
268 result.begin()[i] = lhs.begin()[i] - rhs.begin()[i];
269 }
270 return result;
271 }
272
273 template<typename U = Rhs, typename V = RhsData>
274 static inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR&& std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs)
275 {
276 if (lhs.Size() != rhs.Size())
277 {
278 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
279 }
280
281 Lhs result{};
284 {
286 "BufferOperatorEvents::OnResultCreated event must be handled"));
287 }
289
290 const size_t size = lhs.Size();
291 for (size_t i = 0; i < size; ++i)
292 {
293 result.begin()[i] = rhs.begin()[i] - lhs.begin()[i];
294 }
295 return result;
296 }
297
298 template<typename U = Rhs, typename V = RhsData>
299 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
300 {
301 const size_t minSize = HEPH_MATH_MIN(lhs.Size(), rhs.Size());
302 for (size_t i = 0; i < minSize; ++i)
303 {
304 lhs.begin()[i] -= rhs.begin()[i];
305 }
306 return lhs;
307 }
308 };
309#pragma endregion
310#pragma region Multiplication
315 template<class Lhs, typename LhsData, typename Rhs = LhsData, typename RhsData = Rhs>
317 {
318 static constexpr bool DEFINE_RHS_LHS_OPERATOR = !has_multiplication_operator<Rhs, Lhs, Lhs>::value && !has_multiplication_operator<Rhs, Lhs, Rhs>::value;
319
320 public:
322 {
323 static_assert(std::is_default_constructible<Lhs>::value, "Lhs must have a default constructor");
324 static_assert(std::is_base_of<BufferBase<Lhs, LhsData>, Lhs>::value, "Lhs must derive from BufferBase<Lhs, LhsData>");
325 static_assert(
326 std::is_base_of<BufferBase<Rhs, RhsData>, Rhs>::value || std::is_same<Rhs, RhsData>::value,
327 "Rhs must derive from BufferBase<Rhs, RhsData> or RhsData must be the same type as Rhs"
328 );
329 static_assert(
330 has_multiplication_operator<LhsData, RhsData>::value && has_multiplication_operator<LhsData, RhsData>::value,
331 "LhsData must have operator*(RhsData) and operator*=(RhsData)"
332 );
333 }
336
337 public:
338 friend inline Lhs operator*(const Lhs& lhs, const Rhs& rhs)
339 {
340 return Impl<Rhs, RhsData>(lhs, rhs);
341 }
342
343 friend inline Lhs& operator*=(Lhs& lhs, const Rhs& rhs)
344 {
345 return ImplAssign<Rhs, RhsData>(lhs, rhs);
346 }
347
348 template<typename Ret = Lhs>
349 friend inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR, Ret>::type operator*(const Rhs& rhs, const Lhs& lhs)
350 {
351 return lhs * rhs;
352 }
353
354 template<typename Ret>
355 friend inline typename std::enable_if<!DEFINE_RHS_LHS_OPERATOR, Ret>::type operator*(const Rhs& rhs, const Lhs& lhs);
356
357 private:
358 template<typename U = Rhs, typename V = RhsData>
359 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
360 {
361 Lhs result{};
364 {
365 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
366 }
368
369 const size_t size = lhs.Size();
370 for (size_t i = 0; i < size; ++i)
371 {
372 result.begin()[i] = lhs.begin()[i] * rhs;
373 }
374 return result;
375 }
376
377 template<typename U = Rhs, typename V = RhsData>
378 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
379 {
380 const size_t size = lhs.Size();
381 for (size_t i = 0; i < size; ++i)
382 {
383 lhs.begin()[i] *= rhs;
384 }
385 return lhs;
386 }
387
388 template<typename U = Rhs, typename V = RhsData>
389 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
390 {
391 if (lhs.Size() != rhs.Size())
392 {
393 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
394 }
395
396 Lhs result{};
399 {
401 "BufferOperatorEvents::OnResultCreated event must be handled"));
402 }
404
405 const size_t size = lhs.Size();
406 for (size_t i = 0; i < size; ++i)
407 {
408 result.begin()[i] = lhs.begin()[i] * rhs.begin()[i];
409 }
410 return result;
411 }
412
413 template<typename U = Rhs, typename V = RhsData>
414 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
415 {
416 const size_t minSize = HEPH_MATH_MIN(lhs.Size(), rhs.Size());
417 for (size_t i = 0; i < minSize; ++i)
418 {
419 lhs.begin()[i] *= rhs.begin()[i];
420 }
421 return lhs;
422 }
423 };
424#pragma endregion
425#pragma region Division
430 template<class Lhs, typename LhsData, typename Rhs = LhsData, typename RhsData = Rhs>
432 {
433 static constexpr bool DEFINE_RHS_LHS_OPERATOR = !has_division_operator<Rhs, Lhs, Lhs>::value && !has_division_operator<Rhs, Lhs, Rhs>::value;
434
435 public:
437 {
438 static_assert(std::is_default_constructible<Lhs>::value, "Lhs must have a default constructor");
439 static_assert(std::is_base_of<BufferBase<Lhs, LhsData>, Lhs>::value, "Lhs must derive from BufferBase<Lhs, LhsData>");
440 static_assert(
441 std::is_base_of<BufferBase<Rhs, RhsData>, Rhs>::value || std::is_same<Rhs, RhsData>::value,
442 "Rhs must derive from BufferBase<Rhs, RhsData> or RhsData must be the same type as Rhs"
443 );
444 static_assert(
445 has_division_operator<LhsData, RhsData>::value && has_division_assignment_operator<LhsData, RhsData>::value,
446 "LhsData must have operator/(RhsData) and operator/=(RhsData)"
447 );
448 }
450 BufferDivisionOperator& operator=(const BufferDivisionOperator&) = delete;
451
452 public:
453 friend inline Lhs operator/(const Lhs& lhs, const Rhs& rhs)
454 {
455 return Impl<Rhs, RhsData>(lhs, rhs);
456 }
457
458 friend inline Lhs& operator/=(Lhs& lhs, const Rhs& rhs)
459 {
460 return ImplAssign<Rhs, RhsData>(lhs, rhs);
461 }
462
463 template<typename Ret = Lhs>
464 friend inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR, Ret>::type operator/(const Rhs& rhs, const Lhs& lhs)
465 {
466 return ImplRhs<Rhs, RhsData>(rhs, lhs);
467 }
468
469 template<typename Ret>
470 friend inline typename std::enable_if<!DEFINE_RHS_LHS_OPERATOR, Ret>::type operator/(const Rhs& rhs, const Lhs& lhs);
471
472 private:
473 template<typename U = Rhs, typename V = RhsData>
474 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
475 {
476 Lhs result{};
479 {
480 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
481 }
483
484 const size_t size = lhs.Size();
485 for (size_t i = 0; i < size; ++i)
486 {
487 result.begin()[i] = lhs.begin()[i] / rhs;
488 }
489 return result;
490 }
491
492 template<typename U = Rhs, typename V = RhsData>
493 static inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR&& std::is_same<U, V>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs)
494 {
495 Lhs result{};
498 {
499 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferOperatorEvents::OnResultCreated event must be handled"));
500 }
502
503 const size_t size = lhs.Size();
504 for (size_t i = 0; i < size; ++i)
505 {
506 result.begin()[i] = rhs / lhs.begin()[i];
507 }
508 return result;
509 }
510
511 template<typename U = Rhs, typename V = RhsData>
512 static inline typename std::enable_if<std::is_same<U, V>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
513 {
514 const size_t size = lhs.Size();
515 for (size_t i = 0; i < size; ++i)
516 {
517 lhs.begin()[i] /= rhs;
518 }
519 return lhs;
520 }
521
522 template<typename U = Rhs, typename V = RhsData>
523 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type Impl(const Lhs& lhs, const U& rhs)
524 {
525 if (lhs.Size() != rhs.Size())
526 {
527 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
528 }
529
530 Lhs result{};
533 {
535 "BufferOperatorEvents::OnResultCreated event must be handled"));
536 }
538
539 const size_t size = lhs.Size();
540 for (size_t i = 0; i < size; ++i)
541 {
542 result.begin()[i] = lhs.begin()[i] / rhs.begin()[i];
543 }
544 return result;
545 }
546
547 template<typename U = Rhs, typename V = RhsData>
548 static inline typename std::enable_if<DEFINE_RHS_LHS_OPERATOR&& std::is_base_of<BufferBase<U, V>, U>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs)
549 {
550 if (lhs.Size() != rhs.Size())
551 {
552 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidArgumentException(HEPH_FUNC, "Both operands must have the same size"));
553 }
554
555 Lhs result{};
558 {
560 "BufferOperatorEvents::OnResultCreated event must be handled"));
561 }
563
564 const size_t size = lhs.Size();
565 for (size_t i = 0; i < size; ++i)
566 {
567 result.begin()[i] = rhs.begin()[i] / lhs.begin()[i];
568 }
569 return result;
570 }
571
572 template<typename U = Rhs, typename V = RhsData>
573 static inline typename std::enable_if<std::is_base_of<BufferBase<U, V>, U>::value, Lhs&>::type ImplAssign(Lhs& lhs, const U& rhs)
574 {
575 const size_t minSize = HEPH_MATH_MIN(lhs.Size(), rhs.Size());
576 for (size_t i = 0; i < minSize; ++i)
577 {
578 lhs.begin()[i] /= rhs.begin()[i];
579 }
580 return lhs;
581 }
582 };
583#pragma endregion
584#pragma region Arithmetic
589 template<class Lhs, typename LhsData, typename Rhs = LhsData, typename RhsData = Rhs>
591 public BufferAdditionOperator<Lhs, LhsData, Rhs, RhsData>,
592 public BufferSubtractionOperator<Lhs, LhsData, Rhs, RhsData>,
593 public BufferMultiplicationOperator<Lhs, LhsData, Rhs, RhsData>,
594 public BufferDivisionOperator<Lhs, LhsData, Rhs, RhsData>
595 {
596 public:
597 BufferArithmeticOperators() = default;
599 BufferArithmeticOperators& operator=(const BufferArithmeticOperators&) = delete;
600 };
601#pragma endregion
602#pragma region Unary Minus
607 template<class Lhs, typename LhsData>
609 {
610 public:
612 {
613 static_assert(std::is_default_constructible<Lhs>::value, "Lhs must have a default constructor");
614 static_assert(std::is_base_of<BufferBase<Lhs, LhsData>, Lhs>::value, "Lhs must derive from BufferBase<Lhs, LhsData>");
615 static_assert(has_unary_minus_operator<LhsData>::value, "LhsData must have operator-()");
616 }
618 BufferUnaryMinusOperator& operator=(const BufferUnaryMinusOperator&) = delete;
619
620 public:
621 friend inline Lhs operator-(const Lhs& lhs)
622 {
623 Lhs result{};
626 {
627 HEPH_RAISE_AND_THROW_EXCEPTION(&lhs, InvalidOperationException(HEPH_FUNC, "BufferUnaryMinusOperator::OnResultCreated event must be handled"));
628 }
630
631 const size_t size = lhs.Size();
632 for (size_t i = 0; i < size; ++i)
633 {
634 result.begin()[i] = -lhs.begin()[i];
635 }
636
637 return result;
638 }
639 };
640#pragma endregion
641}
#define HEPH_RAISE_AND_THROW_EXCEPTION(pSender, ex)
Definition Exception.h:27
#define HEPH_MATH_MIN(a, b)
Definition HephMath.h:35
#define HEPH_FUNC
Definition HephShared.h:145
#define HEPH_API
Definition HephShared.h:132
provides + and += operators to the buffer.
Definition BufferOperators.h:43
provides arithmetic operators to the buffer.
Definition BufferOperators.h:595
provides / and /= operators to the buffer.
Definition BufferOperators.h:432
provides * and *= operators to the buffer.
Definition BufferOperators.h:317
provides - and -= operators to the buffer.
Definition BufferOperators.h:158
provides unary minus operator to the buffer.
Definition BufferOperators.h:609
class for managing callback functions.
Definition Event.h:25
raised when an argument passed to a method is invalid.
Definition InvalidArgumentException.h:14
raised when an operation is invalid.
Definition InvalidOperationException.h:14
Definition BufferOperators.h:28
contains the results of the BufferOperatorEvents::OnResultCreated event.
Definition BufferOperators.h:19
base class for storing arguments for an event .
Definition EventArgs.h:13