Skip to content

Commit 0a87c0a

Browse files
gWaceyrlubos
authored andcommitted
lib: tone: Generate tones of differing sample and carrier widths
OCT-3436 Update the library to allow tones of 8-, 16-, 24- and 32-bit samples and 8-, 16 and 32-bit carrier widths to be generated. Twister test cases included. Signed-off-by: Graham Wacey <[email protected]>
1 parent ef853d8 commit 0a87c0a

File tree

3 files changed

+402
-15
lines changed

3 files changed

+402
-15
lines changed

include/tone.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@
2525
* @brief Generates one full pulse-code modulation (PCM) period of a tone with the
2626
* given parameters.
2727
*
28+
* @note The returned frequency of the tone is the quotient of the sample_freq_hz
29+
* divided by the tone_freq_hz.
30+
*
2831
* @param tone User provided buffer. Must be large enough to hold
2932
* the generated PCM tone, depending on settings.
30-
* @param tone_size Resulting tone size.
33+
* @param tone_size Resulting tone size in bytes.
3134
* @param tone_freq_hz The desired tone frequency in the range [100..10000] Hz.
3235
* @param smpl_freq_hz Sampling frequency.
3336
* @param amplitude Amplitude in the range [0..1].
@@ -40,6 +43,28 @@
4043
int tone_gen(int16_t *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t smpl_freq_hz,
4144
float amplitude);
4245

46+
/**
47+
* @brief Generates one full pulse-code modulation (PCM) period of a tone with the
48+
* given parameters.
49+
*
50+
* @note The returned frequency of the tone is the quotient of the sample_freq_hz
51+
* divided by the tone_freq_hz.
52+
* @note The routine returns the tone samples left aligned in the carrier.
53+
*
54+
* @param tone User provided buffer. Must be large enough to hold
55+
* the generated PCM tone, depending on settings.
56+
* @param tone_size Resulting tone size in bytes.
57+
* @param tone_freq_hz The desired tone frequency in the range [100..10000] Hz.
58+
* @param sample_freq_hz Sampling frequency.
59+
* @param sample_bits Number of bits to represent a sample (i.e. 8, 16, 24 or 32 bits).
60+
* @param carrier_bits Number of bits to carry a sample (i.e. 8, 16 or 32 bit).
61+
* @param amplitude Amplitude in the range [0..1].
62+
*
63+
* @return 0 if successful, error otherwise.
64+
*/
65+
int tone_gen_size(void *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t sample_freq_hz,
66+
uint8_t sample_bits, uint8_t carrier_bits, float amplitude);
67+
4368
/**
4469
* @}
4570
*/

lib/tone/tone.c

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <stdio.h>
1212
#include <arm_math.h>
1313

14-
#define FREQ_LIMIT_LOW 100
14+
#define FREQ_LIMIT_LOW 100
1515
#define FREQ_LIMIT_HIGH 10000
1616

1717
int tone_gen(int16_t *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t smpl_freq_hz,
@@ -31,7 +31,7 @@ int tone_gen(int16_t *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t s
3131

3232
uint32_t samples_for_one_period = smpl_freq_hz / tone_freq_hz;
3333

34-
for (uint32_t i = 0; i < samples_for_one_period; i++) {
34+
for (size_t i = 0; i < samples_for_one_period; i++) {
3535
float curr_val = i * 2 * PI / samples_for_one_period;
3636
float32_t res = arm_sin_f32(curr_val);
3737
/* Generate one sine wave */
@@ -43,3 +43,123 @@ int tone_gen(int16_t *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t s
4343

4444
return 0;
4545
}
46+
47+
static int tone_gen_8(int8_t *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t smpl_freq_hz,
48+
uint8_t scale, uint32_t max, float amplitude)
49+
{
50+
uint32_t samples_for_one_period = smpl_freq_hz / tone_freq_hz;
51+
52+
tone[0] = 0;
53+
54+
for (size_t i = 1, j = samples_for_one_period - 1; i <= samples_for_one_period / 2;
55+
i++, j--) {
56+
float curr_val = i * 2 * PI / samples_for_one_period;
57+
float32_t res = arm_sin_f32(curr_val);
58+
/* Generate one sine wave */
59+
tone[i] = amplitude * res * max;
60+
tone[i] <<= scale;
61+
tone[j] = -tone[i];
62+
}
63+
64+
*tone_size = (size_t)samples_for_one_period * sizeof(int8_t);
65+
66+
return 0;
67+
}
68+
69+
static int tone_gen_16(int16_t *tone, size_t *tone_size, uint16_t tone_freq_hz,
70+
uint32_t smpl_freq_hz, uint8_t scale, uint32_t max, float amplitude)
71+
{
72+
uint32_t samples_for_one_period = smpl_freq_hz / tone_freq_hz;
73+
74+
tone[0] = 0;
75+
76+
for (size_t i = 1, j = samples_for_one_period - 1; i <= samples_for_one_period / 2;
77+
i++, j--) {
78+
float curr_val = i * 2 * PI / samples_for_one_period;
79+
float32_t res = arm_sin_f32(curr_val);
80+
/* Generate one sine wave */
81+
tone[i] = amplitude * res * max;
82+
tone[i] <<= scale;
83+
tone[j] = -tone[i];
84+
}
85+
86+
*tone_size = (size_t)samples_for_one_period * sizeof(int16_t);
87+
88+
return 0;
89+
}
90+
91+
static int tone_gen_32(int32_t *tone, size_t *tone_size, uint16_t tone_freq_hz,
92+
uint32_t smpl_freq_hz, uint8_t scale, int32_t max, float amplitude)
93+
{
94+
uint32_t samples_for_one_period = smpl_freq_hz / tone_freq_hz;
95+
96+
tone[0] = 0;
97+
98+
for (size_t i = 1, j = samples_for_one_period - 1; i <= samples_for_one_period / 2;
99+
i++, j--) {
100+
float curr_val = i * 2 * PI / samples_for_one_period;
101+
float32_t res = arm_sin_f32(curr_val);
102+
/* Generate one sine wave */
103+
tone[i] = amplitude * res * max;
104+
tone[i] <<= scale;
105+
tone[j] = -tone[i];
106+
}
107+
108+
*tone_size = (size_t)samples_for_one_period * sizeof(int32_t);
109+
110+
return 0;
111+
}
112+
113+
int tone_gen_size(void *tone, size_t *tone_size, uint16_t tone_freq_hz, uint32_t sample_freq_hz,
114+
uint8_t sample_bits, uint8_t carrier_bits, float amplitude)
115+
{
116+
int ret;
117+
uint8_t scale;
118+
int32_t max;
119+
120+
if (tone == NULL || tone_size == NULL) {
121+
return -ENXIO;
122+
}
123+
124+
if (!sample_freq_hz || tone_freq_hz < FREQ_LIMIT_LOW || tone_freq_hz > FREQ_LIMIT_HIGH ||
125+
sample_freq_hz % tone_freq_hz) {
126+
return -EINVAL;
127+
}
128+
129+
if (amplitude > 1 || amplitude <= 0) {
130+
return -EPERM;
131+
}
132+
133+
if (!sample_bits || !carrier_bits || sample_bits > carrier_bits) {
134+
return -EINVAL;
135+
}
136+
137+
if (sample_bits == 8) {
138+
max = INT8_MAX;
139+
} else if (sample_bits == 16) {
140+
max = INT16_MAX;
141+
} else if (sample_bits == 24) {
142+
max = 0x007FFFFF;
143+
} else if (sample_bits == 32) {
144+
max = INT32_MAX;
145+
} else {
146+
return -EINVAL;
147+
}
148+
149+
scale = carrier_bits - sample_bits;
150+
151+
if (carrier_bits == 8) {
152+
ret = tone_gen_8((int8_t *)tone, tone_size, tone_freq_hz, sample_freq_hz, scale,
153+
max, amplitude);
154+
} else if (carrier_bits == 16) {
155+
ret = tone_gen_16((int16_t *)tone, tone_size, tone_freq_hz, sample_freq_hz, scale,
156+
max, amplitude);
157+
} else if (carrier_bits == 32) {
158+
ret = tone_gen_32((int32_t *)tone, tone_size, tone_freq_hz, sample_freq_hz, scale,
159+
max, amplitude);
160+
} else {
161+
return -EINVAL;
162+
}
163+
164+
return 0;
165+
}

0 commit comments

Comments
 (0)