Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
sample_spec.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_audio/sample_spec.h
10 //! @brief Sample specifications.
11 
12 #ifndef ROC_AUDIO_SAMPLE_SPEC_H_
13 #define ROC_AUDIO_SAMPLE_SPEC_H_
14 
15 #include "roc_audio/channel_set.h"
16 #include "roc_audio/pcm_format.h"
17 #include "roc_audio/sample.h"
19 #include "roc_core/attributes.h"
20 #include "roc_core/stddefs.h"
22 #include "roc_core/time.h"
23 #include "roc_packet/units.h"
24 
25 namespace roc {
26 namespace audio {
27 
28 //! Sample specification.
29 //! Describes sample rate and channels.
30 class SampleSpec {
31 public:
32  //! Construct empty specification.
34 
35  //! Construct specification with parameters.
36  //! @note
37  //! This constructor sets sample_format() to SampleFormat_Pcm.
39 
40  //! Construct specification with parameters.
41  //! @remarks
42  //! This is a convenient overload for the case when 32-bit mask is enough to
43  //! describe channels. Otherwise, use overload that accepts ChannelSet.
44  //! @note
45  //! This constructor sets sample_format() to SampleFormat_Pcm.
47  PcmFormat pcm_fmt,
48  ChannelLayout channel_layout,
49  ChannelOrder channel_order,
50  ChannelMask channel_mask);
51 
52  //! @name Equality
53  //! @{
54 
55  //! Check two specifications for equality.
56  bool operator==(const SampleSpec& other) const;
57 
58  //! Check two specifications for equality.
59  bool operator!=(const SampleSpec& other) const;
60 
61  // @}
62 
63  //! @name Getters and setters
64  //! @{
65 
66  //! Check if sample spec has non-zero rate and valid channel set.
67  bool is_valid() const;
68 
69  //! Check if sample spec has a zero rate, empty channel set, and invalid_format.
70  bool is_empty() const;
71 
72  //! Check if samples are in raw format.
73  //! @returns
74  //! true if sample_format() is SampleFormat_Pcm and pcm_format()
75  //! is Sample_RawFormat (32-bit native-endian floats).
76  bool is_raw() const;
77 
78  //! Unset all fields.
79  void clear();
80 
81  //! Set missing fields from provided defaults.
82  //! @remarks
83  //! Updates only those fields which don't have values,
84  //! with corresponding values provided as arguments.
85  void use_defaults(PcmFormat default_pcm_fmt,
86  ChannelLayout default_channel_layout,
87  ChannelOrder default_channel_order,
88  ChannelMask default_channel_mask,
89  size_t default_sample_rate);
90 
91  //! Get sample rate.
92  //! @remarks
93  //! Defines sample frequency (number of samples per second).
94  size_t sample_rate() const;
95 
96  //! Set sample rate.
98 
99  //! Get sample format.
100  //! @remarks
101  //! Defines how samples are represented in memory.
102  //! When set to SampleFormat_Pcm, pcm_format() defines what exact PCM coding
103  //! and endian are used.
105 
106  //! Set sample format.
107  void set_sample_format(SampleFormat sample_fmt);
108 
109  //! Get PCM format.
110  //! @remarks
111  //! When sample_format() is set to SampleFormat_Pcm, defines what exact PCM coding
112  //! and endian are used.
114 
115  //! Set PCM format.
116  void set_pcm_format(PcmFormat pcm_fmt);
117 
118  //! Get channel set.
119  //! @remarks
120  //! Defines sample channels (layout and numbers).
121  const ChannelSet& channel_set() const;
122 
123  //! Get mutable channel set.
125 
126  //! Set channel set.
128 
129  //! Get number enabled channels in channel set.
130  //! @remarks
131  //! Shorthand for channel_set().num_channels().
132  size_t num_channels() const;
133 
134  // @}
135 
136  //! @name Convert number of samples
137  //! @{
138 
139  //! Convert nanoseconds duration to number of samples per channel.
140  //! @pre
141  //! @p ns_duration should not be negative.
142  //! @note
143  //! In case of overflow, result is saturated.
144  size_t ns_2_samples_per_chan(core::nanoseconds_t ns_duration) const;
145 
146  //! Convert number of samples per channel to nanoseconds duration.
147  //! @note
148  //! In case of overflow, result is saturated.
150 
151  //! Convert (possibly fractional) number samples per channel to nanoseconds duration.
152  //! @note
153  //! In case of overflow, result is saturated.
155 
156  //! Convert nanoseconds duration to number of samples for all channels.
157  //! @pre
158  //! @p ns_duration should not be negative.
159  //! @post
160  //! result is always multiple of number of channels.
161  //! @note
162  //! In case of overflow, result is saturated.
163  size_t ns_2_samples_overall(core::nanoseconds_t ns_duration) const;
164 
165  //! Convert number of samples for all channels to nanoseconds duration.
166  //! @pre
167  //! @p n_samples should be multiple of number of channels.
168  //! @note
169  //! In case of overflow, result is saturated.
170  core::nanoseconds_t samples_overall_2_ns(size_t n_samples) const;
171 
172  //! Convert number of samples (possibly non-integer) to nanoseconds.
173  //! @note
174  //! In case of overflow, result is saturated.
176 
177  // @}
178 
179  //! @name Convert stream timestamps
180  //! @{
181 
182  //! Convert nanoseconds delta to stream timestamp.
183  //! @pre
184  //! @p ns_duration should not be negative.
185  //! @remarks
186  //! Same as ns_2_samples_per_chan(), but with stream_timestamp_t instead of size_t.
189 
190  //! Convert stream timestamp to nanoseconds.
191  //! @remarks
192  //! Same as samples_per_chan_2_ns(), but with stream_timestamp_t instead of size_t.
195 
196  //! Convert stream timestamp to milliseconds.
198 
199  //! Convert nanoseconds delta to stream timestamp delta.
200  //! @remarks
201  //! Same as ns_2_samples_per_chan(), but supports negative deltas.
204 
205  //! Convert stream timestamp delta to nanoseconds delta.
206  //! @remarks
207  //! Same as samples_per_chan_2_ns(), but supports negative deltas.
210 
211  //! Convert stream timestamp delta to milliseconds.
212  double
214 
215  // @}
216 
217  //! @name Convert byte size
218  //! @{
219 
220  //! Convert byte size to stream timestamp.
221  //! @pre
222  //! sample_format() should be PCM.
224 
225  //! Convert stream timestamp to byte size.
226  //! @pre
227  //! sample_format() should be PCM.
229 
230  //! Convert byte size to nanosecond duration.
231  //! @pre
232  //! sample_format() should be PCM.
233  core::nanoseconds_t bytes_2_ns(size_t n_bytes) const;
234 
235  //! Convert nanosecond duration to byte size.
236  //! @pre
237  //! sample_format() should be PCM.
238  size_t ns_2_bytes(core::nanoseconds_t duration) const;
239 
240  // @}
241 
242 private:
243  size_t sample_rate_;
244  SampleFormat sample_fmt_;
245  PcmFormat pcm_fmt_;
246  size_t pcm_width_;
247  ChannelSet channel_set_;
248 };
249 
250 //! Parse sample spec from string.
251 //!
252 //! @remarks
253 //! The input string should have the form:
254 //! - "<format>/<rate>/<channels>"
255 //!
256 //! Where:
257 //! - "<format>" is string name of sample format (e.g. "s16")
258 //! - "<rate>" is a positive integer
259 //! - "<channels>" can be: "<surround preset>", "<surround channel list>",
260 //! "<multitrack mask>", "<multitrack channel list>"
261 //!
262 //! - "<surround preset>" is a string name of predefined surround channel
263 //! mask, e.g. "stereo", "surround4.1", etc.
264 //! - "<surround channel list>" is comma-separated list of surround channel names,
265 //! e.g. "FL,FC,FR"
266 //!
267 //! - "<multitrack mask>" is a 1024-bit hex mask defining which tracks are
268 //! enabled, e.g. "0xAA00BB00"
269 //! - "<multitrack channel list>" is a comma-separated list of track numbers
270 //! or ranges, e.g. "1,2,5-8"
271 //!
272 //! Each of the three components ("<format>", "<rate>", "<channels>") may be set
273 //! to "-", which means "keep unset".
274 //!
275 //! All four forms of "<channels>" component are alternative ways to represent a
276 //! bitmask of enabled channels or tracks. The order of channels does no matter.
277 //!
278 //! Examples:
279 //! - "s16/44100/stereo"
280 //! - "s18_4le/48000/FL,FC,FR"
281 //! - "f32/96000/1,2,10-20,31"
282 //! - "f32/96000/0xA0000000FFFF0000000C"
283 //! - "-/44100/-"
284 //! - "-/-/-"
285 //!
286 //! @returns
287 //! false if string can't be parsed.
288 ROC_ATTR_NODISCARD bool parse_sample_spec(const char* str, SampleSpec& result);
289 
290 //! Format sample spec to string.
291 void format_sample_spec(const SampleSpec& sample_spec, core::StringBuilder& bld);
292 
293 } // namespace audio
294 } // namespace roc
295 
296 #endif // ROC_AUDIO_SAMPLE_SPEC_H_
Compiler attributes.
#define ROC_ATTR_NODISCARD
Emit warning if function result is not checked.
Definition: attributes.h:31
Channel set.
Channel set. Multi-word bitmask with bits corresponding to enabled channels. Meaning of each channel ...
Definition: channel_set.h:26
Sample specification. Describes sample rate and channels.
Definition: sample_spec.h:30
double stream_timestamp_2_ms(packet::stream_timestamp_t sts_duration) const
Convert stream timestamp to milliseconds.
SampleFormat sample_format() const
Get sample format.
void set_channel_set(const ChannelSet &channel_set)
Set channel set.
SampleSpec(size_t sample_rate, PcmFormat pcm_fmt, const ChannelSet &channel_set)
Construct specification with parameters.
size_t ns_2_samples_overall(core::nanoseconds_t ns_duration) const
Convert nanoseconds duration to number of samples for all channels.
core::nanoseconds_t fract_samples_overall_2_ns(float n_samples) const
Convert number of samples (possibly non-integer) to nanoseconds.
core::nanoseconds_t stream_timestamp_delta_2_ns(packet::stream_timestamp_diff_t sts_delta) const
Convert stream timestamp delta to nanoseconds delta.
bool operator==(const SampleSpec &other) const
Check two specifications for equality.
bool is_valid() const
Check if sample spec has non-zero rate and valid channel set.
core::nanoseconds_t stream_timestamp_2_ns(packet::stream_timestamp_t sts_duration) const
Convert stream timestamp to nanoseconds.
bool is_empty() const
Check if sample spec has a zero rate, empty channel set, and invalid_format.
SampleSpec(size_t sample_rate, PcmFormat pcm_fmt, ChannelLayout channel_layout, ChannelOrder channel_order, ChannelMask channel_mask)
Construct specification with parameters.
void clear()
Unset all fields.
void use_defaults(PcmFormat default_pcm_fmt, ChannelLayout default_channel_layout, ChannelOrder default_channel_order, ChannelMask default_channel_mask, size_t default_sample_rate)
Set missing fields from provided defaults.
void set_pcm_format(PcmFormat pcm_fmt)
Set PCM format.
double stream_timestamp_delta_2_ms(packet::stream_timestamp_diff_t sts_duration) const
Convert stream timestamp delta to milliseconds.
size_t stream_timestamp_2_bytes(packet::stream_timestamp_t duration) const
Convert stream timestamp to byte size.
void set_sample_format(SampleFormat sample_fmt)
Set sample format.
size_t num_channels() const
Get number enabled channels in channel set.
SampleSpec()
Construct empty specification.
core::nanoseconds_t bytes_2_ns(size_t n_bytes) const
Convert byte size to nanosecond duration.
size_t sample_rate() const
Get sample rate.
bool operator!=(const SampleSpec &other) const
Check two specifications for equality.
const ChannelSet & channel_set() const
Get channel set.
void set_sample_rate(size_t sample_rate)
Set sample rate.
core::nanoseconds_t samples_overall_2_ns(size_t n_samples) const
Convert number of samples for all channels to nanoseconds duration.
core::nanoseconds_t samples_per_chan_2_ns(size_t n_samples) const
Convert number of samples per channel to nanoseconds duration.
core::nanoseconds_t fract_samples_per_chan_2_ns(float n_samples) const
Convert (possibly fractional) number samples per channel to nanoseconds duration.
packet::stream_timestamp_t ns_2_stream_timestamp(core::nanoseconds_t ns_duration) const
Convert nanoseconds delta to stream timestamp.
packet::stream_timestamp_diff_t ns_2_stream_timestamp_delta(core::nanoseconds_t ns_delta) const
Convert nanoseconds delta to stream timestamp delta.
packet::stream_timestamp_t bytes_2_stream_timestamp(size_t n_bytes) const
Convert byte size to stream timestamp.
PcmFormat pcm_format() const
Get PCM format.
size_t ns_2_samples_per_chan(core::nanoseconds_t ns_duration) const
Convert nanoseconds duration to number of samples per channel.
ChannelSet & channel_set()
Get mutable channel set.
size_t ns_2_bytes(core::nanoseconds_t duration) const
Convert nanosecond duration to byte size.
bool is_raw() const
Check if samples are in raw format.
void format_sample_spec(const SampleSpec &sample_spec, core::StringBuilder &bld)
Format sample spec to string.
SampleFormat
Sample format. Defines representation of samples in memory. Does not define sample rate and channel s...
Definition: sample_format.h:23
ChannelLayout
Channel layout. Defines meaning of channels in ChannelSet. ChannelMapper uses channel layout to decid...
Definition: channel_defs.h:23
uint32_t ChannelMask
Channel mask.
Definition: channel_defs.h:148
ROC_ATTR_NODISCARD bool parse_sample_spec(const char *str, SampleSpec &result)
Parse sample spec from string.
PcmFormat
PCM format. Defines PCM sample coding and endian.
Definition: pcm_format.h:22
ChannelOrder
Surround channel order.
Definition: channel_defs.h:49
int64_t nanoseconds_t
Nanoseconds.
Definition: time.h:58
uint32_t stream_timestamp_t
Packet stream timestamp.
Definition: units.h:36
int32_t stream_timestamp_diff_t
Packet stream timestamp delta.
Definition: units.h:41
Root namespace.
PCM format.
Audio sample.
Sample format.
Commonly used types and functions.
String builder.
Time definitions.
Various units used in packets.