aboutsummaryrefslogtreecommitdiffstats
path: root/src/gaudout
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-02-27 08:04:54 +1000
committerinmarket <andrewh@inmarket.com.au>2014-02-27 08:04:54 +1000
commita56e4ac7dcbf2776690c96656dbcb48b2cf2d818 (patch)
tree1570dc6c25a290197f23262f353b6123e8020356 /src/gaudout
parentf9495a75e1e1fa2f1b86b71de776aee3a4a815e9 (diff)
downloaduGFX-a56e4ac7dcbf2776690c96656dbcb48b2cf2d818.tar.gz
uGFX-a56e4ac7dcbf2776690c96656dbcb48b2cf2d818.tar.bz2
uGFX-a56e4ac7dcbf2776690c96656dbcb48b2cf2d818.zip
First GAUDOUT work. Still incomplete but compiling.
Also moved drivers/gaudin to drivers/audio as most audio codecs support input and output in a single device.
Diffstat (limited to 'src/gaudout')
-rw-r--r--src/gaudout/driver.h123
-rw-r--r--src/gaudout/gaudout.c111
-rw-r--r--src/gaudout/sys_defs.h121
-rw-r--r--src/gaudout/sys_rules.h21
4 files changed, 374 insertions, 2 deletions
diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h
new file mode 100644
index 00000000..cd9ab01b
--- /dev/null
+++ b/src/gaudout/driver.h
@@ -0,0 +1,123 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudout/driver.h
+ * @brief GAUDOUT - Audio Output driver header file.
+ *
+ * @defgroup Driver Driver
+ * @ingroup GAUDOUT
+ * @{
+ */
+
+#ifndef _GAUDOUT_LLD_H
+#define _GAUDOUT_LLD_H
+
+#include "gfx.h"
+
+#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Type definitions */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Get a block of audio data to play
+ * @return A pointer to the GAaudioData structure or NULL if none is currently available
+ *
+ * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
+ *
+ * @iclass
+ * @notapi
+ */
+GAudioData *gaudoutGetDataBlockI(void);
+
+/**
+ * @brief Release a block of audio data after playing
+ *
+ * @param[in] paud The GAudioData block to be released.
+ *
+ * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
+ *
+ * @iclass
+ * @notapi
+ */
+void gaudoutReleaseDataBlockI(GAudioData *paud);
+
+/**
+ * @brief Initialise the driver
+ * @return TRUE if the channel and frequency are valid.
+ *
+ * @param[in] channel The channel to use (see the driver for the available channels provided)
+ * @param[in] frequency The sample frequency to use
+ *
+ * @note The driver will always have been stopped and de-init before this is called.
+ *
+ * @api
+ */
+bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency);
+
+/**
+ * @brief De-Initialise the driver
+ *
+ * @note The audio output will always have been stopped first by the high level layer.
+ * @note This may be called before a @p gaudout_lld_init() has occurred.
+ *
+ * @api
+ */
+void gaudout_lld_deinit(void);
+
+/**
+ * @brief Start the audio output playing
+ *
+ * @note This may be called at any stage including while the driver
+ * is already playing. The driver should check for data blocks
+ * to play using @p gaudoutGetDataBlockI().
+ *
+ * @api
+ */
+void gaudout_lld_start(void);
+
+/**
+ * @brief Stop the audio output playing.
+ *
+ * @note Some drivers may only stop playing at a data block boundary.
+ * @note This may be called before a @p gaudout_lld_init() has occurred.
+ *
+ * @api
+ */
+void gaudout_lld_stop(void);
+
+/**
+ * @brief Set the output volume.
+ * @return TRUE if successful.
+ *
+ * @param[in] 0->255 (0 = muted)
+ *
+ * @note Some drivers may not support this. They will return FALSE.
+ * @note For stereo devices, both channels are set to the same volume.
+ *
+ * @api
+ */
+bool_t gaudout_lld_set_volume(uint8_t vol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GAUDOUT */
+
+#endif /* _GAUDOUT_LLD_H */
+/** @} */
diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c
index 56692453..c0d673a0 100644
--- a/src/gaudout/gaudout.c
+++ b/src/gaudout/gaudout.c
@@ -16,11 +16,47 @@
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
- #error "GAUDOUT: Not implemented yet"
+#include "src/gaudout/driver.h"
+
+static gfxQueueASync playlist;
+static gfxQueueGSync freelist;
+
+static uint16_t audFlags;
+ #define AUDOUTFLG_RUNNING 0x0001
+ #define AUDOUTFLG_USE_EVENTS 0x0002
+
+#if GFX_USE_GEVENT
+ static GTimer AudGTimer;
+
+ static void AudGTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventADC *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
+ if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GAUDIN_LOSTEVENT;
+ continue;
+ }
+
+ pe->type = GEVENT_AUDIO_IN;
+ pe->channel = aud.channel;
+ pe->count = lastcount;
+ pe->buffer = lastbuffer;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ geventSendEvent(psl);
+ }
+ }
+#endif
+
void _gaudoutInit(void)
{
- /* ToDo */
+ gfxQueueASyncInit(&playlist);
+ gfxQueueGSyncInit(&freelist);
}
void _gaudoutDeinit(void)
@@ -28,6 +64,77 @@ void _gaudoutDeinit(void)
/* ToDo */
}
+bool_t gaudioAllocBuffers(unsigned num, size_t size) {
+ GAudioData *paud;
+
+ if (num < 1)
+ return FALSE;
+
+ // Round up to a multiple of 4 to prevent problems with structure alignment
+ size = (size + 3) & ~0x03;
+
+ // Allocate the memory
+ if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num)))
+ return FALSE;
+
+ // Add each of them to our free list
+ for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) {
+ paud->size = size;
+ gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
+ }
+
+ return TRUE;
+}
+
+void gaudioReleaseBuffer(GAudioData *paud) {
+ gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
+}
+
+GAudioData *gaudioGetBuffer(delaytime_t ms) {
+ return (GAudioData *)gfxQueueGSyncGet(&freelist, ms);
+}
+
+bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency) {
+ gaudioPlayStop();
+ gaudout_lld_deinit();
+ return gaudout_lld_init(channel, frequency);
+}
+
+void gaudioPlay(GAudioData *paud) {
+ if (paud)
+ gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
+ gaudout_lld_start();
+}
+
+void gaudioPlayPause(void) {
+ gaudout_lld_stop();
+}
+
+void gaudioPlayStop(void) {
+ GAudioData *paud;
+
+ gaudout_lld_stop();
+ while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
+ gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
+}
+
+bool_t gaudioPlaySetVolume(uint8_t vol) {
+ return gaudout_lld_set_volume(vol);
+}
+
+/**
+ * Routines provided for use by drivers.
+ */
+
+GAudioData *gaudoutGetDataBlockI(void) {
+ return (GAudioData *)gfxQueueASyncGet(&playlist);
+}
+
+void gaudoutReleaseDataBlockI(GAudioData *paud) {
+ gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
+}
+
+
#endif /* GFX_USE_GAUDOUT */
/** @} */
diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h
index f22d269c..c3745b8c 100644
--- a/src/gaudout/sys_defs.h
+++ b/src/gaudout/sys_defs.h
@@ -22,10 +22,26 @@
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
+/* Include the driver defines */
+#include "gaudout_lld_config.h"
+
+
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
+/**
+ * @brief Contains Audio Data Samples
+ * @note This structure is followed immediately by the sample data itself.
+ * When allocating the buffers for the sample data put this structure
+ * at the beginning of the buffer.
+ */
+typedef struct GAudioData {
+ gfxQueueASyncItem next; // @< Used for queuing the buffers
+ size_t size; // @< The size of the buffer area following this structure (in bytes)
+ size_t len; // @< The length of the data in the buffer area (in samples)
+} GAudioData;
+
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@@ -34,6 +50,111 @@
extern "C" {
#endif
+/**
+ * @brief Allocate some audio buffers and put them on the free list
+ * @return TRUE is it succeeded. FALSE on allocation failure.
+ *
+ * @param[in] num The number of buffers to allocate
+ * @param[in] size The size (in bytes) of each buffer
+ *
+ * @api
+ */
+bool_t gaudioAllocBuffers(unsigned num, size_t size);
+
+/**
+ * @brief Get an audio buffer from the free list
+ * @return A GAudioData pointer or NULL if the timeout is exceeded
+ *
+ * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available.
+ *
+ * @api
+ */
+GAudioData *gaudioGetBuffer(delaytime_t ms);
+
+/**
+ * @brief Release a buffer back to the free list
+ *
+ * @param[in] paud The buffer to put (back) on the free-list.
+ *
+ * @note This call should be used to return any buffers that were taken from
+ * the free-list once they have been finished with. It can also be used
+ * to put new buffers onto the free-list. Just make sure the "size" field
+ * of the GAudioData structure has been filled in first.
+ *
+ * @api
+ */
+void gaudioReleaseBuffer(GAudioData *paud);
+
+/**
+ * @brief Set the audio device to play on the specified channel and with the specified
+ * sample frequency.
+ * @return TRUE is successful, FALSE if the driver doesn't accept those parameters.
+ *
+ * @param[in] channel The audio output channel to use.
+ * @param[in] frequency The audio sample rate in samples per second
+ *
+ * @note Some channels are mono, and some are stereo. See your driver config file
+ * to determine which channels to use and whether they are stereo or not.
+ *
+ * @api
+ */
+bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency);
+
+/**
+ * @brief Play the specified sample data.
+ * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list.
+ * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency.
+ *
+ * @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio)
+ *
+ * @note Calling this will cancel any pause.
+ * @note Before calling this function the len field of the GAudioData structure must be
+ * specified. While the buffer size is specified in bytes, this length is specified in samples
+ * and must be even for stereo channels.
+ * @note For stereo channels the sample data is interleaved in the buffer.
+ * @note This call returns before the data has completed playing. Subject to available buffers (which
+ * can be obtained from the free-list), any number of buffers may be played. They will be queued
+ * for playing in the order they are supplied to this routine and played when previous buffers are
+ * complete. In this way continuous playing can be obtained without audio gaps.
+ *
+ * @api
+ */
+void gaudioPlay(GAudioData *paud);
+
+/**
+ * @brief Pause any currently playing sounds.
+ *
+ * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay()
+ * with or without a new sample buffer.
+ * @note Some drivers will not respond until a buffer boundary.
+ *
+ * @api
+ */
+void gaudioPlayPause(void);
+
+/**
+ * @brief Stop any currently playing sounds.
+ *
+ * @note This stops any playing sounds and returns any currently queued buffers back to the free-list.
+ * @note Some drivers will not respond until a buffer boundary.
+ *
+ * @api
+ */
+void gaudioPlayStop(void);
+
+/**
+ * @brief Set the output volume.
+ * @return TRUE if successful.
+ *
+ * @param[in] 0->255 (0 = muted)
+ *
+ * @note Some drivers may not support this. They will return FALSE.
+ * @note For stereo devices, both channels are set to the same volume.
+ *
+ * @api
+ */
+bool_t gaudioPlaySetVolume(uint8_t vol);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gaudout/sys_rules.h b/src/gaudout/sys_rules.h
index 50b9a442..8274e031 100644
--- a/src/gaudout/sys_rules.h
+++ b/src/gaudout/sys_rules.h
@@ -17,6 +17,27 @@
#define _GAUDOUT_RULES_H
#if GFX_USE_GAUDOUT
+ #if !GFX_USE_GQUEUE
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GAUDOUT: GFX_USE_GQUEUE is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you."
+ #endif
+ #undef GFX_USE_GQUEUE
+ #define GFX_USE_GQUEUE TRUE
+ #endif
+ #if !GQUEUE_NEED_ASYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GAUDOUT: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you."
+ #endif
+ #undef GQUEUE_NEED_ASYNC
+ #define GQUEUE_NEED_ASYNC TRUE
+ #endif
+ #if !GQUEUE_NEED_GSYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GAUDOUT: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you."
+ #endif
+ #undef GQUEUE_NEED_GSYNC
+ #define GQUEUE_NEED_GSYNC TRUE
+ #endif
#endif
#endif /* _GAUDOUT_RULES_H */