mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-30 02:50:25 +08:00
* fhandler_dsp.cc: Reformat to GNU standards.
(s_audio): Change to a pointer throughout. (fhandler_dev_dsp::open): Initialize s_audio, if required.
This commit is contained in:
parent
1fcc912f13
commit
1b72f36e89
@ -1,3 +1,9 @@
|
|||||||
|
Sun May 20 13:26:25 2001 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* fhandler_dsp.cc: Reformat to GNU standards.
|
||||||
|
(s_audio): Change to a pointer throughout.
|
||||||
|
(fhandler_dev_dsp::open): Initialize s_audio, if required.
|
||||||
|
|
||||||
Sat May 19 23:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
Sat May 19 23:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* autoload.cc: Add load statements for `LookupAccountNameW',
|
* autoload.cc: Add load statements for `LookupAccountNameW',
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
|
/* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
|
||||||
|
|
||||||
Copyright 2001 Red Hat, Inc
|
Copyright 2001 Red Hat, Inc
|
||||||
|
|
||||||
Written by Andy Younger (andy@snoogie.demon.co.uk)
|
Written by Andy Younger (andy@snoogie.demon.co.uk)
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
This software is a copyrighted work licensed under the terms of the
|
This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
@ -22,17 +22,17 @@ details. */
|
|||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Simple encapsulation of the win32 audio device.
|
// Simple encapsulation of the win32 audio device.
|
||||||
//
|
//
|
||||||
static void CALLBACK wave_callback(HWAVE hWave, UINT msg, DWORD instance,
|
static void CALLBACK wave_callback (HWAVE hWave, UINT msg, DWORD instance,
|
||||||
DWORD param1, DWORD param2);
|
DWORD param1, DWORD param2);
|
||||||
class Audio
|
class Audio
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum { MAX_BLOCKS = 12, BLOCK_SIZE = 16384 };
|
enum { MAX_BLOCKS = 12, BLOCK_SIZE = 16384 };
|
||||||
|
|
||||||
Audio ();
|
Audio ();
|
||||||
~Audio ();
|
~Audio ();
|
||||||
|
|
||||||
bool open (int rate, int bits, int channels, bool bCallback = false);
|
bool open (int rate, int bits, int channels, bool bCallback = false);
|
||||||
void close ();
|
void close ();
|
||||||
int getvolume ();
|
int getvolume ();
|
||||||
@ -40,14 +40,14 @@ public:
|
|||||||
bool write (const void *pSampleData, int nBytes);
|
bool write (const void *pSampleData, int nBytes);
|
||||||
int blocks ();
|
int blocks ();
|
||||||
void callback_sampledone (void *pData);
|
void callback_sampledone (void *pData);
|
||||||
void setformat(int format) { formattype_ = format; }
|
void setformat (int format) {formattype_ = format;}
|
||||||
int numbytesoutput ();
|
int numbytesoutput ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *initialisebuffer ();
|
char *initialisebuffer ();
|
||||||
void waitforcallback ();
|
void waitforcallback ();
|
||||||
bool flush ();
|
bool flush ();
|
||||||
|
|
||||||
HWAVEOUT dev_;
|
HWAVEOUT dev_;
|
||||||
volatile int nBlocksInQue_;
|
volatile int nBlocksInQue_;
|
||||||
int nBytesWritten_;
|
int nBytesWritten_;
|
||||||
@ -60,296 +60,297 @@ private:
|
|||||||
char bigwavebuffer_[MAX_BLOCKS * BLOCK_SIZE];
|
char bigwavebuffer_[MAX_BLOCKS * BLOCK_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
Audio::Audio()
|
Audio::Audio ()
|
||||||
{
|
{
|
||||||
int size = BLOCK_SIZE + sizeof(WAVEHDR);
|
int size = BLOCK_SIZE + sizeof (WAVEHDR);
|
||||||
|
|
||||||
InitializeCriticalSection(&lock_);
|
InitializeCriticalSection (&lock_);
|
||||||
memset(freeblocks_, 0, sizeof(freeblocks_));
|
memset (freeblocks_, 0, sizeof (freeblocks_));
|
||||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||||
{
|
{
|
||||||
char *pBuffer = &bigwavebuffer_[ i * size ];
|
char *pBuffer = &bigwavebuffer_[i * size];
|
||||||
memset(pBuffer, 0, size);
|
memset (pBuffer, 0, size);
|
||||||
freeblocks_[i] = pBuffer;
|
freeblocks_[i] = pBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio::~Audio()
|
Audio::~Audio ()
|
||||||
{
|
{
|
||||||
if (dev_)
|
if (dev_)
|
||||||
close();
|
close ();
|
||||||
DeleteCriticalSection(&lock_);
|
DeleteCriticalSection (&lock_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Audio::open(int rate, int bits, int channels, bool bCallback = false)
|
Audio::open (int rate, int bits, int channels, bool bCallback = false)
|
||||||
{
|
{
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEX format;
|
||||||
int nDevices = waveOutGetNumDevs();
|
int nDevices = waveOutGetNumDevs ();
|
||||||
|
|
||||||
nBytesWritten_ = 0L;
|
nBytesWritten_ = 0L;
|
||||||
bufferIndex_ = 0;
|
bufferIndex_ = 0;
|
||||||
buffer_ = 0L;
|
buffer_ = 0L;
|
||||||
debug_printf("number devices %d\n", nDevices);
|
debug_printf ("number devices %d\n", nDevices);
|
||||||
if (nDevices <= 0)
|
if (nDevices <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
debug_printf("trying to map device freq %d, bits %d, "
|
debug_printf ("trying to map device freq %d, bits %d, "
|
||||||
"channels %d, callback %d\n", rate, bits, channels,
|
"channels %d, callback %d\n", rate, bits, channels,
|
||||||
bCallback);
|
bCallback);
|
||||||
|
|
||||||
int bytesperSample = bits / 8;
|
int bytesperSample = bits / 8;
|
||||||
|
|
||||||
memset(&format, 0, sizeof(format));
|
memset (&format, 0, sizeof (format));
|
||||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
format.wBitsPerSample = bits;
|
format.wBitsPerSample = bits;
|
||||||
format.nChannels = channels;
|
format.nChannels = channels;
|
||||||
format.nSamplesPerSec = rate;
|
format.nSamplesPerSec = rate;
|
||||||
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels *
|
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels *
|
||||||
bytesperSample;
|
bytesperSample;
|
||||||
format.nBlockAlign = format.nChannels * bytesperSample;
|
format.nBlockAlign = format.nChannels * bytesperSample;
|
||||||
|
|
||||||
nBlocksInQue_ = 0;
|
nBlocksInQue_ = 0;
|
||||||
HRESULT res = waveOutOpen(&dev_, WAVE_MAPPER, &format, (DWORD)wave_callback,
|
HRESULT res = waveOutOpen (&dev_, WAVE_MAPPER, &format, (DWORD) wave_callback,
|
||||||
(DWORD)this, bCallback ? CALLBACK_FUNCTION : 0);
|
(DWORD) this, bCallback ? CALLBACK_FUNCTION : 0);
|
||||||
if (res == S_OK)
|
if (res == S_OK)
|
||||||
{
|
{
|
||||||
debug_printf("Sucessfully opened!");
|
debug_printf ("Sucessfully opened!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug_printf("failed to open");
|
debug_printf ("failed to open");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Audio::close()
|
Audio::close ()
|
||||||
{
|
{
|
||||||
if (dev_)
|
if (dev_)
|
||||||
{
|
{
|
||||||
flush(); // force out last block whatever size..
|
flush (); // force out last block whatever size..
|
||||||
|
|
||||||
while (blocks()) // block till finished..
|
while (blocks ()) // block till finished..
|
||||||
waitforcallback();
|
waitforcallback ();
|
||||||
|
|
||||||
waveOutReset(dev_);
|
waveOutReset (dev_);
|
||||||
waveOutClose(dev_);
|
waveOutClose (dev_);
|
||||||
dev_ = 0L;
|
dev_ = 0L;
|
||||||
}
|
}
|
||||||
nBytesWritten_ = 0L;
|
nBytesWritten_ = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Audio::numbytesoutput()
|
Audio::numbytesoutput ()
|
||||||
{
|
{
|
||||||
return nBytesWritten_;
|
return nBytesWritten_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Audio::getvolume()
|
Audio::getvolume ()
|
||||||
{
|
{
|
||||||
DWORD volume;
|
DWORD volume;
|
||||||
|
|
||||||
waveOutGetVolume(dev_, &volume);
|
waveOutGetVolume (dev_, &volume);
|
||||||
return ((volume >> 16) + (volume & 0xffff)) >> 1;
|
return ((volume >> 16) + (volume & 0xffff)) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Audio::setvolume(int newVolume)
|
Audio::setvolume (int newVolume)
|
||||||
{
|
{
|
||||||
waveOutSetVolume(dev_, (newVolume<<16)|newVolume);
|
waveOutSetVolume (dev_, (newVolume << 16) | newVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
Audio::initialisebuffer()
|
Audio::initialisebuffer ()
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&lock_);
|
EnterCriticalSection (&lock_);
|
||||||
WAVEHDR *pHeader = 0L;
|
WAVEHDR *pHeader = 0L;
|
||||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||||
{
|
{
|
||||||
char *pData = freeblocks_[i];
|
char *pData = freeblocks_[i];
|
||||||
if (pData)
|
if (pData)
|
||||||
{
|
{
|
||||||
pHeader = (WAVEHDR *)pData;
|
pHeader = (WAVEHDR *) pData;
|
||||||
if (pHeader->dwFlags & WHDR_DONE)
|
if (pHeader->dwFlags & WHDR_DONE)
|
||||||
{
|
{
|
||||||
waveOutUnprepareHeader(dev_, pHeader, sizeof(WAVEHDR));
|
waveOutUnprepareHeader (dev_, pHeader, sizeof (WAVEHDR));
|
||||||
}
|
}
|
||||||
freeblocks_[i] = 0L;
|
freeblocks_[i] = 0L;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&lock_);
|
LeaveCriticalSection (&lock_);
|
||||||
|
|
||||||
if (pHeader)
|
if (pHeader)
|
||||||
{
|
{
|
||||||
memset(pHeader, 0, sizeof(WAVEHDR));
|
memset (pHeader, 0, sizeof (WAVEHDR));
|
||||||
pHeader->dwBufferLength = BLOCK_SIZE;
|
pHeader->dwBufferLength = BLOCK_SIZE;
|
||||||
pHeader->lpData = (LPSTR)(&pHeader[1]);
|
pHeader->lpData = (LPSTR) (&pHeader[1]);
|
||||||
return (char *)pHeader->lpData;
|
return (char *) pHeader->lpData;
|
||||||
}
|
}
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Audio::write(const void *pSampleData, int nBytes)
|
Audio::write (const void *pSampleData, int nBytes)
|
||||||
{
|
{
|
||||||
// split up big blocks into smaller BLOCK_SIZE chunks
|
// split up big blocks into smaller BLOCK_SIZE chunks
|
||||||
while (nBytes > BLOCK_SIZE)
|
while (nBytes > BLOCK_SIZE)
|
||||||
{
|
{
|
||||||
write(pSampleData, BLOCK_SIZE);
|
write (pSampleData, BLOCK_SIZE);
|
||||||
nBytes -= BLOCK_SIZE;
|
nBytes -= BLOCK_SIZE;
|
||||||
pSampleData = (void *)((char *)pSampleData + BLOCK_SIZE);
|
pSampleData = (void *) ((char *) pSampleData + BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block till next sound is flushed
|
// Block till next sound is flushed
|
||||||
if (blocks() == MAX_BLOCKS)
|
if (blocks () == MAX_BLOCKS)
|
||||||
waitforcallback();
|
waitforcallback ();
|
||||||
|
|
||||||
// Allocate new wave buffer if necessary
|
// Allocate new wave buffer if necessary
|
||||||
if (buffer_ == 0L)
|
if (buffer_ == 0L)
|
||||||
{
|
{
|
||||||
buffer_ = initialisebuffer();
|
buffer_ = initialisebuffer ();
|
||||||
if (buffer_ == 0L)
|
if (buffer_ == 0L)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handle gathering blocks into larger buffer
|
// Handle gathering blocks into larger buffer
|
||||||
int sizeleft = BLOCK_SIZE - bufferIndex_;
|
int sizeleft = BLOCK_SIZE - bufferIndex_;
|
||||||
if (nBytes < sizeleft)
|
if (nBytes < sizeleft)
|
||||||
{
|
{
|
||||||
memcpy(&buffer_[bufferIndex_], pSampleData, nBytes);
|
memcpy (&buffer_[bufferIndex_], pSampleData, nBytes);
|
||||||
bufferIndex_ += nBytes;
|
bufferIndex_ += nBytes;
|
||||||
nBytesWritten_ += nBytes;
|
nBytesWritten_ += nBytes;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flushing when we reach our limit of BLOCK_SIZE
|
// flushing when we reach our limit of BLOCK_SIZE
|
||||||
memcpy(&buffer_[bufferIndex_], pSampleData, sizeleft);
|
memcpy (&buffer_[bufferIndex_], pSampleData, sizeleft);
|
||||||
bufferIndex_ += sizeleft;
|
bufferIndex_ += sizeleft;
|
||||||
nBytesWritten_ += sizeleft;
|
nBytesWritten_ += sizeleft;
|
||||||
flush();
|
flush ();
|
||||||
|
|
||||||
// change pointer to rest of sample, and size accordingly
|
// change pointer to rest of sample, and size accordingly
|
||||||
pSampleData = (void *)((char *)pSampleData + sizeleft);
|
pSampleData = (void *) ((char *) pSampleData + sizeleft);
|
||||||
nBytes -= sizeleft;
|
nBytes -= sizeleft;
|
||||||
|
|
||||||
// if we still have some sample left over write it out
|
// if we still have some sample left over write it out
|
||||||
if (nBytes)
|
if (nBytes)
|
||||||
return write(pSampleData, nBytes);
|
return write (pSampleData, nBytes);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return number of blocks back.
|
// return number of blocks back.
|
||||||
int
|
int
|
||||||
Audio::blocks()
|
Audio::blocks ()
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&lock_);
|
EnterCriticalSection (&lock_);
|
||||||
int ret = nBlocksInQue_;
|
int ret = nBlocksInQue_;
|
||||||
LeaveCriticalSection(&lock_);
|
LeaveCriticalSection (&lock_);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called on an interupt so use locking.. Note nBlocksInQue_ is
|
// This is called on an interupt so use locking.. Note nBlocksInQue_ is
|
||||||
// modified by it so we should wrap all references to it in locks.
|
// modified by it so we should wrap all references to it in locks.
|
||||||
void
|
void
|
||||||
Audio::callback_sampledone(void *pData)
|
Audio::callback_sampledone (void *pData)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&lock_);
|
EnterCriticalSection (&lock_);
|
||||||
|
|
||||||
nBlocksInQue_--;
|
nBlocksInQue_--;
|
||||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||||
if (!freeblocks_[i])
|
if (!freeblocks_[i])
|
||||||
{
|
{
|
||||||
freeblocks_[i] = (char *)pData;
|
freeblocks_[i] = (char *) pData;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&lock_);
|
LeaveCriticalSection (&lock_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Audio::waitforcallback()
|
Audio::waitforcallback ()
|
||||||
{
|
{
|
||||||
int n = blocks();
|
int n = blocks ();
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Sleep(250);
|
Sleep (250);
|
||||||
}
|
}
|
||||||
while (n == blocks());
|
while (n == blocks ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Audio::flush()
|
Audio::flush ()
|
||||||
{
|
{
|
||||||
if (!buffer_)
|
if (!buffer_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Send internal buffer out to the soundcard
|
// Send internal buffer out to the soundcard
|
||||||
WAVEHDR *pHeader = ((WAVEHDR *)buffer_) - 1;
|
WAVEHDR *pHeader = ((WAVEHDR *) buffer_) - 1;
|
||||||
pHeader->dwBufferLength = bufferIndex_;
|
pHeader->dwBufferLength = bufferIndex_;
|
||||||
|
|
||||||
// Quick bit of sample buffer conversion
|
// Quick bit of sample buffer conversion
|
||||||
if (formattype_ == AFMT_S8)
|
if (formattype_ == AFMT_S8)
|
||||||
{
|
{
|
||||||
unsigned char *p = ((unsigned char *)buffer_);
|
unsigned char *p = ((unsigned char *) buffer_);
|
||||||
for (int i = 0; i < bufferIndex_; i++)
|
for (int i = 0; i < bufferIndex_; i++)
|
||||||
{
|
{
|
||||||
p[i] -= 0x7f;
|
p[i] -= 0x7f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waveOutPrepareHeader(dev_, pHeader, sizeof(WAVEHDR)) == S_OK &&
|
if (waveOutPrepareHeader (dev_, pHeader, sizeof (WAVEHDR)) == S_OK &&
|
||||||
waveOutWrite(dev_, pHeader, sizeof (WAVEHDR)) == S_OK)
|
waveOutWrite (dev_, pHeader, sizeof (WAVEHDR)) == S_OK)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&lock_);
|
EnterCriticalSection (&lock_);
|
||||||
nBlocksInQue_++;
|
nBlocksInQue_++;
|
||||||
LeaveCriticalSection(&lock_);
|
LeaveCriticalSection (&lock_);
|
||||||
bufferIndex_ = 0;
|
bufferIndex_ = 0;
|
||||||
buffer_ = 0L;
|
buffer_ = 0L;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&lock_);
|
EnterCriticalSection (&lock_);
|
||||||
for (int i = 0; i < MAX_BLOCKS; i++)
|
for (int i = 0; i < MAX_BLOCKS; i++)
|
||||||
if (!freeblocks_[i])
|
if (!freeblocks_[i])
|
||||||
{
|
{
|
||||||
freeblocks_[i] = (char *)pHeader;
|
freeblocks_[i] = (char *) pHeader;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&lock_);
|
LeaveCriticalSection (&lock_);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Call back routine
|
// Call back routine
|
||||||
static void CALLBACK
|
static void CALLBACK
|
||||||
wave_callback(HWAVE hWave, UINT msg, DWORD instance, DWORD param1, DWORD param2)
|
wave_callback (HWAVE hWave, UINT msg, DWORD instance, DWORD param1,
|
||||||
|
DWORD param2)
|
||||||
{
|
{
|
||||||
if (msg == WOM_DONE)
|
if (msg == WOM_DONE)
|
||||||
{
|
{
|
||||||
Audio *ptr = (Audio *)instance;
|
Audio *ptr = (Audio *) instance;
|
||||||
ptr->callback_sampledone((void *)param1);
|
ptr->callback_sampledone ((void *) param1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// /dev/dsp handler
|
// /dev/dsp handler
|
||||||
static Audio s_audio; // static instance of the Audio handler
|
static Audio *s_audio; // static instance of the Audio handler
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// wav file detection..
|
// wav file detection..
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
struct wavchunk
|
struct wavchunk
|
||||||
{
|
{
|
||||||
char id[4];
|
char id[4];
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
};
|
};
|
||||||
@ -365,40 +366,40 @@ struct wavformat
|
|||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
bool
|
bool
|
||||||
fhandler_dev_dsp::setupwav(const char *pData, int nBytes)
|
fhandler_dev_dsp::setupwav (const char *pData, int nBytes)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
const char *end = pData + nBytes;
|
const char *end = pData + nBytes;
|
||||||
|
|
||||||
if (!(pData[0] == 'R' && pData[1] == 'I' &&
|
if (!(pData[0] == 'R' && pData[1] == 'I' &&
|
||||||
pData[2] == 'F' && pData[3] == 'F'))
|
pData[2] == 'F' && pData[3] == 'F'))
|
||||||
return false;
|
return false;
|
||||||
if (!(pData[8] == 'W' && pData[9] == 'A' &&
|
if (!(pData[8] == 'W' && pData[9] == 'A' &&
|
||||||
pData[10] == 'V' && pData[11] == 'E'))
|
pData[10] == 'V' && pData[11] == 'E'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
len = *(int *)&pData[4];
|
len = *(int *) &pData[4];
|
||||||
pData += 12;
|
pData += 12;
|
||||||
while (len && pData < end)
|
while (len && pData < end)
|
||||||
{
|
{
|
||||||
wavchunk *pChunk = (wavchunk *)pData;
|
wavchunk * pChunk = (wavchunk *) pData;
|
||||||
int blklen = pChunk->len;
|
int blklen = pChunk-> len;
|
||||||
if (pChunk->id[0] == 'f' && pChunk->id[1] == 'm' &&
|
if (pChunk->id[0] == 'f' && pChunk->id[1] == 'm' &&
|
||||||
pChunk->id[2] == 't' && pChunk->id[3] == ' ')
|
pChunk->id[2] == 't' && pChunk->id[3] == ' ')
|
||||||
{
|
{
|
||||||
wavformat *format = (wavformat *)(pChunk+1);
|
wavformat *format = (wavformat *) (pChunk + 1);
|
||||||
if ((char *)(format+1) > end)
|
if ((char *) (format + 1) > end)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Open up audio device with correct frequency for wav file
|
// Open up audio device with correct frequency for wav file
|
||||||
//
|
//
|
||||||
// FIXME: should through away all the header & not output
|
// FIXME: should through away all the header & not output
|
||||||
// it to the soundcard.
|
// it to the soundcard.
|
||||||
s_audio.close();
|
s_audio->close ();
|
||||||
if (s_audio.open(format->dwSamplesPerSec, format->wBitsPerSample,
|
if (s_audio->open (format->dwSamplesPerSec, format->wBitsPerSample,
|
||||||
format->wChannels) == false)
|
format->wChannels) == false)
|
||||||
{
|
{
|
||||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
s_audio->open (audiofreq_, audiobits_, audiochannels_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -409,33 +410,36 @@ fhandler_dev_dsp::setupwav(const char *pData, int nBytes)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pData += blklen + sizeof(wavchunk);
|
pData += blklen + sizeof (wavchunk);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
fhandler_dev_dsp::fhandler_dev_dsp (const char *name)
|
fhandler_dev_dsp::fhandler_dev_dsp (const char *name):
|
||||||
: fhandler_base (FH_OSS_DSP, name)
|
fhandler_base (FH_OSS_DSP, name)
|
||||||
{
|
{
|
||||||
set_cb (sizeof *this);
|
set_cb (sizeof *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_dev_dsp::~fhandler_dev_dsp()
|
fhandler_dev_dsp::~fhandler_dev_dsp ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_dev_dsp::open (const char *path, int flags, mode_t mode = 0)
|
fhandler_dev_dsp::open (const char *path, int flags, mode_t mode = 0)
|
||||||
{
|
{
|
||||||
// currently we only support writing
|
// currently we only support writing
|
||||||
if ((flags & (O_WRONLY|O_RDONLY|O_RDWR)) != O_WRONLY)
|
if ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_WRONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
set_flags(flags);
|
set_flags (flags);
|
||||||
|
|
||||||
|
if (!s_audio)
|
||||||
|
s_audio = new Audio;
|
||||||
|
|
||||||
// Work out initial sample format & frequency
|
// Work out initial sample format & frequency
|
||||||
if (strcmp(path, "/dev/dsp") == 0L)
|
if (strcmp (path, "/dev/dsp") == 0L)
|
||||||
{
|
{
|
||||||
// dev/dsp defaults
|
// dev/dsp defaults
|
||||||
audioformat_ = AFMT_S8;
|
audioformat_ = AFMT_S8;
|
||||||
@ -444,12 +448,12 @@ fhandler_dev_dsp::open (const char *path, int flags, mode_t mode = 0)
|
|||||||
audiochannels_ = 1;
|
audiochannels_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_audio.open(audiofreq_, audiobits_, audiochannels_))
|
if (!s_audio->open (audiofreq_, audiobits_, audiochannels_))
|
||||||
debug_printf("/dev/dsp: failed to open\n");
|
debug_printf ("/dev/dsp: failed to open\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_open_status ();
|
set_open_status ();
|
||||||
debug_printf("/dev/dsp: successfully opened\n");
|
debug_printf ("/dev/dsp: successfully opened\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -457,18 +461,18 @@ fhandler_dev_dsp::open (const char *path, int flags, mode_t mode = 0)
|
|||||||
int
|
int
|
||||||
fhandler_dev_dsp::write (const void *ptr, size_t len)
|
fhandler_dev_dsp::write (const void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
if (s_audio.numbytesoutput() == 0)
|
if (s_audio->numbytesoutput () == 0)
|
||||||
{
|
{
|
||||||
// check for wave file & setup frequencys properly if possible.
|
// check for wave file & setup frequencys properly if possible.
|
||||||
setupwav((const char *)ptr, len);
|
setupwav ((const char *) ptr, len);
|
||||||
|
|
||||||
// Open audio device properly with callbacks.
|
// Open audio device properly with callbacks.
|
||||||
s_audio.close();
|
s_audio->close ();
|
||||||
if (!s_audio.open(audiofreq_, audiobits_, audiochannels_, true))
|
if (!s_audio->open (audiofreq_, audiobits_, audiochannels_, true))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_audio.write(ptr, len);
|
s_audio->write (ptr, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,16 +491,16 @@ fhandler_dev_dsp::lseek (off_t offset, int whence)
|
|||||||
int
|
int
|
||||||
fhandler_dev_dsp::close (void)
|
fhandler_dev_dsp::close (void)
|
||||||
{
|
{
|
||||||
s_audio.close();
|
s_audio->close ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_dev_dsp::dup (fhandler_base * child)
|
fhandler_dev_dsp::dup (fhandler_base * child)
|
||||||
{
|
{
|
||||||
fhandler_dev_dsp *fhc = (fhandler_dev_dsp *)child;
|
fhandler_dev_dsp *fhc = (fhandler_dev_dsp *) child;
|
||||||
|
|
||||||
fhc->set_flags(get_flags());
|
fhc->set_flags (get_flags ());
|
||||||
fhc->audiochannels_ = audiochannels_;
|
fhc->audiochannels_ = audiochannels_;
|
||||||
fhc->audiobits_ = audiobits_;
|
fhc->audiobits_ = audiobits_;
|
||||||
fhc->audiofreq_ = audiofreq_;
|
fhc->audiofreq_ = audiofreq_;
|
||||||
@ -504,119 +508,121 @@ fhandler_dev_dsp::dup (fhandler_base * child)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_dev_dsp::ioctl(unsigned int cmd, void *ptr)
|
fhandler_dev_dsp::ioctl (unsigned int cmd, void *ptr)
|
||||||
{
|
{
|
||||||
int *intptr = (int *)ptr;
|
int *intptr = (int *) ptr;
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
#define CASE(a) case a : debug_printf("/dev/dsp: ioctl %s\n", #a);
|
#define CASE(a) case a : debug_printf("/dev/dsp: ioctl %s\n", #a);
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_RESET)
|
|
||||||
audioformat_ = AFMT_S8;
|
|
||||||
audiofreq_ = 8000;
|
|
||||||
audiobits_ = 8;
|
|
||||||
audiochannels_ = 1;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_GETBLKSIZE)
|
|
||||||
*intptr = Audio::BLOCK_SIZE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_SETFMT)
|
CASE (SNDCTL_DSP_RESET)
|
||||||
{
|
audioformat_ = AFMT_S8;
|
||||||
int nBits = 0;
|
audiofreq_ = 8000;
|
||||||
if (*intptr == AFMT_S16_LE)
|
audiobits_ = 8;
|
||||||
nBits = 16;
|
audiochannels_ = 1;
|
||||||
else if (*intptr == AFMT_U8)
|
return 1;
|
||||||
nBits = 8;
|
|
||||||
else if (*intptr == AFMT_S8)
|
|
||||||
nBits = 8;
|
|
||||||
if (nBits)
|
|
||||||
{
|
|
||||||
s_audio.setformat(*intptr);
|
|
||||||
s_audio.close();
|
|
||||||
if (s_audio.open(audiofreq_, nBits, audiochannels_) == true)
|
|
||||||
{
|
|
||||||
audiobits_ = nBits;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_SPEED)
|
|
||||||
s_audio.close();
|
|
||||||
if (s_audio.open(*intptr, audiobits_, audiochannels_) == true)
|
|
||||||
{
|
|
||||||
audiofreq_ = *intptr;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_STEREO)
|
|
||||||
{
|
|
||||||
int nChannels = *intptr + 1;
|
|
||||||
|
|
||||||
s_audio.close();
|
|
||||||
if (s_audio.open(audiofreq_, audiobits_, nChannels) == true)
|
|
||||||
{
|
|
||||||
audiochannels_ = nChannels;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_audio.open(audiofreq_, audiobits_, audiochannels_);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_GETOSPACE)
|
CASE (SNDCTL_DSP_GETBLKSIZE)
|
||||||
{
|
*intptr = Audio::BLOCK_SIZE;
|
||||||
audio_buf_info *p = (audio_buf_info *)ptr;
|
|
||||||
|
|
||||||
int nBlocks = s_audio.blocks();
|
|
||||||
int leftblocks = ((Audio::MAX_BLOCKS - nBlocks)-1);
|
|
||||||
if (leftblocks < 0) leftblocks = 0;
|
|
||||||
if (leftblocks > 1)
|
|
||||||
leftblocks = 1;
|
|
||||||
int left = leftblocks * Audio::BLOCK_SIZE;
|
|
||||||
|
|
||||||
p->fragments = leftblocks;
|
|
||||||
p->fragstotal = Audio::MAX_BLOCKS;
|
|
||||||
p->fragsize = Audio::BLOCK_SIZE;
|
|
||||||
p->bytes = left;
|
|
||||||
|
|
||||||
debug_printf("ptr: %p "
|
|
||||||
"nblocks: %d "
|
|
||||||
"leftblocks: %d "
|
|
||||||
"left bytes: %d ", ptr, nBlocks, leftblocks, left);
|
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
CASE(SNDCTL_DSP_SETFRAGMENT)
|
|
||||||
{
|
|
||||||
// Fake!! esound & mikmod require this on non PowerPC platforms.
|
|
||||||
//
|
|
||||||
return 1;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
debug_printf("/dev/dsp: ioctl not handled yet! FIXME:\n");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#undef CASE
|
CASE (SNDCTL_DSP_SETFMT)
|
||||||
|
{
|
||||||
|
int nBits = 0;
|
||||||
|
if (*intptr == AFMT_S16_LE)
|
||||||
|
nBits = 16;
|
||||||
|
else if (*intptr == AFMT_U8)
|
||||||
|
nBits = 8;
|
||||||
|
else if (*intptr == AFMT_S8)
|
||||||
|
nBits = 8;
|
||||||
|
if (nBits)
|
||||||
|
{
|
||||||
|
s_audio->setformat (*intptr);
|
||||||
|
s_audio->close ();
|
||||||
|
if (s_audio->open (audiofreq_, nBits, audiochannels_) == true)
|
||||||
|
{
|
||||||
|
audiobits_ = nBits;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_audio->open (audiofreq_, audiobits_, audiochannels_);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
CASE (SNDCTL_DSP_SPEED)
|
||||||
|
s_audio->close ();
|
||||||
|
if (s_audio->open (*intptr, audiobits_, audiochannels_) == true)
|
||||||
|
{
|
||||||
|
audiofreq_ = *intptr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_audio->open (audiofreq_, audiobits_, audiochannels_);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
CASE (SNDCTL_DSP_STEREO)
|
||||||
|
{
|
||||||
|
int nChannels = *intptr + 1;
|
||||||
|
|
||||||
|
s_audio->close ();
|
||||||
|
if (s_audio->open (audiofreq_, audiobits_, nChannels) == true)
|
||||||
|
{
|
||||||
|
audiochannels_ = nChannels;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_audio->open (audiofreq_, audiobits_, audiochannels_);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
CASE (SNDCTL_DSP_GETOSPACE)
|
||||||
|
{
|
||||||
|
audio_buf_info *p = (audio_buf_info *) ptr;
|
||||||
|
|
||||||
|
int nBlocks = s_audio->blocks ();
|
||||||
|
int leftblocks = ((Audio::MAX_BLOCKS - nBlocks) - 1);
|
||||||
|
if (leftblocks < 0)
|
||||||
|
leftblocks = 0;
|
||||||
|
if (leftblocks > 1)
|
||||||
|
leftblocks = 1;
|
||||||
|
int left = leftblocks * Audio::BLOCK_SIZE;
|
||||||
|
|
||||||
|
p->fragments = leftblocks;
|
||||||
|
p->fragstotal = Audio::MAX_BLOCKS;
|
||||||
|
p->fragsize = Audio::BLOCK_SIZE;
|
||||||
|
p->bytes = left;
|
||||||
|
|
||||||
|
debug_printf ("ptr %p nblocks %d leftblocks %d left bytes %d ",
|
||||||
|
ptr, nBlocks, leftblocks, left);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
CASE (SNDCTL_DSP_SETFRAGMENT)
|
||||||
|
{
|
||||||
|
// Fake!! esound & mikmod require this on non PowerPC platforms.
|
||||||
|
//
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
debug_printf ("/dev/dsp: ioctl not handled yet! FIXME:\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
#undef CASE
|
||||||
};
|
};
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -624,6 +630,5 @@ fhandler_dev_dsp::ioctl(unsigned int cmd, void *ptr)
|
|||||||
void
|
void
|
||||||
fhandler_dev_dsp::dump ()
|
fhandler_dev_dsp::dump ()
|
||||||
{
|
{
|
||||||
paranoid_printf("here, fhandler_dev_dsp");
|
paranoid_printf ("here, fhandler_dev_dsp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user