1313
1414AudioClass Audio;
1515
16- /* Begin class can be extended to support more options */
17- int AudioClass::begin (uint32_t sampleRate, uint32_t msPreBuffer, AudioMode audioMode) {
18- int ret;
16+ /* *
17+ * @brief Stops audio playing/recording and Power down the Audio Codec.
18+ * @param sampleRate: sample rate of the sound file in Hz (ex: 48000Hz for 48kHz)
19+ * @param preBufferSize: size of the audio out buffer (default 1024)
20+ * @param audioMode: defined which audio path to configured:
21+ * - AUDIO_IN
22+ * - AUDIO_OUT (default)
23+ * - AUDIO_BOTH
24+ * @note: begin method can be extended to support more options
25+ * @retval AUDIO_OK if correct init, else wrong
26+ */
27+ int AudioClass::begin (uint32_t sampleRate, uint32_t preBufferSize, AudioMode audioMode) {
28+ int ret = AUDIO_OK;
1929 mode = audioMode;
2030
2131 /* Audio Out */
22- if (mode != AUDIO_IN)
23- {
24- bufferOutSize = 2 * 1024 * sizeof (uint32_t );
32+ if (mode != AUDIO_IN) {
33+ if (bufferOut != NULL ) {
34+ free (bufferOut);
35+ bufferOut = NULL ;
36+ }
37+ bufferOutSize = 2 * preBufferSize * sizeof (uint32_t );
2538 bufferOut = (uint8_t *) malloc (bufferOutSize);
2639
2740 /* Buffering starts from the beginning */
@@ -30,161 +43,224 @@ int AudioClass::begin(uint32_t sampleRate, uint32_t msPreBuffer, AudioMode audio
3043 last = bufferOut + bufferOutSize;
3144 next = bufferOut;
3245 }
33-
46+ /* Required even if AUDIO_IN only */
3447 ret = BSP_AUDIO_OUT_Init (OUTPUT_DEVICE_HEADPHONE, 0 , sampleRate);
48+ audio_out_init = ((mode != AUDIO_IN) && (ret == AUDIO_OK)) ? true : false ;
3549
3650 /* Audio In */
37- if (mode != AUDIO_OUT)
38- {
51+ if ((mode != AUDIO_OUT) && (ret == AUDIO_OK)) {
52+ bufferIn_fptr = 44 ; // Wave header size
53+ bufferInFull = false ;
54+ bufferIn_ptr = 0 ;
55+ bufferIn_offset = 0 ;
3956 ret += BSP_AUDIO_IN_Init (INPUT_DEVICE_DIGITAL_MICROPHONE_2, 0 , sampleRate);
57+ audio_in_init = (ret == AUDIO_OK) ? true : false ;
58+ /* Start the record*/
4059 ret += BSP_AUDIO_IN_Record ((uint16_t *)&bufferIn[0 ], bufferInSize);
41- bufferIn_fptr += 44 ;
4260 }
4361
4462 return ret;
4563}
4664
47- void AudioClass::end () {
48- if (mode != AUDIO_OUT)
49- {
65+ /* *
66+ * @brief Ends audio playing/recording and Power down the Audio Codec.
67+ * @param Option: could be one of the following parameters
68+ * - CODEC_PDWN_SW: for software power off (by writing registers).
69+ * Then no need to reconfigure the Codec after power on. (default)
70+ * - CODEC_PDWN_HW: completely shut down the codec (physically).
71+ * Then need to reconfigure the Codec after power on.
72+ * @retval AUDIO_OK if correct communication, else wrong communication
73+ * @note For Audio IN, begin() call is required in any case after called this function
74+ * even if CODEC_PDWN_SW is used.
75+ */
76+ uint32_t AudioClass::end (uint32_t Option) {
77+ uint32_t ret = AUDIO_OK;
78+
79+ if ((Option != CODEC_PDWN_SW) && (Option != CODEC_PDWN_HW)) {
80+ Option = CODEC_PDWN_SW; // Force stop to avoid any noise issue
81+ }
82+
83+ if ((audio_in_init) && (mode != AUDIO_OUT)) {
5084 /* Stop recorder */
51- BSP_AUDIO_IN_Stop (CODEC_PDWN_SW );
85+ ret = BSP_AUDIO_IN_Stop (Option );
5286 }
53- BSP_AUDIO_OUT_Stop (CODEC_PDWN_SW);
54- if (bufferOut)
55- {
87+ if (audio_in_init || audio_out_init) {
88+ ret |= BSP_AUDIO_OUT_Stop (Option);
89+ }
90+ audio_in_init = false ;
91+
92+ if (Option == CODEC_PDWN_HW) {
93+ audio_out_init = false ;
94+ if (bufferOut) {
5695 free (bufferOut);
5796 bufferOut = NULL ;
5897 }
98+ bufferOutSize = 0 ;
99+ }
100+ // Ensure to reset all variables
101+ // Audio Out
102+ half = bufferOut + bufferOutSize/2 ;
103+ last = bufferOut + bufferOutSize;
104+ next = bufferOut;
59105 running = NULL ;
106+ // Audio In
107+ bufferIn_fptr = 0 ;
108+ bufferInFull = false ;
109+ bufferIn_ptr = 0 ;
110+ bufferIn_offset = 0 ;
111+ return ret;
60112}
61113
62- void AudioClass::prepare (int16_t *buffer, int S, int volume){
114+ /* *
115+ * @brief Not used. Added to be inline with Arduino Audio library
116+ * @param buffer
117+ * @param S
118+ * @param volume
119+ * @note: See: https://www.arduino.cc/en/Reference/Audio
120+ * @retval None
121+ */
122+ void AudioClass::prepare (int16_t *buffer, int S, int volume) {
63123 uint16_t *ubuffer = (uint16_t *) buffer;
64124
65125 if (volume >= 100 )
66126 volume = 100 ;
67127 if (volume <= 0 )
68128 volume = 0 ;
69-
70- if (mode == AUDIO_OUT)
71- BSP_AUDIO_OUT_SetVolume (volume);
72- if (mode == AUDIO_IN)
73- BSP_AUDIO_IN_SetVolume (volume);
74- if (mode == AUDIO_BOTH) {
75- BSP_AUDIO_OUT_SetVolume (volume);
76- BSP_AUDIO_IN_SetVolume (volume);
77- }
78-
79-
129+ setVolume (volume);
80130}
81131
132+ /* *
133+ * @brief Playing audio stream from a data buffer for a determined size.
134+ * @param data: Pointer to the buffer
135+ * @param size: Number of audio data bytes
136+ * @retval Number of bytes written
137+ */
82138size_t AudioClass::write (const uint32_t *data, size_t size) {
83-
84139 int i;
140+ if (!audio_out_init) return 0 ;
141+
142+ if (size > (bufferOutSize / 2 ))
143+ return size;
144+
145+ /* Not running yet, need to fill-in full FIFO */
146+ if (running == NULL ) {
147+ memcpy (next, (uint8_t *) data, size);
148+ /* First half FIFO */
149+ if (next == bufferOut) {
150+ next = half;
151+ /* Second half FIfO, when copied, start playing */
152+ } else {
153+ next = bufferOut;
154+ running = bufferOut;
155+ BSP_AUDIO_OUT_Play ((uint16_t *)bufferOut, bufferOutSize);
156+ }
157+ _receivedBytes += size;
158+ return size;
159+ }
85160
86- if (size > (bufferOutSize / 2 ))
87- return size;
88-
89- /* not running yet, need to fill-in full FIFO */
90- if (running == NULL ) {
91- memcpy (next, (uint8_t *) data, size);
92- /* First half FIFO */
93- if (next == bufferOut) {
94- next = half;
95- /* Second half FIfO, when copied, start playing */
96- } else {
97- next = bufferOut;
98- running = bufferOut;
99- BSP_AUDIO_OUT_Play ((uint16_t *)bufferOut, bufferOutSize);
100- }
101- _receivedBytes += size;
102- return size;
103- }
104-
105- /* Wait for room in FIFO*/
106- while ((int )next == (int ) running);
161+ /* Wait for room in FIFO*/
162+ while ((int )next == (int ) running);
107163
108- _receivedBytes += size;
164+ _receivedBytes += size;
109165
110- /* If running is not next there is room in fifo */
111- memcpy (next,(uint8_t *) data, size);
166+ /* If running is not next there is room in fifo */
167+ memcpy (next,(uint8_t *) data, size);
112168
113- if (next == bufferOut) {
114- next = half;
115- } else {
116- next = bufferOut;
117- }
169+ if (next == bufferOut) {
170+ next = half;
171+ } else {
172+ next = bufferOut;
173+ }
118174
119175 return size;
120176}
121177
122- int AudioClass::receivedBytes (void )
123- {
178+ /* *
179+ * @brief Controls the current audio volume level.
180+ * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for
181+ * Mute and 100 for Max volume level).
182+ * @param audioMode: defined which audio path to configured:
183+ * - AUDIO_IN
184+ * - AUDIO_OUT (default)
185+ * - AUDIO_BOTH
186+ * @retval AUDIO_OK if correct communication, else wrong communication
187+ */
188+ uint32_t AudioClass::setVolume (uint8_t volume, AudioMode audioMode) {
189+ uint32_t ret = AUDIO_OK;
190+ if ((!audio_in_init) && (!audio_out_init))
191+ ret = AUDIO_ERROR;
192+ if ((audio_out_init) && (audioMode != AUDIO_IN))
193+ ret = BSP_AUDIO_OUT_SetVolume (volume);
194+ if ((audio_in_init) && (audioMode != AUDIO_OUT))
195+ ret |= BSP_AUDIO_IN_SetVolume (volume);
196+ return ret;
197+ }
198+
199+ /* Accessors */
200+ int AudioClass::receivedBytes (void ) {
124201 return _receivedBytes;
125202}
126203
127- int AudioClass::playedBytes (void )
128- {
204+ int AudioClass::playedBytes (void ) {
129205 return _playedBytes;
130206}
131- int AudioClass::getBufferOut (void )
132- {
207+ int AudioClass::getBufferOut (void ) {
133208 return (int )bufferOut;
134209}
135- int AudioClass::getHalf (void )
136- {
210+ int AudioClass::getHalf (void ) {
137211 return (int )half;
138212}
139- int AudioClass::getLast (void )
140- {
213+ int AudioClass::getLast (void ) {
141214 return (int )last;
142215}
143- int AudioClass::getBufferOutSize (void )
144- {
216+ int AudioClass::getBufferOutSize (void ) {
145217 return (int )bufferOutSize;
146218}
147219
148220extern int begin_status;
149- void BSP_AUDIO_OUT_HalfTransfer_CallBack (void )
150- {
151- if (Audio.running != NULL ) {
152- /* tell write function we're now playing the 2nd half*/
221+ /* *
222+ * @brief Manages the DMA Half Transfer complete event.
223+ */
224+ void BSP_AUDIO_OUT_HalfTransfer_CallBack (void ) {
225+ if (Audio.running != NULL ) {
226+ /* Tell write function we're now playing the 2nd half*/
153227 Audio.running = Audio.half ;
154228 Audio._playedBytes = (Audio.bufferOutSize /2 );
155229 }
156230}
157231
158- void BSP_AUDIO_OUT_TransferComplete_CallBack (void )
159- {
160- if (Audio.running != NULL ) {
161- /* tell write function we're now playing the 1st half*/
232+ /* *
233+ * @brief Manages the DMA full Transfer complete event.
234+ */
235+ void BSP_AUDIO_OUT_TransferComplete_CallBack (void ) {
236+ if (Audio.running != NULL ) {
237+ /* Tell write function we're now playing the 1st half*/
162238 Audio.running = Audio.bufferOut ;
163239 Audio._playedBytes += (Audio.bufferOutSize /2 );
164240 }
165241}
166242
167- void BSP_AUDIO_OUT_Error_CallBack ()
168- {
169-
243+ /* *
244+ * @brief Audio OUT Error callback function.
245+ */
246+ void BSP_AUDIO_OUT_Error_CallBack () {
247+ /* This function is called when an Interrupt due to transfer error on or peripheral
248+ error occurs. */
170249}
171250
172251/* *
173252 * @brief Calculates the remaining file size and new position of the pointer.
174253 * @param None
175254 * @retval None
176255 */
177- void BSP_AUDIO_IN_TransferComplete_CallBack (void )
178- {
256+ void BSP_AUDIO_IN_TransferComplete_CallBack (void ) {
179257 Audio.bufferIn_ptr += Audio.bufferInSize /2 ;
180- if (Audio.bufferIn_ptr == Audio.bufferInSize /2 )
181- {
258+ if (Audio.bufferIn_ptr == Audio.bufferInSize /2 ) {
182259 Audio.bufferInFull = true ;
183260 Audio.bufferIn_offset = 0 ;
184261 }
185262
186- if (Audio.bufferIn_ptr >= Audio.bufferInSize )
187- {
263+ if (Audio.bufferIn_ptr >= Audio.bufferInSize ) {
188264 Audio.bufferInFull = true ;
189265 Audio.bufferIn_offset = Audio.bufferInSize /2 ;
190266 Audio.bufferIn_ptr = 0 ;
@@ -196,17 +272,14 @@ void BSP_AUDIO_IN_TransferComplete_CallBack(void)
196272 * @param None
197273 * @retval None
198274 */
199- void BSP_AUDIO_IN_HalfTransfer_CallBack (void )
200- {
275+ void BSP_AUDIO_IN_HalfTransfer_CallBack (void ) {
201276 Audio.bufferIn_ptr += Audio.bufferInSize /2 ;
202- if (Audio.bufferIn_ptr == Audio.bufferInSize /2 )
203- {
277+ if (Audio.bufferIn_ptr == Audio.bufferInSize /2 ) {
204278 Audio.bufferInFull = true ;
205279 Audio.bufferIn_offset = 0 ;
206280 }
207281
208- if (Audio.bufferIn_ptr >= Audio.bufferInSize )
209- {
282+ if (Audio.bufferIn_ptr >= Audio.bufferInSize ) {
210283 Audio.bufferInFull = true ;
211284 Audio.bufferIn_offset = Audio.bufferInSize /2 ;
212285 Audio.bufferIn_ptr = 0 ;
@@ -216,8 +289,7 @@ void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
216289/* *
217290 * @brief Audio IN Error callback function.
218291 */
219- void BSP_AUDIO_IN_Error_CallBack (void )
220- {
292+ void BSP_AUDIO_IN_Error_CallBack (void ) {
221293 /* This function is called when an Interrupt due to transfer error on or peripheral
222294 error occurs. */
223295}
0 commit comments