version 2.8
gaudio.c
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.org/license.html
6  */
7 
8 #include "../../gfx.h"
9 
10 #if GFX_USE_GAUDIO
11 
12 #if GAUDIO_NEED_PLAY
13  #include "gaudio_driver_play.h"
14 
15  static gfxQueueASync playList;
16  static gfxSem playComplete;
17  static uint16_t playFlags;
18  #define PLAYFLG_USEEVENTS 0x0001
19  #define PLAYFLG_PLAYING 0x0002
20  #define PLAYFLG_ISINIT 0x0004
21  #if GFX_USE_GEVENT
22  static GTimer playTimer;
23  static void PlayTimerCallback(void *param);
24  #endif
25 #endif
26 
27 #if GAUDIO_NEED_RECORD
28  #include "gaudio_driver_record.h"
29 
30  static gfxQueueGSync recordList;
31  static uint16_t recordFlags;
32  #define RECORDFLG_USEEVENTS 0x0001
33  #define RECORDFLG_RECORDING 0x0002
34  #define RECORDFLG_STALLED 0x0004
35  #define RECORDFLG_ISINIT 0x0008
36  #if GFX_USE_GEVENT
37  static GTimer recordTimer;
38  static void RecordTimerCallback(void *param);
39  #endif
40 #endif
41 
42 
43 void _gaudioInit(void)
44 {
45  #if GAUDIO_NEED_PLAY
46  gfxQueueASyncInit(&playList);
47  #if GFX_USE_GEVENT
48  gtimerInit(&playTimer);
49  #endif
50  gfxSemInit(&playComplete, 0, 0);
51  #endif
52  #if GAUDIO_NEED_RECORD
53  gfxQueueGSyncInit(&recordList);
54  #if GFX_USE_GEVENT
55  gtimerInit(&recordTimer);
56  #endif
57  #endif
58 }
59 
60 void _gaudioDeinit(void)
61 {
62  #if GAUDIO_NEED_PLAY
63  gfxQueueASyncDeinit(&playList);
64  #if GFX_USE_GEVENT
65  gtimerDeinit(&playTimer);
66  #endif
67  gfxSemDestroy(&playComplete);
68  #endif
69  #if GAUDIO_NEED_RECORD
70  gfxQueueGSyncDeinit(&recordList);
71  #if GFX_USE_GEVENT
72  gtimerDeinit(&recordTimer);
73  #endif
74  #endif
75 }
76 
77 #if GAUDIO_NEED_PLAY
78 
79  bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
81  playFlags &= ~PLAYFLG_ISINIT;
82  if (!gaudio_play_lld_init(channel, frequency, format))
83  return FALSE;
84  playFlags |= PLAYFLG_ISINIT;
85  return TRUE;
86  }
87 
88  void gaudioPlay(GDataBuffer *pd) {
89  if (!(playFlags & PLAYFLG_ISINIT)) {
90  // Oops - init failed - return it directly to the free-list
91  if (pd) {
92  gfxBufferRelease(pd);
93  gfxYield(); // Make sure we get no endless cpu hogging loops
94  }
95  return;
96  }
97 
98  if (pd)
99  gfxQueueASyncPut(&playList, (gfxQueueASyncItem *)pd);
100  playFlags |= PLAYFLG_PLAYING;
102  }
103 
104  void gaudioPlayPause(void) {
105  if ((playFlags & (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) == (PLAYFLG_ISINIT|PLAYFLG_PLAYING))
107  }
108 
109  void gaudioPlayStop(void) {
110  GDataBuffer *pd;
111 
112  if (playFlags & PLAYFLG_PLAYING)
114  while((pd = (GDataBuffer *)gfxQueueASyncGet(&playList)))
115  gfxBufferRelease(pd);
116  }
117 
118  bool_t gaudioPlaySetVolume(uint8_t vol) {
119  return gaudio_play_lld_set_volume(vol);
120  }
121 
122  bool_t gaudioPlayWait(delaytime_t ms) {
123  if (!(playFlags & PLAYFLG_PLAYING))
124  return TRUE;
125  return gfxSemWait(&playComplete, ms);
126  }
127 
128  #if GFX_USE_GEVENT
129  static void PlayTimerCallback(void *param) {
130  (void) param;
131  GSourceListener *psl;
132  GEventAudioPlay *pe;
133 
134  psl = 0;
135  while ((psl = geventGetSourceListener((GSourceHandle)&playTimer, psl))) {
136  if (!(pe = (GEventAudioPlay *)geventGetEventBuffer(psl))) {
137  // This listener is missing - save this.
138  psl->srcflags |= GAUDIO_PLAY_LOSTEVENT;
139  continue;
140  }
141 
142  pe->type = GEVENT_AUDIO_PLAY;
143  pe->flags = psl->srcflags;
144  psl->srcflags = 0;
145  if ((playFlags & PLAYFLG_PLAYING))
146  pe->flags |= GAUDIO_PLAY_PLAYING;
147  if (gfxBufferIsAvailable())
149  geventSendEvent(psl);
150  }
151  }
152 
153  GSourceHandle gaudioPlayGetSource(void) {
154  if (!gtimerIsActive(&playTimer))
155  gtimerStart(&playTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
156  playFlags |= PLAYFLG_USEEVENTS;
157  return (GSourceHandle)&playTimer;
158  }
159  #endif
160 
161  /**
162  * Routines provided for use by drivers.
163  */
164 
166  return (GDataBuffer *)gfxQueueASyncGetI(&playList);
167  }
168 
170  gfxBufferReleaseI(pd);
171  #if GFX_USE_GEVENT
172  if (playFlags & PLAYFLG_USEEVENTS)
173  gtimerJabI(&playTimer);
174  #endif
175  }
176 
177  void gaudioPlayDoneI(void) {
178  playFlags &= ~PLAYFLG_PLAYING;
179  #if GFX_USE_GEVENT
180  if (playFlags & PLAYFLG_USEEVENTS)
181  gtimerJabI(&playTimer);
182  #endif
183  gfxSemSignalI(&playComplete); // This should really be gfxSemSignalAllI(&playComplete);
184  }
185 #endif
186 
187 #if GAUDIO_NEED_RECORD
188  bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
190  recordFlags &= ~RECORDFLG_ISINIT;
191  if (!gaudio_record_lld_init(channel, frequency, format))
192  return FALSE;
193  recordFlags |= RECORDFLG_ISINIT;
194  return TRUE;
195  }
196 
197  void gaudioRecordStart(void) {
198  if (!(recordFlags & RECORDFLG_ISINIT))
199  return; // Oops - init failed
200 
201  recordFlags |= RECORDFLG_RECORDING;
202  recordFlags &= ~RECORDFLG_STALLED;
204  }
205 
206  void gaudioRecordStop(void) {
207  GDataBuffer *pd;
208 
209  if ((recordFlags & (RECORDFLG_RECORDING|RECORDFLG_STALLED)) == RECORDFLG_RECORDING)
211  recordFlags &= ~(RECORDFLG_RECORDING|RECORDFLG_STALLED);
212  while((pd = (GDataBuffer *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE)))
213  gfxBufferRelease(pd);
214  }
215 
216  GDataBuffer *gaudioRecordGetData(delaytime_t ms) {
217  return (GDataBuffer *)gfxQueueGSyncGet(&recordList, ms);
218  }
219 
220  #if GFX_USE_GEVENT
221  static void RecordTimerCallback(void *param) {
222  (void) param;
223  GSourceListener *psl;
224  GEventAudioRecord *pe;
225 
226  psl = 0;
227  while ((psl = geventGetSourceListener((GSourceHandle)&recordTimer, psl))) {
228  if (!(pe = (GEventAudioRecord *)geventGetEventBuffer(psl))) {
229  // This listener is missing - save this.
230  psl->srcflags |= GAUDIO_RECORD_LOSTEVENT;
231  continue;
232  }
233  pe->type = GEVENT_AUDIO_RECORD;
234  pe->flags = psl->srcflags;
235  psl->srcflags = 0;
236  if ((recordFlags & RECORDFLG_RECORDING))
238  if ((recordFlags & RECORDFLG_STALLED))
239  pe->flags |= GAUDIO_RECORD_STALL;
240  if (!gfxQueueGSyncIsEmpty(&recordList))
242  geventSendEvent(psl);
243  }
244  }
245 
246  GSourceHandle gaudioRecordGetSource(void) {
247  if (!gtimerIsActive(&recordTimer))
248  gtimerStart(&recordTimer, RecordTimerCallback, 0, TRUE, TIME_INFINITE);
249  recordFlags |= RECORDFLG_USEEVENTS;
250  return (GSourceHandle)&recordTimer;
251  }
252  #endif
253 
254  /**
255  * Routines provided for use by drivers.
256  */
257 
259  gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud);
260  #if GFX_USE_GEVENT
261  if (recordFlags & RECORDFLG_USEEVENTS)
262  gtimerJabI(&recordTimer);
263  #endif
264  }
265 
266  void gaudioRecordDoneI(void) {
267  recordFlags |= RECORDFLG_STALLED;
268  #if GFX_USE_GEVENT
269  if (recordFlags & RECORDFLG_USEEVENTS)
270  gtimerJabI(&recordTimer);
271  #endif
272  }
273 #endif
274 
275 #endif /* GFX_USE_GAUDIO */
bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format)
Initialise (but not start) the Audio Recording sub-system.
void gtimerJabI(GTimer *pt)
Jab a timer causing the current period to immediate expire.
Definition: gtimer.c:223
#define GAUDIO_RECORD_GOTBUFFER
An audio buffer is ready for processing.
Definition: gaudio.h:85
#define GAUDIO_RECORD_STALL
The recording process has stalled due to no free buffers.
Definition: gaudio.h:86
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit)
Initialise a Counted Semaphore.
void gtimerDeinit(GTimer *pt)
Deinitialise a timer.
Definition: gtimer.c:134
void gtimerInit(GTimer *pt)
Initialise a timer.
Definition: gtimer.c:129
GDataBuffer * gaudioRecordGetData(delaytime_t ms)
Get a filled audio buffer from the recording list.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
A Data Buffer Queue.
Definition: gqueue.h:78
void gaudio_play_lld_start(void)
Start the audio output playing.
A GTimer structure.
Definition: gtimer.h:52
GEventType type
The type of this event (GEVENT_AUDIO_RECORD)
Definition: gaudio.h:74
void gaudio_record_lld_start(void)
Start the audio recording.
void gaudioRecordSaveDataBlockI(GDataBuffer *paud)
Save a block of recorded audio data ready for the application.
A queue item.
Definition: gqueue.h:40
bool_t gtimerIsActive(GTimer *pt)
Test if a timer is currently active.
Definition: gtimer.c:208
void gaudioPlayReleaseDataBlockI(GDataBuffer *paud)
Release a block of audio data to the free list.
bool_t gaudioPlayWait(delaytime_t ms)
Wait for any currently playing sounds to complete.
uint16_t flags
The event flags.
Definition: gaudio.h:78
GEventType type
The type of this event (GEVENT_AUDIO_PLAY)
Definition: gaudio.h:50
void gaudioRecordStop(void)
Stop the audio recording.
bool_t gaudioPlaySetVolume(uint8_t vol)
Set the output volume.
#define FALSE
Generic 'false' boolean constant.
Definition: gfx.h:31
GAUDIO - Audio play driver header file.
void gaudio_record_lld_stop(void)
Stop the audio recording.
#define GAUDIO_PLAY_LOSTEVENT
The event flag values.
Definition: gaudio.h:59
void gfxSemDestroy(gfxSem *psem)
Destroy a Counted Semaphore.
#define GAUDIO_PLAY_FREEBLOCK
An audio buffer has been freed.
Definition: gaudio.h:61
GAUDIO - Audio Recording driver header file.
A queue.
Definition: gqueue.h:54
void gaudioPlay(GDataBuffer *paud)
Play the specified sample data.
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms)
Wait on a semaphore.
GSourceHandle gaudioPlayGetSource(void)
Turn on sending results to the GEVENT sub-system.
void gfxSemSignalI(gfxSem *psem)
Signal a semaphore.
A semaphore.
Definition: gos.h:105
void gaudioPlayDoneI(void)
Signal that all playing has now stopped.
uint16_t flags
The event flags.
Definition: gaudio.h:54
GSourceHandle gaudioRecordGetSource(void)
Turn on sending results to the GEVENT sub-system.
void gaudioRecordDoneI(void)
Signal that all recording has now stopped.
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
Definition: gevent.c:200
bool_t gaudio_play_lld_set_volume(uint8_t vol)
Set the output volume.
#define GAUDIO_RECORD_LOSTEVENT
The event flag values.
Definition: gaudio.h:83
bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format)
Initialise the play driver.
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
#define GAUDIO_RECORD_RECORDING
The audio recording system is currently recording.
Definition: gaudio.h:84
void gaudioRecordStart(void)
Start the audio recording.
bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format)
Initialise the record driver.
GDataBuffer * gaudioPlayGetDataBlockI(void)
Get a block of audio data to play.
enum ArrayDataFormat_e ArrayDataFormat
Sample data formats.
void gaudioPlayPause(void)
Pause any currently playing sounds.
void gfxYield(void)
Yield the current thread.
The Audio record event structure.
Definition: gaudio.h:70
#define GAUDIO_PLAY_PLAYING
The audio out system is currently playing.
Definition: gaudio.h:60
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format)
Set the audio device to play on the specified channel and with the specified sample frequency...
void gaudio_play_lld_stop(void)
Stop the audio output playing.
The Audio play event structure.
Definition: gaudio.h:46
#define TRUE
Generic 'true' boolean constant.
Definition: gfx.h:38
void gaudioPlayStop(void)
Stop any currently playing sounds.
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163