-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsample_rate_converter.h
177 lines (156 loc) · 6.8 KB
/
sample_rate_converter.h
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
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/** @file
* @brief Sample Rate Converter library header.
*/
#ifndef _SAMPLE_RATE_CONVERTER_H_
#define _SAMPLE_RATE_CONVERTER_H_
/**
* @defgroup sample_rate_converter Sample Rate Converter library
* @brief Implements functionality to increase or decrease the sample rate of a data array using
* the CMSIS DSP filtering library.
*
* @{
*/
#include <zephyr/sys/ring_buffer.h>
#include <dsp/filtering_functions.h>
/**
* Maximum size for the internal state buffers.
*
* The internal state buffer must for each context fulfill the following equations:
* Interpolation:
* number of filter taps + block size - 1
* Decimation:
* (number of filter taps / conversion ratio) + block size - 1
*
* The equation for interpolation is used as size as this gives the largest number.
*/
#define SAMPLE_RATE_CONVERTER_STATE_BUFFER_SIZE \
(CONFIG_SAMPLE_RATE_CONVERTER_BLOCK_SIZE_MAX + \
CONFIG_SAMPLE_RATE_CONVERTER_MAX_FILTER_SIZE - 1)
/** Filter types supported by the sample rate converter */
enum sample_rate_converter_filter {
SAMPLE_RATE_FILTER_TEST = 1,
SAMPLE_RATE_FILTER_SIMPLE
};
/**
* To maintain filter requirements the input buffer must in some cases store two samples between
* each block processed.
*/
#define SAMPLE_RATE_CONVERTER_INPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES 2
/**
* To maintain filter requirements the output buffer must in some cases store six samples between
* each block processed. The output buffer must be able to store a full block in addition to these
* overflow samples.
*/
#define SAMPLE_RATE_CONVERTER_OUTPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES 6
#ifdef CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_16
#define SAMPLE_RATE_CONVERTER_INPUT_BUF_SIZE \
(SAMPLE_RATE_CONVERTER_INPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES * sizeof(uint16_t))
#define SAMPLE_RATE_CONVERTER_RINGBUF_SIZE \
((CONFIG_SAMPLE_RATE_CONVERTER_BLOCK_SIZE_MAX + \
SAMPLE_RATE_CONVERTER_OUTPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES) * \
sizeof(uint16_t))
#elif CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_32
#define SAMPLE_RATE_CONVERTER_INPUT_BUF_SIZE \
(SAMPLE_RATE_CONVERTER_INPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES * sizeof(uint32_t))
#define SAMPLE_RATE_CONVERTER_RINGBUF_SIZE \
((CONFIG_SAMPLE_RATE_CONVERTER_BLOCK_SIZE_MAX + \
SAMPLE_RATE_CONVERTER_OUTPUT_BUFFER_NUMBER_OVERFLOW_SAMPLES) * \
sizeof(uint32_t))
#else
#define SAMPLE_RATE_CONVERTER_INPUT_BUF_SIZE 0
#define SAMPLE_RATE_CONVERTER_RINGBUF_SIZE 0
#endif
/** Buffer used for storing input bytes to the sample rate converter */
struct buf_ctx {
uint8_t buf[SAMPLE_RATE_CONVERTER_INPUT_BUF_SIZE];
size_t bytes_in_buf;
};
/** Context for the sample rate conversion */
struct sample_rate_converter_ctx {
/* Input and output sample rate to be used for the conversion. */
uint32_t sample_rate_input;
uint32_t sample_rate_output;
/* The ratio for the current conversion. When the conversion is upsampling the ratio is
* positive and negative when downsampling.
*/
int conversion_ratio;
/* Filter type to be used for the conversion. */
enum sample_rate_converter_filter filter_type;
/* Buffer used to store input samples between process calls. */
struct buf_ctx input_buf;
/* Ring buffer used to store output samples between process calls. */
struct ring_buf output_ringbuf;
uint8_t output_ringbuf_data[SAMPLE_RATE_CONVERTER_RINGBUF_SIZE];
/* Contexts for the CMSIS DSP filter functions. */
union {
#ifdef CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_16
arm_fir_interpolate_instance_q15 fir_interpolate_q15;
arm_fir_decimate_instance_q15 fir_decimate_q15;
#elif CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_32
arm_fir_interpolate_instance_q31 fir_interpolate_q31;
arm_fir_decimate_instance_q31 fir_decimate_q31;
#endif
};
/* State buffers used by the CMSIS DSP filters to keep history of the stream between process
* calls.
*/
#ifdef CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_16
q15_t state_buf_15[SAMPLE_RATE_CONVERTER_STATE_BUFFER_SIZE];
#elif CONFIG_SAMPLE_RATE_CONVERTER_BIT_DEPTH_32
q31_t state_buf_31[SAMPLE_RATE_CONVERTER_STATE_BUFFER_SIZE];
#endif
};
/**
* @brief Open the sample rate converter for a new context.
*
* @details Sets the entire context to 0 to ensure it is ready for a new sample rate conversion
* context. This should be done before a context is used with a new stream, and does
* not need to be called if the parameters for a conversion context changes during the
* stream.
*
* @param[out] ctx Pointer to the sample rate conversion context.
*
* @retval 0 On success.
* @retval -EINVAL NULL pointer given for context.
*/
int sample_rate_converter_open(struct sample_rate_converter_ctx *ctx);
/**
* @brief Process input samples and produce output samples with new sample rate.
*
* @details Takes samples with the input sample rate, and converts them to the new requested
* sample rate by filtering the samples before adding or removing samples. The context
* for the sample rate conversion does not need to be initialized before calling
* process, and if any parameters change between calls the context will be
* re-inititalized. As the process has requirements for the number of input samples
* based on the conversion ratio, the module will buffer both input and output bytes
* when needed to meet this criteria.
*
* @param[in,out] ctx Pointer to the sample rate conversion context.
* @param[in] filter Filter type to be used for the conversion.
* @param[in] input Pointer to samples to process.
* @param[in] input_size Size of the input in bytes.
* @param[in] input_sample_rate Sample rate of the input bytes.
* @param[out] output Array that output will be written.
* @param[in] output_size Size of the output array in bytes.
* @param[out] output_written Number of bytes written to output.
* @param[in] output_sample_rate Sample rate of output.
*
* @retval 0 On success.
* @retval -EINVAL Invalid parameters for sample rate conversion.
* @retval -EFAULT Output ring buffer has either not enough bytes to output, or not enough
* space to store bytes.
*/
int sample_rate_converter_process(struct sample_rate_converter_ctx *ctx,
enum sample_rate_converter_filter filter, void const *const input,
size_t input_size, uint32_t input_sample_rate, void *const output,
size_t output_size, size_t *output_written,
uint32_t output_sample_rate);
/**
* @}
*/
#endif /* _SAMPLE_RATE_CONVERTER_H_ */