Combine GAUDIN and GAUDOUT into a single GAUDIO module.

Simplify GAUDIN (now GAUDIO RECORD) api.
Update audio demo's to match.
Port Win32 driver to new audio api.
ugfx_release_2.6
inmarket 2014-03-11 17:13:31 +10:00
parent 944c33cbff
commit ea5a1b849d
57 changed files with 1405 additions and 1521 deletions

View File

@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
include $(GFXLIB)/drivers/audio/gadc/driver.mk include $(GFXLIB)/drivers/gaudio/gadc/driver.mk

View File

@ -6,7 +6,7 @@ On this board uGFX currently supports:
- GADC via the AT91SAM7 driver - GADC via the AT91SAM7 driver
- GINPUT-dials via the GADC driver - GINPUT-dials via the GADC driver
- GINPUT-toggles via the Pal driver - GINPUT-toggles via the Pal driver
- GAUDIN via the GADC driver - GAUDIO recording via the GADC driver
Note there are two variants of this board - one with the GE8 display Note there are two variants of this board - one with the GE8 display
and one with the GE12 display. This one is for the GE12 display. and one with the GE12 display. This one is for the GE12 display.

View File

@ -5,4 +5,4 @@ include $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk include $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.mk
include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk include $(GFXLIB)/drivers/ginput/dial/GADC/ginput_lld.mk
include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk
include $(GFXLIB)/drivers/audio/gadc/driver.mk include $(GFXLIB)/drivers/gaudio/gadc/driver.mk

View File

@ -6,28 +6,28 @@
*/ */
/** /**
* @file boards/base/Olimex-SAM7EX256-GE8/gaudin_lld_board.h * @file boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h
* @brief GAUDIN Driver board config file for the Olimex SAM7EX256 board * @brief GAUDIO Record Driver board config file for the Olimex SAM7EX256 board
*/ */
#ifndef _GAUDIN_LLD_BOARD_H #ifndef _GAUDIO_RECORD_BOARD_H
#define _GAUDIN_LLD_BOARD_H #define _GAUDIO_RECORD_BOARD_H
/*===========================================================================*/ /*===========================================================================*/
/* Audio inputs on this board */ /* Audio inputs on this board */
/*===========================================================================*/ /*===========================================================================*/
#define GAUDIN_NUM_CHANNELS 1 #define GAUDIO_RECORD_NUM_CHANNELS 1
/** /**
* The list of audio channels and their uses * The list of audio channels and their uses
*/ */
#define GAUDIN_MICROPHONE 0 #define GAUDIO_RECORD_MICROPHONE 0
#ifdef GAUDIN_LLD_IMPLEMENTATION #ifdef GAUDIO_RECORD_IMPLEMENTATION
static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = { static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
GADC_PHYSDEV_MICROPHONE, GADC_PHYSDEV_MICROPHONE,
}; };
#endif #endif
#endif /* _GAUDIN_LLD_BOARD_H */ #endif /* _GAUDIO_RECORD_BOARD_H */

View File

@ -6,7 +6,7 @@ On this board uGFX currently supports:
- GADC via the AT91SAM7 driver - GADC via the AT91SAM7 driver
- GINPUT-dials via the GADC driver - GINPUT-dials via the GADC driver
- GINPUT-toggles via the Pal driver - GINPUT-toggles via the Pal driver
- GAUDIN via the GADC driver - GAUDIO recording via the GADC driver
Note there are two variants of this board - one with the GE8 display Note there are two variants of this board - one with the GE8 display
and one with the GE12 display. This one is for the GE8 display. and one with the GE12 display. This one is for the GE8 display.

View File

@ -2,4 +2,4 @@ GFXINC += $(GFXLIB)/boards/base/Win32
GFXSRC += GFXSRC +=
include $(GFXLIB)/drivers/multiple/Win32/driver.mk include $(GFXLIB)/drivers/multiple/Win32/driver.mk
include $(GFXLIB)/drivers/audio/Win32/driver.mk include $(GFXLIB)/drivers/gaudio/Win32/driver.mk

View File

@ -1,3 +1,3 @@
DEMODIR = $(GFXLIB)/demos/modules/audio/oscilloscope DEMODIR = $(GFXLIB)/demos/modules/gaudio/oscilloscope
GFXINC += $(DEMODIR) GFXINC += $(DEMODIR)
GFXSRC += $(DEMODIR)/main.c $(DEMODIR)/gwinosc.c GFXSRC += $(DEMODIR)/main.c $(DEMODIR)/gwinosc.c

View File

@ -46,11 +46,14 @@
#define GFX_USE_GWIN TRUE #define GFX_USE_GWIN TRUE
#define GFX_USE_GTIMER TRUE #define GFX_USE_GTIMER TRUE
//#define GFX_USE_GADC TRUE //#define GFX_USE_GADC TRUE
#define GFX_USE_GAUDIN TRUE #define GFX_USE_GAUDIO TRUE
/* Features for the GDISP sub-system. */ /* Features for the GDISP sub-system. */
#define GDISP_NEED_VALIDATION TRUE #define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE #define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_MULTITHREAD TRUE #define GDISP_NEED_MULTITHREAD TRUE
/* Features for the GAUDIO sub-system */
#define GAUDIO_NEED_RECORD TRUE
#endif /* _GFXCONF_H */ #endif /* _GFXCONF_H */

View File

@ -32,8 +32,8 @@
* *
* This GWIN superset implements a simple audio oscilloscope using the GAUDIN module. * This GWIN superset implements a simple audio oscilloscope using the GAUDIN module.
* *
* It makes many assumptions, the most fundamental of which is that the audio device * It makes many assumptions, the most fundamental of which is that the audio data
* produces unsigned integer samples. * should be scaled to SCOPE_Y_BITS.
* *
* The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more * The GMISC module with GMISC_NEED_ARRAYOPS could be used to process the samples more
* correctly if we were really building something generic. * correctly if we were really building something generic.
@ -45,22 +45,15 @@
/* Include internal GWIN routines so we can build our own superset class */ /* Include internal GWIN routines so we can build our own superset class */
#include "src/gwin/class_gwin.h" #include "src/gwin/class_gwin.h"
/* The size of our dynamically allocated audio buffer */
#define AUDIOBUFSZ 64*2
/* How many flat-line sample before we trigger */ /* How many flat-line sample before we trigger */
#define FLATLINE_SAMPLES 8 #define FLATLINE_SAMPLES 8
static void _destroy(GHandle gh) { static void _destroy(GHandle gh) {
gaudinStop(); gaudioRecordStop();
if (((GScopeObject *)gh)->lastscopetrace) { if (((GScopeObject *)gh)->lastscopetrace) {
gfxFree(((GScopeObject *)gh)->lastscopetrace); gfxFree(((GScopeObject *)gh)->lastscopetrace);
((GScopeObject *)gh)->lastscopetrace = 0; ((GScopeObject *)gh)->lastscopetrace = 0;
} }
if (((GScopeObject *)gh)->audiobuf) {
gfxFree(((GScopeObject *)gh)->audiobuf);
((GScopeObject *)gh)->audiobuf = 0;
}
} }
static const gwinVMT scopeVMT = { static const gwinVMT scopeVMT = {
@ -71,127 +64,136 @@ static const gwinVMT scopeVMT = {
0, // The after-clear routine 0, // The after-clear routine
}; };
GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency) { GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
/* Make sure the audio parameters are valid first */
if (!gaudioRecordInit(channel, frequency, format))
return 0;
/* Initialise the base class GWIN */ /* Initialise the base class GWIN */
if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0))) if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0)))
return 0; return 0;
/* Initialise the scope object members and allocate memory for buffers */ /* Initialise the scope object members and allocate memory for buffers */
gfxSemInit(&gs->bsem, 0, 1); gs->format = format;
gs->nextx = 0; gs->nextx = 0;
if (!(gs->lastscopetrace = (coord_t *)gfxAlloc(gs->g.width * sizeof(coord_t)))) if (!(gs->lastscopetrace = (coord_t *)gfxAlloc(gs->g.width * sizeof(coord_t))))
return 0; return 0;
if (!(gs->audiobuf = (audin_sample_t *)gfxAlloc(AUDIOBUFSZ * sizeof(audin_sample_t)))) #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
return 0; gs->lasty = gs->g.height/2;
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP #elif TRIGGER_METHOD == TRIGGER_MINVALUE
gs->lasty = gs->g.height/2; gs->lasty = gs->g.height/2;
#elif TRIGGER_METHOD == TRIGGER_MINVALUE gs->scopemin = 0;
gs->lasty = gs->g.height/2; #endif
gs->scopemin = 0;
#endif
/* Start the GADC high speed converter */
gaudinInit(channel, frequency, gs->audiobuf, AUDIOBUFSZ, AUDIOBUFSZ/2);
gaudinSetBSem(&gs->bsem, &gs->myEvent);
gaudinStart();
/* Set visibility */
gwinSetVisible((GHandle)gs, pInit->show); gwinSetVisible((GHandle)gs, pInit->show);
/* Start the audio recording */
gaudioRecordStart();
return (GHandle)gs; return (GHandle)gs;
} }
void gwinScopeWaitForTrace(GHandle gh) { void gwinScopeWaitForTrace(GHandle gh) {
#define gs ((GScopeObject *)(gh)) #define gs ((GScopeObject *)(gh))
GAudioData *paud;
int i; int i;
coord_t x, y; coord_t x, y;
coord_t yoffset; coord_t yoffset;
audin_sample_t *pa; uint8_t *pa8;
uint16_t *pa16;
coord_t *pc; coord_t *pc;
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP uint8_t shr;
bool_t rdytrigger;
int flsamples; #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
#elif TRIGGER_METHOD == TRIGGER_MINVALUE bool_t rdytrigger;
bool_t rdytrigger; int flsamples;
int flsamples; #elif TRIGGER_METHOD == TRIGGER_MINVALUE
coord_t scopemin; bool_t rdytrigger;
#endif int flsamples;
coord_t scopemin;
#endif
if (gh->vmt != &scopeVMT) if (gh->vmt != &scopeVMT)
return; return;
/* Wait for a set of audio conversions */ /* Wait for a set of audio conversions */
gfxSemWait(&gs->bsem, TIME_INFINITE); paud = gaudioRecordGetData(TIME_INFINITE);
/* Ensure we are drawing in the right area */ /* Ensure we are drawing in the right area */
#if GDISP_NEED_CLIP #if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif #endif
shr = 16 - gfxSampleFormatBits(gs->format);
yoffset = gh->height/2; yoffset = gh->height/2;
if (!(GAUDIN_SAMPLE_FORMAT & 1)) if (!gfxSampleFormatIsSigned(gs->format))
yoffset += (1<<SCOPE_Y_BITS)/2; yoffset += (1<<SCOPE_Y_BITS)/2;
x = gs->nextx; x = gs->nextx;
pc = gs->lastscopetrace+x; pc = gs->lastscopetrace+x;
pa = gs->myEvent.buffer; pa8 = (uint8_t *)(paud+1);
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP pa16 = (uint16_t *)(paud+1);
rdytrigger = FALSE;
flsamples = 0;
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
rdytrigger = FALSE;
flsamples = 0;
scopemin = 0;
#endif
for(i = gs->myEvent.count; i; i--) { #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
rdytrigger = FALSE;
flsamples = 0;
#elif TRIGGER_METHOD == TRIGGER_MINVALUE
rdytrigger = FALSE;
flsamples = 0;
scopemin = 0;
#endif
for(i = paud->len/(gfxSampleFormatBits(gs->format)/8); i; i--) {
/* Calculate the new scope value - re-scale using simple shifts for efficiency, re-center and y-invert */ /* Calculate the new scope value - re-scale using simple shifts for efficiency, re-center and y-invert */
#if GAUDIN_BITS_PER_SAMPLE > SCOPE_Y_BITS if (gs->format <= 8)
y = yoffset - (*pa++ >> (GAUDIN_BITS_PER_SAMPLE - SCOPE_Y_BITS)); y = yoffset - (((coord_t)(*pa8++ ) << shr) >> (16-SCOPE_Y_BITS));
#else else
y = yoffset - (*pa++ << (SCOPE_Y_BITS - GAUDIN_BITS_PER_SAMPLE)); y = yoffset - (((coord_t)(*pa16++) << shr) >> (16-SCOPE_Y_BITS));
#endif
#if TRIGGER_METHOD == TRIGGER_MINVALUE #if TRIGGER_METHOD == TRIGGER_MINVALUE
/* Calculate the scopemin ready for the next trace */ /* Calculate the scopemin ready for the next trace */
if (y > scopemin) if (y > scopemin)
scopemin = y; scopemin = y;
#endif #endif
/* Have we reached the end of a scope trace? */ /* Have we reached the end of a scope trace? */
if (x >= gh->width) { if (x >= gh->width) {
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP || TRIGGER_METHOD == TRIGGER_MINVALUE
/* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */ /* Handle triggering - we trigger on the next sample minimum (y value maximum) or a flat-line */
#if TRIGGER_METHOD == TRIGGER_MINVALUE #if TRIGGER_METHOD == TRIGGER_MINVALUE
/* Arm when we reach the sample minimum (y value maximum) of the previous trace */ /* Arm when we reach the sample minimum (y value maximum) of the previous trace */
if (!rdytrigger && y >= gs->scopemin) if (!rdytrigger && y >= gs->scopemin)
rdytrigger = TRUE; rdytrigger = TRUE;
#endif
if (y == gs->lasty) {
/* Trigger if we get too many flat-line samples regardless of the armed state */
if (++flsamples < FLATLINE_SAMPLES)
continue;
flsamples = 0;
} else if (y > gs->lasty) {
gs->lasty = y;
flsamples = 0;
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
/* Arm the trigger when samples fall (y increases) ie. negative slope */
rdytrigger = TRUE;
#endif #endif
continue;
} else {
/* If the trigger is armed, Trigger when samples increases (y decreases) ie. positive slope */
gs->lasty = y;
flsamples = 0;
if (!rdytrigger)
continue;
}
/* Ready for a the next trigger cycle */ if (y == gs->lasty) {
rdytrigger = FALSE; /* Trigger if we get too many flat-line samples regardless of the armed state */
#endif if (++flsamples < FLATLINE_SAMPLES)
continue;
flsamples = 0;
} else if (y > gs->lasty) {
gs->lasty = y;
flsamples = 0;
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
/* Arm the trigger when samples fall (y increases) ie. negative slope */
rdytrigger = TRUE;
#endif
continue;
} else {
/* If the trigger is armed, Trigger when samples increases (y decreases) ie. positive slope */
gs->lasty = y;
flsamples = 0;
if (!rdytrigger)
continue;
}
/* Ready for a the next trigger cycle */
rdytrigger = FALSE;
#endif
/* Prepare for a scope trace */ /* Prepare for a scope trace */
x = 0; x = 0;
@ -214,5 +216,6 @@ void gwinScopeWaitForTrace(GHandle gh) {
gs->scopemin = scopemin; gs->scopemin = scopemin;
#endif #endif
gaudioReleaseBuffer(paud);
#undef gs #undef gs
} }

View File

@ -64,9 +64,7 @@ typedef struct GScopeObject_t {
GWindowObject g; // Base Class GWindowObject g; // Base Class
coord_t *lastscopetrace; // To store last scope trace coord_t *lastscopetrace; // To store last scope trace
gfxSem bsem; // We get signalled on this ArrayDataFormat format; // The sample format
audin_sample_t *audiobuf; // To store audio samples
GEventAudioIn myEvent; // Information on received samples
coord_t nextx; // Where we are up to coord_t nextx; // Where we are up to
#if TRIGGER_METHOD == TRIGGER_POSITIVERAMP #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP
coord_t lasty; // The last y value - used for trigger slope detection coord_t lasty; // The last y value - used for trigger slope detection
@ -83,8 +81,8 @@ extern "C" {
/** /**
* Create a scope window. * Create a scope window.
*/ */
GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency); GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint16_t channel, uint32_t frequency, ArrayDataFormat format);
#define gwinScopeCreate(gs,pI,ch,f) gwinGScopeCreate(GDISP,gs,pI,ch,f) #define gwinScopeCreate(gs,pI,ch,f,fmt) gwinGScopeCreate(GDISP,gs,pI,ch,f,fmt)
/** /**
* Wait for a scope trace to be ready and then draw it. * Wait for a scope trace to be ready and then draw it.

View File

@ -39,8 +39,9 @@
#include "gwinosc.h" #include "gwinosc.h"
/* Specify our timing parameters */ /* Specify our timing parameters */
#define MY_AUDIO_FREQUENCY 4000 /* 4khz */ #define MY_AUDIO_FREQUENCY 8000 /* 8khz. If this is too much try 4000 (4khz) */
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */ #define MY_AUDIO_CHANNEL 0 /* Use channel 0 - must be a mono channel */
#define MY_AUDIO_FORMAT GAUDIO_RECORD_FORMAT1 /* The default format */
/* Data */ /* Data */
static GScopeObject gScopeWindow; static GScopeObject gScopeWindow;
@ -54,6 +55,11 @@ int main(void) {
gfxInit(); gfxInit();
// Allocate audio buffers - 4 x 128 byte buffers.
// You may need to increase this for slower cpu's.
// You may be able to decrease this for low latency operating systems.
gaudioAllocBuffers(4, 128);
/* Get the screen dimensions */ /* Get the screen dimensions */
swidth = gdispGetWidth(); swidth = gdispGetWidth();
sheight = gdispGetHeight(); sheight = gdispGetHeight();
@ -65,7 +71,7 @@ int main(void) {
wi.show = TRUE; wi.show = TRUE;
wi.x = wi.y = 0; wi.x = wi.y = 0;
wi.width = swidth; wi.height = sheight; wi.width = swidth; wi.height = sheight;
ghScope = gwinScopeCreate(&gScopeWindow, &wi, MY_AUDIO_CHANNEL, MY_AUDIO_FREQUENCY); ghScope = gwinScopeCreate(&gScopeWindow, &wi, MY_AUDIO_CHANNEL, MY_AUDIO_FREQUENCY, MY_AUDIO_FORMAT);
} }
gwinSetBgColor(ghScope, White); gwinSetBgColor(ghScope, White);
gwinSetColor(ghScope, Red); gwinSetColor(ghScope, Red);

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,3 +1,3 @@
DEMODIR = $(GFXLIB)/demos/modules/audio/play-wave DEMODIR = $(GFXLIB)/demos/modules/gaudio/play-wave
GFXINC += $(DEMODIR) GFXINC += $(DEMODIR)
GFXSRC += $(DEMODIR)/main.c GFXSRC += $(DEMODIR)/main.c

View File

@ -43,7 +43,7 @@
/* GFX sub-systems to turn on */ /* GFX sub-systems to turn on */
#define GFX_USE_GDISP TRUE #define GFX_USE_GDISP TRUE
#define GFX_USE_GAUDOUT TRUE #define GFX_USE_GAUDIO TRUE
#define GFX_USE_GFILE TRUE #define GFX_USE_GFILE TRUE
/* Features for the GDISP sub-system. */ /* Features for the GDISP sub-system. */
@ -53,6 +53,9 @@
/* GDISP fonts to include */ /* GDISP fonts to include */
#define GDISP_INCLUDE_FONT_UI2 TRUE #define GDISP_INCLUDE_FONT_UI2 TRUE
/* Features for the GAUDIO sub-system */
#define GAUDIO_NEED_PLAY TRUE
/* Features for the GFILE sub-system */ /* Features for the GFILE sub-system */
#define GFILE_NEED_ROMFS TRUE #define GFILE_NEED_ROMFS TRUE

View File

@ -34,8 +34,8 @@
#include "gfx.h" #include "gfx.h"
/* Specify our timing parameters */ /* Specify our timing parameters */
#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */ #define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_STEREO /* Is it stereo? */ #define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_IS_STEREO /* Is it stereo? */
// Storage for the wave header // Storage for the wave header
static char whdr[32]; static char whdr[32];
@ -61,7 +61,9 @@ int main(void) {
// Any font will do // Any font will do
font = gdispOpenFont("*"); font = gdispOpenFont("*");
// Allocate audio buffers - 4 x 512 byte buffers. You may need to increase this for slower cpu's. // Allocate audio buffers - 4 x 512 byte buffers.
// You may need to increase this for slower cpu's.
// You may be able to decrease this for low latency operating systems.
if (!gaudioAllocBuffers(4, 512)) { if (!gaudioAllocBuffers(4, 512)) {
errmsg = "Err: No Memory"; errmsg = "Err: No Memory";
goto theend; goto theend;
@ -179,8 +181,8 @@ int main(void) {
} }
gfileClose(f); gfileClose(f);
// Wait 3 seconds for the play to finish - FIX THIS // Wait for the play to finish
gfxSleepMilliseconds(3000); gaudioPlayWait(TIME_INFINITE);
gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green); gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green);
// The end // The end

View File

@ -1,7 +1,7 @@
/** /**
* This file was generated from "allwrong.wav" using... * This file was generated from "allwrong.wav" using...
* *
* file2c -bcs allwrong.wav romfs_allwrong.h * file2c -dcs allwrong.wav romfs_allwrong.h
* *
*/ */
static const char allwrong[] = { static const char allwrong[] = {

View File

@ -1,6 +0,0 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/audio/Win32/gaudin_lld.c \
$(GFXLIB)/drivers/audio/Win32/gaudout_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/audio/Win32

View File

@ -1,170 +0,0 @@
/*
* 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 drivers/audio/Win32/gaudin_lld.c
* @brief GAUDIN - Driver file for Win32.
*/
#include "gfx.h"
#if GFX_USE_GAUDIN
/* Include the driver defines */
#include "src/gaudin/driver.h"
#undef Red
#undef Green
#undef Blue
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
static HWAVEIN ah;
static volatile int nQueuedBuffers;
static bool_t isClosing;
static WAVEHDR *pWaveHdrs;
static HANDLE waveThread;
static DWORD threadID;
/*
static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
{
#define BUFFERSIZE 128
char buffer[BUFFERSIZE];
fprintf(stderr, "GAUDIN: ERROR 0x%08X: %s\r\n", err, str);
if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
fprintf(stderr, "%s\r\n", &buffer[0]);
else
fprintf(stderr, "0x%08X returned!\r\n", err);
}
*/
/**************************** waveProc() *******************************
* We don't use CALLBACK_FUNCTION because it is restricted to calling only
* a few particular Windows functions, namely some of the time functions,
* and a few of the Low Level MIDI API. If you violate this rule, your app can
* hang inside of the callback). One of the Windows API that a callback can't
* call is waveInAddBuffer() which is what we need to use whenever we receive a
* MM_WIM_DATA. My callback would need to defer that job to another thread
* anyway, so instead just use CALLBACK_THREAD here instead.
*************************************************************************/
static DWORD WINAPI waveProc(LPVOID arg) {
MSG msg;
(void) arg;
while (GetMessage(&msg, 0, 0, 0)) {
switch (msg.message) {
case MM_WIM_DATA:
GAUDIN_ISR_CompleteI((audin_sample_t *)((WAVEHDR *)msg.lParam)->lpData, ((WAVEHDR *)msg.lParam)->dwBytesRecorded/sizeof(audin_sample_t));
/* Are we closing? */
if (isClosing) {
/* Yes. We aren't recording, so another WAVEHDR has been returned to us after recording has stopped.
* When we get all of them back, things can be cleaned up
*/
nQueuedBuffers--;
waveInUnprepareHeader(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
} else {
/* No. Now we need to requeue this buffer so the driver can use it for another block of audio
* data. NOTE: We shouldn't need to waveInPrepareHeader() a WAVEHDR that has already been prepared once.
* Note: We are assuming here that both the application can still access the buffer while
* it is on the queue.
*/
waveInAddBuffer(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
}
break;
}
}
return 0;
}
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
void gaudin_lld_deinit(void) {
if (ah) {
isClosing = TRUE;
waveInReset(ah);
while(nQueuedBuffers) Sleep(1);
waveInClose(ah);
ah = 0;
if (pWaveHdrs) gfxFree(pWaveHdrs);
pWaveHdrs = 0;
isClosing = FALSE;
}
}
void gaudin_lld_init(const gaudin_params *paud) {
WAVEFORMATEX wfx;
size_t spaceleft;
audin_sample_t *p;
WAVEHDR *phdr;
size_t nBuffers;
size_t sz;
if (!waveThread) {
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
fprintf(stderr, "GAUDIN/GAUDOUT: Can't create WAVE recording thread\n");
return;
}
CloseHandle(waveThread);
}
gaudin_lld_deinit();
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = paud->channel == GAUDIN_STEREO ? 2 : 1;
wfx.nSamplesPerSec = paud->frequency;
wfx.nBlockAlign = wfx.nChannels * sizeof(audin_sample_t);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.wBitsPerSample = sizeof(audin_sample_t) * 8;
wfx.cbSize = 0;
if (waveInOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, (DWORD_PTR)paud, CALLBACK_THREAD)) {
fprintf(stderr, "GAUDIN: Can't open WAVE recording device\n");
return;
}
/* We need to allocate a wave header for each buffer */
nBuffers = (paud->bufcount + paud->samplesPerEvent - 1) / paud->samplesPerEvent;
if (!(pWaveHdrs = gfxAlloc(nBuffers * sizeof(WAVEHDR)))) {
fprintf(stderr, "GAUDIN: Buffer header allocation failed\n");
return;
}
/* Prepare each buffer and send to the wavein device */
spaceleft = paud->bufcount;
for(p = paud->buffer, phdr = pWaveHdrs, spaceleft = paud->bufcount; spaceleft; p += sz, phdr++, spaceleft -= sz) {
sz = spaceleft > paud->samplesPerEvent ? paud->samplesPerEvent : spaceleft;
phdr->dwBufferLength = sz * sizeof(audin_sample_t);
phdr->lpData = (LPSTR)p;
phdr->dwFlags = 0;
if (!waveInPrepareHeader(ah, phdr, sizeof(WAVEHDR))
&& !waveInAddBuffer(ah, phdr, sizeof(WAVEHDR)))
nQueuedBuffers++;
else
fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
}
if (!nQueuedBuffers)
fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
}
void gaudin_lld_start(void) {
waveInStart(ah);
}
void gaudin_lld_stop(void) {
waveInStop(ah);
}
#endif /* GFX_USE_GAUDIN */

View File

@ -1,64 +0,0 @@
/*
* 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 drivers/audio/Win32/gaudin_lld_config.h
* @brief GAUDIN Driver config file.
*
* @addtogroup GAUDIN
* @{
*/
#ifndef GAUDIN_LLD_CONFIG_H
#define GAUDIN_LLD_CONFIG_H
#if GFX_USE_GAUDIN
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
/**
* @brief The audio input sample type
*/
//typedef uint8_t audin_sample_t;
typedef int16_t audin_sample_t;
/**
* @brief The maximum sample frequency supported by this audio device
*/
#define GAUDIN_MAX_SAMPLE_FREQUENCY 44100
/**
* @brief The number of bits in a sample
*/
//#define GAUDIN_BITS_PER_SAMPLE 8
#define GAUDIN_BITS_PER_SAMPLE 16
/**
* @brief The format of an audio sample
*/
//#define GAUDIN_SAMPLE_FORMAT ARRAY_DATA_8BITUNSIGNED
#define GAUDIN_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
/**
* @brief The number of audio channels supported by this driver
*/
#define GAUDIN_NUM_CHANNELS 2
/**
* @brief The list of audio channels and their uses
* @{
*/
#define GAUDIN_MONO 0
#define GAUDIN_STEREO 1
/** @} */
#endif /* GFX_USE_GAUDIN */
#endif /* GAUDIN_LLD_CONFIG_H */
/** @} */

View File

@ -1,10 +0,0 @@
This driver uses the Win32 audio system to provide GAUDIN and GAUDOUT channels.
For GAUDIN - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
For GAUDOUT - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
sample period.
This is a simple driver that makes no changes to the mixer so set up the audio mixer using
the windows control panel audio mixer before starting recording/playback.

View File

@ -1,5 +0,0 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/audio/gadc

View File

@ -0,0 +1,6 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/gaudio/Win32/gaudio_record_lld.c \
$(GFXLIB)/drivers/gaudio/Win32/gaudio_play_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/gaudio/Win32

View File

@ -6,17 +6,17 @@
*/ */
/** /**
* @file drivers/audio/Win32/gaudout_lld_config.h * @file drivers/gaudio/Win32/gaudio_play_config.h
* @brief GAUDOUT Driver config file. * @brief GAUDIO Play Driver config file.
* *
* @addtogroup GAUDOUT * @addtogroup GAUDIO
* @{ * @{
*/ */
#ifndef GAUDOUT_LLD_CONFIG_H #ifndef GAUDIO_PLAY_CONFIG_H
#define GAUDIN_LLD_CONFIG_H #define GAUDIO_PLAY_CONFIG_H
#if GFX_USE_GAUDOUT #if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
/*===========================================================================*/ /*===========================================================================*/
/* Driver hardware support. */ /* Driver hardware support. */
@ -25,39 +25,39 @@
/** /**
* @brief The maximum sample frequency supported by this audio device * @brief The maximum sample frequency supported by this audio device
*/ */
#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100 #define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 44100
/** /**
* @brief The number of audio formats supported by this driver * @brief The number of audio formats supported by this driver
*/ */
#define GAUDOUT_NUM_FORMATS 2 #define GAUDIO_PLAY_NUM_FORMATS 2
/** /**
* @brief The available audio sample formats in order of preference * @brief The available audio sample formats in order of preference
*/ */
#define GAUDOUT_FORMAT1 ARRAY_DATA_16BITSIGNED #define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED
#define GAUDOUT_FORMAT2 ARRAY_DATA_8BITUNSIGNED #define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED
/** /**
* @brief The number of audio channels supported by this driver * @brief The number of audio channels supported by this driver
*/ */
#define GAUDOUT_NUM_CHANNELS 2 #define GAUDIO_PLAY_NUM_CHANNELS 2
/** /**
* @brief Whether each channel is mono or stereo * @brief Whether each channel is mono or stereo
*/ */
#define GAUDOUT_CHANNEL0_STEREO FALSE #define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE
#define GAUDOUT_CHANNEL1_STEREO TRUE #define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE
/** /**
* @brief The list of audio channel names and their uses * @brief The list of audio channel names and their uses
* @{ * @{
*/ */
#define GAUDOUT_MONO 0 #define GAUDIO_PLAY_MONO 0
#define GAUDOUT_STEREO 1 #define GAUDIO_PLAY_STEREO 1
/** @} */ /** @} */
#endif /* GFX_USE_GAUDOUT */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
#endif /* GAUDOUT_LLD_CONFIG_H */ #endif /* GAUDIO_PLAY_CONFIG_H */
/** @} */ /** @} */

View File

@ -6,16 +6,16 @@
*/ */
/** /**
* @file drivers/audio/Win32/gaudout_lld.c * @file drivers/gaudio/Win32/gaudio_play_lld.c
* @brief GAUDOUT - Driver file for Win32. * @brief GAUDIO - Play Driver file for Win32.
*/ */
#include "gfx.h" #include "gfx.h"
#if GFX_USE_GAUDOUT #if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY
/* Include the driver defines */ /* Include the driver defines */
#include "src/gaudout/driver.h" #include "src/gaudio/driver_play.h"
#undef Red #undef Red
#undef Green #undef Green
@ -36,20 +36,6 @@ static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
static HANDLE waveThread; static HANDLE waveThread;
static DWORD threadID; static DWORD threadID;
/*
static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
{
#define BUFFERSIZE 128
char buffer[BUFFERSIZE];
fprintf(stderr, "GAUDOUT: ERROR 0x%08X: %s\r\n", err, str);
if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
fprintf(stderr, "%s\r\n", &buffer[0]);
else
fprintf(stderr, "0x%08X returned!\r\n", err);
}
*/
/**************************** waveProc() ******************************* /**************************** waveProc() *******************************
* We don't use CALLBACK_FUNCTION because it is restricted to calling only * We don't use CALLBACK_FUNCTION because it is restricted to calling only
* a few particular Windows functions, namely some of the time functions, * a few particular Windows functions, namely some of the time functions,
@ -65,7 +51,9 @@ static bool_t senddata(WAVEHDR *pwh) {
// Get the next data block to send // Get the next data block to send
gfxSystemLock(); gfxSystemLock();
paud = gaudoutGetDataBlockI(); paud = gaudioPlayGetDataBlockI();
if (!paud && !nQueuedBuffers)
gaudioPlayDoneI();
gfxSystemUnlock(); gfxSystemUnlock();
if (!paud) if (!paud)
return FALSE; return FALSE;
@ -77,13 +65,13 @@ static bool_t senddata(WAVEHDR *pwh) {
pwh->dwFlags = 0; pwh->dwFlags = 0;
pwh->dwLoops = 0; pwh->dwLoops = 0;
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) { if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
fprintf(stderr, "GAUDOUT: Failed to prepare a buffer"); fprintf(stderr, "GAUDIO: Failed to prepare a play buffer");
exit(-1); exit(-1);
} }
// Send it to windows // Send it to windows
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) { if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
fprintf(stderr, "GAUDOUT: Failed to write the buffer"); fprintf(stderr, "GAUDIO: Failed to write the play buffer");
exit(-1); exit(-1);
} }
@ -106,18 +94,25 @@ static DWORD WINAPI waveProc(LPVOID arg) {
// Give the buffer back to the Audio Free List // Give the buffer back to the Audio Free List
gfxSystemLock(); gfxSystemLock();
gaudoutReleaseDataBlockI((GAudioData *)pwh->dwUser); gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser);
gfxSystemUnlock(); gfxSystemUnlock();
pwh->lpData = 0; pwh->lpData = 0;
nQueuedBuffers--; nQueuedBuffers--;
// Try and get a new block // Are we stopping?
if ((!isRunning || !senddata(pwh)) && !nQueuedBuffers) { if (!isRunning) {
gfxSystemLock(); // Have we finished yet?
gaudoutDoneI(); if (!nQueuedBuffers) {
gfxSystemUnlock(); gfxSystemLock();
gaudioPlayDoneI();
gfxSystemUnlock();
}
break;
} }
break;
// Try and get a new block
senddata(pwh);
break;
} }
} }
return 0; return 0;
@ -127,17 +122,7 @@ static DWORD WINAPI waveProc(LPVOID arg) {
/* External declarations. */ /* External declarations. */
/*===========================================================================*/ /*===========================================================================*/
void gaudout_lld_deinit() { bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
if (ah) {
isRunning = FALSE;
waveOutReset(ah);
while(nQueuedBuffers) Sleep(1);
waveOutClose(ah);
ah = 0;
}
}
bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
WAVEFORMATEX wfx; WAVEFORMATEX wfx;
if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED) if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
@ -145,40 +130,41 @@ bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat fo
if (!waveThread) { if (!waveThread) {
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) { if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n"); fprintf(stderr, "GAUDIO: Can't create WAVE play-back thread\n");
exit(-1); exit(-1);
} }
CloseHandle(waveThread); CloseHandle(waveThread);
} }
wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = channel == GAUDOUT_STEREO ? 2 : 1; wfx.nChannels = channel == GAUDIO_PLAY_STEREO ? 2 : 1;
wfx.nSamplesPerSec = frequency; wfx.nSamplesPerSec = frequency;
wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2); wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16); wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
wfx.cbSize = 0; wfx.cbSize = 0;
if (ah) {
waveOutClose(ah);
ah = 0;
}
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) { if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n"); fprintf(stderr, "GAUDIO: Can't open WAVE play-back device\n");
exit(-1); exit(-1);
} }
return TRUE; return TRUE;
} }
bool_t gaudout_lld_set_volume(uint8_t vol) { bool_t gaudio_play_lld_set_volume(uint8_t vol) {
if (!ah) if (!ah)
return FALSE; return FALSE;
return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0; return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
} }
void gaudout_lld_start(void) { void gaudio_play_lld_start(void) {
WAVEHDR *pwh; WAVEHDR *pwh;
if (!ah)
return;
isRunning = TRUE; isRunning = TRUE;
while (nQueuedBuffers < MAX_WAVE_HEADERS) { while (nQueuedBuffers < MAX_WAVE_HEADERS) {
// Find the empty one - there will always be at least one. // Find the empty one - there will always be at least one.
@ -190,10 +176,10 @@ void gaudout_lld_start(void) {
} }
} }
void gaudout_lld_stop(void) { void gaudio_play_lld_stop(void) {
isRunning = FALSE; isRunning = FALSE;
if (ah) waveOutReset(ah);
waveOutReset(ah); while(nQueuedBuffers) Sleep(1);
} }
#endif /* GFX_USE_GAUDOUT */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */

View File

@ -0,0 +1,63 @@
/*
* 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 drivers/gaudio/Win32/gaudio_record_config.h
* @brief GAUDIO Record Driver config file.
*
* @addtogroup GAUDIO
* @{
*/
#ifndef GAUDIO_RECORD_CONFIG_H
#define GAUDIO_RECORD_CONFIG_H
#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
/**
* @brief The maximum sample frequency supported by this audio device
*/
#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY 44100
/**
* @brief The number of audio formats supported by this driver
*/
#define GAUDIO_RECORD_NUM_FORMATS 2
/**
* @brief The available audio sample formats in order of preference
*/
#define GAUDIO_RECORD_FORMAT1 ARRAY_DATA_16BITSIGNED
#define GAUDIO_RECORD_FORMAT2 ARRAY_DATA_8BITUNSIGNED
/**
* @brief The number of audio channels supported by this driver
*/
#define GAUDIO_RECORD_NUM_CHANNELS 2
/**
* @brief Whether each channel is mono or stereo
*/
#define GAUDIO_RECORD_CHANNEL0_IS_STEREO FALSE
#define GAUDIO_RECORD_CHANNEL1_IS_STEREO TRUE
/**
* @brief The list of audio channels and their uses
* @{
*/
#define GAUDIO_RECORD_MONO 0
#define GAUDIO_RECORD_STEREO 1
/** @} */
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
#endif /* GAUDIO_RECORD_CONFIG_H */
/** @} */

View File

@ -0,0 +1,187 @@
/*
* 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 drivers/gaudio/Win32/gaudio_record_lld.c
* @brief GAUDIO - Record Driver file for Win32.
*/
#include "gfx.h"
#if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/* Include the driver defines */
#include "src/gaudio/driver_record.h"
#undef Red
#undef Green
#undef Blue
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#define MAX_WAVE_HEADERS 2 // Larger numbers enable more buffering which is good for ensuring
// there are no skips due to data not being available, however larger
// numbers of buffers chews buffers on the free-list.
static HWAVEIN ah = 0;
static volatile int nQueuedBuffers;
static bool_t isRunning;
static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
static HANDLE waveThread;
static DWORD threadID;
/**************************** waveProc() *******************************
* We don't use CALLBACK_FUNCTION because it is restricted to calling only
* a few particular Windows functions, namely some of the time functions,
* and a few of the Low Level MIDI API. If you violate this rule, your app can
* hang inside of the callback). One of the Windows API that a callback can't
* call is waveInAddBuffer() which is what we need to use whenever we receive a
* MM_WIM_DATA. My callback would need to defer that job to another thread
* anyway, so instead just use CALLBACK_THREAD here instead.
*************************************************************************/
static bool_t getbuffer(WAVEHDR *pwh) {
GAudioData *paud;
// Get the next data block to send
gfxSystemLock();
paud = gaudioRecordGetFreeBlockI();
if (!paud && !nQueuedBuffers)
gaudioRecordDoneI();
gfxSystemUnlock();
if (!paud)
return FALSE;
// Prepare the wave header for Windows
pwh->dwUser = (DWORD_PTR)paud;
pwh->lpData = (LPSTR)(paud+1); // The data is on the end of the structure
pwh->dwBufferLength = paud->size;
pwh->dwFlags = 0;
if (waveInPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
fprintf(stderr, "GAUDIO: Failed to prepare a record buffer");
exit(-1);
}
// Send it to windows
if (waveInAddBuffer(ah, pwh, sizeof(WAVEHDR))) {
fprintf(stderr, "GAUDIO: Failed to add the record buffer");
exit(-1);
}
nQueuedBuffers++;
return TRUE;
}
static DWORD WINAPI waveProc(LPVOID arg) {
MSG msg;
WAVEHDR *pwh;
GAudioData *paud;
(void) arg;
while (GetMessage(&msg, 0, 0, 0)) {
switch (msg.message) {
case MM_WIM_DATA:
pwh = (WAVEHDR *)msg.lParam;
// Windows - Let go!
waveInUnprepareHeader(ah, pwh, sizeof(WAVEHDR));
// Save the buffer in the audio record list
paud = (GAudioData *)pwh->dwUser;
paud->len = pwh->dwBytesRecorded;
gfxSystemLock();
gaudioRecordSaveDataBlockI(paud);
gfxSystemUnlock();
pwh->lpData = 0;
nQueuedBuffers--;
// Are we stopping?
if (!isRunning) {
// Have we finished yet?
if (!nQueuedBuffers) {
gfxSystemLock();
gaudioRecordDoneI();
gfxSystemUnlock();
}
break;
}
// Try and get a new block
getbuffer(pwh);
break;
}
}
return 0;
}
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
WAVEFORMATEX wfx;
if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED)
return FALSE;
if (!waveThread) {
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
fprintf(stderr, "GAUDIO: Can't create WAVE recording thread\n");
exit(-1);
}
CloseHandle(waveThread);
}
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = channel == GAUDIO_RECORD_STEREO ? 2 : 1;
wfx.nSamplesPerSec = frequency;
wfx.nBlockAlign = wfx.nChannels * (format == ARRAY_DATA_8BITUNSIGNED ? 1 : 2);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.wBitsPerSample = (format == ARRAY_DATA_8BITUNSIGNED ? 8 : 16);
wfx.cbSize = 0;
if (ah) {
waveInClose(ah);
ah = 0;
}
if (waveInOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
fprintf(stderr, "GAUDIN: Can't open WAVE recording device\n");
exit(-1);
}
return TRUE;
}
void gaudio_record_lld_start(void) {
WAVEHDR *pwh;
if (!ah)
return;
while (nQueuedBuffers < MAX_WAVE_HEADERS) {
// Find the empty one - there will always be at least one.
for(pwh = WaveHdrs; pwh->lpData; pwh++);
// Grab the next audio block from the free-list
if (!getbuffer(pwh))
break;
}
if (!isRunning) {
isRunning = TRUE;
waveInStart(ah);
}
}
void gaudio_record_lld_stop(void) {
isRunning = FALSE;
waveInReset(ah);
while(nQueuedBuffers) Sleep(1);
}
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */

View File

@ -0,0 +1,10 @@
This driver uses the Win32 audio system to provide GAUDIO play and record channels.
For PLAY - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
For RECORD - It supports 2 channels, Channel 0 being a mono channel and Channel 1 being a stereo channel.
For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
sample period.
This is a simple driver that makes no changes to the mixer so set up the audio mixer using
the windows control panel audio mixer before starting recording/playback.

View File

@ -0,0 +1,5 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/gaudio/gadc/gaudio_record_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/gaudio/gadc

View File

@ -6,15 +6,15 @@
*/ */
/** /**
* @file drivers/gaudin/gadc/gaudin_lld_board_template.h * @file drivers/gaudio/gadc/gaudio_record_board_template.h
* @brief GAUDIN Driver board config board file * @brief GAUDIO Record Driver board config board file
* *
* @addtogroup GAUDIN * @addtogroup GAUDIO
* @{ * @{
*/ */
#ifndef _GAUDIN_LLD_BOARD_H #ifndef _GAUDIO_RECORD_BOARD_H
#define _GAUDIN_LLD_BOARD_H #define _GAUDIO_RECORD_BOARD_H
/*===========================================================================*/ /*===========================================================================*/
/* Audio inputs on this board */ /* Audio inputs on this board */
@ -24,14 +24,14 @@
* @brief The number of audio channels supported by this driver * @brief The number of audio channels supported by this driver
* @note This is an example * @note This is an example
*/ */
#define GAUDIN_NUM_CHANNELS 1 #define GAUDIO_RECORD_NUM_CHANNELS 1
/** /**
* @brief The list of audio channels and their uses * @brief The list of audio channels and their uses
* @note This is an example * @note This is an example
* @{ * @{
*/ */
#define GAUDIN_MICROPHONE 0 #define GAUDIO_RECORD_MICROPHONE 0
/** @} */ /** @} */
/** /**
@ -39,12 +39,12 @@
* @note This is an example * @note This is an example
* @{ * @{
*/ */
#ifdef GAUDIN_LLD_IMPLEMENTATION #ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION
static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = { static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {
GADC_PHYSDEV_MICROPHONE, GADC_PHYSDEV_MICROPHONE,
}; };
#endif #endif
/** @} */ /** @} */
#endif /* _GAUDIN_LLD_BOARD_H */ #endif /* _GAUDIO_RECORD_BOARD_H */
/** @} */ /** @} */

View File

@ -6,54 +6,54 @@
*/ */
/** /**
* @file drivers/gaudin/gadc/gaudin_lld_config.h * @file drivers/gaudio/gadc/gaudio_record_config.h
* @brief GAUDIN Driver config file. * @brief GAUDIN Record Driver config file.
* *
* @addtogroup GAUDIN * @addtogroup GAUDIO
* @{ * @{
*/ */
#ifndef GAUDIN_LLD_CONFIG_H #ifndef GAUDIO_RECORD_CONFIG_H
#define GAUDIN_LLD_CONFIG_H #define GAUDIO_RECORD_CONFIG_H
#if GFX_USE_GAUDIN #if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/*===========================================================================*/ /*===========================================================================*/
/* Driver hardware support. */ /* Driver hardware support. */
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief The audio input sample type * @brief The audio record sample type
* @details For this driver it matches the cpu sample type * @details For this driver it matches the cpu sample type
*/ */
typedef adcsample_t audin_sample_t; typedef adcsample_t audio_record_sample_t;
/** /**
* @brief The maximum sample frequency supported by this audio device * @brief The maximum sample frequency supported by this audio device
* @details For this driver it matches the GADC maximum high speed sample rate * @details For this driver it matches the GADC maximum high speed sample rate
*/ */
#define GAUDIN_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE #define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE
/** /**
* @brief The number of bits in a sample * @brief The number of bits in a sample
* @details For this driver it matches the cpu sample bits * @details For this driver it matches the cpu sample bits
*/ */
#define GAUDIN_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE #define GAUDIO_RECORD_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE
/** /**
* @brief The format of an audio sample * @brief The format of an audio sample
* @details For this driver it matches the cpu sample format * @details For this driver it matches the cpu sample format
*/ */
#define GAUDIN_SAMPLE_FORMAT GADC_SAMPLE_FORMAT #define GAUDIO_RECORD_SAMPLE_FORMAT GADC_SAMPLE_FORMAT
/** /**
* For the GAUDIN driver that uses GADC - all the remaining config definitions are specific * For the GAUDIO driver that uses GADC - all the remaining config definitions are specific
* to the board. * to the board.
*/ */
/* Include the user supplied board definitions */ /* Include the user supplied board definitions */
#include "gaudin_lld_board.h" #include "gaudio_record_board.h"
#endif /* GFX_USE_GAUDIN */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
#endif /* GAUDIN_LLD_CONFIG_H */ #endif /* GAUDIO_RECORD_CONFIG_H */
/** @} */ /** @} */

View File

@ -6,10 +6,10 @@
*/ */
/** /**
* @file drivers/gaudin/gadc/gaudin_lld.c * @file drivers/gaudio/gadc/gaudio_record_lld.c
* @brief GAUDIN - Driver file for using the cpu ADC (via GADC). * @brief GAUDIO - Record Driver file for using the cpu ADC (via GADC).
* *
* @addtogroup GAUDIN * @addtogroup GAUDIO
* *
* @{ * @{
*/ */
@ -18,20 +18,20 @@
* We are now implementing the driver - pull in our channel table * We are now implementing the driver - pull in our channel table
* from the board definitions. * from the board definitions.
*/ */
#define GAUDIN_LLD_IMPLEMENTATION #define GAUDIO_RECORD_IMPLEMENTATION
#include "gfx.h" #include "gfx.h"
#if GFX_USE_GAUDIN #if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD
/* Double check the GADC system is turned on */ /* Double check the GADC system is turned on */
#if !GFX_USE_GADC #if !GFX_USE_GADC
#error "GAUDIN - The GADC driver for GAUDIN requires GFX_USE_GADC to be TRUE" #error "GAUDIO - The GADC driver for GAUDIO requires GFX_USE_GADC to be TRUE"
#endif #endif
/* Include the driver defines */ /* Include the driver defines */
#include "src/gaudin/driver.h" #include "src/gaudio/driver_record.h"
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */ /* External declarations. */
@ -58,5 +58,5 @@ void gaudin_lld_stop(void) {
gadcHighSpeedStop(); gadcHighSpeedStop();
} }
#endif /* GFX_USE_GAUDIN */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
/** @} */ /** @} */

View File

@ -1,4 +1,4 @@
This driver uses the generic GADC driver to provide a GAUDIN device. This driver uses the generic GADC driver to provide a GAUDIO recording device.
It supports whatever high speed device channels that your GADC driver and board supports. It supports whatever high speed device channels that your GADC driver and board supports.

35
gfx.h
View File

@ -62,7 +62,7 @@
* @brief GFX Graphics Display Basic API * @brief GFX Graphics Display Basic API
* @details Defaults to FALSE * @details Defaults to FALSE
* @note Also add the specific hardware driver to your makefile. * @note Also add the specific hardware driver to your makefile.
* Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/gdisp_lld.mk * Eg. include $(GFXLIB)/drivers/gdisp/Nokia6610/driver.mk
*/ */
#ifndef GFX_USE_GDISP #ifndef GFX_USE_GDISP
#define GFX_USE_GDISP FALSE #define GFX_USE_GDISP FALSE
@ -106,9 +106,9 @@
* @details Defaults to FALSE * @details Defaults to FALSE
* @note Also add the specific hardware drivers to your makefile. * @note Also add the specific hardware drivers to your makefile.
* Eg. * Eg.
* include $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld.mk * include $(GFXLIB)/drivers/ginput/toggle/Pal/driver.mk
* and... * and...
* include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk * include $(GFXLIB)/drivers/ginput/touch/MCU/driver.mk
*/ */
#ifndef GFX_USE_GINPUT #ifndef GFX_USE_GINPUT
#define GFX_USE_GINPUT FALSE #define GFX_USE_GINPUT FALSE
@ -121,24 +121,14 @@
#define GFX_USE_GADC FALSE #define GFX_USE_GADC FALSE
#endif #endif
/** /**
* @brief GFX Audio Input Device API * @brief GFX Audio API
* @details Defaults to FALSE * @details Defaults to FALSE
* @note Also add the specific hardware drivers to your makefile. * @note Also add the specific hardware drivers to your makefile.
* Eg. * Eg.
* include $(GFXLIB)/drivers/gaudin/GADC/gaudin_lld.mk * include $(GFXLIB)/drivers/gaudio/GADC/driver.mk
*/ */
#ifndef GFX_USE_GAUDIN #ifndef GFX_USE_GAUDIO
#define GFX_USE_GAUDIN FALSE #define GFX_USE_GAUDIO FALSE
#endif
/**
* @brief GFX Audio Output Device API
* @details Defaults to FALSE
* @note Also add the specific hardware drivers to your makefile.
* Eg.
* include $(GFXLIB)/drivers/gaudout/PWM/gaudout_lld.mk
*/
#ifndef GFX_USE_GAUDOUT
#define GFX_USE_GAUDOUT FALSE
#endif #endif
/** /**
* @brief GFX Miscellaneous Routines API * @brief GFX Miscellaneous Routines API
@ -173,8 +163,7 @@
#include "src/gwin/sys_options.h" #include "src/gwin/sys_options.h"
#include "src/ginput/sys_options.h" #include "src/ginput/sys_options.h"
#include "src/gadc/sys_options.h" #include "src/gadc/sys_options.h"
#include "src/gaudin/sys_options.h" #include "src/gaudio/sys_options.h"
#include "src/gaudout/sys_options.h"
/** /**
* Interdependency safety checks on the sub-systems. * Interdependency safety checks on the sub-systems.
@ -187,8 +176,7 @@
#include "src/gwin/sys_rules.h" #include "src/gwin/sys_rules.h"
#include "src/ginput/sys_rules.h" #include "src/ginput/sys_rules.h"
#include "src/gdisp/sys_rules.h" #include "src/gdisp/sys_rules.h"
#include "src/gaudout/sys_rules.h" #include "src/gaudio/sys_rules.h"
#include "src/gaudin/sys_rules.h"
#include "src/gadc/sys_rules.h" #include "src/gadc/sys_rules.h"
#include "src/gevent/sys_rules.h" #include "src/gevent/sys_rules.h"
#include "src/gtimer/sys_rules.h" #include "src/gtimer/sys_rules.h"
@ -210,8 +198,7 @@
#include "src/gwin/sys_defs.h" #include "src/gwin/sys_defs.h"
#include "src/ginput/sys_defs.h" #include "src/ginput/sys_defs.h"
#include "src/gadc/sys_defs.h" #include "src/gadc/sys_defs.h"
#include "src/gaudin/sys_defs.h" #include "src/gaudio/sys_defs.h"
#include "src/gaudout/sys_defs.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -231,7 +218,7 @@ extern "C" {
/** /**
* @brief The one call to end it all * @brief The one call to end it all
* *
* @note This will deinitialise each sub-system that has been turned on. * @note This will de-initialise each sub-system that has been turned on.
* *
* @api * @api
*/ */

3
gfx.mk
View File

@ -9,7 +9,6 @@ include $(GFXLIB)/src/gtimer/sys_make.mk
include $(GFXLIB)/src/gwin/sys_make.mk include $(GFXLIB)/src/gwin/sys_make.mk
include $(GFXLIB)/src/ginput/sys_make.mk include $(GFXLIB)/src/ginput/sys_make.mk
include $(GFXLIB)/src/gadc/sys_make.mk include $(GFXLIB)/src/gadc/sys_make.mk
include $(GFXLIB)/src/gaudin/sys_make.mk include $(GFXLIB)/src/gaudio/sys_make.mk
include $(GFXLIB)/src/gaudout/sys_make.mk
include $(GFXLIB)/src/gmisc/sys_make.mk include $(GFXLIB)/src/gmisc/sys_make.mk
include $(GFXLIB)/src/gfile/sys_make.mk include $(GFXLIB)/src/gfile/sys_make.mk

View File

@ -218,15 +218,11 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// GAUDIN // // GAUDIO //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
#define GFX_USE_GAUDIN FALSE #define GFX_USE_GAUDIO FALSE
#define GAUDIO_NEED_PLAY FALSE
#define GAUDIO_NEED_RECORD FALSE
///////////////////////////////////////////////////////////////////////////
// GAUDOUT //
///////////////////////////////////////////////////////////////////////////
#define GFX_USE_GAUDOUT FALSE
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -243,4 +239,3 @@
#endif /* _GFXCONF_H */ #endif /* _GFXCONF_H */

View File

@ -1,102 +0,0 @@
/*
* 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/gaudin/driver.h
* @brief GAUDIN - Audio Input driver header file.
*
* @defgroup Driver Driver
* @ingroup GAUDIN
* @{
*/
#ifndef _GAUDIN_LLD_H
#define _GAUDIN_LLD_H
#include "gfx.h"
#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @brief The structure passed to start a audio conversion
* @note We use the structure instead of parameters purely to save
* interrupt stack space which is very limited in some platforms.
* @{
*/
typedef struct gaudin_params_t {
uint16_t channel;
uint32_t frequency;
audin_sample_t *buffer;
size_t bufcount;
size_t samplesPerEvent;
} gaudin_params;
/** @} */
/**
* @brief These routines are the callbacks that the driver uses.
* @details Defined in the high level GAUDIN code.
*
* @iclass
* @notapi
*
* @{
*/
/**
* @param[in] buffer The buffer
* @param[in] n The amount of samples
* */
extern void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n);
extern void GAUDIN_ISR_ErrorI(void);
/**
* @}
*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise the driver
*
* @param[in] paud Initialisation parameters
*
* @api
*/
void gaudin_lld_init(const gaudin_params *paud);
/**
* @brief Start the audio input sampling
*
* @api
*/
void gaudin_lld_start(void);
/**
* @brief Stop the audio input sampling
*
* @api
*/
void gaudin_lld_stop(void);
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GADC */
#endif /* _GADC_LLD_H */
/** @} */

View File

@ -1,158 +0,0 @@
/*
* 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/gaudin/gaudin.c
* @brief GAUDIN sub-system code.
*
* @addtogroup GAUDIN
* @{
*/
#include "gfx.h"
#if GFX_USE_GAUDIN
/* Include the driver defines */
#include "src/gaudin/driver.h"
static gaudin_params aud;
static gfxSem *paudSem;
static GEventAudioIn *paudEvent;
static audin_sample_t *lastbuffer;
static size_t lastcount;
static uint16_t audFlags;
#define AUDFLG_RUNNING 0x0001
#define AUDFLG_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 GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n) {
/* Save the details */
lastcount = n;
lastbuffer = buffer;
/* Signal the user with the data */
if (paudEvent) {
#if GFX_USE_GEVENT
paudEvent->type = GEVENT_AUDIO_IN;
#endif
paudEvent->channel = aud.channel;
paudEvent->count = lastcount;
paudEvent->buffer = lastbuffer;
paudEvent->flags = 0;
}
/* Our two signalling mechanisms */
if (paudSem)
gfxSemSignalI(paudSem);
#if GFX_USE_GEVENT
if (audFlags & AUDFLG_USE_EVENTS)
gtimerJabI(&AudGTimer);
#endif
}
void GAUDIN_ISR_ErrorI(void) {
/* Ignore any errors for now */
}
void _gaudinInit(void)
{
#if GFX_USE_GEVENT
gtimerInit(&AudGTimer);
#endif
}
void _gaudinDeinit(void)
{
// Commented stuff still ToDo
#if GFX_USE_GEVENT
gtimerDeinit(&AudGTimer);
#endif
}
bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent) {
/* Check the channel is valid */
if (channel >= GAUDIN_NUM_CHANNELS || frequency > GAUDIN_MAX_SAMPLE_FREQUENCY)
return FALSE;
/* Stop any existing transfers */
if ((audFlags & AUDFLG_RUNNING))
gaudin_lld_stop();
audFlags = 0;
/* Initialise everything */
aud.channel = channel;
aud.frequency = frequency;
aud.buffer = buffer;
aud.bufcount = bufcount;
aud.samplesPerEvent = samplesPerEvent;
paudSem = 0;
paudEvent = 0;
/* Set up the low level driver */
gaudin_lld_init(&aud);
return TRUE;
}
#if GFX_USE_GEVENT
GSourceHandle gaudinGetSource(void) {
if (!gtimerIsActive(&AudGTimer))
gtimerStart(&AudGTimer, AudGTimerCallback, 0, TRUE, TIME_INFINITE);
audFlags |= AUDFLG_USE_EVENTS;
return (GSourceHandle)&aud;
}
#endif
void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent) {
gfxSystemLock();
paudSem = pbsem;
paudEvent = pEvent;
gfxSystemUnlock();
}
void gaudinStart(void) {
if (!(audFlags & AUDFLG_RUNNING)) {
audFlags |= AUDFLG_RUNNING;
gaudin_lld_start();
}
}
void gaudinStop(void) {
if ((audFlags & AUDFLG_RUNNING)) {
gaudin_lld_stop();
audFlags &= ~AUDFLG_RUNNING;
}
}
#endif /* GFX_USE_GAUDIN */
/** @} */

View File

@ -1,174 +0,0 @@
/*
* 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/gaudin/sys_defs.h
*
* @addtogroup GAUDIN
*
* @brief Module to read audio inputs
*
* @{
*/
#ifndef _GAUDIN_H
#define _GAUDIN_H
#include "gfx.h"
#if GFX_USE_GAUDIN || defined(__DOXYGEN__)
/* Include the driver defines */
#include "gaudin_lld_config.h"
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
// Event types for GAUDIN
#define GEVENT_AUDIO_IN (GEVENT_GAUDIN_FIRST+0)
/**
* @brief The Audio Input event structure.
* @{
*/
typedef struct GEventAudioIn_t {
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief The type of this event (GEVENT_AUDIO_IN)
*/
GEventType type;
#endif
/**
* @brief The current channel
*/
uint16_t channel;
/**
* @brief The event flags
*/
uint16_t flags;
/**
* @brief The event flag values.
* @{
*/
#define GAUDIN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
/** @} */
/**
* @brief The number of audio samples in the buffer
*/
size_t count;
/**
* @brief The buffer containing the audio samples
*/
audin_sample_t *buffer;
} GEventAudioIn;
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise (but not start) the Audio Input Subsystem.
* @details Returns FALSE for an invalid channel or other invalid parameter.
*
* @param[in] channel The channel to convert. Can be set from 0 to GAUDIN_NUM_CHANNELS - 1.
* @param[in] frequency The sample frequency
* @param[in] buffer The static buffer to put the samples into.
* @param[in] bufcount The total number of conversions that will fit in the buffer.
* @param[in] samplesPerEvent The number of conversions to do before returning an event.
*
* @note Only one channel is active at a time. If an audio input is running it will be stopped.
* The Event subsystem is disconnected from the audio subsystem and any binary semaphore
* event is forgotten.
* @note Some channels may be stereo channels which return twice as much sample data with
* the left and right channel data interleaved. Other channels may be mono channels.
* Where stereo channels exist it would be common for the low level driver to also
* offer the left and right channels separately.
* @note Due to a bug in Chibi-OS countPerEvent must be even if using the GADC low level audio driver.
* If bufcount is not evenly divisable by countPerEvent, the remainder must also be even.
* This requirement may not apply to other GAUDIN drivers.
* @note The number of samples for stereo devices will be double the number of conversions.
* Make sure you allocate your buffers large enough. Each channel is then interleaved
* into the provided buffer. Note 'bufcount' and 'countPerEvent' parameters describe the
* number of conversions not the number of samples.
* @note The buffer is circular. When the end of the buffer is reached it will start
* putting data into the beginning of the buffer again.
* @note The event listener must process the event (and the data in it) before the
* next event occurs. If not, the following event will be lost.
* @note If bufcount is evenly divisable by countPerEvent, then every event will return
* countPerEvent conversions. If bufcount is not evenly divisable, it will return
* a block of samples containing less than countPerEvent samples when it reaches the
* end of the buffer.
*
* @return FALSE if invalid channel or parameter
*
* @api
*/
bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent);
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief Turn on sending results to the GEVENT sub-system.
* @details Returns a GSourceHandle to listen for GEVENT_AUDIO_IN events.
*
* @note The audio input will not use the GEVENT system unless this is
* called first. This saves processing time if the application does
* not want to use the GEVENT sub-system for audio input.
* Once turned on it can only be turned off by calling @p gaudinInit() again.
* @note The audio input is capable of signalling via this method and a binary semaphore
* at the same time.
*
* @return The GSourceHandle
*
* @api
*/
GSourceHandle gaudinGetSource(void);
#endif
/**
* @brief Allow retrieving of results from the audio input using a Binary Semaphore and a static event buffer.
*
* @param[in] pbsem The semaphore is signaled when data is available.
* @param[in] pEvent The static event buffer to place the result information.
*
* @note Passing a NULL for pbsem or pEvent will turn off signalling via this method.
* @note The audio input is capable of signalling via this method and the GEVENT
* sub-system at the same time.
*
* @api
*/
void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent);
/**
* @brief Start the audio input conversions.
* @pre It must have been initialised first with @p gaudinInit()
*
* @api
*/
void gaudinStart(void);
/**
* @brief Stop the audio input conversions.
*
* @api
*/
void gaudinStop(void);
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GAUDIN */
#endif /* _GAUDIN_H */
/** @} */

View File

@ -1 +0,0 @@
GFXSRC += $(GFXLIB)/src/gaudin/gaudin.c

View File

@ -1,32 +0,0 @@
/*
* 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/gaudin/sys_options.h
* @brief GAUDIN - Audio Input subsystem options header file.
*
* @addtogroup GAUDIN
* @{
*/
#ifndef _GAUDIN_OPTIONS_H
#define _GAUDIN_OPTIONS_H
/**
* @name GAUDIN Functionality to be included
* @{
*/
/**
* @}
*
* @name GAUDIN Optional Sizing Parameters
* @{
*/
/** @} */
#endif /* _GAUDIN_OPTIONS_H */
/** @} */

View File

@ -1,30 +0,0 @@
/*
* 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/gaudin/sys_rules.h
* @brief GAUDIN safety rules header file.
*
* @addtogroup GAUDIN
* @{
*/
#ifndef _GAUDIN_RULES_H
#define _GAUDIN_RULES_H
#if GFX_USE_GAUDIN
#if GFX_USE_GEVENT && !GFX_USE_GTIMER
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GAUDIN: GFX_USE_GTIMER is required if GFX_USE_GAUDIN and GFX_USE_GEVENT are TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GTIMER
#define GFX_USE_GTIMER TRUE
#endif
#endif
#endif /* _GAUDIN_RULES_H */
/** @} */

View File

@ -6,20 +6,20 @@
*/ */
/** /**
* @file src/gaudout/driver.h * @file src/gaudio/driver_play.h
* @brief GAUDOUT - Audio Output driver header file. * @brief GAUDIO - Audio play driver header file.
* *
* @defgroup Driver Driver * @defgroup Driver Driver
* @ingroup GAUDOUT * @ingroup GAUDIO
* @{ * @{
*/ */
#ifndef _GAUDOUT_LLD_H #ifndef _GAUDIO_PLAY_LLD_H
#define _GAUDOUT_LLD_H #define _GAUDIO_PLAY_LLD_H
#include "gfx.h" #include "gfx.h"
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__) #if (GFX_USE_GAUDIO && GAUDIO_NEED_PLAY) || defined(__DOXYGEN__)
/*===========================================================================*/ /*===========================================================================*/
/* Type definitions */ /* Type definitions */
@ -37,38 +37,38 @@ extern "C" {
* @brief Get a block of audio data to play * @brief Get a block of audio data to play
* @return A pointer to the GAaudioData structure or NULL if none is currently available * @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. * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
* *
* @iclass * @iclass
* @notapi * @notapi
*/ */
GAudioData *gaudoutGetDataBlockI(void); GAudioData *gaudioPlayGetDataBlockI(void);
/** /**
* @brief Release a block of audio data after playing * @brief Release a block of audio data to the free list
* *
* @param[in] paud The GAudioData block to be released. * @param[in] paud The GAudioData block to be released.
* *
* @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
* *
* @iclass * @iclass
* @notapi * @notapi
*/ */
void gaudoutReleaseDataBlockI(GAudioData *paud); void gaudioPlayReleaseDataBlockI(GAudioData *paud);
/** /**
* @brief Signal that all playing has now stopped * @brief Signal that all playing has now stopped
* *
* @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers.
* *
* @iclass * @iclass
* @notapi * @notapi
*/ */
void gaudoutDoneI(void); void gaudioPlayDoneI(void);
/** /**
* @brief Initialise the driver * @brief Initialise the play driver
* @return TRUE if the channel and frequency are valid. * @return TRUE if the channel, frequency and format are valid.
* *
* @param[in] channel The channel to use (see the driver for the available channels provided) * @param[in] channel The channel to use (see the driver for the available channels provided)
* @param[in] frequency The sample frequency to use * @param[in] frequency The sample frequency to use
@ -78,38 +78,30 @@ void gaudoutDoneI(void);
* *
* @api * @api
*/ */
bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format); bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @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 * @brief Start the audio output playing
* *
* @note This may be called at any stage including while the driver * @note This may be called at any stage including while the driver
* is already playing. The driver should check for data blocks * is already playing. The driver should check for data blocks
* to play using @p gaudoutGetDataBlockI(). * to play using @p gaudioPlayGetDataBlockI().
* *
* @api * @api
*/ */
void gaudout_lld_start(void); void gaudio_play_lld_start(void);
/** /**
* @brief Stop the audio output playing. * @brief Stop the audio output playing.
* *
* @note Some drivers may only stop playing at a data block boundary. * @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. * @note It is possible but unlikely for it to be called when playing has already stopped.
* @note It should not return until all active buffers (currently in use by the driver)
* have been returned to the free-list and @p gaudioPlayDoneI() has been called.
* *
* @api * @api
*/ */
void gaudout_lld_stop(void); void gaudio_play_lld_stop(void);
/** /**
* @brief Set the output volume. * @brief Set the output volume.
@ -122,13 +114,13 @@ void gaudout_lld_stop(void);
* *
* @api * @api
*/ */
bool_t gaudout_lld_set_volume(uint8_t vol); bool_t gaudio_play_lld_set_volume(uint8_t vol);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* GFX_USE_GAUDOUT */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */
#endif /* _GAUDOUT_LLD_H */ #endif /* _GAUDIO_PLAY_LLD_H */
/** @} */ /** @} */

View File

@ -0,0 +1,108 @@
/*
* 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/gaudio/driver_record.h
* @brief GAUDIO - Audio Recording driver header file.
*
* @defgroup Driver Driver
* @ingroup GAUDIO
* @{
*/
#ifndef _GAUDIO_RECORD_LLD_H
#define _GAUDIO_RECORD_LLD_H
#include "gfx.h"
#if (GFX_USE_GAUDIO && GAUDIO_NEED_RECORD) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @brief Get a free block of audio data that we can record into
* @return A pointer to the GAaudioData structure or NULL if none is currently available
*
* @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
*
* @iclass
* @notapi
*/
GAudioData *gaudioRecordGetFreeBlockI(void);
/**
* @brief Save a block of recorded audio data ready for the application
*
* @param[in] paud The GAudioData block with data.
*
* @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
*
* @iclass
* @notapi
*/
void gaudioRecordSaveDataBlockI(GAudioData *paud);
/**
* @brief Signal that all recording has now stopped
*
* @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers.
*
* @iclass
* @notapi
*/
void gaudioRecordDoneI(void);
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise the record driver
* @return TRUE if the channel, frequency and format 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
* @param[in] format The sample format
*
* @note The driver will always have been stopped and de-init before this is called.
*
* @api
*/
bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @brief Start the audio recording
*
* @api
*/
void gaudio_record_lld_start(void);
/**
* @brief Stop the audio recording.
*
* @note Some drivers may only stop recording at a data block boundary.
* @note This routine should not return until any currently active buffers have been
* saved (even if with zero length) and @p gaudioRecordDoneI() has been called.
*
* @api
*/
void gaudio_record_lld_stop(void);
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */
#endif /* _GAUDIO_RECORD_LLD_H */
/** @} */

318
src/gaudio/gaudio.c 100644
View File

@ -0,0 +1,318 @@
/*
* 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/gaudio/gaudio.c
* @brief GAUDIO sub-system code.
*
* @addtogroup GAUDIO
* @{
*/
#include "gfx.h"
#if GFX_USE_GAUDIO
static gfxQueueGSync freeList;
#if GAUDIO_NEED_PLAY
#include "src/gaudio/driver_play.h"
static gfxQueueASync playList;
static gfxSem playComplete;
static uint16_t playFlags;
#define PLAYFLG_USEEVENTS 0x0001
#define PLAYFLG_PLAYING 0x0002
#define PLAYFLG_ISINIT 0x0004
#if GFX_USE_GEVENT
static GTimer playTimer;
static void PlayTimerCallback(void *param);
#endif
#endif
#if GAUDIO_NEED_RECORD
#include "src/gaudio/driver_record.h"
static gfxQueueGSync recordList;
static uint16_t recordFlags;
#define RECORDFLG_USEEVENTS 0x0001
#define RECORDFLG_RECORDING 0x0002
#define RECORDFLG_STALLED 0x0004
#define RECORDFLG_ISINIT 0x0008
#if GFX_USE_GEVENT
static GTimer recordTimer;
static void RecordTimerCallback(void *param);
#endif
#endif
void _gaudioInit(void)
{
gfxQueueGSyncInit(&freeList);
#if GAUDIO_NEED_PLAY
gfxQueueASyncInit(&playList);
#if GFX_USE_GEVENT
gtimerInit(&playTimer);
#endif
gfxSemInit(&playComplete, 0, 0);
#endif
#if GAUDIO_NEED_RECORD
gfxQueueGSyncInit(&recordList);
#if GFX_USE_GEVENT
gtimerInit(&recordTimer);
#endif
#endif
}
void _gaudioDeinit(void)
{
#if GAUDIO_NEED_PLAY
#if GFX_USE_GEVENT
gtimerDeinit(&playTimer);
#endif
gfxSemDestroy(&playComplete);
#endif
#if GAUDIO_NEED_RECORD
#if GFX_USE_GEVENT
gtimerDeinit(&recordTimer);
#endif
#endif
}
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);
}
#if GAUDIO_NEED_PLAY
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
gaudioPlayStop();
playFlags &= ~PLAYFLG_ISINIT;
if (!gaudio_play_lld_init(channel, frequency, format))
return FALSE;
playFlags |= PLAYFLG_ISINIT;
return TRUE;
}
void gaudioPlay(GAudioData *paud) {
if (!(playFlags & PLAYFLG_ISINIT)) {
// Oops - init failed - return it directly to the free-list
if (paud) {
gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud);
gfxYield(); // Make sure we get no endless cpu hogging loops
}
return;
}
if (paud)
gfxQueueASyncPut(&playList, (gfxQueueASyncItem *)paud);
playFlags |= PLAYFLG_PLAYING;
gaudio_play_lld_start();
}
void gaudioPlayPause(void) {
if ((playFlags & (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) == (PLAYFLG_ISINIT|PLAYFLG_PLAYING))
gaudio_play_lld_stop();
}
void gaudioPlayStop(void) {
GAudioData *paud;
if (playFlags & PLAYFLG_PLAYING)
gaudio_play_lld_stop();
while((paud = (GAudioData *)gfxQueueASyncGet(&playList)))
gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud);
}
bool_t gaudioPlaySetVolume(uint8_t vol) {
return gaudio_play_lld_set_volume(vol);
}
bool_t gaudioPlayWait(delaytime_t ms) {
if (!(playFlags & PLAYFLG_PLAYING))
return TRUE;
return gfxSemWait(&playComplete, ms);
}
#if GFX_USE_GEVENT
static void PlayTimerCallback(void *param) {
(void) param;
GSourceListener *psl;
GEventAudioPlay *pe;
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)&playTimer, psl))) {
if (!(pe = (GEventAudioPlay *)geventGetEventBuffer(psl))) {
// This listener is missing - save this.
psl->srcflags |= GAUDIO_PLAY_LOSTEVENT;
continue;
}
pe->type = GEVENT_AUDIO_PLAY;
pe->flags = psl->srcflags;
psl->srcflags = 0;
if ((playFlags & PLAYFLG_PLAYING))
pe->flags |= GAUDIO_PLAY_PLAYING;
if (!gfxQueueGSyncIsEmpty(&freeList))
pe->flags |= GAUDIO_PLAY_FREEBLOCK;
geventSendEvent(psl);
}
}
GSourceHandle gaudioPlayGetSource(void) {
if (!gtimerIsActive(&playTimer))
gtimerStart(&playTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
playFlags |= PLAYFLG_USEEVENTS;
return (GSourceHandle)&playTimer;
}
#endif
/**
* Routines provided for use by drivers.
*/
GAudioData *gaudioPlayGetDataBlockI(void) {
return (GAudioData *)gfxQueueASyncGetI(&playList);
}
void gaudioPlayReleaseDataBlockI(GAudioData *paud) {
gfxQueueGSyncPutI(&freeList, (gfxQueueGSyncItem *)paud);
#if GFX_USE_GEVENT
if (playFlags & PLAYFLG_USEEVENTS)
gtimerJabI(&playTimer);
#endif
}
void gaudioPlayDoneI(void) {
playFlags &= ~PLAYFLG_PLAYING;
#if GFX_USE_GEVENT
if (playFlags & PLAYFLG_USEEVENTS)
gtimerJabI(&playTimer);
#endif
gfxSemSignalI(&playComplete); // This should really be gfxSemSignalAllI(&playComplete);
}
#endif
#if GAUDIO_NEED_RECORD
bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
gaudioRecordStop();
recordFlags &= ~RECORDFLG_ISINIT;
if (!gaudio_record_lld_init(channel, frequency, format))
return FALSE;
recordFlags |= RECORDFLG_ISINIT;
return TRUE;
}
void gaudioRecordStart(void) {
if (!(recordFlags & RECORDFLG_ISINIT))
return; // Oops - init failed
recordFlags |= RECORDFLG_RECORDING;
recordFlags &= ~RECORDFLG_STALLED;
gaudio_record_lld_start();
}
void gaudioRecordStop(void) {
GAudioData *paud;
if ((recordFlags & (RECORDFLG_RECORDING|RECORDFLG_STALLED)) == RECORDFLG_RECORDING)
gaudio_record_lld_stop();
recordFlags &= ~(RECORDFLG_RECORDING|RECORDFLG_STALLED);
while((paud = (GAudioData *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE)))
gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud);
}
GAudioData *gaudioRecordGetData(delaytime_t ms) {
return (GAudioData *)gfxQueueGSyncGet(&recordList, ms);
}
#if GFX_USE_GEVENT
static void RecordTimerCallback(void *param) {
(void) param;
GSourceListener *psl;
GEventAudioRecord *pe;
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)&recordTimer, psl))) {
if (!(pe = (GEventAudioRecord *)geventGetEventBuffer(psl))) {
// This listener is missing - save this.
psl->srcflags |= GAUDIO_RECORD_LOSTEVENT;
continue;
}
pe->type = GEVENT_AUDIO_RECORD;
pe->flags = psl->srcflags;
psl->srcflags = 0;
if ((recordFlags & RECORDFLG_RECORDING))
pe->flags |= GAUDIO_RECORD_RECORDING;
if ((recordFlags & RECORDFLG_STALLED))
pe->flags |= GAUDIO_RECORD_STALL;
if (!gfxQueueGSyncIsEmpty(&recordList))
pe->flags |= GAUDIO_RECORD_GOTBLOCK;
geventSendEvent(psl);
}
}
GSourceHandle gaudioRecordGetSource(void) {
if (!gtimerIsActive(&recordTimer))
gtimerStart(&recordTimer, RecordTimerCallback, 0, TRUE, TIME_INFINITE);
recordFlags |= RECORDFLG_USEEVENTS;
return (GSourceHandle)&recordTimer;
}
#endif
/**
* Routines provided for use by drivers.
*/
GAudioData *gaudioRecordGetFreeBlockI(void) {
return (GAudioData *)gfxQueueGSyncGetI(&freeList);
}
void gaudioRecordSaveDataBlockI(GAudioData *paud) {
gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud);
#if GFX_USE_GEVENT
if (recordFlags & RECORDFLG_USEEVENTS)
gtimerJabI(&recordTimer);
#endif
}
void gaudioRecordDoneI(void) {
recordFlags |= RECORDFLG_STALLED;
#if GFX_USE_GEVENT
if (recordFlags & RECORDFLG_USEEVENTS)
gtimerJabI(&recordTimer);
#endif
}
#endif
#endif /* GFX_USE_GAUDIO */
/** @} */

View File

@ -0,0 +1,340 @@
/*
* 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/gaudio/sys_defs.h
*
* @addtogroup GAUDIO
*
* @brief Module to handle audio recording and play-back
*
* @{
*/
#ifndef _GAUDIO_H
#define _GAUDIO_H
#include "gfx.h"
#if GFX_USE_GAUDIO || defined(__DOXYGEN__)
/* Include the driver defines */
#if GAUDIO_NEED_PLAY
#include "gaudio_play_config.h"
#endif
#if GAUDIO_NEED_RECORD
#include "gaudio_record_config.h"
#endif
/*===========================================================================*/
/* 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 bytes)
} GAudioData;
// Event types for GAUDIO
#define GEVENT_AUDIO_PLAY (GEVENT_GAUDIO_FIRST+0)
#define GEVENT_AUDIO_RECORD (GEVENT_GAUDIO_FIRST+1)
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief The Audio play event structure.
* @{
*/
typedef struct GEventAudioPlay_t {
/**
* @brief The type of this event (GEVENT_AUDIO_PLAY)
*/
GEventType type;
/**
* @brief The event flags
*/
uint16_t flags;
/**
* @brief The event flag values.
* @{
*/
#define GAUDIO_PLAY_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_PLAY event was lost */
#define GAUDIO_PLAY_PLAYING 0x0002 /**< @brief The audio out system is currently playing */
#define GAUDIO_PLAY_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */
/** @} */
} GEventAudioPlay;
/** @} */
/**
* @brief The Audio record event structure.
* @{
*/
typedef struct GEventAudioRecord_t {
/**
* @brief The type of this event (GEVENT_AUDIO_RECORD)
*/
GEventType type;
/**
* @brief The event flags
*/
uint16_t flags;
/**
* @brief The event flag values.
* @{
*/
#define GAUDIO_RECORD_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
#define GAUDIO_RECORD_RECORDING 0x0002 /**< @brief The audio recording system is currently recording */
#define GAUDIO_RECORD_GOTBLOCK 0x0004 /**< @brief An audio buffer is ready for processing */
#define GAUDIO_RECORD_STALL 0x0008 /**< @brief The recording process has stalled due to no free buffers */
/** @} */
} GEventAudioRecord;
/** @} */
#endif
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
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);
#if GAUDIO_NEED_PLAY || defined(__DOXYGEN__)
/**
* @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. Can be set from 0 to GAUDIO_PLAY_NUM_CHANNELS - 1
* @param[in] frequency The audio sample rate in samples per second
* @param[in] format The audio sample format
*
* @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.
* @note Only one channel can be playing at a time. Calling this will stop any
* currently playing channel.
*
* @api
*/
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @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 (in bytes).
* @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);
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief Turn on sending results to the GEVENT sub-system.
* @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events.
*
* @note The audio output will not use the GEVENT system unless this is
* called first. This saves processing time if the application does
* not want to use the GEVENT sub-system for audio output.
* Once turned on it can only be turned off by calling @p gaudioPlayInit() again.
* @note The audio output is capable of signaling via this method and other methods
* at the same time.
*
* @return The GSourceHandle
*
* @api
*/
GSourceHandle gaudioPlayGetSource(void);
#endif
/**
* @brief Wait for any currently playing sounds to complete
* @return TRUE if there is now nothing playing or FALSE if the timeout is exceeded
*
* @params[in] ms The maximum amount of time in milliseconds to wait for playing to complete.
*
* @api
*/
bool_t gaudioPlayWait(delaytime_t ms);
#endif
#if GAUDIO_NEED_RECORD || defined(__DOXYGEN__)
/**
* @brief Initialise (but not start) the Audio Recording sub-system.
* @details Returns FALSE for an invalid channel or other invalid parameter.
*
* @param[in] channel The channel to convert. Can be set from 0 to GAUDIO_RECORD_NUM_CHANNELS - 1
* @param[in] frequency The sample frequency
* @param[in] format The audio sample format requested
*
* @note Only one channel is active at a time. If an audio input is running it will be stopped.
* The Event subsystem is disconnected from the audio subsystem and any binary semaphore
* event is forgotten.
* @note Some channels may be stereo channels which return twice as much sample data with
* the left and right channel data interleaved. Other channels may be mono channels.
* Where stereo channels exist the low level driver may also
* offer the left and right channels separately.
* @note Due to a bug in Chibi-OS each buffer on the free-list must contain an even number of
* samples and for stereo devices it must hold a number of samples that is evenly divisible by 4.
* This requirement applies only to ChibiOS where the audio driver uses
* a ChibiOS hal driver like the cpu ADC driver. This applies even it is used indirectly via
* the uGFX GADC driver.
* @note The number of samples for stereo devices will be double the number of conversions.
* Make sure you allocate your buffers large enough. Each channel is then interleaved
* into the provided buffer.
*
* @return FALSE if invalid channel or parameter
*
* @api
*/
bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @brief Start the audio recording.
* @pre It must have been initialised first with @p gaudioRecordInit()
*
* @api
*/
void gaudioRecordStart(void);
/**
* @brief Stop the audio recording.
*
* @note All audio recording data that has not yet been retrieved is automatically
* returned to the free-list.
* @api
*/
void gaudioRecordStop(void);
/**
* @brief Get a filled audio buffer from the recording 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 data if some is not currently available.
*
* @note After processing the audio data, your application must return the buffer to the free-list so that
* it can be used to record more audio into. This can be done via the play list using @p gaudioPlay() or
* directly using @p gaudioReleaseBuffer().
* @api
*/
GAudioData *gaudioRecordGetData(delaytime_t ms);
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief Turn on sending results to the GEVENT sub-system.
* @details Returns a GSourceHandle to listen for GEVENT_AUDIO_RECORD events.
*
* @note Audio recording will not use the GEVENT system unless this is
* called first. This saves processing time if the application does
* not want to use the GEVENT sub-system for audio recording.
* Once turned on it can only be turned off by calling @p gaudioRecordInit() again.
* @note The audio input is capable of signaling via this and other methods
* at the same time.
*
* @return The GSourceHandle
*
* @api
*/
GSourceHandle gaudioRecordGetSource(void);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GAUDIO */
#endif /* _GAUDIO_H */
/** @} */

View File

@ -0,0 +1 @@
GFXSRC += $(GFXLIB)/src/gaudio/gaudio.c

View File

@ -0,0 +1,44 @@
/*
* 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/gaudio/sys_options.h
* @brief GAUDIO - Audio subsystem options header file.
*
* @addtogroup GAUDIO
* @{
*/
#ifndef _GAUDIO_OPTIONS_H
#define _GAUDOUT_OPTIONS_H
/**
* @name GAUDIO Functionality to be included
* @{
*/
/**
* @brief Audio Play capability is needed
*/
#ifndef GAUDIO_NEED_PLAY
#define GAUDIO_NEED_PLAY FALSE
#endif
/**
* @brief Audio Recording capability is needed
*/
#ifndef GAUDIO_NEED_RECORD
#define GAUDIO_NEED_RECORD FALSE
#endif
/**
* @}
*
* @name GAUDIO Optional Sizing Parameters
* @{
*/
/** @} */
#endif /* _GAUDIO_OPTIONS_H */
/** @} */

View File

@ -0,0 +1,54 @@
/*
* 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/gaudio/sys_rules.h
* @brief GAUDIO safety rules header file.
*
* @addtogroup GAUDIO
* @{
*/
#ifndef _GAUDIO_RULES_H
#define _GAUDIO_RULES_H
#if GFX_USE_GAUDIO
#if !GAUDIO_NEED_PLAY && !GAUDIO_NEED_RECORD
#error "GAUDIO: GAUDIO_NEED_PLAY and/or GAUDIO_NEED_RECORD is required if GFX_USE_GAUDIO is TRUE"
#endif
#if !GFX_USE_GQUEUE
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GAUDIO: GFX_USE_GQUEUE is required if GFX_USE_GAUDIO 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 "GAUDIO: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDIO 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 "GAUDIO: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you."
#endif
#undef GQUEUE_NEED_GSYNC
#define GQUEUE_NEED_GSYNC TRUE
#endif
#if GFX_USE_GEVENT && !GFX_USE_GTIMER
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GAUDIO: GFX_USE_GTIMER is required if GFX_USE_GAUDIO and GFX_USE_GEVENT are TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GTIMER
#define GFX_USE_GTIMER TRUE
#endif
#endif
#endif /* _GAUDIO_RULES_H */
/** @} */

View File

@ -1,169 +0,0 @@
/*
* 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/gaudout.c
* @brief GAUDOUT sub-system code.
*
* @addtogroup GAUDOUT
* @{
*/
#include "gfx.h"
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
#include "src/gaudout/driver.h"
static gfxQueueASync playlist;
static gfxQueueGSync freelist;
static uint16_t PlayFlags;
#define PLAYFLG_USEEVENTS 0x0001
#define PLAYFLG_PLAYING 0x0002
#if GFX_USE_GEVENT
static GTimer PlayTimer;
static void PlayTimerCallback(void *param) {
(void) param;
GSourceListener *psl;
GEventAudioOut *pe;
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) {
// This listener is missing - save this.
psl->srcflags |= GAUDOUT_LOSTEVENT;
continue;
}
pe->type = GEVENT_AUDIO_OUT;
pe->flags = psl->srcflags;
psl->srcflags = 0;
if ((PlayFlags & PLAYFLG_PLAYING))
pe->flags |= GAUDOUT_PLAYING;
if (!gfxQueueGSyncIsEmpty(&freelist))
pe->flags |= GAUDOUT_FREEBLOCK;
geventSendEvent(psl);
}
}
#endif
void _gaudoutInit(void)
{
gfxQueueASyncInit(&playlist);
gfxQueueGSyncInit(&freelist);
#if GFX_USE_GEVENT
gtimerInit(&PlayTimer);
#endif
}
void _gaudoutDeinit(void)
{
/* ToDo */
#if GFX_USE_GEVENT
gtimerDeinit(&PlayTimer);
#endif
}
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, ArrayDataFormat format) {
gaudioPlayStop();
gaudout_lld_deinit();
return gaudout_lld_init(channel, frequency, format);
}
void gaudioPlay(GAudioData *paud) {
if (paud)
gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
PlayFlags |= PLAYFLG_PLAYING;
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);
PlayFlags &= ~PLAYFLG_PLAYING;
}
bool_t gaudioPlaySetVolume(uint8_t vol) {
return gaudout_lld_set_volume(vol);
}
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
GSourceHandle gaudioPlayGetSource(void) {
if (!gtimerIsActive(&PlayTimer))
gtimerStart(&PlayTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
PlayFlags |= PLAYFLG_USEEVENTS;
return (GSourceHandle)&PlayFlags;
}
#endif
/**
* Routines provided for use by drivers.
*/
GAudioData *gaudoutGetDataBlockI(void) {
return (GAudioData *)gfxQueueASyncGetI(&playlist);
}
void gaudoutReleaseDataBlockI(GAudioData *paud) {
gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud);
#if GFX_USE_GEVENT
if (PlayFlags & PLAYFLG_USEEVENTS)
gtimerJabI(&PlayTimer);
#endif
}
void gaudoutDoneI(void) {
PlayFlags &= ~PLAYFLG_PLAYING;
#if GFX_USE_GEVENT
if (PlayFlags & PLAYFLG_USEEVENTS)
gtimerJabI(&PlayTimer);
#endif
}
#endif /* GFX_USE_GAUDOUT */
/** @} */

View File

@ -1,217 +0,0 @@
/*
* 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/sys_defs.h
*
* @addtogroup GAUDOUT
*
* @brief Module to output audio data (under development)
*
* @{
*/
#ifndef _GAUDOUT_H
#define _GAUDOUT_H
#include "gfx.h"
#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 bytes)
} GAudioData;
// Event types for GAUDOUT
#define GEVENT_AUDIO_OUT (GEVENT_GAUDOUT_FIRST+0)
/**
* @brief The Audio output event structure.
* @{
*/
typedef struct GEventAudioOut_t {
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief The type of this event (GEVENT_AUDIO_OUT)
*/
GEventType type;
#endif
/**
* @brief The event flags
*/
uint16_t flags;
/**
* @brief The event flag values.
* @{
*/
#define GAUDOUT_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_OUT event was lost */
#define GAUDOUT_PLAYING 0x0002 /**< @brief The audio out system is currently playing */
#define GAUDOUT_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */
/** @} */
} GEventAudioOut;
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
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
* @param[in] format The audio sample format
*
* @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.
* @note Only one channel can be playing at a time. Calling this will stop any
* currently playing channel.
*
* @api
*/
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format);
/**
* @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 (in bytes).
* @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);
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
/**
* @brief Turn on sending results to the GEVENT sub-system.
* @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events.
*
* @note The audio output will not use the GEVENT system unless this is
* called first. This saves processing time if the application does
* not want to use the GEVENT sub-system for audio output.
* Once turned on it can only be turned off by calling @p gaudioPlayInit() again.
* @note The audio output is capable of signalling via this method and other methods
* at the same time.
*
* @return The GSourceHandle
*
* @api
*/
GSourceHandle gaudioPlayGetSource(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GAUDOUT */
#endif /* _GAUDOUT_H */
/** @} */

View File

@ -1 +0,0 @@
GFXSRC += $(GFXLIB)/src/gaudout/gaudout.c

View File

@ -1,32 +0,0 @@
/*
* 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/sys_options.h
* @brief GAUDOUT - Audio Output subsystem options header file.
*
* @addtogroup GAUDOUT
* @{
*/
#ifndef _GAUDOUT_OPTIONS_H
#define _GAUDOUT_OPTIONS_H
/**
* @name GAUDOUT Functionality to be included
* @{
*/
/**
* @}
*
* @name GAUDOUT Optional Sizing Parameters
* @{
*/
/** @} */
#endif /* _GAUDOUT_OPTIONS_H */
/** @} */

View File

@ -1,44 +0,0 @@
/*
* 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/sys_rules.h
* @brief GAUDOUT safety rules header file.
*
* @addtogroup GAUDOUT
* @{
*/
#ifndef _GAUDOUT_RULES_H
#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 */
/** @} */

View File

@ -38,8 +38,7 @@ typedef uint16_t GEventType;
#define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF #define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF
#define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF #define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF
#define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F #define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F
#define GEVENT_GAUDIN_FIRST 0x0340 // GAUDIN events range from 0x0340 to 0x037F #define GEVENT_GAUDIO_FIRST 0x0340 // GAUDIO events range from 0x0340 to 0x037F
#define GEVENT_GAUDOUT_FIRST 0x0380 // GAUDOUT events range from 0x0380 to 0x03BF
#define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000 #define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000
// This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events. // This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events.

View File

@ -44,13 +44,9 @@ extern void _gosDeinit(void);
extern void _gadcInit(void); extern void _gadcInit(void);
extern void _gadcDeinit(void); extern void _gadcDeinit(void);
#endif #endif
#if GFX_USE_GAUDIN #if GFX_USE_GAUDIO
extern void _gaudinInit(void); extern void _gaudioInit(void);
extern void _gaudinDeinit(void); extern void _gaudioDeinit(void);
#endif
#if GFX_USE_GAUDOUT
extern void _gaudoutInit(void);
extern void _gaudoutDeinit(void);
#endif #endif
#if GFX_USE_GMISC #if GFX_USE_GMISC
extern void _gmiscInit(void); extern void _gmiscInit(void);
@ -88,11 +84,8 @@ void gfxInit(void)
#if GFX_USE_GADC #if GFX_USE_GADC
_gadcInit(); _gadcInit();
#endif #endif
#if GFX_USE_GAUDIN #if GFX_USE_GAUDIO
_gaudinInit(); _gaudioInit();
#endif
#if GFX_USE_GAUDOUT
_gaudoutInit();
#endif #endif
} }
@ -103,11 +96,8 @@ void gfxDeinit(void)
initDone = FALSE; initDone = FALSE;
// We deinitialise the opposite way as we initialised // We deinitialise the opposite way as we initialised
#if GFX_USE_GAUDOUT
_gaudoutDeinit();
#endif
#if GFX_USE_GAUDIN #if GFX_USE_GAUDIN
_gaudinDeinit(); _gaudioDeinit();
#endif #endif
#if GFX_USE_GADC #if GFX_USE_GADC
_gadcDeinit(); _gadcDeinit();