home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wvis0626.zip
/
warpvision_20020626.zip
/
audio
/
dart.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-06-21
|
14KB
|
582 lines
/*
Direct Audio Interface library for OS/2
Copyright (C) 1998 by Andrew Zabolotny <bit@eltech.ru>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Modified by Alex Strelnikov
*/
#define INCL_OS2MM
#ifdef MAIN_DEBUG
#define INCL_KBD
#define INCL_DOSPROCESS
#endif
#include <os2.h>
#include <os2me.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "dart.h"
DartStruct DART;
int dart_error(APIRET rc)
{
if (rc)
{
mciGetErrorString(rc,
(PSZ)DART.ErrorCode,
sizeof(DART.ErrorCode));
fprintf(stdout, "\nDART error:%s\n", DART.ErrorCode);
return TRUE;
}
else
{
DART.ErrorCode[0] = 0;
return FALSE;
}
}
void dart_stop(void)
{
MCI_GENERIC_PARMS GenericParms;
if (DART.DeviceID)
{
GenericParms.hwndCallback = 0;
mciSendCommand(DART.DeviceID,
MCI_STOP,
MCI_WAIT,
(PVOID)&GenericParms,
0);
}
return;
}
int dart_fill_buffer(PMCI_MIX_BUFFER pBuffer)
{
size_t top = 0;
memset (pBuffer->pBuffer, 0x80, pBuffer->ulBufferLength);
if (DART.InputCallback && DART.WaitStreamEnd != TRUE)
top = DART.InputCallback(pBuffer->pBuffer, DART.BufferParms.ulBufferSize);
if (top < DART.BufferParms.ulBufferSize)
{
pBuffer->ulFlags = MIX_BUFFER_EOS;
DART.WaitStreamEnd = TRUE;
}
else
pBuffer->ulFlags = 0;
pBuffer->ulBufferLength = top;
return top;
}
void dart_free_buffers(void)
{
APIRET rc;
int i;
if (DART.MixBuffers == NULL)
return;
// restore original buffer sizes -- just in case
for (i = 0; i < DART.BufferCount; i++)
DART.MixBuffers[i].ulBufferLength = DART.BufferParms.ulBufferSize;
rc = mciSendCommand (DART.DeviceID,
MCI_BUFFER,
MCI_WAIT | MCI_DEALLOCATE_MEMORY,
(PVOID)&DART.BufferParms, 0);
if (DART.MixBuffers)
free(DART.MixBuffers);
DART.MixBuffers = NULL;
dart_error(rc);
}
long MixHandler (ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
{
if (DART.Stopped == TRUE || DART.Paused == TRUE)
return TRUE;
switch (ulFlags)
{
case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE:
// on error, fill next buffer and continue
case MIX_WRITE_COMPLETE:
DART.BytesPlayed += pBuffer->ulBufferLength;
// If this is the last buffer, stop
if (pBuffer->ulFlags & MIX_BUFFER_EOS)
DART.Stopped = TRUE;
else
{
// Transfer buffer to DART
if (dart_fill_buffer(pBuffer) == 0)
{
// if user callback failed to fill the buffer,
// we should fill it with silence to avoid annoying
// clicks that happens on some soundcards
pBuffer->ulBufferLength = DART.BufferParms.ulBufferSize;
memset (pBuffer->pBuffer, 0x80, pBuffer->ulBufferLength);
}
DART.MixSetupParms.pmixWrite(DART.MixSetupParms.ulMixHandle, pBuffer, 1);
}
break;
}
return TRUE;
}
int dart_init(int DeviceIndex, int BitsPerSample, int SamplingRate,
int DataFormat, int Channels, int Buffers,
dartInputCallback Callback)
{
APIRET rc;
LONG dart_fl;
MCI_AMP_OPEN_PARMS MciOpenParms;
MCI_GENERIC_PARMS GenericParms;
DART.DeviceID = 0;
DART.MixBuffers = NULL;
DART.InputCallback = NULL;
if (DART.Shareable)
{
dart_fl = MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE;
printf("DART: open in SHARE mode\n");
}
else
{
dart_fl = MCI_WAIT | MCI_OPEN_TYPE_ID;
printf("DART: open in EXCLUSIVE mode\n");
}
fflush(stdout);
memset(&MciOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
MciOpenParms.usDeviceID = 0;
MciOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX |
(DeviceIndex << 16));
rc = mciSendCommand (0,
MCI_OPEN,
dart_fl,
(PVOID) &MciOpenParms,
0);
if (dart_error(rc))
return FALSE;
DART.DeviceID = MciOpenParms.usDeviceID;
if (!DART.Shareable)
{
// Grab exclusive rights to device instance (NOT entire device)
GenericParms.hwndCallback = 0;
rc = mciSendCommand (DART.DeviceID,
MCI_ACQUIREDEVICE,
MCI_EXCLUSIVE_INSTANCE,
(PVOID)&GenericParms,
0);
}
if (dart_error(rc))
return FALSE;
// Allocate mixer buffers
DART.MixBuffers = (MCI_MIX_BUFFER *)malloc(sizeof(MCI_MIX_BUFFER)*Buffers);
// Setup the mixer for playback of wave data
memset (&DART.MixSetupParms, 0, sizeof (MCI_MIXSETUP_PARMS));
DART.MixSetupParms.ulBitsPerSample = BitsPerSample;
DART.MixSetupParms.ulSamplesPerSec = SamplingRate;
DART.MixSetupParms.ulFormatTag = DataFormat;
DART.MixSetupParms.ulChannels = Channels;
DART.MixSetupParms.ulFormatMode = MCI_PLAY;
DART.MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
DART.MixSetupParms.pmixEvent = (MIXEREVENT*)MixHandler;
rc = mciSendCommand(DART.DeviceID,
MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_INIT,
(PVOID)&DART.MixSetupParms,
0);
if (dart_error(rc))
return FALSE;
// Use the suggested buffer size provide by the mixer device
// Set up the BufferParms data structure and allocate device buffers
// from the Amp-Mixer
DART.BufferParms.ulStructLength = sizeof(MCI_BUFFER_PARMS);
DART.BufferParms.ulNumBuffers = Buffers;
DART.BufferParms.ulBufferSize = DART.MixSetupParms.ulBufferSize;
DART.BufferParms.pBufList = DART.MixBuffers;
DART.BufLen = DART.MixSetupParms.ulBufferSize;
rc = mciSendCommand(DART.DeviceID,
MCI_BUFFER,
MCI_WAIT | MCI_ALLOCATE_MEMORY,
(PVOID)&DART.BufferParms,
0);
if (dart_error (rc))
return FALSE;
// The mixer possibly changed these values
DART.BufferCount = DART.BufferParms.ulNumBuffers;
DART.SeekPosition = 0;
DART.InputCallback = Callback;
return TRUE;
}
int dart_close(void)
{
MCI_GENERIC_PARMS GenericParms;
APIRET rc;
if (DART.DeviceID != 0)
{
dart_stop();
dart_free_buffers();
GenericParms.hwndCallback = 0;
if (!DART.Shareable)
{
// Release exclusive rights to device instance (NOT entire device)
rc = mciSendCommand (DART.DeviceID,
MCI_ACQUIREDEVICE,
MCI_RELEASEDEVICE,
(PVOID)&GenericParms,
0);
}
rc = mciSendCommand(DART.DeviceID,
MCI_CLOSE,
MCI_WAIT,
(PVOID)&GenericParms,
0);
dart_error(rc);
}
return 0;
}
int dart_play(void)
{
int buffcount, outsize;
DART.Stopped = DART.WaitStreamEnd = FALSE;
DART.BytesPlayed = 0;
for (buffcount = 0; buffcount < DART.BufferCount; buffcount++)
{
outsize = dart_fill_buffer(&DART.MixBuffers[buffcount]);
if (outsize != DART.BufLen)
break;
}
if (buffcount == 0)
DART.Stopped = DART.WaitStreamEnd = TRUE;
else
{
APIRET rc = DART.MixSetupParms.pmixWrite(DART.MixSetupParms.ulMixHandle,
&DART.MixBuffers[0], buffcount);
dart_error(rc);
}
return TRUE;
}
void dart_pause(void)
{
if (DART.DeviceID)
{
MCI_GENERIC_PARMS GenericParms;
mciSendCommand(DART.DeviceID,
MCI_PAUSE,
MCI_WAIT,
(PVOID)&GenericParms,
0);
}
DART.Paused = TRUE;
}
void dart_resume(void)
{
if (DART.DeviceID)
{
MCI_GENERIC_PARMS GenericParms;
mciSendCommand(DART.DeviceID,
MCI_RESUME,
MCI_WAIT,
(PVOID)&GenericParms,
0);
}
DART.Paused = FALSE;
}
ULONG dart_get_pos(void)
{
MCI_STATUS_PARMS statParms;
memset(&statParms, 0, sizeof(MCI_STATUS_PARMS));
statParms.ulItem = MCI_STATUS_POSITION;
mciSendCommand(DART.DeviceID,
MCI_STATUS,
MCI_WAIT | MCI_STATUS_ITEM,
(PVOID)&statParms,
0);
return statParms.ulReturn + DART.SeekPosition;
}
void dart_set_pos(ULONG new_position)
{
DART.SeekPosition = 0;
DART.SeekPosition = new_position - dart_get_pos();
/*
int rc;
MCI_SEEK_PARMS mciSeekParm;
mciSeekParm.hwndCallback = 0;
mciSeekParm.ulTo = Position;
rc = mciSendCommand(DART.DeviceID,
MCI_SEEK,
MCI_WAIT | MCI_TO,
(PVOID)&mciSeekParm,
0);
dart_error(rc);
*/
return;
}
void dart_set_sound_state(BOOL state)
{
USHORT usDeviceID;
MCI_SET_PARMS msp;
USHORT ushSt;
if (DART.DeviceID)
{
if (state == FALSE)
ushSt = MCI_SET_ON;
else
ushSt = MCI_SET_OFF;
msp.ulAudio = MCI_SET_AUDIO_ALL;
mciSendCommand(DART.DeviceID,
MCI_SET,
MCI_WAIT | MCI_SET_AUDIO | ushSt,
(PVOID)&msp, 0);
}
return;
}
void dart_set_volume(ULONG vol)
{
USHORT usDeviceID;
MCI_SET_PARMS msp;
if (DART.DeviceID)
{
msp.ulLevel = vol;
msp.ulAudio = MCI_SET_AUDIO_ALL;
mciSendCommand(DART.DeviceID,
MCI_SET,
MCI_WAIT | MCI_SET_AUDIO |
MCI_SET_VOLUME,
(PVOID)&msp, 0);
}
return;
}
USHORT dart_get_volume(void)
{
ULONG ulError;
BOOL disc_loaded;
USHORT vol;
MCI_STATUS_PARMS mstatusp;
memset(&mstatusp, 0, sizeof (MCI_STATUS_PARMS));
mstatusp.ulItem = MCI_STATUS_VOLUME;
if (DART.DeviceID)
{
ulError = mciSendCommand(DART.DeviceID,
MCI_STATUS,
MCI_WAIT | MCI_STATUS_ITEM,
(PVOID)&mstatusp,
0);
if (!(ulError & 0xffff))
{
vol = LOUSHORT(mstatusp.ulReturn);
}
else
vol = 0;
}
return vol;
}
#ifdef MAIN_DEBUG
#include <io.h>
#include <fcntl.h>
#include <conio.h>
int input_handle;
int switch_sign = FALSE;
size_t dartCallback (void *Buffer, size_t BufferSize)
{
size_t bytesread = 1, count = 0;
while ((bytesread) && (count < BufferSize))
{
bytesread = read (input_handle, &((char *)Buffer) [count], BufferSize - count);
if ((int)bytesread == -1)
break;
count += bytesread;
}
if (switch_sign)
{
char *sample = (char *)Buffer;
char *lastsample = ((char *)Buffer) + count;
while (sample < lastsample)
{
sample++;
*sample ^= 0x80;
sample++;
} /* endwhile */
} /* endif */
return count;
}
int read_key(void)
{
static ULONG time = 0;
KBDKEYINFO Char;
KbdCharIn(&Char, IO_NOWAIT, 0);
if (time == Char.time)
return 0;
time = Char.time;
return Char.chChar;
}
int main()
{
APIRET rc;
int key;
input_handle = open("debug.wav", O_RDONLY | O_BINARY);
rc = dart_init(0, BPS_16, 44100, MCI_WAVE_FORMAT_PCM, 2, 2, dartCallback);
dart_play();
while(DART.Stopped == FALSE)
{
key = read_key();
if (key == 27)
break;
if (key == 113)
dart_stop();
if (key == 119)
dart_play();
if (key == 101)
dart_pause();
if (key == 114)
dart_resume();
if (key == 99)
dart_set_pos(14000L);
fprintf(stdout, "Played: %ld %d \r", dart_get_pos(), key);
fflush(stdout);
DosSleep(200);
}
dart_close();
return 0;
}
#endif