µGFX  2.9
version 2.9
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.io/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 gSem playComplete;
17  static gU16 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 gU16 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  gBool gaudioPlayInit(gU16 channel, gU32 frequency, ArrayDataFormat format) {
81  playFlags &= ~PLAYFLG_ISINIT;
82  if (!gaudio_play_lld_init(channel, frequency, format))
83  return gFalse;
84  playFlags |= PLAYFLG_ISINIT;
85  return gTrue;
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  gBool gaudioPlaySetVolume(gU8 vol) {
119  return gaudio_play_lld_set_volume(vol);
120  }
121 
122  gBool gaudioPlayWait(gDelay ms) {
123  if (!(playFlags & PLAYFLG_PLAYING))
124  return gTrue;
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, gTrue, gDelayForever);
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  gBool gaudioRecordInit(gU16 channel, gU32 frequency, ArrayDataFormat format) {
190  recordFlags &= ~RECORDFLG_ISINIT;
191  if (!gaudio_record_lld_init(channel, frequency, format))
192  return gFalse;
193  recordFlags |= RECORDFLG_ISINIT;
194  return gTrue;
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, gDelayNone)))
213  gfxBufferRelease(pd);
214  }
215 
216  GDataBuffer *gaudioRecordGetData(gDelay 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, gTrue, gDelayForever);
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 */
#define GAUDIO_RECORD_LOSTEVENT
The event flag values.
Definition: gaudio.h:83
#define GAUDIO_PLAY_LOSTEVENT
The event flag values.
Definition: gaudio.h:59
#define GAUDIO_PLAY_FREEBLOCK
An audio buffer has been freed.
Definition: gaudio.h:61
#define GAUDIO_PLAY_PLAYING
The audio out system is currently playing.
Definition: gaudio.h:60
#define GAUDIO_RECORD_STALL
The recording process has stalled due to no free buffers.
Definition: gaudio.h:86
#define GAUDIO_RECORD_RECORDING
The audio recording system is currently recording.
Definition: gaudio.h:84
#define GAUDIO_RECORD_GOTBUFFER
An audio buffer is ready for processing.
Definition: gaudio.h:85
GAUDIO - Audio play driver header file.
GAUDIO - Audio Recording driver header file.
void gaudioPlayReleaseDataBlockI(GDataBuffer *paud)
Release a block of audio data to the free list.
gBool gaudio_play_lld_set_volume(gU8 vol)
Set the output volume.
GDataBuffer * gaudioPlayGetDataBlockI(void)
Get a block of audio data to play.
void gaudioPlayDoneI(void)
Signal that all playing has now stopped.
gBool gaudio_play_lld_init(gU16 channel, gU32 frequency, ArrayDataFormat format)
Initialise the play driver.
void gaudio_play_lld_start(void)
Start the audio output playing.
void gaudio_play_lld_stop(void)
Stop the audio output playing.
void gaudio_record_lld_stop(void)
Stop the audio recording.
void gaudioRecordSaveDataBlockI(GDataBuffer *paud)
Save a block of recorded audio data ready for the application.
void gaudioRecordDoneI(void)
Signal that all recording has now stopped.
void gaudio_record_lld_start(void)
Start the audio recording.
gBool gaudio_record_lld_init(gU16 channel, gU32 frequency, ArrayDataFormat format)
Initialise the record driver.
void gaudioPlayStop(void)
Stop any currently playing sounds.
GSourceHandle gaudioPlayGetSource(void)
Turn on sending results to the GEVENT sub-system.
void gaudioRecordStart(void)
Start the audio recording.
gBool gaudioPlaySetVolume(gU8 vol)
Set the output volume.
GDataBuffer * gaudioRecordGetData(gDelay ms)
Get a filled audio buffer from the recording list.
void gaudioRecordStop(void)
Stop the audio recording.
gBool gaudioPlayInit(gU16 channel, gU32 frequency, ArrayDataFormat format)
Set the audio device to play on the specified channel and with the specified sample frequency.
gBool gaudioRecordInit(gU16 channel, gU32 frequency, ArrayDataFormat format)
Initialise (but not start) the Audio Recording sub-system.
void gaudioPlayPause(void)
Pause any currently playing sounds.
void gaudioPlay(GDataBuffer *paud)
Play the specified sample data.
GSourceHandle gaudioRecordGetSource(void)
Turn on sending results to the GEVENT sub-system.
gBool gaudioPlayWait(gDelay ms)
Wait for any currently playing sounds to complete.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
Definition: gevent.c:200
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163
enum ArrayDataFormat_e ArrayDataFormat
Sample data formats.
void gfxYield(void)
Yield the current thread.
gBool gfxSemWait(gSem *psem, gDelay ms)
Wait on a semaphore.
void gfxSemDestroy(gSem *psem)
Destroy a Counted Semaphore.
void gfxSemInit(gSem *psem, gSemcount val, gSemcount limit)
Initialise a Counted Semaphore.
void gfxSemSignalI(gSem *psem)
Signal a semaphore.
void gtimerJabI(GTimer *pt)
Jab a timer causing the current period to immediate expire.
Definition: gtimer.c:223
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, gBool periodic, gDelay millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
void gtimerInit(GTimer *pt)
Initialise a timer.
Definition: gtimer.c:129
void gtimerDeinit(GTimer *pt)
Deinitialise a timer.
Definition: gtimer.c:134
gBool gtimerIsActive(GTimer *pt)
Test if a timer is currently active.
Definition: gtimer.c:208
A Data Buffer Queue.
Definition: gqueue.h:78
The Audio play event structure.
Definition: gaudio.h:46
gU16 flags
The event flags.
Definition: gaudio.h:54
GEventType type
The type of this event (GEVENT_AUDIO_PLAY)
Definition: gaudio.h:50
The Audio record event structure.
Definition: gaudio.h:70
gU16 flags
The event flags.
Definition: gaudio.h:78
GEventType type
The type of this event (GEVENT_AUDIO_RECORD)
Definition: gaudio.h:74
A GTimer structure.
Definition: gtimer.h:52
A semaphore.
Definition: gos.h:104
A queue.
Definition: gqueue.h:54
A queue item.
Definition: gqueue.h:40