sequencer
sample.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <atomic>
5 #include <cstdint>
6 #include <cstring>
7 #include <iterator>
8 #include <vector>
9 
10 namespace sequencer::audio
11 {
12  namespace underlying_t
13  {
14  using mode_t = std::uint8_t;
15  }
16 
18  {
19  mono = 1,
20  stereo = 2
21  };
22 
23  constexpr underlying_t::mode_t channels( mode_t mode ) noexcept
24  {
25  return static_cast< underlying_t::mode_t >( mode );
26  }
27 
28  struct sample_t
29  {
30  using frame_rep = float;
31  using size_type = std::vector< frame_rep >::size_type;
32 
33  sample_t() = default;
34 
35  explicit sample_t( size_type number_of_frames, mode_t mode = mode_t::stereo )
36  : frames( number_of_frames * channels( mode ), 0 ), mode( mode )
37  {
38  }
39 
40  void trim()
41  {
42  using std::rbegin;
43  using std::rend;
44  const auto last_non_zero = std::find_if_not(
45  rbegin( frames ), rend( frames ), []( frame_rep value ) { return value == 0.0f; } );
46  frames.resize( size_type( std::distance( last_non_zero, rend( frames ) ) ) );
47  }
48 
49  void clear()
50  {
51  frames =
52  std::vector< frame_rep >( std::max( frames.size(), initial_size ), frame_rep{0} );
53  }
54 
55  size_type number_of_frames() const noexcept
56  {
57  return frames.size() / channels( mode );
58  }
59 
60  std::vector< frame_rep > frames{};
62  size_type initial_size{frames.size()};
63  };
64 
65  inline void swap( sample_t& lhs, sample_t& rhs )
66  {
67  using std::swap;
68  swap( lhs.frames, rhs.frames );
69  swap( lhs.mode, rhs.mode );
70  swap( lhs.initial_size, rhs.initial_size );
71  }
72 
73  template < class Type >
74  struct read_write_lockable : Type
75  {
76  using Type::Type;
77 
78  constexpr void block_reading( bool lock ) noexcept
79  {
80  block_reading_ = lock;
81  }
82 
83  constexpr void block_writing( bool lock ) noexcept
84  {
85  block_writing_ = lock;
86  }
87 
88  constexpr bool reading_is_blocked() const noexcept
89  {
90  return block_reading_;
91  }
92 
93  constexpr bool writing_is_blocked() const noexcept
94  {
95  return block_writing_;
96  }
97 
98  private:
99  std::atomic_bool block_reading_{false};
100  std::atomic_bool block_writing_{false};
101  };
102 
104  {
105  public:
108 
110  : sample_{sample}
111  {
112  }
113 
114  constexpr void reset_frame_index() noexcept
115  {
116  frame_index_ = 0;
117  }
118 
119  bool has_frames_left() const noexcept
120  {
121  return frame_index_ < sample_.number_of_frames();
122  }
123 
124  protected:
125  size_type frames_to_copy( size_type frames_per_buffer ) const noexcept
126  {
127  const auto frames_left = sample_.number_of_frames() - frame_index_;
128  return std::min( frames_left, frames_per_buffer );
129  }
130 
131  constexpr void increase_frame_index( unsigned long increment ) noexcept
132  {
133  frame_index_ += increment;
134  }
135 
137  {
138  return &sample_.frames[ frame_index_ * channels( sample_.mode ) ];
139  }
140 
141  constexpr size_type frame_size_in_bytes() const noexcept
142  {
143  return sizeof( frame_rep ) * channels( sample_.mode );
144  }
145 
146  constexpr bool reading_is_blocked() const noexcept
147  {
148  return sample_.reading_is_blocked();
149  }
150 
151  constexpr bool writing_is_blocked() const noexcept
152  {
153  return sample_.writing_is_blocked();
154  }
155 
156  private:
158  size_type frame_index_{0};
159  };
160 
162  {
163  public:
165 
166  void write( const frame_rep* data, std::size_t frames_per_buffer )
167  {
168  if ( writing_is_blocked() )
169  {
170  return;
171  }
172 
173  const auto size = frames_to_copy( frames_per_buffer );
174  if ( data != nullptr )
175  {
176  std::memcpy( current_frame(), data, size * frame_size_in_bytes() );
177  increase_frame_index( size );
178  }
179  }
180  };
181 
183  {
184  public:
186 
187  void read( frame_rep* data, std::size_t frames_per_buffer )
188  {
189  if ( reading_is_blocked() )
190  {
191  return;
192  }
193 
194  const auto size = frames_to_copy( frames_per_buffer );
195  std::memcpy( data, current_frame(), size * frame_size_in_bytes() );
196  increase_frame_index( size );
197  }
198 
199  bool continue_reading() const noexcept
200  {
201  return has_frames_left();
202  }
203  };
204 } // namespace sequencer::audio
constexpr bool reading_is_blocked() const noexcept
Definition: sample.hpp:146
Definition: sample.hpp:28
sample_t::size_type size_type
Definition: sample.hpp:107
constexpr void increase_frame_index(unsigned long increment) noexcept
Definition: sample.hpp:131
bool has_frames_left() const noexcept
Definition: sample.hpp:119
constexpr bool writing_is_blocked() const noexcept
Definition: sample.hpp:93
bool continue_reading() const noexcept
Definition: sample.hpp:199
constexpr bool reading_is_blocked() const noexcept
Definition: sample.hpp:88
constexpr void block_reading(bool lock) noexcept
Definition: sample.hpp:78
size_type initial_size
Definition: sample.hpp:62
void clear()
Definition: sample.hpp:49
sample_read_write_base_t(read_write_lockable< sample_t > &sample) noexcept
Definition: sample.hpp:109
void swap(sample_t &lhs, sample_t &rhs)
Definition: sample.hpp:65
size_type frames_to_copy(size_type frames_per_buffer) const noexcept
Definition: sample.hpp:125
constexpr bool writing_is_blocked() const noexcept
Definition: sample.hpp:151
Definition: sample.hpp:74
void trim()
Definition: sample.hpp:40
Definition: delay.hpp:12
constexpr size_type frame_size_in_bytes() const noexcept
Definition: sample.hpp:141
size_type number_of_frames() const noexcept
Definition: sample.hpp:55
mode_t mode
Definition: sample.hpp:61
constexpr underlying_t::mode_t channels(mode_t mode) noexcept
Definition: sample.hpp:23
mode_t
Definition: sample.hpp:17
void write(const frame_rep *data, std::size_t frames_per_buffer)
Definition: sample.hpp:166
void read(frame_rep *data, std::size_t frames_per_buffer)
Definition: sample.hpp:187
constexpr void reset_frame_index() noexcept
Definition: sample.hpp:114
frame_rep * current_frame()
Definition: sample.hpp:136
sample_t(size_type number_of_frames, mode_t mode=mode_t::stereo)
Definition: sample.hpp:35
Definition: sample.hpp:161
constexpr void block_writing(bool lock) noexcept
Definition: sample.hpp:83
sample_t::frame_rep frame_rep
Definition: sample.hpp:106
std::uint8_t mode_t
Definition: sample.hpp:14
float frame_rep
Definition: sample.hpp:30
Definition: sample.hpp:182
std::vector< frame_rep >::size_type size_type
Definition: sample.hpp:31
std::vector< frame_rep > frames
Definition: sample.hpp:60