Skip to content
This repository was archived by the owner on Feb 21, 2020. It is now read-only.

Commit a116d43

Browse files
fpistmsergiotomasello
authored andcommitted
Audio rework
Add setVolume function Add some descriptions Harden the code (avoid call BSP function if audio In/Out not initialized) Signed-off-by: Frederic.Pillon <frederic.pillon@st.com>
1 parent d48a3f6 commit a116d43

File tree

2 files changed

+181
-100
lines changed

2 files changed

+181
-100
lines changed

libraries/Audio/src/Audio.cpp

Lines changed: 168 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,28 @@
1313

1414
AudioClass 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+
*/
82138
size_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

148220
extern 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

Comments
 (0)