xenocara/app/xlockmore/xlock/vms_mmov.c
2006-11-26 11:07:42 +00:00

257 lines
6.2 KiB
C

#include <stdio.h>
#include <signal.h>
#include <mme/mme_api.h>
#include "mmc_buffers.h"
#include "mmc_cmdlin.h"
#include "mmc_memory.h"
#include "mmc_wave_format.h"
#include "mmc_wave_file.h"
#include "mmc_wave.h"
#define BUFFER_PAD 4
#define DEFAULT_NCHANNELS 1
#define DEFAULT_ENCODING WAVE_FORMAT_MULAW
#define DEFAULT_SAMPLESIZE 8
#define DEFAULT_SAMPLERATE 8000
#define DIV_ROUND_UP_(n,d) ((n + d - 1) / d)
#define ROUND_UP_(n,d) (DIV_ROUND_UP_(n,d) * d)
enum mmov_state
{
MMOV_START,
MMOV_PLAY,
MMOV_WAITING,
MMOV_CLOSE
};
#define NUM_DATA 32
struct mmov_soundformat
{
WAVEFORMATEX wave;
char extra_data[ NUM_DATA ];
};
static int Verbose;
static mmcWaveFileState_t wavefilestatus = mmcWaveFileStateInitialValue;
static mmcBufferList_t mmov_buffer = mmcBufferListInitialValue;
static enum mmov_state play_state;
static void mmov_cleanup( )
{
if (mmov_buffer.b)
{
mmcBuffersFree (&mmov_buffer);
}
mmcFreeAll ();
{
mmcWaveInFileClose (&wavefilestatus);
}
return;
}
static void mmov_driver (HANDLE hWaveOut,
UINT wMsg,
DWORD dwInstance,
LPARAM lParam1,
LPARAM lParam2)
{
switch (wMsg)
{
case WOM_OPEN:
play_state = MMOV_PLAY;
break;
case WOM_CLOSE:
play_state = MMOV_CLOSE;
break;
case WOM_DONE:
{
int buffer_index = mmcWaveOutGotData (&mmov_buffer, lParam1);
mmcBuffer_p bp = &mmov_buffer.b[buffer_index];
mmcBufferSetStatus (&mmov_buffer, buffer_index, Empty,
mmov_buffer.nbytes);
}
break;
default:
mmcVerboseDisplay(Verbose, "Unknown index %d", wMsg);
break;
}
}
void play_sound_mmov( char* FileName , int verbose )
{
HWAVEOUT hwaveout;
MMRESULT status;
int mask1;
int allDone;
static int uDeviceId = WAVE_MAPPER;
static int AdpcmBitsPerSample = 16;
static int AdpcmSamplesPerBlock = 0;
static int sizeBuffers = 0;
static int msBuffers = 0;
static int numBuffers = 4;
static struct mmov_soundformat sound_format =
{
{
DEFAULT_ENCODING,
DEFAULT_NCHANNELS,
DEFAULT_SAMPLERATE,
0,
0,
DEFAULT_SAMPLESIZE,
NUM_DATA
}, {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
}
};
Verbose = verbose;
play_state = MMOV_START;
/* Open the Wave In file */
if (mmcWaveInFileOpen (FileName, &sound_format.wave, &wavefilestatus) != 0)
{
mmcVerboseDisplay(Verbose,"Error opening input file");
mmov_cleanup();
return;
}
if ( sound_format.wave.wFormatTag == WAVE_FORMAT_PCM)
mmcVerboseDisplay(Verbose,"PCM file");
else if ( sound_format.wave.wFormatTag == WAVE_FORMAT_MULAW)
mmcVerboseDisplay(Verbose,"mu-law file");
else if ( sound_format.wave.wFormatTag == WAVE_FORMAT_IMA_ADPCM)
mmcVerboseDisplay(Verbose,"IMA file");
else
mmcVerboseDisplay(Verbose,"Unknown sound format %d",
sound_format.wave.wFormatTag);
mmcVerboseDisplay(Verbose,"Channels = %d ", sound_format.wave.nChannels );
mmcVerboseDisplay(Verbose,"Sample rate = %d",
sound_format.wave.nSamplesPerSec);
mmcVerboseDisplay(Verbose,
"Sample size = %d", sound_format.wave.wBitsPerSample );
if( sound_format.wave.nChannels == 0)
sound_format.wave.nChannels = DEFAULT_NCHANNELS;
if( sound_format.wave.nSamplesPerSec == 0)
sound_format.wave.nSamplesPerSec = DEFAULT_SAMPLERATE;
if( sound_format.wave.wBitsPerSample == 0)
sound_format.wave.wBitsPerSample = DEFAULT_SAMPLESIZE;
if ( sound_format.wave.wFormatTag == WAVE_FORMAT_IMA_ADPCM ) {
AdpcmSamplesPerBlock = *(Uint16 *)(&sound_format.extra_data[0]);
}
if ( ( sound_format.wave.wFormatTag == WAVE_FORMAT_PCM) ||
( sound_format.wave.wFormatTag == WAVE_FORMAT_MULAW) ) {
mask1 = WAVE_FORMAT_FIX_BLOCK_ALIGN | WAVE_FORMAT_FIX_AVG_BPS;
mmcWaveFormatFix((LPPCMWAVEFORMAT)(&sound_format), mask1 );
}
if ( sound_format.wave.wFormatTag == WAVE_FORMAT_IMA_ADPCM) {
sizeBuffers = sound_format.wave.nBlockAlign;
msBuffers = sizeBuffers * 1000 /
(DIV_ROUND_UP_(AdpcmBitsPerSample,8) *
sound_format.wave.nSamplesPerSec *
sound_format.wave.nChannels);
} else {
if (!msBuffers && !sizeBuffers)
msBuffers = 1000/numBuffers;
if (msBuffers)
sizeBuffers =
ROUND_UP_(DIV_ROUND_UP_(msBuffers *
DIV_ROUND_UP_( sound_format.wave.wBitsPerSample,
8) *
sound_format.wave.nSamplesPerSec *
sound_format.wave.nChannels,1000), BUFFER_PAD);
else
{
sizeBuffers = ROUND_UP_(sizeBuffers, BUFFER_PAD);
msBuffers = sizeBuffers * 1000 /
(DIV_ROUND_UP_( sound_format.wave.wBitsPerSample,8) *
sound_format.wave.nSamplesPerSec *
sound_format.wave.nChannels);
}
}
mmcVerboseDisplay(Verbose, "Buffer size = %d bytes or %d milliseconds",
sizeBuffers, msBuffers);
hwaveout = NULL;
status = mmcWaveOutOpen(&sound_format.wave, uDeviceId, &mmov_driver ,
WAVE_OPEN_SHAREABLE, &hwaveout);
if (status != MMSYSERR_NOERROR)
{
mmov_cleanup();
return;
}
if (mmcBuffersCreate (&mmov_buffer, numBuffers, sizeBuffers, BUFFER_PAD)
!= MMSYSERR_NOERROR)
{
mmov_cleanup();
return;
}
for (;;)
{
switch ( play_state )
{
case MMOV_START:
break;
case MMOV_PLAY:
status = mmcWaveOutQueueBufferAll (hwaveout, &mmov_buffer, Verbose,
&wavefilestatus, &allDone);
if (allDone)
play_state = MMOV_WAITING;
else
{
if (status != MMSYSERR_NOERROR)
{
mmov_cleanup();
return;
}
}
break;
case MMOV_WAITING:
if ((mmcBufferFind(&mmov_buffer,Filling) != mmcBufferNone) ||
(mmcBufferFind(&mmov_buffer,Full) != mmcBufferNone) ||
(mmcBufferFind(&mmov_buffer,Playing) != mmcBufferNone))
break;
play_state = MMOV_CLOSE;
case MMOV_CLOSE:
status = mmcWaveOutClose (hwaveout, &mmov_buffer);
if (status != MMSYSERR_NOERROR)
{
mmov_cleanup();
return;
}
mmov_cleanup();
return;
default:
mmcVerboseDisplay(Verbose,"Unknown play_state %d", play_state);
mmov_cleanup();
return;
}
mmeWaitForCallbacks (); /* block so we don't hog 100% of the CPU */
mmeProcessCallbacks ();
}
}