colorchord/colorchord2/sound_win.c

182 lines
4 KiB
C
Raw Normal View History

2015-07-29 07:56:18 +02:00
//Copyright 2015 <>< Charles Lohr under the ColorChord License.
#include <windows.h>
#include "parameters.h"
#include "sound.h"
#include "os_generic.h"
#include <mmsystem.h>
#include <stdio.h>
#include <stdint.h>
#if defined(WIN32)
#pragma comment(lib,"winmm.lib")
#endif
#define BUFFS 2
struct SoundDriverWin
{
void (*CloseFn)( struct SoundDriverWin * object );
int (*SoundStateFn)( struct SoundDriverWin * object );
SoundCBType callback;
int channelsPlay;
int spsPlay;
int channelsRec;
int spsRec;
int buffer;
int isEnding;
int GOBUFF;
int recording;
HWAVEIN hMyWave;
WAVEHDR WavBuff[BUFFS];
};
static struct SoundDriverWin * w;
void CloseSoundWin( struct SoundDriverWin * r )
{
int i;
if( r )
{
waveInStop(r->hMyWave);
waveInReset(r->hMyWave);
for ( i=0;i<BUFFS;i++)
{
waveInUnprepareHeader(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR));
free ((r->WavBuff[i]).lpData);
}
waveInClose(r->hMyWave);
free( r );
}
}
int SoundStateWin( struct SoundDriverWin * soundobject )
{
return soundobject->recording;
}
void CALLBACK HANDLEMIC(HWAVEIN hwi,UINT umsg, DWORD dwi, DWORD hdr, DWORD dwparm)
{
int ctr;
int ob;
long cValue;
unsigned int maxWave=0;
float buffer[w->buffer*w->channelsRec];
if (w->isEnding) return;
switch (umsg)
{
case MM_WIM_OPEN:
printf( "Mic Open.\n" );
w->recording = 1;
break;
case MM_WIM_DATA:
// printf( "Mic Data.\n");
ob = (w->GOBUFF+(BUFFS))%BUFFS;
// waveInPrepareHeader(w->hMyWave,&(w->WavBuff[w->Cbuff]),sizeof(WAVEHDR));
for (ctr=0;ctr<w->buffer * w->channelsRec;ctr++) {
float cv = (uint16_t)(((uint8_t)w->WavBuff[ob].lpData[ctr*2+1])*256+((uint8_t)w->WavBuff[ob].lpData[ctr*2])+32768)-32768;
cv /= 32768;
// if( ctr < 3 ) cv = -1;
// buffer[(w->buffer * w->channelsRec)-ctr-1] = cv;
buffer[ctr] = cv;
}
waveInAddBuffer(w->hMyWave,&(w->WavBuff[w->GOBUFF]),sizeof(WAVEHDR));
w->GOBUFF = ( w->GOBUFF + 1 ) % BUFFS;
int playbacksamples; //Unused
w->callback( 0, buffer, w->buffer, &playbacksamples, (struct SoundDriver*)w );
}
}
static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r )
{
int i;
WAVEFORMATEX wfmt;
if( GetParameterI( "play", 0 ) )
{
fprintf( stderr, "Error: This Windows Sound Driver does not support playback.\n" );
exit( -1 );
}
w = r;
printf( "WFMT: %d %d %d\n", r->channelsRec, r->spsRec,
r->spsRec * r->channelsRec );
wfmt.wFormatTag = WAVE_FORMAT_PCM;
wfmt.nChannels = r->channelsRec;
wfmt.nSamplesPerSec = r->spsRec;
wfmt.nAvgBytesPerSec = r->spsRec * r->channelsRec;
wfmt.nBlockAlign = r->channelsRec * 2;
wfmt.wBitsPerSample = 16;
wfmt.cbSize = 0;
long dwdevice;
dwdevice = GetParameterI( "wininput", WAVE_MAPPER );
printf( "Wave Devs: %d; WAVE_MAPPER: %d; Selected Input: %d\n", waveInGetNumDevs(), WAVE_MAPPER, dwdevice );
printf( "waveInOpen: %p, %p\n", &r->hMyWave, &wfmt );
int p = waveInOpen(&r->hMyWave, dwdevice, &wfmt,(DWORD)(void*)(&HANDLEMIC) , 0, CALLBACK_FUNCTION);
printf( "WIO: %d\n", p ); //On real windows, returns 11
for ( i=0;i<BUFFS;i++)
{
memset( &(r->WavBuff[i]), 0, sizeof(r->WavBuff[i]) );
(r->WavBuff[i]).dwBufferLength = r->buffer*2*r->channelsRec;
(r->WavBuff[i]).dwLoops = 1;
(r->WavBuff[i]).lpData=(char*) malloc(r->buffer*r->channelsRec*2);
waveInPrepareHeader(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR));
waveInAddBuffer(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR));
}
p = waveInStart(r->hMyWave);
printf( "WIS: %d\n", p ); //On real windows returns 5.
return r;
}
void * InitSoundWin( SoundCBType cb )
{
struct SoundDriverWin * r = malloc( sizeof( struct SoundDriverWin ) );
r->CloseFn = CloseSoundWin;
r->SoundStateFn = SoundStateWin;
r->callback = cb;
r->spsRec = GetParameterI( "samplerate", 44100 );
r->channelsRec = GetParameterI( "channels", 2 );
r->buffer = GetParameterI( "buffer", 384 );
r->recording = 0;
r->isEnding = 0;
printf( "Buffer: %d\n", r->buffer );
r->GOBUFF=0;
return InitWinSound(r);
}
EXECUTE_AT_BOOT( WinSoundReg, RegSound( 10, "WIN", InitSoundWin ) );