First GAUDOUT work. Still incomplete but compiling.
Also moved drivers/gaudin to drivers/audio as most audio codecs support input and output in a single device.
This commit is contained in:
parent
f9495a75e1
commit
a56e4ac7dc
24 changed files with 707 additions and 81 deletions
|
@ -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/gaudin/gadc/gaudin_lld.mk
|
include $(GFXLIB)/drivers/audio/gadc/driver.mk
|
||||||
|
|
|
@ -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/gaudin/gadc/gaudin_lld.mk
|
include $(GFXLIB)/drivers/audio/gadc/driver.mk
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
GFXINC += $(GFXLIB)/boards/base/Win32
|
GFXINC += $(GFXLIB)/boards/base/Win32
|
||||||
GFXSRC +=
|
GFXSRC +=
|
||||||
|
|
||||||
include $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.mk
|
include $(GFXLIB)/drivers/multiple/Win32/driver.mk
|
||||||
include $(GFXLIB)/drivers/gaudin/Win32/gaudin_lld.mk
|
include $(GFXLIB)/drivers/audio/Win32/driver.mk
|
||||||
|
|
6
drivers/audio/Win32/driver.mk
Normal file
6
drivers/audio/Win32/driver.mk
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# 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
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/gaudin/Win32/gaudin_lld.c
|
* @file drivers/audio/Win32/gaudin_lld.c
|
||||||
* @brief GAUDIN - Driver file for Win32.
|
* @brief GAUDIN - Driver file for Win32.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -26,9 +26,10 @@
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
|
|
||||||
static HWAVEIN ah;
|
static HWAVEIN ah;
|
||||||
static volatile int nUsedBuffers;
|
static volatile int nQueuedBuffers;
|
||||||
|
static bool_t isClosing;
|
||||||
static WAVEHDR *pWaveHdrs;
|
static WAVEHDR *pWaveHdrs;
|
||||||
static HANDLE waveInThread;
|
static HANDLE waveThread;
|
||||||
static DWORD threadID;
|
static DWORD threadID;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -45,7 +46,7 @@ static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**************************** waveInProc() *******************************
|
/**************************** 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,
|
||||||
* and a few of the Low Level MIDI API. If you violate this rule, your app can
|
* and a few of the Low Level MIDI API. If you violate this rule, your app can
|
||||||
|
@ -55,43 +56,32 @@ static void PrintWaveErrorMsg(DWORD err, TCHAR * str)
|
||||||
* anyway, so instead just use CALLBACK_THREAD here instead.
|
* anyway, so instead just use CALLBACK_THREAD here instead.
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
DWORD WINAPI waveInProc(LPVOID arg) {
|
static DWORD WINAPI waveProc(LPVOID arg) {
|
||||||
MSG msg;
|
MSG msg;
|
||||||
bool_t isRecording;
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
isRecording = FALSE;
|
|
||||||
while (GetMessage(&msg, 0, 0, 0)) {
|
while (GetMessage(&msg, 0, 0, 0)) {
|
||||||
switch (msg.message) {
|
switch (msg.message) {
|
||||||
case MM_WIM_DATA:
|
case MM_WIM_DATA:
|
||||||
GAUDIN_ISR_CompleteI((audin_sample_t *)((WAVEHDR *)msg.lParam)->lpData, ((WAVEHDR *)msg.lParam)->dwBytesRecorded/sizeof(audin_sample_t));
|
GAUDIN_ISR_CompleteI((audin_sample_t *)((WAVEHDR *)msg.lParam)->lpData, ((WAVEHDR *)msg.lParam)->dwBytesRecorded/sizeof(audin_sample_t));
|
||||||
|
|
||||||
/* Are we still recording? */
|
/* Are we closing? */
|
||||||
if (isRecording) {
|
if (isClosing) {
|
||||||
/* Yes. Now we need to requeue this buffer so the driver can use it for another block of audio
|
/* 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.
|
* 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
|
* Note: We are assuming here that both the application can still access the buffer while
|
||||||
* it is on the queue.
|
* it is on the queue.
|
||||||
*/
|
*/
|
||||||
waveInAddBuffer(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
|
waveInAddBuffer(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
|
||||||
|
|
||||||
} else {
|
|
||||||
/* We aren't recording, so another WAVEHDR has been returned to us after recording has stopped.
|
|
||||||
* When we get all of them back, DoneAll will be equal to how many WAVEHDRs we queued
|
|
||||||
*/
|
|
||||||
nUsedBuffers--;
|
|
||||||
waveInUnprepareHeader(ah, (WAVEHDR *)msg.lParam, sizeof(WAVEHDR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MM_WIM_OPEN:
|
|
||||||
isRecording = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MM_WIM_CLOSE:
|
|
||||||
isRecording = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -101,12 +91,20 @@ DWORD WINAPI waveInProc(LPVOID arg) {
|
||||||
/* External declarations. */
|
/* 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) {
|
void gaudin_lld_init(const gaudin_params *paud) {
|
||||||
// uint16_t channel;
|
|
||||||
// uint32_t frequency;
|
|
||||||
// audin_sample_t *buffer;
|
|
||||||
// size_t bufcount;
|
|
||||||
// size_t samplesPerEvent;
|
|
||||||
WAVEFORMATEX wfx;
|
WAVEFORMATEX wfx;
|
||||||
size_t spaceleft;
|
size_t spaceleft;
|
||||||
audin_sample_t *p;
|
audin_sample_t *p;
|
||||||
|
@ -114,15 +112,15 @@ void gaudin_lld_init(const gaudin_params *paud) {
|
||||||
size_t nBuffers;
|
size_t nBuffers;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
if (!waveInThread) {
|
if (!waveThread) {
|
||||||
if (!(waveInThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveInProc, 0, 0, &threadID))) {
|
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
|
||||||
fprintf(stderr, "GAUDIN: Can't create WAVE recording thread\n");
|
fprintf(stderr, "GAUDIN/GAUDOUT: Can't create WAVE recording thread\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CloseHandle(waveInThread);
|
CloseHandle(waveThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
nUsedBuffers = 0;
|
gaudin_lld_deinit();
|
||||||
|
|
||||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
wfx.nChannels = paud->channel == GAUDIN_STEREO ? 2 : 1;
|
wfx.nChannels = paud->channel == GAUDIN_STEREO ? 2 : 1;
|
||||||
|
@ -153,26 +151,20 @@ void gaudin_lld_init(const gaudin_params *paud) {
|
||||||
phdr->dwFlags = 0;
|
phdr->dwFlags = 0;
|
||||||
if (!waveInPrepareHeader(ah, phdr, sizeof(WAVEHDR))
|
if (!waveInPrepareHeader(ah, phdr, sizeof(WAVEHDR))
|
||||||
&& !waveInAddBuffer(ah, phdr, sizeof(WAVEHDR)))
|
&& !waveInAddBuffer(ah, phdr, sizeof(WAVEHDR)))
|
||||||
nUsedBuffers++;
|
nQueuedBuffers++;
|
||||||
else
|
else
|
||||||
fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
|
fprintf(stderr, "GAUDIN: Buffer prepare failed\n");
|
||||||
}
|
}
|
||||||
if (!nUsedBuffers)
|
if (!nQueuedBuffers)
|
||||||
fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
|
fprintf(stderr, "GAUDIN: Failed to prepare any buffers\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void gadc_lld_start(void) {
|
void gaudin_lld_start(void) {
|
||||||
if (nUsedBuffers)
|
waveInStart(ah);
|
||||||
waveInStart(ah);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gadc_lld_stop(void) {
|
void gaudin_lld_stop(void) {
|
||||||
waveInReset(ah);
|
waveInStop(ah);
|
||||||
while(nUsedBuffers) Sleep(1);
|
|
||||||
if (pWaveHdrs) {
|
|
||||||
gfxFree(pWaveHdrs);
|
|
||||||
pWaveHdrs = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDIN */
|
#endif /* GFX_USE_GAUDIN */
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/multiple/Win32/gaudin_lld_config.h
|
* @file drivers/audio/Win32/gaudin_lld_config.h
|
||||||
* @brief GAUDIN Driver config file.
|
* @brief GAUDIN Driver config file.
|
||||||
*
|
*
|
||||||
* @addtogroup GAUDIN
|
* @addtogroup GAUDIN
|
190
drivers/audio/Win32/gaudout_lld.c
Normal file
190
drivers/audio/Win32/gaudout_lld.c
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* 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/gaudout_lld.c
|
||||||
|
* @brief GAUDOUT - Driver file for Win32.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#if GFX_USE_GAUDOUT
|
||||||
|
|
||||||
|
/* Include the driver defines */
|
||||||
|
#include "src/gaudout/driver.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 also create higher latency.
|
||||||
|
|
||||||
|
static HWAVEOUT ah = 0;
|
||||||
|
static volatile int nQueuedBuffers;
|
||||||
|
static bool_t isRunning;
|
||||||
|
static WAVEHDR WaveHdrs[MAX_WAVE_HEADERS];
|
||||||
|
static HANDLE waveThread;
|
||||||
|
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() *******************************
|
||||||
|
* 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 waveOutUnPrepareBuffer() which is what we need to use whenever we receive a
|
||||||
|
* MM_WOM_DONE. My callback would need to defer that job to another thread
|
||||||
|
* anyway, so instead just use CALLBACK_THREAD here instead.
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
static bool_t senddata(WAVEHDR *pwh) {
|
||||||
|
GAudioData *paud;
|
||||||
|
|
||||||
|
// Get the next data block to send
|
||||||
|
if (!(paud = gaudoutGetDataBlockI()))
|
||||||
|
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->len;
|
||||||
|
pwh->dwFlags = 0;
|
||||||
|
pwh->dwLoops = 0;
|
||||||
|
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
|
||||||
|
pwh->lpData = 0;
|
||||||
|
fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send it to windows
|
||||||
|
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
|
||||||
|
pwh->lpData = 0;
|
||||||
|
fprintf(stderr, "GAUDOUT: Failed to write the buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nQueuedBuffers++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI waveProc(LPVOID arg) {
|
||||||
|
MSG msg;
|
||||||
|
WAVEHDR *pwh;
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
while (GetMessage(&msg, 0, 0, 0)) {
|
||||||
|
switch (msg.message) {
|
||||||
|
case MM_WOM_DONE:
|
||||||
|
pwh = (WAVEHDR *)msg.lParam;
|
||||||
|
|
||||||
|
// Windows - Let go!
|
||||||
|
waveOutUnprepareHeader(ah, pwh, sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
// Give the buffer back to the Audio Free List
|
||||||
|
gaudoutReleaseDataBlockI((GAudioData *)pwh->dwUser);
|
||||||
|
pwh->lpData = 0;
|
||||||
|
nQueuedBuffers--;
|
||||||
|
|
||||||
|
// Try and get a new block
|
||||||
|
if (isRunning)
|
||||||
|
senddata(pwh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
void gaudout_lld_deinit() {
|
||||||
|
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) {
|
||||||
|
WAVEFORMATEX wfx;
|
||||||
|
|
||||||
|
if (!waveThread) {
|
||||||
|
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
|
||||||
|
fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
CloseHandle(waveThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
wfx.nChannels = channel == GAUDOUT_STEREO ? 2 : 1;
|
||||||
|
wfx.nSamplesPerSec = frequency;
|
||||||
|
wfx.nBlockAlign = wfx.nChannels * sizeof(audout_sample_t);
|
||||||
|
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||||
|
wfx.wBitsPerSample = sizeof(audout_sample_t) * 8;
|
||||||
|
wfx.cbSize = 0;
|
||||||
|
|
||||||
|
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
|
||||||
|
fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t gaudout_lld_set_volume(uint8_t vol) {
|
||||||
|
if (!ah)
|
||||||
|
return FALSE;
|
||||||
|
return waveOutSetVolume(ah, (((uint16_t)vol)<<8)|vol) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudout_lld_start(void) {
|
||||||
|
WAVEHDR *pwh;
|
||||||
|
|
||||||
|
if (!ah)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isRunning = TRUE;
|
||||||
|
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 Audio Out Queue
|
||||||
|
if (!senddata(pwh))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudout_lld_stop(void) {
|
||||||
|
isRunning = FALSE;
|
||||||
|
if (ah)
|
||||||
|
waveOutReset(ah);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GFX_USE_GAUDOUT */
|
64
drivers/audio/Win32/gaudout_lld_config.h
Normal file
64
drivers/audio/Win32/gaudout_lld_config.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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/gaudout_lld_config.h
|
||||||
|
* @brief GAUDOUT Driver config file.
|
||||||
|
*
|
||||||
|
* @addtogroup GAUDOUT
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GAUDOUT_LLD_CONFIG_H
|
||||||
|
#define GAUDIN_LLD_CONFIG_H
|
||||||
|
|
||||||
|
#if GFX_USE_GAUDOUT
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver hardware support. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The audio input sample type
|
||||||
|
*/
|
||||||
|
//typedef uint8_t audout_sample_t;
|
||||||
|
typedef int16_t audout_sample_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum sample frequency supported by this audio device
|
||||||
|
*/
|
||||||
|
#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of bits in a sample
|
||||||
|
*/
|
||||||
|
//#define GAUDOUT_BITS_PER_SAMPLE 8
|
||||||
|
#define GAUDOUT_BITS_PER_SAMPLE 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The format of an audio sample
|
||||||
|
*/
|
||||||
|
//#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_8BITUNSIGNED
|
||||||
|
#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of audio channels supported by this driver
|
||||||
|
*/
|
||||||
|
#define GAUDOUT_NUM_CHANNELS 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The list of audio channels and their uses
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GAUDOUT_MONO 0
|
||||||
|
#define GAUDOUT_STEREO 1
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* GFX_USE_GAUDOUT */
|
||||||
|
|
||||||
|
#endif /* GAUDOUT_LLD_CONFIG_H */
|
||||||
|
/** @} */
|
10
drivers/audio/Win32/readme.txt
Normal file
10
drivers/audio/Win32/readme.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
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.
|
|
@ -2,4 +2,4 @@
|
||||||
GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
|
GFXSRC += $(GFXLIB)/drivers/gaudin/gadc/gaudin_lld.c
|
||||||
|
|
||||||
# Required include directories
|
# Required include directories
|
||||||
GFXINC += $(GFXLIB)/drivers/gaudin/gadc
|
GFXINC += $(GFXLIB)/drivers/audio/gadc
|
|
@ -50,11 +50,11 @@ void gaudin_lld_init(const gaudin_params *paud) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void gadc_lld_start(void) {
|
void gaudin_lld_start(void) {
|
||||||
gadcHighSpeedStart();
|
gadcHighSpeedStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gadc_lld_stop(void) {
|
void gaudin_lld_stop(void) {
|
||||||
gadcHighSpeedStop();
|
gadcHighSpeedStop();
|
||||||
}
|
}
|
||||||
|
|
6
drivers/audio/gadc/readme.txt
Normal file
6
drivers/audio/gadc/readme.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
This driver uses the generic GADC driver to provide a GAUDIN device.
|
||||||
|
|
||||||
|
It supports whatever high speed device channels that your GADC driver and board supports.
|
||||||
|
|
||||||
|
For stereo, the samples are interleaved. Remember to allocate enough space for two samples per
|
||||||
|
sample period.
|
|
@ -1,5 +0,0 @@
|
||||||
# List the required driver.
|
|
||||||
GFXSRC += $(GFXLIB)/drivers/gaudin/Win32/gaudin_lld.c
|
|
||||||
|
|
||||||
# Required include directories
|
|
||||||
GFXINC += $(GFXLIB)/drivers/gaudin/Win32
|
|
|
@ -1,9 +0,0 @@
|
||||||
This driver uses the Win32 audio system to provide a GAUDIN channel.
|
|
||||||
|
|
||||||
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 (obviously in record mode) before starting recording.
|
|
|
@ -83,14 +83,14 @@ void gaudin_lld_init(const gaudin_params *paud);
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
void gadc_lld_start(void);
|
void gaudin_lld_start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the audio input sampling
|
* @brief Stop the audio input sampling
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
void gadc_lld_stop(void);
|
void gaudin_lld_stop(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ static uint16_t audFlags;
|
||||||
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
|
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
|
||||||
if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
|
if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
|
||||||
// This listener is missing - save this.
|
// This listener is missing - save this.
|
||||||
psl->srcflags |= GADC_AUDIO_IN_LOSTEVENT;
|
psl->srcflags |= GAUDIN_LOSTEVENT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer,
|
||||||
|
|
||||||
/* Stop any existing transfers */
|
/* Stop any existing transfers */
|
||||||
if ((audFlags & AUDFLG_RUNNING))
|
if ((audFlags & AUDFLG_RUNNING))
|
||||||
gadc_lld_stop();
|
gaudin_lld_stop();
|
||||||
audFlags = 0;
|
audFlags = 0;
|
||||||
|
|
||||||
/* Initialise everything */
|
/* Initialise everything */
|
||||||
|
@ -143,13 +143,13 @@ void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent) {
|
||||||
void gaudinStart(void) {
|
void gaudinStart(void) {
|
||||||
if (!(audFlags & AUDFLG_RUNNING)) {
|
if (!(audFlags & AUDFLG_RUNNING)) {
|
||||||
audFlags |= AUDFLG_RUNNING;
|
audFlags |= AUDFLG_RUNNING;
|
||||||
gadc_lld_start();
|
gaudin_lld_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gaudinStop(void) {
|
void gaudinStop(void) {
|
||||||
if ((audFlags & AUDFLG_RUNNING)) {
|
if ((audFlags & AUDFLG_RUNNING)) {
|
||||||
gadc_lld_stop();
|
gaudin_lld_stop();
|
||||||
audFlags &= ~AUDFLG_RUNNING;
|
audFlags &= ~AUDFLG_RUNNING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ typedef struct GEventAudioIn_t {
|
||||||
* @brief The event flag values.
|
* @brief The event flag values.
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define GADC_AUDIO_IN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
|
#define GAUDIN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */
|
||||||
/** @} */
|
/** @} */
|
||||||
/**
|
/**
|
||||||
* @brief The number of audio samples in the buffer
|
* @brief The number of audio samples in the buffer
|
||||||
|
@ -123,7 +123,7 @@ bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer,
|
||||||
* @note The audio input will not use the GEVENT system unless this is
|
* @note The audio input will not use the GEVENT system unless this is
|
||||||
* called first. This saves processing time if the application does
|
* called first. This saves processing time if the application does
|
||||||
* not want to use the GEVENT sub-system for audio input.
|
* not want to use the GEVENT sub-system for audio input.
|
||||||
* Once turned on it can only be turned off by calling @p gadcHighSpeedInit() again.
|
* 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
|
* @note The audio input is capable of signalling via this method and a binary semaphore
|
||||||
* at the same time.
|
* at the same time.
|
||||||
*
|
*
|
||||||
|
|
123
src/gaudout/driver.h
Normal file
123
src/gaudout/driver.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gaudout/driver.h
|
||||||
|
* @brief GAUDOUT - Audio Output driver header file.
|
||||||
|
*
|
||||||
|
* @defgroup Driver Driver
|
||||||
|
* @ingroup GAUDOUT
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GAUDOUT_LLD_H
|
||||||
|
#define _GAUDOUT_LLD_H
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Type definitions */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a block of audio data to play
|
||||||
|
* @return A pointer to the GAaudioData structure or NULL if none is currently available
|
||||||
|
*
|
||||||
|
* @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
GAudioData *gaudoutGetDataBlockI(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release a block of audio data after playing
|
||||||
|
*
|
||||||
|
* @param[in] paud The GAudioData block to be released.
|
||||||
|
*
|
||||||
|
* @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void gaudoutReleaseDataBlockI(GAudioData *paud);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise the driver
|
||||||
|
* @return TRUE if the channel and frequency are valid.
|
||||||
|
*
|
||||||
|
* @param[in] channel The channel to use (see the driver for the available channels provided)
|
||||||
|
* @param[in] frequency The sample frequency to use
|
||||||
|
*
|
||||||
|
* @note The driver will always have been stopped and de-init before this is called.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief De-Initialise the driver
|
||||||
|
*
|
||||||
|
* @note The audio output will always have been stopped first by the high level layer.
|
||||||
|
* @note This may be called before a @p gaudout_lld_init() has occurred.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudout_lld_deinit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start the audio output playing
|
||||||
|
*
|
||||||
|
* @note This may be called at any stage including while the driver
|
||||||
|
* is already playing. The driver should check for data blocks
|
||||||
|
* to play using @p gaudoutGetDataBlockI().
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudout_lld_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the audio output playing.
|
||||||
|
*
|
||||||
|
* @note Some drivers may only stop playing at a data block boundary.
|
||||||
|
* @note This may be called before a @p gaudout_lld_init() has occurred.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudout_lld_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the output volume.
|
||||||
|
* @return TRUE if successful.
|
||||||
|
*
|
||||||
|
* @param[in] 0->255 (0 = muted)
|
||||||
|
*
|
||||||
|
* @note Some drivers may not support this. They will return FALSE.
|
||||||
|
* @note For stereo devices, both channels are set to the same volume.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gaudout_lld_set_volume(uint8_t vol);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GFX_USE_GAUDOUT */
|
||||||
|
|
||||||
|
#endif /* _GAUDOUT_LLD_H */
|
||||||
|
/** @} */
|
|
@ -16,11 +16,47 @@
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
||||||
|
|
||||||
#error "GAUDOUT: Not implemented yet"
|
#include "src/gaudout/driver.h"
|
||||||
|
|
||||||
|
static gfxQueueASync playlist;
|
||||||
|
static gfxQueueGSync freelist;
|
||||||
|
|
||||||
|
static uint16_t audFlags;
|
||||||
|
#define AUDOUTFLG_RUNNING 0x0001
|
||||||
|
#define AUDOUTFLG_USE_EVENTS 0x0002
|
||||||
|
|
||||||
|
#if GFX_USE_GEVENT
|
||||||
|
static GTimer AudGTimer;
|
||||||
|
|
||||||
|
static void AudGTimerCallback(void *param) {
|
||||||
|
(void) param;
|
||||||
|
GSourceListener *psl;
|
||||||
|
GEventADC *pe;
|
||||||
|
|
||||||
|
psl = 0;
|
||||||
|
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
|
||||||
|
if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
|
||||||
|
// This listener is missing - save this.
|
||||||
|
psl->srcflags |= GAUDIN_LOSTEVENT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pe->type = GEVENT_AUDIO_IN;
|
||||||
|
pe->channel = aud.channel;
|
||||||
|
pe->count = lastcount;
|
||||||
|
pe->buffer = lastbuffer;
|
||||||
|
pe->flags = psl->srcflags;
|
||||||
|
psl->srcflags = 0;
|
||||||
|
geventSendEvent(psl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void _gaudoutInit(void)
|
void _gaudoutInit(void)
|
||||||
{
|
{
|
||||||
/* ToDo */
|
gfxQueueASyncInit(&playlist);
|
||||||
|
gfxQueueGSyncInit(&freelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gaudoutDeinit(void)
|
void _gaudoutDeinit(void)
|
||||||
|
@ -28,6 +64,77 @@ void _gaudoutDeinit(void)
|
||||||
/* ToDo */
|
/* ToDo */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t gaudioAllocBuffers(unsigned num, size_t size) {
|
||||||
|
GAudioData *paud;
|
||||||
|
|
||||||
|
if (num < 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Round up to a multiple of 4 to prevent problems with structure alignment
|
||||||
|
size = (size + 3) & ~0x03;
|
||||||
|
|
||||||
|
// Allocate the memory
|
||||||
|
if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Add each of them to our free list
|
||||||
|
for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) {
|
||||||
|
paud->size = size;
|
||||||
|
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudioReleaseBuffer(GAudioData *paud) {
|
||||||
|
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
}
|
||||||
|
|
||||||
|
GAudioData *gaudioGetBuffer(delaytime_t ms) {
|
||||||
|
return (GAudioData *)gfxQueueGSyncGet(&freelist, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency) {
|
||||||
|
gaudioPlayStop();
|
||||||
|
gaudout_lld_deinit();
|
||||||
|
return gaudout_lld_init(channel, frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudioPlay(GAudioData *paud) {
|
||||||
|
if (paud)
|
||||||
|
gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
|
||||||
|
gaudout_lld_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudioPlayPause(void) {
|
||||||
|
gaudout_lld_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudioPlayStop(void) {
|
||||||
|
GAudioData *paud;
|
||||||
|
|
||||||
|
gaudout_lld_stop();
|
||||||
|
while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
|
||||||
|
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t gaudioPlaySetVolume(uint8_t vol) {
|
||||||
|
return gaudout_lld_set_volume(vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routines provided for use by drivers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GAudioData *gaudoutGetDataBlockI(void) {
|
||||||
|
return (GAudioData *)gfxQueueASyncGet(&playlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaudoutReleaseDataBlockI(GAudioData *paud) {
|
||||||
|
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDOUT */
|
#endif /* GFX_USE_GAUDOUT */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,26 @@
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
#if GFX_USE_GAUDOUT || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/* Include the driver defines */
|
||||||
|
#include "gaudout_lld_config.h"
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Type definitions */
|
/* Type definitions */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains Audio Data Samples
|
||||||
|
* @note This structure is followed immediately by the sample data itself.
|
||||||
|
* When allocating the buffers for the sample data put this structure
|
||||||
|
* at the beginning of the buffer.
|
||||||
|
*/
|
||||||
|
typedef struct GAudioData {
|
||||||
|
gfxQueueASyncItem next; // @< Used for queuing the buffers
|
||||||
|
size_t size; // @< The size of the buffer area following this structure (in bytes)
|
||||||
|
size_t len; // @< The length of the data in the buffer area (in samples)
|
||||||
|
} GAudioData;
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -34,6 +50,111 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate some audio buffers and put them on the free list
|
||||||
|
* @return TRUE is it succeeded. FALSE on allocation failure.
|
||||||
|
*
|
||||||
|
* @param[in] num The number of buffers to allocate
|
||||||
|
* @param[in] size The size (in bytes) of each buffer
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gaudioAllocBuffers(unsigned num, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an audio buffer from the free list
|
||||||
|
* @return A GAudioData pointer or NULL if the timeout is exceeded
|
||||||
|
*
|
||||||
|
* @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
GAudioData *gaudioGetBuffer(delaytime_t ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release a buffer back to the free list
|
||||||
|
*
|
||||||
|
* @param[in] paud The buffer to put (back) on the free-list.
|
||||||
|
*
|
||||||
|
* @note This call should be used to return any buffers that were taken from
|
||||||
|
* the free-list once they have been finished with. It can also be used
|
||||||
|
* to put new buffers onto the free-list. Just make sure the "size" field
|
||||||
|
* of the GAudioData structure has been filled in first.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudioReleaseBuffer(GAudioData *paud);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the audio device to play on the specified channel and with the specified
|
||||||
|
* sample frequency.
|
||||||
|
* @return TRUE is successful, FALSE if the driver doesn't accept those parameters.
|
||||||
|
*
|
||||||
|
* @param[in] channel The audio output channel to use.
|
||||||
|
* @param[in] frequency The audio sample rate in samples per second
|
||||||
|
*
|
||||||
|
* @note Some channels are mono, and some are stereo. See your driver config file
|
||||||
|
* to determine which channels to use and whether they are stereo or not.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Play the specified sample data.
|
||||||
|
* @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list.
|
||||||
|
* @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency.
|
||||||
|
*
|
||||||
|
* @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio)
|
||||||
|
*
|
||||||
|
* @note Calling this will cancel any pause.
|
||||||
|
* @note Before calling this function the len field of the GAudioData structure must be
|
||||||
|
* specified. While the buffer size is specified in bytes, this length is specified in samples
|
||||||
|
* and must be even for stereo channels.
|
||||||
|
* @note For stereo channels the sample data is interleaved in the buffer.
|
||||||
|
* @note This call returns before the data has completed playing. Subject to available buffers (which
|
||||||
|
* can be obtained from the free-list), any number of buffers may be played. They will be queued
|
||||||
|
* for playing in the order they are supplied to this routine and played when previous buffers are
|
||||||
|
* complete. In this way continuous playing can be obtained without audio gaps.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudioPlay(GAudioData *paud);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pause any currently playing sounds.
|
||||||
|
*
|
||||||
|
* @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay()
|
||||||
|
* with or without a new sample buffer.
|
||||||
|
* @note Some drivers will not respond until a buffer boundary.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudioPlayPause(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop any currently playing sounds.
|
||||||
|
*
|
||||||
|
* @note This stops any playing sounds and returns any currently queued buffers back to the free-list.
|
||||||
|
* @note Some drivers will not respond until a buffer boundary.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gaudioPlayStop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the output volume.
|
||||||
|
* @return TRUE if successful.
|
||||||
|
*
|
||||||
|
* @param[in] 0->255 (0 = muted)
|
||||||
|
*
|
||||||
|
* @note Some drivers may not support this. They will return FALSE.
|
||||||
|
* @note For stereo devices, both channels are set to the same volume.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gaudioPlaySetVolume(uint8_t vol);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,27 @@
|
||||||
#define _GAUDOUT_RULES_H
|
#define _GAUDOUT_RULES_H
|
||||||
|
|
||||||
#if GFX_USE_GAUDOUT
|
#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
|
||||||
|
|
||||||
#endif /* _GAUDOUT_RULES_H */
|
#endif /* _GAUDOUT_RULES_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue