OSSIA
Open Scenario System for Interactive Application
drwav_handle.hpp
1 #pragma once
2 #include <ossia/dataflow/float_to_sample.hpp>
3 
4 #include <dr_wav.h>
5 
6 #include <ossia-config.hpp>
7 
8 namespace ossia
9 {
10 #pragma pack(push, 1)
11 struct acid_chunk
12 {
13  // https://github.com/erikd/libsndfile/blob/master/src/wav.c#L1427
14  int32_t file_type{};
15  int16_t root_note{};
16  int16_t fill_0{};
17  float fill_1{};
18  int32_t num_beats{};
19  int16_t meter_denom{};
20  int16_t meter_num{};
21  float tempo{};
22 };
23 #pragma pack(pop)
24 
25 struct drwav_handle final
26 {
27 public:
28  static const constexpr drwav_allocation_callbacks drwav_allocs{
29  nullptr, [](size_t sz, void* pUserData) { return malloc(sz); },
30  [](void* p, size_t sz, void* pUserData) { return realloc(p, sz); },
31  [](void* p, void* pUserData) { return free(p); }};
32  drwav_handle() noexcept = default;
33  drwav_handle(const void* data, size_t dataSize) noexcept
34  : impl{new drwav}
35  {
36  drwav_init_memory_ex(impl, data, dataSize, on_chunk, this, 0, &drwav_allocs);
37  }
38 
39  drwav_handle(drwav_handle&& other) noexcept
40  : impl{other.impl}
41  , m_acid{other.m_acid}
42  {
43  other.impl = nullptr;
44  other.m_acid = {};
45  }
46 
47  drwav_handle(const drwav_handle& other) noexcept
48  {
49  if(other.impl && other.impl->memoryStream.data)
50  {
51  impl = new drwav;
52  drwav_init_memory_ex(
53  impl, other.impl->memoryStream.data, other.impl->memoryStream.dataSize,
54  on_chunk, this, 0, &drwav_allocs);
55  }
56  }
57 
58  static drwav_uint64 on_chunk(
59  void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek,
60  void* pReadSeekUserData, const drwav_chunk_header* pChunkHeader,
61  drwav_container container, const drwav_fmt* pFMT) noexcept
62  {
63  drwav_handle& self = *(drwav_handle*)pChunkUserData;
64  auto& cc = pChunkHeader->id.fourcc;
65  static const constexpr drwav_uint8 acid[4] = {'a', 'c', 'i', 'd'};
66  if(std::equal(cc, cc + 4, acid, acid + 4))
67  {
68  onRead(pReadSeekUserData, &self.m_acid, sizeof(acid_chunk));
69  return sizeof(acid_chunk);
70  }
71  return 0;
72  }
73 
74  drwav_handle& operator=(drwav_handle&& other) noexcept
75  {
76  if(impl)
77  {
78  drwav_uninit(impl);
79  delete impl;
80  impl = nullptr;
81  }
82 
83  impl = other.impl;
84  other.impl = nullptr;
85  return *this;
86  }
87 
88  drwav_handle& operator=(const drwav_handle& other) noexcept
89  {
90  if(impl)
91  {
92  drwav_uninit(impl);
93  delete impl;
94  impl = nullptr;
95  }
96 
97  if(other.impl->memoryStream.data)
98  {
99  impl = new drwav;
100  drwav_init_memory_ex(
101  impl, other.impl->memoryStream.data, other.impl->memoryStream.dataSize,
102  on_chunk, this, 0, &drwav_allocs);
103  }
104  return *this;
105  }
106 
107  ~drwav_handle()
108  {
109  if(impl)
110  {
111  drwav_uninit(impl);
112  delete impl;
113  }
114  }
115 
116  operator bool() const noexcept { return bool(impl); }
117  auto open_memory(const void* data, size_t dataSize) noexcept
118  {
119  if(impl)
120  {
121  drwav_uninit(impl);
122  delete impl;
123  }
124 
125  impl = new drwav;
126  drwav_init_memory_ex(impl, data, dataSize, on_chunk, this, 0, &drwav_allocs);
127  }
128 
129  auto seek_to_pcm_frame(drwav_uint64 targetFrameIndex) noexcept
130  {
131  return drwav_seek_to_pcm_frame(impl, targetFrameIndex);
132  }
133 
134  auto read_pcm_frames(drwav_uint64 framesToRead, void* buffer) noexcept
135  {
136  return drwav_read_pcm_frames(impl, framesToRead, buffer);
137  }
138 
139  auto read_pcm_frames_s16(drwav_uint64 framesToRead, int16_t* buffer) noexcept
140  {
141  return drwav_read_pcm_frames_s16(impl, framesToRead, buffer);
142  }
143 
144  auto read_pcm_frames_f32(drwav_uint64 framesToRead, float* buffer) noexcept
145  {
146  return drwav_read_pcm_frames_f32(impl, framesToRead, buffer);
147  }
148 
149  [[nodiscard]] auto channels() const noexcept { return impl->channels; }
150  [[nodiscard]] auto translatedFormatTag() const noexcept
151  {
152  return impl->translatedFormatTag;
153  }
154  [[nodiscard]] auto bitsPerSample() const noexcept { return impl->bitsPerSample; }
155  [[nodiscard]] auto sampleRate() const noexcept { return impl->sampleRate; }
156  [[nodiscard]] auto totalPCMFrameCount() const noexcept
157  {
158  return impl->totalPCMFrameCount;
159  }
160 
161  [[nodiscard]] ::drwav* wav() const noexcept { return impl; }
162 
163  [[nodiscard]] acid_chunk acid() const noexcept { return m_acid; }
164 
165 private:
166  ::drwav* impl{};
167  acid_chunk m_acid{};
168 };
169 }
Definition: git_info.h:7