Skip to content

Update Makefile #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Prev Previous commit
Next Next commit
build under ALSA
  • Loading branch information
va7yaa committed Jan 15, 2017
commit 99e7095f17b864908f8156b6be49e71f6eb23d9b
24 changes: 16 additions & 8 deletions audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down
86 changes: 42 additions & 44 deletions audio_ptt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 )) {

// 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;
}
}
}

//
// ptt_set on
//

for (i=0; i<50; i++) {
frames = snd_pcm_writei(handle, pnData, nSamples);
}

//
// ptt_set off
//

//
// close
//

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);

if (ptt_state == PTT_AUDIO_STATE_STOP) {
snd_pcm_drop (handle);

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);

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);

break;
}
}

free (pnData);
}

snd_pcm_close(handle);
snd_pcm_close (handle);
}
#else
int oss_audio_device_fd;
Expand All @@ -165,3 +162,4 @@ static void * ptt_thread (void *arg)
}

#endif

210 changes: 97 additions & 113 deletions audio_ptt_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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.
*/

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;

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;

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 );
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;

/*
* 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;
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;

pnData = (short*)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;
}
}
}

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;
return 0;
}
#endif
4 changes: 4 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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 {
Expand Down
Loading