build under ALSA

This commit is contained in:
Andrew 2017-01-15 13:42:52 -08:00
parent 52bf2ff5bd
commit 99e7095f17
5 changed files with 169 additions and 167 deletions

24
audio.h
View File

@ -30,11 +30,17 @@ enum ptt_method_e {
PTT_METHOD_SERIAL, /* Serial port RTS or DTR. */
PTT_METHOD_GPIO, /* General purpose I/O, Linux only. */
PTT_METHOD_LPT, /* Parallel printer port, Linux only. */
PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */
PTT_METHOD_AUDIO }; /* Audio channel. */
PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */
PTT_METHOD_AUDIO }; /* Audio channel. */
typedef enum ptt_method_e ptt_method_t;
enum ptt_audio_state_e {
PTT_AUDIO_STATE_STOP,
PTT_AUDIO_STATE_START,
PTT_AUDIO_STATE_CLOSE };
typedef enum ptt_audio_state_e ptt_audio_state_t;
enum ptt_line_e { PTT_LINE_NONE = 0, PTT_LINE_RTS = 1, PTT_LINE_DTR = 2 }; // Important: 0 for neither.
typedef enum ptt_line_e ptt_line_t;
@ -196,14 +202,16 @@ struct audio_s {
int ptt_invert; /* Invert the output. */
int ptt_invert2; /* Invert the secondary output. */
int ptt_channel; /* Channel number for audio PTT. */
int ptt_frequency; /* Audio frequency for audio PTT. */
int ptt_channel; /* Channel number for audio PTT. */
int ptt_frequency; /* Audio frequency for audio PTT. */
#if __WIN32__
HANDLE ptt_start; /* Handle for event that starts ptt tone. */
HANDLE ptt_stop; /* Handle for event that stops ptt tone. */
HANDLE ptt_close; /* Handle for event that closes ptt. */
HANDLE ptt_start; /* Handle for event that starts ptt tone. */
HANDLE ptt_stop; /* Handle for event that stops ptt tone. */
HANDLE ptt_close; /* Handle for event that closes ptt. */
#else
pthread_mutex_t ptt_mutex; /* Mutex for controlling ptt tone state. */
pthread_cond_t ptt_condition; /* Condition for controlling ptt tone state. */
ptt_audio_state_t ptt_state; /* State of ptt tone. */
#endif
#ifdef USE_HAMLIB

View File

@ -91,67 +91,64 @@ static void * ptt_thread (void *arg)
err = snd_pcm_open(&handle, save_audio_config_p->adev[a].adevice_out, SND_PCM_STREAM_PLAYBACK, 0);
if (err == 0) {
snd_pcm_sframes_t frames;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
err = snd_pcm_set_params(handle, format, SND_PCM_ACCESS_RW_INTERLEAVED,
save_audio_config_p->adev[a].num_channels,
save_audio_config_p->adev[a].samples_per_sec, 1, 500000);
if (err == 0) {
short* pnData;
short* pnData;
short sample;
int nSamples = save_audio_config_p->adev[a].samples_per_sec / 10;
int nSamples = save_audio_config_p->adev[a].samples_per_sec / 5;
int nBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof(short);
int i;
int j;
pnData = (short*)malloc (nBufferLength);
if (save_audio_config_p->adev[a].num_channels == 1) {
for (i = 0; i < nSamples; i++) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
pnData[i] = sample;
for (i = 0; i < nSamples; i++) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
for (j = 0; j < save_audio_config_p->adev[a].num_channels; j++) {
if (channel == ADEVFIRSTCHAN( a ) + j) {
pnData[i*save_audio_config_p->adev[a].num_channels + j] = sample;
} else {
pnData[i*save_audio_config_p->adev[a].num_channels + j] = 0;
}
}
}
else {
for (i = 0; i < nSamples; i++) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
if (channel == ADEVFIRSTCHAN( a )) {
while (1) {
pthread_mutex_lock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
ptt_audio_state_t ptt_state = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_state;
pthread_mutex_unlock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
// Stereo, left channel.
if (ptt_state == PTT_AUDIO_STATE_STOP) {
snd_pcm_drop (handle);
pnData[i*2 + 0] = sample;
pnData[i*2 + 1] = 0;
}
else {
pthread_mutex_lock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
pthread_cond_wait (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_condition, &save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
ptt_state = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_state;
pthread_mutex_unlock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
// Stereo, right channel.
if (ptt_state == PTT_AUDIO_STATE_START) {
snd_pcm_prepare (handle);
}
}
if (ptt_state == PTT_AUDIO_STATE_START) {
snd_pcm_writei (handle, pnData, nSamples);
}
else if (ptt_state == PTT_AUDIO_STATE_CLOSE) {
snd_pcm_drop (handle);
pnData[i*2 + 0] = 0;
pnData[i*2 + 1] = sample;
}
}
}
//
// ptt_set on
//
for (i=0; i<50; i++) {
frames = snd_pcm_writei(handle, pnData, nSamples);
}
//
// ptt_set off
//
//
// close
//
break;
}
}
free (pnData);
}
snd_pcm_close(handle);
snd_pcm_close (handle);
}
#else
int oss_audio_device_fd;
@ -165,3 +162,4 @@ static void * ptt_thread (void *arg)
}
#endif

View File

@ -64,126 +64,110 @@ static unsigned __stdcall ptt_thread ( void *arg );
HANDLE start_ptt_thread (struct audio_s *pa , int ch)
{
save_audio_config_p = pa;
save_audio_config_p = pa;
return (HANDLE)_beginthreadex (NULL, 0, ptt_thread, (void*)(long)ch, 0, NULL);
return (HANDLE)_beginthreadex (NULL, 0, ptt_thread, (void*)(long)ch, 0, NULL);
}
unsigned __stdcall ptt_thread (void *arg)
{
WAVEFORMATEX wf;
HWAVEOUT hWaveOut;
int ch = (int)(long)arg; // channel number.
int channel = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_channel;
int freq = save_audio_config_p->achan[channel].octrl[OCTYPE_PTT].ptt_frequency;
int a = ACHAN2ADEV( channel );
int err;
WAVEFORMATEX wf;
HWAVEOUT hWaveOut;
int ch = (int)(long)arg; // channel number.
int channel = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_channel;
int freq = save_audio_config_p->achan[channel].octrl[OCTYPE_PTT].ptt_frequency;
int a = ACHAN2ADEV( channel );
int err;
if( save_audio_config_p->adev[a].defined ) {
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = save_audio_config_p->adev[a].num_channels;
wf.nSamplesPerSec = save_audio_config_p->adev[a].samples_per_sec;
wf.wBitsPerSample = save_audio_config_p->adev[a].bits_per_sample;
wf.nBlockAlign = ( wf.wBitsPerSample / 8 ) * wf.nChannels;
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
wf.cbSize = 0;
if (save_audio_config_p->adev[a].defined) {
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = save_audio_config_p->adev[a].num_channels;
wf.nSamplesPerSec = save_audio_config_p->adev[a].samples_per_sec;
wf.wBitsPerSample = save_audio_config_p->adev[a].bits_per_sample;
wf.nBlockAlign = ( wf.wBitsPerSample / 8 ) * wf.nChannels;
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
wf.cbSize = 0;
/*
* Open the audio output device.
* Soundcard is only possibility at this time.
*/
/*
* Open the audio output device.
* Soundcard is only possibility at this time.
*/
err = waveOutOpen ( &hWaveOut, atoi( save_audio_config_p->adev[a].adevice_out ), &wf, (DWORD_PTR)NULL, 0, CALLBACK_NULL );
if( err == MMSYSERR_NOERROR ) {
WAVEHDR waveHeader;
short* pnData;
short sample;
int nSamples = save_audio_config_p->adev[a].samples_per_sec / freq;
int i;
err = waveOutOpen ( &hWaveOut, atoi( save_audio_config_p->adev[a].adevice_out ), &wf, (DWORD_PTR)NULL, 0, CALLBACK_NULL );
if (err == MMSYSERR_NOERROR) {
WAVEHDR waveHeader;
short* pnData;
short sample;
int nSamples = save_audio_config_p->adev[a].samples_per_sec / freq;
int i;
int j;
waveHeader.dwBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof( short );
waveHeader.lpData = malloc( waveHeader.dwBufferLength );
waveHeader.dwUser = 0;
waveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
waveHeader.dwLoops = 0xFFFF;
waveHeader.dwBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof( short );
waveHeader.lpData = malloc( waveHeader.dwBufferLength );
waveHeader.dwUser = 0;
waveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
waveHeader.dwLoops = 0xFFFF;
pnData = (short*)waveHeader.lpData;
pnData = (short*)waveHeader.lpData;
if( save_audio_config_p->adev[a].num_channels == 1 ) {
for( i = 0; i < nSamples; i++ ) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
pnData[i] = sample;
}
}
else {
for( i = 0; i < nSamples; i++ ) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
if( channel == ADEVFIRSTCHAN( a ) ) {
// Stereo, left channel.
pnData[i*2 + 0] = sample;
pnData[i*2 + 1] = 0;
}
else {
// Stereo, right channel.
pnData[i*2 + 0] = 0;
pnData[i*2 + 1] = sample;
}
}
}
err = waveOutPrepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
if( err == MMSYSERR_NOERROR ) {
HANDLE handles[3];
DWORD dwWait;
handles[0] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_start;
handles[1] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_stop;
handles[2] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_close;
while( 1 )
{
dwWait = WaitForMultipleObjects ( 3, handles, FALSE, INFINITE );
if( dwWait == WAIT_OBJECT_0 + 0 )
{
//
// ptt_set on
//
waveOutWrite ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
}
else if( dwWait == WAIT_OBJECT_0 + 1 )
{
//
// ptt_set off
//
waveOutReset ( hWaveOut );
}
else if( dwWait == WAIT_OBJECT_0 + 2 )
{
//
// close
//
waveOutReset ( hWaveOut );
waveOutUnprepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
break;
}
}
}
waveOutClose ( hWaveOut );
free( waveHeader.lpData );
for (i = 0; i < nSamples; i++) {
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
for (j = 0; j < save_audio_config_p->adev[a].num_channels; j++) {
if (channel == ADEVFIRSTCHAN( a ) + j) {
pnData[i*save_audio_config_p->adev[a].num_channels + j] = sample;
} else {
pnData[i*save_audio_config_p->adev[a].num_channels + j] = 0;
}
}
}
}
return 0;
err = waveOutPrepareHeader (hWaveOut, &waveHeader, sizeof( WAVEHDR ));
if (err == MMSYSERR_NOERROR) {
HANDLE handles[3];
DWORD dwWait;
handles[0] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_start;
handles[1] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_stop;
handles[2] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_close;
while (1)
{
dwWait = WaitForMultipleObjects (3, handles, FALSE, INFINITE);
if (dwWait == WAIT_OBJECT_0 + 0) {
//
// ptt_set on
//
waveOutWrite ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
}
else if (dwWait == WAIT_OBJECT_0 + 1) {
//
// ptt_set off
//
waveOutReset ( hWaveOut );
}
else if( dwWait == WAIT_OBJECT_0 + 2 ) {
//
// close
//
waveOutReset ( hWaveOut );
waveOutUnprepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
break;
}
}
}
waveOutClose ( hWaveOut );
free( waveHeader.lpData );
}
}
return 0;
}
#endif

View File

@ -673,6 +673,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_audio_config->achan[channel].octrl[ot].ptt_stop = NULL;
p_audio_config->achan[channel].octrl[ot].ptt_close = NULL;
#else
p_audio_config->achan[channel].octrl[ot].ptt_state = PTT_AUDIO_STATE_STOP;
#endif
}
@ -1635,6 +1636,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_audio_config->achan[channel].octrl[ot].ptt_stop = CreateEvent (NULL, FALSE, FALSE, NULL);
p_audio_config->achan[channel].octrl[ot].ptt_close = CreateEvent (NULL, FALSE, FALSE, NULL);
#else
p_audio_config->achan[channel].octrl[ot].ptt_state = PTT_AUDIO_STATE_STOP;
pthread_mutex_init(&p_audio_config->achan[channel].octrl[ot].ptt_mutex, 0);
pthread_cond_init(&p_audio_config->achan[channel].octrl[ot].ptt_condition, 0);
#endif
}
else {

30
ptt.c
View File

@ -1010,22 +1010,27 @@ void ptt_set (int ot, int chan, int ptt_signal)
* Using audio channel?
*/
if( save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_AUDIO ) {
if( ptt_signal ) {
if (save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_AUDIO) {
if (ptt_signal) {
#ifdef __WIN32__
SetEvent( save_audio_config_p->achan[chan].octrl[ot].ptt_start );
SetEvent (save_audio_config_p->achan[chan].octrl[ot].ptt_start);
#else
pthread_mutex_lock (&save_audio_config_p->achan[chan].octrl[ot].ptt_mutex);
save_audio_config_p->achan[chan].octrl[ot].ptt_state = PTT_AUDIO_STATE_START;
pthread_cond_signal (&save_audio_config_p->achan[chan].octrl[ot].ptt_condition);
pthread_mutex_unlock (&save_audio_config_p->achan[chan].octrl[ot].ptt_mutex);
#endif
}
else
{
}
else
{
#ifdef __WIN32__
SetEvent( save_audio_config_p->achan[chan].octrl[ot].ptt_stop );
SetEvent (save_audio_config_p->achan[chan].octrl[ot].ptt_stop);
#else
pthread_mutex_lock (&save_audio_config_p->achan[chan].octrl[ot].ptt_mutex);
save_audio_config_p->achan[chan].octrl[ot].ptt_state = PTT_AUDIO_STATE_STOP;
pthread_mutex_unlock (&save_audio_config_p->achan[chan].octrl[ot].ptt_mutex);
#endif
}
}
}
} /* end ptt_set */
@ -1137,7 +1142,10 @@ void ptt_term (void)
#ifdef __WIN32__
SetEvent (save_audio_config_p->achan[n].octrl[OCTYPE_PTT].ptt_close) ;
#else
pthread_mutex_lock (&save_audio_config_p->achan[n].octrl[OCTYPE_PTT].ptt_mutex);
save_audio_config_p->achan[n].octrl[OCTYPE_PTT].ptt_state = PTT_AUDIO_STATE_CLOSE;
pthread_cond_signal (&save_audio_config_p->achan[n].octrl[OCTYPE_PTT].ptt_condition);
pthread_mutex_unlock (&save_audio_config_p->achan[n].octrl[OCTYPE_PTT].ptt_mutex);
#endif
}
}