summaryrefslogtreecommitdiff
path: root/examples/alsa_timed_audio/sdk.h
blob: 82f8a93b494d5bd095627ee385a31115f60b96fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/******************************************************************************

  Copyright (c) 2018, Intel Corporation
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

   3. Neither the name of the Intel Corporation nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.

******************************************************************************/

#ifndef SDK_H
#define SDK_H

#include <bool.h>

#include <thread_signal.h>

#include <stdint.h>
#include <unistd.h>

//! \addtogroup StreamAPI Stream API
//! The Stream API is is used to create time synchronized audio applications.
//! It implements a mixer and capture module that are time-aware. The API is
//! similar in scope (albeit simplified) to PulseAudio adding calls to start
//! audio at a requested system time and returns the actual start time. It
//! provides a simplified API as well as a mixer that is able to mix streams
//! with a precision of +/- .5 sample.

//! \typedef isaudk_stream_handle_t
//! \brief Audio stream reference
//! \detail	Each is either capture or render
//!
//! \typedef isaudk_mixer_handle_t
//! \brief Audio mixer reference.
//! \details	One per audio output device. Default mixer is sufficient for
//!		most users
//!
//! \typedef isaudk_capture_handle_t
//! \brief Audio capture reference.
//! \details	One per audio input device. Default capture is sufficient for
//!		most users
//!
typedef struct isaudk_stream_handle*	isaudk_stream_handle_t;
typedef struct isaudk_mixer_handle*	isaudk_mixer_handle_t;
typedef struct isaudk_capture_handle*	isaudk_capture_handle_t;

//! \enum isaudk_direction_t
//! \brief Stream direction.
//! \details	Either render or capture
typedef enum
{
	ISAUDK_RENDER,		//!< Render stream
	ISAUDK_CAPTURE,		//!< Capture stream
} isaudk_direction_t;

// \enum isaudk_mode_t
// \either pre-play mode (playing zeros)
// \or audio-play mode (playing audio file)
typedef enum
{
	ISAUDK_SILENCE,		//play silence
	ISAUDK_AUDIO,		//play audio
} isaudk_mode_t;

//! \enum isaudk_error_t
//! \brief Error return value.
typedef enum
{
	ISAUDK_SUCCESS,	    	//!< No error
	ISAUDK_NOMEMORY,	//!< Failed to allocate dynamic memory
	ISAUDK_PTHREAD,		//!< Error internal to pthread library
	ISAUDK_BADFORMAT,	//!< Requested format is unavailable
	ISAUDK_INVALIDARG,	//!< One or more arguments are invalid
	ISAUDK_UNIMPL,		//!< Feature not implemented
	ISAUDK_AGAIN,		//!< Procedure may succeed if called again
	ISAUDK_FATAL,		//!< Error is unrecoverable, system error
	ISAUDK_INVALIDTIME = 255,	//!< An invalid start time was requested
} isaudk_error_t;

//! \enum isaudk_encoding_t
//! \brief Frame sample encoding.
//! \details	Includes frame layout (e.g. default is interleaved)
typedef enum
{
	ISAUDK_ENC_NONE,	//!< Defer format
	ISAUDK_ENC_PS16 = 0x02,	//!< PCM signed 16 bit
} isaudk_encoding_t;

//! \def PS16_SAMPLE_COUNT
//! \brief 16 bit signed sample count per sample block.
//!
//! \def PS16_JUMBO_SAMPLE_COUNT
//! \brief 16 bit signed sample count per jumbo sample block.
//!
#define PS16_SAMPLE_COUNT 2016
#define PS16_JUMBO_SAMPLE_COUNT 24576

//! \struct isaudk_format
//! \brief Audio frame format.
//! \details	Consists of sample encoding (including frame layout e.g.
//!		interleaved is default) and number of channels
struct isaudk_format
{
	isaudk_encoding_t encoding; //!< per-sample encoding / frame layout
	uint8_t channels;	    //!< channel count
};

//! \def ISAUDK_RATE_MULTIPLIER
//! \brief Multiplier for sample rate constant.
//! \details	Results in number of samples per second
//!
//! \typedef isaudk_sample_rate_t
//! \brief Sample rate.
//! \details	multiply by rate multiplier for samples per second
//!		\see ISAUDK_RATE_MULTIPLIER
//! \var _48K_SAMPLE_RATE
//! \brief 48 KHz sample rate
#define ISAUDK_RATE_MULTIPLIER 25
typedef unsigned short isaudk_sample_rate_t;
extern const isaudk_sample_rate_t _48K_SAMPLE_RATE;


//! \union isaudk_sample_block_t
//! \brief Sample block.
//! \details	Maximum 4096 byte block containing a whole number of audio
//!		frames for common channel configuration and sample sizes
typedef union
{
	int16_t PS16[2*PS16_SAMPLE_COUNT]; //!< 16 bit signed sample values
} isaudk_sample_block_t;

//! \union isaudk_jumbo_sample_block_t
//! \brief Large sample block.
//! \details	Maximum 12 x 4096 byte block containing a whole number of audio
//!		frames for common channel configuration and sample sizes.
//!		Contains several milliseconds of audio at high sample rates
//!		and 8 channel audio
typedef union
{
	int16_t PS16[PS16_JUMBO_SAMPLE_COUNT];
} isaudk_jumbo_sample_block_t;

//! \struct isaudk_system_time
//! \brief Local system time.
//! \details	In terms of POSIX-ish CLOCK_MONOTONIC_RAW
struct isaudk_system_time
{
	uint64_t time; //!< 64-bit system time scalar
};

//! \var ISAUDK_PLAY_IMMED
//! \brief system time indicating that playback or record begins immediately
extern const struct isaudk_system_time ISAUDK_PLAY_IMMED;

//! \struct isaudk_audio_time
//! \brief Audio device time.
//! \details	Is the sample count multiplied by nominal nanoseconds per
//!		sample. Includes fractional samples.
struct isaudk_audio_time
{
	uint64_t time;
};

//! \struct isaudk_cross_time
//! \brief Correlated audio and system time.
//! \details	Captured simultaneously. Degree of simultaneity depends on
//!		timestamp function of underlying audio driver. If available,
//!		ALSA can capture timestamps using hardware
struct isaudk_cross_time
{
	struct isaudk_system_time	sys;
	struct isaudk_audio_time	dev;
};

//! \brief Check cross-timestamps for equality
//!
//! \param a one cross-timestamp
//! \param b another cross-timestamp
//!
//! \return true if cross-timestamps are equal
static inline bool
isaudk_crosstime_equal( const struct isaudk_cross_time *a,
			const struct isaudk_cross_time *b )
{
	if( a->sys.time != b->sys.time )
		return false;
	if( a->dev.time != b->dev.time )
		return false;

	return true;
}

//! \brief Opens render stream.
//! \details	Using specified mixer.
//! \ingroup StreamAPI
//!
//! \param handle[out]		stream_handle
//! \param format[in]		audio frame format
//! \param rate[in]		sample rate
//! \param mixer[in]		mixer handle (NULL: use default)
//!
//! \return Return code
isaudk_error_t
isaudk_open_stream_mixer( isaudk_stream_handle_t *handle,
			  struct isaudk_format *format,
			  isaudk_sample_rate_t rate,
			  isaudk_mixer_handle_t mixer );

//! \brief Opens capture stream.
//! \details	Using specified capture module.
//! \ingroup StreamAPI
//!
//! \param handle[out]		stream_handle
//! \param format[in]		audio frame format
//! \param rate[in]		sample rate
//! \param capture[in]		capture module handle (NULL: use default)
//!
//! \return Return code
isaudk_error_t
isaudk_open_stream_capture( isaudk_stream_handle_t *handle,
			  struct isaudk_format *format,
			  isaudk_sample_rate_t rate,
			  isaudk_capture_handle_t capture );

//! \brief Opens stream.
//! \details	Using default mixer or capture module.
//! \ingroup StreamAPI
//!
//! \param handle[out]		stream_handle
//! \param format[in]		audio frame format
//! \param rate[in]		sample rate
//! \param direction[in]	specify capture or render \see
//!				isaudk_direction_t
//! \return Return code
isaudk_error_t
isaudk_open_stream( isaudk_stream_handle_t *handle,
		    struct isaudk_format *format,
		    isaudk_sample_rate_t rate,
		    isaudk_direction_t direction );

//! \brief Opens stream using default stream format/rate.
//! \ingroup StreamAPI
//!
//! \param handle[out]		stream_handle
//! \param direction[in]	specify capture or render \see
//!				isaudk_direction_t
//! \return Return code
isaudk_error_t
isaudk_open_default_stream( isaudk_stream_handle_t *handle,
			    isaudk_direction_t direction );

//! \brief Get stream info.
//! \details	Useful after stream is opened using default parameters
//!		\see isaudk_open_default_stream
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param format[out]		audio frame format
//! \param rate[out]		sample rate
//! \param direction[out]	specify capture or render \see
//!				isaudk_direction_t
//! \return Return code
isaudk_error_t
isaudk_get_stream_info( isaudk_stream_handle_t handle,
			struct isaudk_format *format,
			isaudk_sample_rate_t *rate,
			isaudk_direction_t *direction );

//! \brief Get buffers.
//! \details	Exchange data with mixer or capture module.
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param buffer[out]		audio buffer array
//! \param count[out]		buffer array size
//! \param signal[out]		signals when mixer is ready for more data or
//!				capture stream is ready for reading
//! \return Return code
void
isaudk_get_stream_buffers( isaudk_stream_handle_t handle,
			   isaudk_sample_block_t **buffer, size_t *count,
			   isaudk_signal_t *signal );

//! \brief Get buffers.
//! \details	Useful after stream is opened using default parameters
//!		\see isaudk_open_default_stream
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param buffer[out]		audio buffer array
//! \param count[out]		buffer array size
//! \param signal[out]		signals when mixer is ready for more data or
//!				capture stream is ready for reading
//! \return Return code
isaudk_error_t
isaudk_stream_set_buffer_sample_count( isaudk_stream_handle_t handle,
				       size_t idx, size_t count, bool eos );

//! \brief Get current buffer index for render.
//! \details	Useful after stream is opened using default parameters
//!		\see isaudk_open_default_stream
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param roll[out]		Current buffer index is ready to read, may
//!				indicate that wrap-around has occured
//! \return Buffer index
uint8_t
isaudk_get_stream_buffer_index( isaudk_stream_handle_t handle, bool *roll );

//! \brief Mark buffer index as consumed.
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param idx[in]		Buffer index consumed
//!
//! \return Return code
isaudk_error_t
isaudk_stream_mark_buffer_done( isaudk_stream_handle_t stream, size_t idx );

//! \brief Request stream start time.
//! \details	Is accurated within 1 samples period. \see ISAUDK_PLAY_IMMED
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param start_time[out]	Start time in nanoseconds
//!
//! \return Return code
isaudk_error_t
isaudk_start_stream_at( isaudk_stream_handle_t handle,
			struct isaudk_system_time start_time );

//! \brief Get actual stream start time.
//! \details	In nanosecond units, accurate within system clock tick
//!		usually sub-microsecond
//! \ingroup StreamAPI
//!
//! \param handle[in]		stream_handle
//! \param roll[out]		Current buffer index is ready to read, may
//!				indicate that wrap-around has occured
//! \return Return code
isaudk_error_t
isaudk_get_stream_start_time( isaudk_stream_handle_t handle,
		       struct isaudk_system_time *start_time );
isaudk_error_t
isaudk_get_stream_audio_start_time( isaudk_stream_handle_t handle,
		       struct isaudk_system_time *start_time );

#endif/*SDK_H*/