OSSIA
Open Scenario System for Interactive Application
float_to_sample.hpp
1 #pragma once
2 
3 #include <ossia/dataflow/nodes/media.hpp>
4 #include <ossia/detail/math.hpp>
5 
6 #include <cstdint>
7 #include <limits>
8 
9 namespace ossia
10 {
28 template <typename SampleFormat, int N>
29 constexpr SampleFormat float_to_sample(ossia::audio_sample sample) noexcept;
30 
31 template <>
32 constexpr uint8_t float_to_sample<uint8_t, 8>(ossia::audio_sample sample) noexcept
33 {
34  // 0 -> 255 to -1 -> 1
35  if constexpr(std::is_same_v<ossia::audio_sample, float>)
36  {
37  return (sample + 1.f) * 127.5f;
38  }
39  else
40  {
41  return (sample + 1.) * 127.5;
42  }
43 }
44 
45 template <>
46 constexpr int16_t float_to_sample<int16_t, 16>(ossia::audio_sample sample) noexcept
47 {
48  // TODO division -> multiplication
49  if constexpr(std::is_same_v<ossia::audio_sample, float>)
50  {
51  return sample * (0x7FFF + .5f) - 0.5f;
52  }
53  else
54  {
55  return sample * (0x7FFF + .5) - 0.5;
56  }
57 }
58 
59 // ALSA S24_LE: https://stackoverflow.com/a/40301874/1495627
60 template <>
61 constexpr int32_t float_to_sample<int32_t, 24>(ossia::audio_sample sample) noexcept
62 {
63  const constexpr ossia::audio_sample int24_max
65  return int32_t(sample * int24_max);
66 }
67 
68 /*
69 template <>
70 constexpr int32_t float_to_sample<int32_t, 24>(audio_sample x) noexcept
71 {
72  // TODO division -> multiplication
73  if constexpr(std::is_same_v<ossia::audio_sample, float>)
74  {
75  return (x * (0x7FFFFF + 0.5f)) - 0.5f;
76  }
77  else
78  return (x * (0x7FFFFF + 0.5)) - 0.5;
79 }
80 */
81 
82 template <>
83 constexpr int32_t float_to_sample<int32_t, 32>(audio_sample x) noexcept
84 {
85  return x * (audio_sample)std::numeric_limits<int32_t>::max();
86 }
87 
88 template <>
89 constexpr float float_to_sample<float, 32>(float sample) noexcept
90 {
91  return sample;
92 }
93 
94 #if defined(_MSC_VER)
95 #define OSSIA_RESTRICT __restrict
96 #else
97 #define OSSIA_RESTRICT __restrict__
98 #endif
99 
100 template <typename SampleFormat, int N, int ByteIncrement, typename InputFormat>
101  requires(sizeof(SampleFormat) == ByteIncrement)
102 inline void interleave(
103  const InputFormat* const* OSSIA_RESTRICT in, SampleFormat* OSSIA_RESTRICT out,
104  int channels, int bs)
105 {
106  for(int c = 0; c < channels; c++)
107  {
108  auto* in_channel = in[c];
109  for(int k = 0; k < bs; k++)
110  {
111  out[k * channels + c] = float_to_sample<SampleFormat, N>(in_channel[k]);
112  }
113  }
114 }
115 
116 template <typename SampleFormat, int N, int ByteIncrement, typename InputFormat>
117  requires(sizeof(SampleFormat) != ByteIncrement)
118 inline void interleave(
119  const InputFormat* const* OSSIA_RESTRICT in, SampleFormat* out, int channels, int bs)
120 {
121  for(int c = 0; c < channels; c++)
122  {
123  auto* in_channel = in[c];
124  for(int k = 0; k < bs; k++)
125  {
126  // Case packed 24-bit: we have to go through raw char*
127  char* out_raw = reinterpret_cast<char*>(out);
128  auto mem
129  = reinterpret_cast<SampleFormat*>(out_raw[(k * channels + c) * ByteIncrement]);
130  *mem = float_to_sample<SampleFormat, N>(in_channel[k]);
131  }
132  }
133 }
134 
135 template <typename SampleFormat, int N, typename InputFormat>
136 inline void convert(
137  const InputFormat* const* OSSIA_RESTRICT in, SampleFormat* OSSIA_RESTRICT out,
138  int channels, int bs)
139 {
140  for(int c = 0; c < channels; c++)
141  {
142  auto* in_channel = in[c];
143  auto* out_channel = out + c * bs;
144  for(int k = 0; k < bs; k++)
145  {
146  out_channel[k] = float_to_sample<SampleFormat, N>(in_channel[k]);
147  }
148  }
149 }
150 }
Definition: git_info.h:7
constexpr SampleFormat float_to_sample(ossia::audio_sample sample) noexcept
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96