1
1
#include "dtmf_dolphin_audio.h"
2
2
3
- DTMFDolphinAudio * current_player ;
3
+ DTMFDolphinAudio * current_player ;
4
4
5
5
static void dtmf_dolphin_audio_dma_isr (void * ctx ) {
6
- FuriMessageQueue * event_queue = ctx ;
6
+ FuriMessageQueue * event_queue = ctx ;
7
7
8
- if (LL_DMA_IsActiveFlag_HT1 (DMA1 )) {
8
+ if (LL_DMA_IsActiveFlag_HT1 (DMA1 )) {
9
9
LL_DMA_ClearFlag_HT1 (DMA1 );
10
10
11
11
DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer };
@@ -21,13 +21,13 @@ static void dtmf_dolphin_audio_dma_isr(void* ctx) {
21
21
}
22
22
23
23
void dtmf_dolphin_audio_clear_samples (DTMFDolphinAudio * player ) {
24
- for (size_t i = 0 ; i < player -> buffer_length ; i ++ ) {
24
+ for (size_t i = 0 ; i < player -> buffer_length ; i ++ ) {
25
25
player -> sample_buffer [i ] = 0 ;
26
26
}
27
27
}
28
28
29
29
DTMFDolphinOsc * dtmf_dolphin_osc_alloc () {
30
- DTMFDolphinOsc * osc = malloc (sizeof (DTMFDolphinOsc ));
30
+ DTMFDolphinOsc * osc = malloc (sizeof (DTMFDolphinOsc ));
31
31
osc -> cached_freq = 0 ;
32
32
osc -> offset = 0 ;
33
33
osc -> period = 0 ;
@@ -36,7 +36,7 @@ DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
36
36
}
37
37
38
38
DTMFDolphinPulseFilter * dtmf_dolphin_pulse_filter_alloc () {
39
- DTMFDolphinPulseFilter * pf = malloc (sizeof (DTMFDolphinPulseFilter ));
39
+ DTMFDolphinPulseFilter * pf = malloc (sizeof (DTMFDolphinPulseFilter ));
40
40
pf -> duration = 0 ;
41
41
pf -> period = 0 ;
42
42
pf -> offset = 0 ;
@@ -45,7 +45,7 @@ DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() {
45
45
}
46
46
47
47
DTMFDolphinAudio * dtmf_dolphin_audio_alloc () {
48
- DTMFDolphinAudio * player = malloc (sizeof (DTMFDolphinAudio ));
48
+ DTMFDolphinAudio * player = malloc (sizeof (DTMFDolphinAudio ));
49
49
player -> buffer_length = SAMPLE_BUFFER_LENGTH ;
50
50
player -> half_buffer_length = SAMPLE_BUFFER_LENGTH / 2 ;
51
51
player -> sample_buffer = malloc (sizeof (uint16_t ) * player -> buffer_length );
@@ -61,64 +61,66 @@ DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
61
61
}
62
62
63
63
size_t calc_waveform_period (float freq ) {
64
- if (!freq ) {
64
+ if (!freq ) {
65
65
return 0 ;
66
66
}
67
67
// DMA Rate calculation, thanks to Dr_Zlo
68
- float dma_rate = CPU_CLOCK_FREQ \
69
- / 2 \
70
- / DTMF_DOLPHIN_HAL_DMA_PRESCALER \
71
- / (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1 );
68
+ float dma_rate = CPU_CLOCK_FREQ / 2 / DTMF_DOLPHIN_HAL_DMA_PRESCALER /
69
+ (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1 );
72
70
73
71
// Using a constant scaling modifier, which likely represents
74
72
// the combined system overhead and isr latency.
75
- return (uint16_t ) dma_rate * 2 / freq * 0.801923 ;
73
+ return (uint16_t )dma_rate * 2 / freq * 0.801923 ;
76
74
}
77
75
78
76
void osc_generate_lookup_table (DTMFDolphinOsc * osc , float freq ) {
79
- if (osc -> lookup_table != NULL ) {
77
+ if (osc -> lookup_table != NULL ) {
80
78
free (osc -> lookup_table );
81
79
}
82
80
osc -> offset = 0 ;
83
81
osc -> cached_freq = freq ;
84
82
osc -> period = calc_waveform_period (freq );
85
- if (!osc -> period ) {
83
+ if (!osc -> period ) {
86
84
osc -> lookup_table = NULL ;
87
85
return ;
88
86
}
89
87
osc -> lookup_table = malloc (sizeof (float ) * osc -> period );
90
88
91
- for (size_t i = 0 ; i < osc -> period ; i ++ ) {
89
+ for (size_t i = 0 ; i < osc -> period ; i ++ ) {
92
90
osc -> lookup_table [i ] = sin (i * PERIOD_2_PI / osc -> period ) + 1 ;
93
91
}
94
92
}
95
93
96
- void filter_generate_lookup_table (DTMFDolphinPulseFilter * pf , uint16_t pulses , uint16_t pulse_ms , uint16_t gap_ms ) {
97
- if (pf -> lookup_table != NULL ) {
94
+ void filter_generate_lookup_table (
95
+ DTMFDolphinPulseFilter * pf ,
96
+ uint16_t pulses ,
97
+ uint16_t pulse_ms ,
98
+ uint16_t gap_ms ) {
99
+ if (pf -> lookup_table != NULL ) {
98
100
free (pf -> lookup_table );
99
101
}
100
102
pf -> offset = 0 ;
101
103
102
- uint16_t gap_period = calc_waveform_period (1000 / (float ) gap_ms );
103
- uint16_t pulse_period = calc_waveform_period (1000 / (float ) pulse_ms );
104
+ uint16_t gap_period = calc_waveform_period (1000 / (float )gap_ms );
105
+ uint16_t pulse_period = calc_waveform_period (1000 / (float )pulse_ms );
104
106
pf -> period = pulse_period + gap_period ;
105
107
106
- if (!pf -> period ) {
108
+ if (!pf -> period ) {
107
109
pf -> lookup_table = NULL ;
108
110
return ;
109
111
}
110
112
pf -> duration = pf -> period * pulses ;
111
113
pf -> lookup_table = malloc (sizeof (bool ) * pf -> duration );
112
114
113
- for (size_t i = 0 ; i < pf -> duration ; i ++ ) {
115
+ for (size_t i = 0 ; i < pf -> duration ; i ++ ) {
114
116
pf -> lookup_table [i ] = i % pf -> period < pulse_period ;
115
117
}
116
118
}
117
119
118
120
float sample_frame (DTMFDolphinOsc * osc ) {
119
121
float frame = 0.0 ;
120
122
121
- if (osc -> period ) {
123
+ if (osc -> period ) {
122
124
frame = osc -> lookup_table [osc -> offset ];
123
125
osc -> offset = (osc -> offset + 1 ) % osc -> period ;
124
126
}
@@ -129,8 +131,8 @@ float sample_frame(DTMFDolphinOsc* osc) {
129
131
bool sample_filter (DTMFDolphinPulseFilter * pf ) {
130
132
bool frame = true;
131
133
132
- if (pf -> duration ) {
133
- if (pf -> offset < pf -> duration ) {
134
+ if (pf -> duration ) {
135
+ if (pf -> offset < pf -> duration ) {
134
136
frame = pf -> lookup_table [pf -> offset ];
135
137
pf -> offset = pf -> offset + 1 ;
136
138
} else {
@@ -142,14 +144,14 @@ bool sample_filter(DTMFDolphinPulseFilter* pf) {
142
144
}
143
145
144
146
void dtmf_dolphin_osc_free (DTMFDolphinOsc * osc ) {
145
- if (osc -> lookup_table != NULL ) {
147
+ if (osc -> lookup_table != NULL ) {
146
148
free (osc -> lookup_table );
147
149
}
148
150
free (osc );
149
151
}
150
152
151
153
void dtmf_dolphin_filter_free (DTMFDolphinPulseFilter * pf ) {
152
- if (pf -> lookup_table != NULL ) {
154
+ if (pf -> lookup_table != NULL ) {
153
155
free (pf -> lookup_table );
154
156
}
155
157
free (pf );
@@ -165,22 +167,19 @@ void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) {
165
167
current_player = NULL ;
166
168
}
167
169
168
-
169
170
bool generate_waveform (DTMFDolphinAudio * player , uint16_t buffer_index ) {
170
171
uint16_t * sample_buffer_start = & player -> sample_buffer [buffer_index ];
171
172
172
- for (size_t i = 0 ; i < player -> half_buffer_length ; i ++ ) {
173
+ for (size_t i = 0 ; i < player -> half_buffer_length ; i ++ ) {
173
174
float data = 0 ;
174
- if (player -> osc2 -> period ) {
175
- data = \
176
- (sample_frame (player -> osc1 ) / 2 ) + \
177
- (sample_frame (player -> osc2 ) / 2 );
175
+ if (player -> osc2 -> period ) {
176
+ data = (sample_frame (player -> osc1 ) / 2 ) + (sample_frame (player -> osc2 ) / 2 );
178
177
} else {
179
178
data = (sample_frame (player -> osc1 ));
180
179
}
181
180
data *= sample_filter (player -> filter ) ? player -> volume : 0.0 ;
182
- data *= UINT8_MAX / 2 ; // scale -128..127
183
- data += UINT8_MAX / 2 ; // to unsigned
181
+ data *= UINT8_MAX / 2 ; // scale -128..127
182
+ data += UINT8_MAX / 2 ; // to unsigned
184
183
185
184
if (data < 0 ) {
186
185
data = 0 ;
@@ -196,8 +195,13 @@ bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) {
196
195
return true;
197
196
}
198
197
199
- bool dtmf_dolphin_audio_play_tones (float freq1 , float freq2 , uint16_t pulses , uint16_t pulse_ms , uint16_t gap_ms ) {
200
- if (current_player != NULL && current_player -> playing ) {
198
+ bool dtmf_dolphin_audio_play_tones (
199
+ float freq1 ,
200
+ float freq2 ,
201
+ uint16_t pulses ,
202
+ uint16_t pulse_ms ,
203
+ uint16_t gap_ms ) {
204
+ if (current_player != NULL && current_player -> playing ) {
201
205
// Cannot start playing while still playing something else
202
206
return false;
203
207
}
@@ -213,7 +217,8 @@ bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, ui
213
217
dtmf_dolphin_speaker_init ();
214
218
dtmf_dolphin_dma_init ((uint32_t )current_player -> sample_buffer , current_player -> buffer_length );
215
219
216
- furi_hal_interrupt_set_isr (FuriHalInterruptIdDma1Ch1 , dtmf_dolphin_audio_dma_isr , current_player -> queue );
220
+ furi_hal_interrupt_set_isr (
221
+ FuriHalInterruptIdDma1Ch1 , dtmf_dolphin_audio_dma_isr , current_player -> queue );
217
222
218
223
dtmf_dolphin_dma_start ();
219
224
dtmf_dolphin_speaker_start ();
@@ -222,11 +227,12 @@ bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, ui
222
227
}
223
228
224
229
bool dtmf_dolphin_audio_stop_tones () {
225
- if (current_player != NULL && !current_player -> playing ) {
230
+ if (current_player != NULL && !current_player -> playing ) {
226
231
// Can't stop a player that isn't playing.
227
232
return false;
228
233
}
229
- while (current_player -> filter -> offset > 0 && current_player -> filter -> offset < current_player -> filter -> duration ) {
234
+ while (current_player -> filter -> offset > 0 &&
235
+ current_player -> filter -> offset < current_player -> filter -> duration ) {
230
236
// run remaining ticks if needed to complete filter sequence
231
237
dtmf_dolphin_audio_handle_tick ();
232
238
}
@@ -236,20 +242,20 @@ bool dtmf_dolphin_audio_stop_tones() {
236
242
furi_hal_interrupt_set_isr (FuriHalInterruptIdDma1Ch1 , NULL , NULL );
237
243
238
244
dtmf_dolphin_audio_free (current_player );
239
-
245
+
240
246
return true;
241
247
}
242
248
243
249
bool dtmf_dolphin_audio_handle_tick () {
244
250
bool handled = false;
245
251
246
- if (current_player ) {
252
+ if (current_player ) {
247
253
DTMFDolphinCustomEvent event ;
248
254
if (furi_message_queue_get (current_player -> queue , & event , 250 ) == FuriStatusOk ) {
249
255
if (event .type == DTMFDolphinEventDMAHalfTransfer ) {
250
256
generate_waveform (current_player , 0 );
251
257
handled = true;
252
- } else if (event .type == DTMFDolphinEventDMAFullTransfer ) {
258
+ } else if (event .type == DTMFDolphinEventDMAFullTransfer ) {
253
259
generate_waveform (current_player , current_player -> half_buffer_length );
254
260
handled = true;
255
261
}
0 commit comments