Wayverb
audio_file.h
1 #pragma once
2 
3 #include <string>
4 #include <vector>
5 
6 namespace audio_file {
7 
8 enum class bit_depth { pcm16 = 1, pcm24, pcm32, float32 };
9 
10 constexpr auto get_description(bit_depth b) {
11  switch (b) {
12  case bit_depth::pcm16: return "signed 16-bit pcm";
13  case bit_depth::pcm24: return "signed 24-bit pcm";
14  case bit_depth::pcm32: return "signed 32-bit pcm";
15  case bit_depth::float32: return "32-bit float";
16  }
17 }
18 
19 enum class format { wav = 1, aif };
20 
21 constexpr auto get_extension(format f) {
22  switch (f) {
23  case format::wav: return "wav";
24  case format::aif: return "aif";
25  }
26 }
27 
29 template <typename It>
30 auto interleave(It b, It e) {
31  using std::cbegin;
32  using std::cend;
33 
34  using value_type = std::decay_t<decltype(*cbegin(*b))>;
35  using return_type = std::vector<value_type>;
36 
37  const auto channels = std::distance(b, e);
38  if (channels <= 0) {
39  return return_type{};
40  }
41 
42  const auto frames = std::distance(cbegin(*b), cend(*b));
43  if (frames <= 0) {
44  return return_type{};
45  }
46 
47  for (auto it = b; it != e; ++it) {
48  if (std::distance(cbegin(*it), cend(*it)) != frames) {
49  throw std::runtime_error{"All channels must have equal length."};
50  }
51  }
52 
53  return_type interleaved(channels * frames);
54  for (auto i = 0ul; i != channels; ++i) {
55  for (auto j = 0ul; j != frames; ++j) {
56  interleaved[j * channels + i] = b[i][j];
57  }
58  }
59  return interleaved;
60 }
61 
64 template <typename It>
65 auto deinterleave(It b, It e, size_t channels) {
66  if (channels == 0) {
67  throw std::runtime_error{"Channels must be non-zero."};
68  }
69  const auto in_size = std::distance(b, e);
70  if (in_size % channels) {
71  throw std::runtime_error{
72  "Input size must be divisible by number of channels."};
73  }
74 
75  const auto frames = in_size / channels;
76  using value_type = std::decay_t<decltype(*b)>;
77  std::vector<std::vector<value_type>> deinterleaved(
78  channels, std::vector<value_type>(frames));
79 
80  for (auto i = 0ul; b != e; ++b, ++i) {
81  const auto channel = i % channels;
82  const auto sample = i / channels;
83  deinterleaved[channel][sample] = *b;
84  }
85 
86  return deinterleaved;
87 }
88 
89 template <typename T>
90 void write_interleaved(const char* fname,
91  const T* data,
92  size_t num,
93  int channels,
94  int sr,
95  format format,
96  bit_depth bit_depth);
97 
98 template <typename T>
99 void write(const char* fname,
100  const T* data,
101  size_t num,
102  int sr,
103  format format,
104  bit_depth bit_depth) {
105  write_interleaved(fname, data, num, 1, sr, format, bit_depth);
106 }
107 
108 template <typename T>
109 void write(const char* fname,
110  const T& data,
111  int sr,
112  format format,
113  bit_depth bit_depth) {
114  write(fname, data.data(), data.size(), sr, format, bit_depth);
115 }
116 
117 template <typename T>
118 struct audio_file final {
119  std::vector<std::vector<T>> signal;
120  double sample_rate;
121 };
122 
123 audio_file<double> read(const char* fname);
124 
125 template <typename It>
126 void write(const char* fname,
127  It b,
128  It e,
129  int sample_rate,
130  format format,
131  bit_depth bit_depth) {
132  const auto channels = std::distance(b, e);
133  if (channels <= 0) {
134  return;
135  }
136  const auto interleaved = interleave(b, e);
137  write_interleaved(fname,
138  interleaved.data(),
139  interleaved.size(),
140  channels,
141  sample_rate,
142  format,
143  bit_depth);
144 }
145 
146 } // namespace audio_file
Definition: audio_file.h:118
Definition: audio_file.h:6