ARMEBS4  revision-26.06.2015
audio.c
Go to the documentation of this file.
1 /************************************************************************//**
2  * \file heivs/audio.c
3  * \brief ARMEBS4 audio
4  * \author marc dot pignat at hevs dot ch & Pascal Sartoretti (sap at hevs dot ch)
5  ***************************************************************************/
6 
7 #include "heivs/audio.h"
8 #include "heivs/audio_stm32.h"
9 #include "heivs/audio_codec.h"
10 #include "stm32/stm32f4xx_rcc.h"
11 #include "stm32/stm32f4xx_spi.h"
12 #include "stm32/stm32f4xx_dma.h"
13 #include "stm32/stm32f4xx_misc.h"
14 #include "heivs/delay.h"
15 #include "heivs/time.h"
16 #include <math.h>
17 
18 #include "heivs/config.h"
19 #if USE_FREERTOS
20 #include "freertos/FreeRTOS.h"
21 #endif
22 
23 
24 /**
25  * A fast sine wave generator, by Charles Praplan
26  *
27  * The following difference equation implements an IIR filter whose poles
28  * are on the unit circle if -2 < f_a < 2.
29  *
30  * A*sin(2*pi*f0/FS)
31  * H(z) = -----------------------
32  * 1 - f_a*(z^-1) + (z^-2)
33  *
34  * We are here interested in the impulse response which is a pure sine wave.
35  * Instead of applying a delta impulse at the input of the system we provide
36  * initial conditions.
37  *
38  * If a little change occurs in the 'a' (due to numerical precision), the
39  * stability is maintained as far the coefficient 'a' stays in the limits
40  * mentioned above. But both the frequency and the amplitude of the wave change.
41  *
42  * The start conditions of the digital oscillator implemented in the
43  * sine_wave_sample function are 2 succeeding samples of the sine wave.
44  * This 2 values and the knowledge of the frequency (contained in the
45  * coefficient 'a') determine completely the sine wave.
46  *
47  * We calculate here the start conditions for k = -1 and k = 0 so that
48  * the first calculated sample is non zero if phase = 0.
49  */
51 {
52  float f_a;
53  float af_Y[2];
54 };
55 
56 /**
57  * \brief Fast sine wave generator initialization
58  *
59  * \param state, the internal state of the generator
60  * \param amplitude, the amplitude of the sine wave
61  * \param fs, the sampling frequency (in Hz)
62  * \param frequency, the sine frequency (in Hz)
63  * \param phase, the start phase (in radians)
64  *
65  * \return #NO_ERROR for no problem
66  *
67  * \see sine_wave_sample
68  *
69  * \warning : on a TMS320C6211, the amplitude of the sine wave increases slowly
70  */
71 static void init_sine_wave_float(struct sine_wave_state_t *state, float amplitude, float fs, float frequency, float phase)
72 {
73  state->f_a = 2 * cos(2 * M_PI * frequency/fs);
74  state->af_Y[1] = amplitude * sin(-2 * M_PI * frequency/fs + phase);
75  state->af_Y[0] = amplitude * sin(phase);
76 }
77 
78 /**
79  * \brief Fast sine wave generator
80  *
81  * \param state, the internal state of the generator
82  * \return the value of the current sample
83  *
84  * \see sine_wave_init
85  */
86 static float gen_sine_wave_float(struct sine_wave_state_t *state)
87 {
88  float result;
89  result = state->f_a * state->af_Y[0] - state->af_Y[1];
90 
91  state->af_Y[1] = state->af_Y[0];
92  state->af_Y[0] = result;
93 
94  return result;
95 }
96 
97 status_e Audio_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void (*done)(const void *))
98 {
99  return AudioSTM32_Stream_Play_Init(length, buffer0, buffer1, done);
100 }
101 
103 {
105 }
106 
108 {
110 }
111 
113 {
114  return AudioSTM32_Stream_Play_Pause();
115 }
116 
117 status_e Audio_Stream_Play(const void *data)
118 {
119  return AudioSTM32_Stream_Play(data);
120 }
121 
122 status_e Audio_Stream_Record_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
123 {
124  return AudioSTM32_Stream_Record_Init(length, buffer0, buffer1, done);
125 }
126 
128 {
129  return AudioSTM32_Stream_Record_Stop();
130 }
131 
132 struct setup_t
133 {
134  uint32_t fs;
135  uint32_t byte_per_sample;
136 };
137 
138 static struct setup_t setup;
139 
140 status_e Audio_Init(uint32_t fs, uint32_t sample_size)
141 {
142  status_e status;
143  setup.fs = fs;
144 
145  switch (sample_size)
146  {
147  case 16:
148  setup.byte_per_sample = 2;
149  break;
150  case 24:
151  setup.byte_per_sample = 3;
152  break;
153  case 32:
154  setup.byte_per_sample = 4;
155  break;
156  default:
157  return ERROR_BAD_PARAM;
158  }
159 
160  status = AudioCodec_Init(fs);
161  if (status != NO_ERROR)
162  {
163  return status;
164  }
165 
168 
169  status = AudioSTM32_Init(fs, sample_size);
170  if (status != NO_ERROR)
171  {
172  return status;
173  }
174 
175  return NO_ERROR;
176 }
177 
178 static void send_when_ready(uint16_t data)
179 {
180  while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
181  SPI_I2S_SendData(SPI2, data);
182 }
183 
184 status_e Audio_PlaySin(uint16_t freq, uint16_t duration)
185 {
186  timeout_t elapsed;
187  struct sine_wave_state_t sine_state;
188 
189  init_sine_wave_float(&sine_state, 1.0, setup.fs, freq, 0);
190  elapsed = time_set_timeout_ms(duration);
191 
192  switch (setup.byte_per_sample)
193  {
194  case 2:
195  while (!time_elapsed(elapsed))
196  {
197  int16_t sample = (gen_sine_wave_float(&sine_state)*INT16_MAX/2);
198  send_when_ready(sample);
199  send_when_ready(sample);
200  }
201  break;
202  case 3:
203  while (!time_elapsed(elapsed))
204  {
205  int32_t sample = (gen_sine_wave_float(&sine_state)*INT32_MAX/2);
206  sample >>=8;
207  int32_t left = sample;
208  int32_t right = sample;
209 
210  send_when_ready(left << 8);
211  send_when_ready((left & 0xff) >> 8 | (right & 0xff) << 8);
212  send_when_ready(right >> 8);
213  }
214  break;
215  case 4:
216  while (!time_elapsed(elapsed))
217  {
218  int32_t sample = (gen_sine_wave_float(&sine_state)*INT32_MAX/2);
219  send_when_ready(sample >> 16);
220  send_when_ready(sample);
221  send_when_ready(sample >> 16);
222  send_when_ready(sample);
223  }
224  break;
225  }
226 
227  return NO_ERROR;
228 }
229 
230 status_e Audio_Play(const int16_t *src, uint32_t length)
231 {
232  return AudioSTM32_Play(src, length);
233 }
234 
235 status_e Audio_Record(int16_t *dest, uint32_t length)
236 {
237  return AudioSTM32_Record(dest, length);
238 }
239 
241 {
242  return AudioCodec_VolumeSpeaker(volume);
243 }
244 
246 {
247  return AudioCodec_VolumeHeadphone(volume);
248 }
249 
This file contains all the functions prototypes for the RCC firmware library.
status_e AudioSTM32_Stream_Play_Status(void)
Is AudioSTM32_Stream_Play ready for the next buffer?
Definition: audio_stm32.c:469
ARMEBS4 audio.
status_e AudioSTM32_Stream_Play_Stop(void)
Audio stream stop.
Definition: audio_stm32.c:462
ARMEBS4 audio codec support.
simple time abstraction
This file contains all the functions prototypes for the SPI firmware library.
static struct audio_setup_t setup
Definition: audio_stm32.c:90
libheivs configuration file
status_e Audio_Stream_Play_Pause(void)
Audio stream play pause.
Definition: audio.c:112
static uint32_t time_elapsed(timeout_t timeout)
Is this time passed?
Definition: time.h:71
status_e Audio_Stream_Play(const void *data)
Audio stream play buffer.
Definition: audio.c:117
status_e Audio_SetVolumeSpeaker(uint8_t volume)
Set the volume for speaker output.
Definition: audio.c:240
status_e Audio_Stream_Play_Stop(void)
Audio stream playing stop.
Definition: audio.c:102
Parameter unsupported.
Definition: error.h:56
This file contains all the functions prototypes for the DMA firmware library.
status_e Audio_Stream_Record_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
Audio stream record initialization.
Definition: audio.c:122
status_e Audio_Stream_Record_Stop(void)
Audio stream record stop.
Definition: audio.c:127
status_e AudioSTM32_Stream_Play(const void *data)
Audio stream play buffer.
Definition: audio_stm32.c:479
status_e Audio_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
Audio stream play initialization.
Definition: audio.c:97
static void init_sine_wave_float(struct sine_wave_state_t *state, float amplitude, float fs, float frequency, float phase)
Fast sine wave generator initialization.
Definition: audio.c:71
simple delays
status_e AudioSTM32_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
Audio stream initialization.
Definition: audio_stm32.c:403
status_e Audio_Record(int16_t *dest, uint32_t length)
Record a sound (polling mode)
Definition: audio.c:235
Timeout structure.
Definition: time.h:34
static float gen_sine_wave_float(struct sine_wave_state_t *state)
Fast sine wave generator.
Definition: audio.c:86
status_e Audio_Stream_Play_Status(void)
Is Audio_Stream_Play ready for the next buffer?
Definition: audio.c:107
timeout_t time_set_timeout_ms(uint32_t ms)
Set an obscure time at least ms milliseconds in the future.
Definition: time.c:15
status_e Audio_SetVolumeHeadphone(uint8_t volume)
Set the volume for headphone output.
Definition: audio.c:245
status_e
Known errors.
Definition: error.h:21
status_e AudioSTM32_Play(const int16_t *dataBuf, uint32_t length)
Play a sound (polling mode)
Definition: audio_stm32.c:523
No error.
Definition: error.h:28
status_e Audio_Init(uint32_t fs, uint32_t sample_size)
Audio initialization.
Definition: audio.c:140
status_e Audio_PlaySin(uint16_t freq, uint16_t duration)
Play a sine sound at a given frequency.
Definition: audio.c:184
status_e Audio_Play(const int16_t *src, uint32_t length)
Play a sound (polling mode)
Definition: audio.c:230