Skip to content

Commit 99e7095

Browse files
committed
build under ALSA
1 parent 52bf2ff commit 99e7095

File tree

5 files changed

+178
-176
lines changed

5 files changed

+178
-176
lines changed

audio.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@ enum ptt_method_e {
3030
PTT_METHOD_SERIAL, /* Serial port RTS or DTR. */
3131
PTT_METHOD_GPIO, /* General purpose I/O, Linux only. */
3232
PTT_METHOD_LPT, /* Parallel printer port, Linux only. */
33-
PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */
34-
PTT_METHOD_AUDIO }; /* Audio channel. */
33+
PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */
34+
PTT_METHOD_AUDIO }; /* Audio channel. */
3535

3636
typedef enum ptt_method_e ptt_method_t;
3737

38+
enum ptt_audio_state_e {
39+
PTT_AUDIO_STATE_STOP,
40+
PTT_AUDIO_STATE_START,
41+
PTT_AUDIO_STATE_CLOSE };
42+
typedef enum ptt_audio_state_e ptt_audio_state_t;
43+
3844
enum ptt_line_e { PTT_LINE_NONE = 0, PTT_LINE_RTS = 1, PTT_LINE_DTR = 2 }; // Important: 0 for neither.
3945
typedef enum ptt_line_e ptt_line_t;
4046

@@ -196,14 +202,16 @@ struct audio_s {
196202
int ptt_invert; /* Invert the output. */
197203
int ptt_invert2; /* Invert the secondary output. */
198204

199-
int ptt_channel; /* Channel number for audio PTT. */
200-
int ptt_frequency; /* Audio frequency for audio PTT. */
205+
int ptt_channel; /* Channel number for audio PTT. */
206+
int ptt_frequency; /* Audio frequency for audio PTT. */
201207
#if __WIN32__
202-
HANDLE ptt_start; /* Handle for event that starts ptt tone. */
203-
HANDLE ptt_stop; /* Handle for event that stops ptt tone. */
204-
HANDLE ptt_close; /* Handle for event that closes ptt. */
208+
HANDLE ptt_start; /* Handle for event that starts ptt tone. */
209+
HANDLE ptt_stop; /* Handle for event that stops ptt tone. */
210+
HANDLE ptt_close; /* Handle for event that closes ptt. */
205211
#else
206-
212+
pthread_mutex_t ptt_mutex; /* Mutex for controlling ptt tone state. */
213+
pthread_cond_t ptt_condition; /* Condition for controlling ptt tone state. */
214+
ptt_audio_state_t ptt_state; /* State of ptt tone. */
207215
#endif
208216

209217
#ifdef USE_HAMLIB

audio_ptt.c

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -91,67 +91,64 @@ static void * ptt_thread (void *arg)
9191

9292
err = snd_pcm_open(&handle, save_audio_config_p->adev[a].adevice_out, SND_PCM_STREAM_PLAYBACK, 0);
9393
if (err == 0) {
94-
snd_pcm_sframes_t frames;
9594
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
9695

9796
err = snd_pcm_set_params(handle, format, SND_PCM_ACCESS_RW_INTERLEAVED,
9897
save_audio_config_p->adev[a].num_channels,
9998
save_audio_config_p->adev[a].samples_per_sec, 1, 500000);
10099
if (err == 0) {
101-
short* pnData;
100+
short* pnData;
102101
short sample;
103-
int nSamples = save_audio_config_p->adev[a].samples_per_sec / 10;
102+
int nSamples = save_audio_config_p->adev[a].samples_per_sec / 5;
104103
int nBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof(short);
105104
int i;
105+
int j;
106106

107107
pnData = (short*)malloc (nBufferLength);
108108

109-
if (save_audio_config_p->adev[a].num_channels == 1) {
110-
for (i = 0; i < nSamples; i++) {
111-
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
112-
pnData[i] = sample;
109+
for (i = 0; i < nSamples; i++) {
110+
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
111+
112+
for (j = 0; j < save_audio_config_p->adev[a].num_channels; j++) {
113+
if (channel == ADEVFIRSTCHAN( a ) + j) {
114+
pnData[i*save_audio_config_p->adev[a].num_channels + j] = sample;
115+
} else {
116+
pnData[i*save_audio_config_p->adev[a].num_channels + j] = 0;
117+
}
113118
}
114119
}
115-
else {
116-
for (i = 0; i < nSamples; i++) {
117-
sample = (short)( (double)SHRT_MAX * sin( ( (double)i * freq / (double)save_audio_config_p->adev[a].samples_per_sec ) * 2.0 * M_PI ) );
118-
if (channel == ADEVFIRSTCHAN( a )) {
119-
120-
// Stereo, left channel.
121-
122-
pnData[i*2 + 0] = sample;
123-
pnData[i*2 + 1] = 0;
124-
}
125-
else {
126-
127-
// Stereo, right channel.
128-
129-
pnData[i*2 + 0] = 0;
130-
pnData[i*2 + 1] = sample;
131-
}
132-
}
133-
}
134-
135-
//
136-
// ptt_set on
137-
//
138-
139-
for (i=0; i<50; i++) {
140-
frames = snd_pcm_writei(handle, pnData, nSamples);
141-
}
142-
143-
//
144-
// ptt_set off
145-
//
146-
147-
//
148-
// close
149-
//
120+
121+
while (1) {
122+
pthread_mutex_lock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
123+
ptt_audio_state_t ptt_state = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_state;
124+
pthread_mutex_unlock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
125+
126+
if (ptt_state == PTT_AUDIO_STATE_STOP) {
127+
snd_pcm_drop (handle);
128+
129+
pthread_mutex_lock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
130+
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);
131+
ptt_state = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_state;
132+
pthread_mutex_unlock (&save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_mutex);
133+
134+
if (ptt_state == PTT_AUDIO_STATE_START) {
135+
snd_pcm_prepare (handle);
136+
}
137+
}
138+
139+
if (ptt_state == PTT_AUDIO_STATE_START) {
140+
snd_pcm_writei (handle, pnData, nSamples);
141+
}
142+
else if (ptt_state == PTT_AUDIO_STATE_CLOSE) {
143+
snd_pcm_drop (handle);
144+
145+
break;
146+
}
147+
}
150148

151149
free (pnData);
152150
}
153-
154-
snd_pcm_close(handle);
151+
snd_pcm_close (handle);
155152
}
156153
#else
157154
int oss_audio_device_fd;
@@ -165,3 +162,4 @@ static void * ptt_thread (void *arg)
165162
}
166163

167164
#endif
165+

audio_ptt_win.c

Lines changed: 97 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -64,126 +64,110 @@ static unsigned __stdcall ptt_thread ( void *arg );
6464

6565
HANDLE start_ptt_thread (struct audio_s *pa , int ch)
6666
{
67-
save_audio_config_p = pa;
67+
save_audio_config_p = pa;
6868

69-
return (HANDLE)_beginthreadex (NULL, 0, ptt_thread, (void*)(long)ch, 0, NULL);
69+
return (HANDLE)_beginthreadex (NULL, 0, ptt_thread, (void*)(long)ch, 0, NULL);
7070
}
7171

7272
unsigned __stdcall ptt_thread (void *arg)
7373
{
74-
WAVEFORMATEX wf;
75-
HWAVEOUT hWaveOut;
76-
int ch = (int)(long)arg; // channel number.
77-
int channel = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_channel;
78-
int freq = save_audio_config_p->achan[channel].octrl[OCTYPE_PTT].ptt_frequency;
79-
int a = ACHAN2ADEV( channel );
80-
int err;
81-
82-
if( save_audio_config_p->adev[a].defined ) {
83-
wf.wFormatTag = WAVE_FORMAT_PCM;
84-
wf.nChannels = save_audio_config_p->adev[a].num_channels;
85-
wf.nSamplesPerSec = save_audio_config_p->adev[a].samples_per_sec;
86-
wf.wBitsPerSample = save_audio_config_p->adev[a].bits_per_sample;
87-
wf.nBlockAlign = ( wf.wBitsPerSample / 8 ) * wf.nChannels;
88-
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
89-
wf.cbSize = 0;
90-
91-
/*
92-
* Open the audio output device.
93-
* Soundcard is only possibility at this time.
94-
*/
95-
96-
err = waveOutOpen ( &hWaveOut, atoi( save_audio_config_p->adev[a].adevice_out ), &wf, (DWORD_PTR)NULL, 0, CALLBACK_NULL );
97-
if( err == MMSYSERR_NOERROR ) {
98-
WAVEHDR waveHeader;
99-
short* pnData;
100-
short sample;
101-
int nSamples = save_audio_config_p->adev[a].samples_per_sec / freq;
102-
int i;
103-
104-
waveHeader.dwBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof( short );
105-
waveHeader.lpData = malloc( waveHeader.dwBufferLength );
106-
waveHeader.dwUser = 0;
107-
waveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
108-
waveHeader.dwLoops = 0xFFFF;
109-
110-
pnData = (short*)waveHeader.lpData;
111-
112-
if( save_audio_config_p->adev[a].num_channels == 1 ) {
113-
for( i = 0; i < nSamples; i++ ) {
114-
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
115-
pnData[i] = sample;
116-
}
117-
}
118-
else {
119-
for( i = 0; i < nSamples; i++ ) {
120-
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
121-
if( channel == ADEVFIRSTCHAN( a ) ) {
122-
123-
// Stereo, left channel.
124-
125-
pnData[i*2 + 0] = sample;
126-
pnData[i*2 + 1] = 0;
127-
}
128-
else {
129-
130-
// Stereo, right channel.
131-
132-
pnData[i*2 + 0] = 0;
133-
pnData[i*2 + 1] = sample;
134-
}
135-
}
136-
}
137-
138-
err = waveOutPrepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
139-
if( err == MMSYSERR_NOERROR ) {
140-
HANDLE handles[3];
141-
DWORD dwWait;
142-
143-
handles[0] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_start;
144-
handles[1] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_stop;
145-
handles[2] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_close;
146-
147-
while( 1 )
148-
{
149-
dwWait = WaitForMultipleObjects ( 3, handles, FALSE, INFINITE );
150-
151-
if( dwWait == WAIT_OBJECT_0 + 0 )
152-
{
153-
//
154-
// ptt_set on
155-
//
156-
157-
waveOutWrite ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
158-
}
159-
else if( dwWait == WAIT_OBJECT_0 + 1 )
160-
{
161-
//
162-
// ptt_set off
163-
//
164-
165-
waveOutReset ( hWaveOut );
166-
}
167-
else if( dwWait == WAIT_OBJECT_0 + 2 )
168-
{
169-
//
170-
// close
171-
//
172-
173-
waveOutReset ( hWaveOut );
174-
waveOutUnprepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
175-
176-
break;
177-
}
178-
}
179-
}
180-
181-
waveOutClose ( hWaveOut );
182-
183-
free( waveHeader.lpData );
74+
WAVEFORMATEX wf;
75+
HWAVEOUT hWaveOut;
76+
int ch = (int)(long)arg; // channel number.
77+
int channel = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_channel;
78+
int freq = save_audio_config_p->achan[channel].octrl[OCTYPE_PTT].ptt_frequency;
79+
int a = ACHAN2ADEV( channel );
80+
int err;
81+
82+
if (save_audio_config_p->adev[a].defined) {
83+
wf.wFormatTag = WAVE_FORMAT_PCM;
84+
wf.nChannels = save_audio_config_p->adev[a].num_channels;
85+
wf.nSamplesPerSec = save_audio_config_p->adev[a].samples_per_sec;
86+
wf.wBitsPerSample = save_audio_config_p->adev[a].bits_per_sample;
87+
wf.nBlockAlign = ( wf.wBitsPerSample / 8 ) * wf.nChannels;
88+
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
89+
wf.cbSize = 0;
90+
91+
/*
92+
* Open the audio output device.
93+
* Soundcard is only possibility at this time.
94+
*/
95+
96+
err = waveOutOpen ( &hWaveOut, atoi( save_audio_config_p->adev[a].adevice_out ), &wf, (DWORD_PTR)NULL, 0, CALLBACK_NULL );
97+
if (err == MMSYSERR_NOERROR) {
98+
WAVEHDR waveHeader;
99+
short* pnData;
100+
short sample;
101+
int nSamples = save_audio_config_p->adev[a].samples_per_sec / freq;
102+
int i;
103+
int j;
104+
105+
waveHeader.dwBufferLength = save_audio_config_p->adev[a].num_channels * nSamples * sizeof( short );
106+
waveHeader.lpData = malloc( waveHeader.dwBufferLength );
107+
waveHeader.dwUser = 0;
108+
waveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
109+
waveHeader.dwLoops = 0xFFFF;
110+
111+
pnData = (short*)waveHeader.lpData;
112+
113+
for (i = 0; i < nSamples; i++) {
114+
sample = (short)( (double)SHRT_MAX * sin( ( (double)i / (double)nSamples ) * 2.0 * M_PI ) );
115+
116+
for (j = 0; j < save_audio_config_p->adev[a].num_channels; j++) {
117+
if (channel == ADEVFIRSTCHAN( a ) + j) {
118+
pnData[i*save_audio_config_p->adev[a].num_channels + j] = sample;
119+
} else {
120+
pnData[i*save_audio_config_p->adev[a].num_channels + j] = 0;
121+
}
184122
}
123+
}
124+
125+
err = waveOutPrepareHeader (hWaveOut, &waveHeader, sizeof( WAVEHDR ));
126+
if (err == MMSYSERR_NOERROR) {
127+
HANDLE handles[3];
128+
DWORD dwWait;
129+
130+
handles[0] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_start;
131+
handles[1] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_stop;
132+
handles[2] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_close;
133+
134+
while (1)
135+
{
136+
dwWait = WaitForMultipleObjects (3, handles, FALSE, INFINITE);
137+
138+
if (dwWait == WAIT_OBJECT_0 + 0) {
139+
//
140+
// ptt_set on
141+
//
142+
143+
waveOutWrite ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
144+
}
145+
else if (dwWait == WAIT_OBJECT_0 + 1) {
146+
//
147+
// ptt_set off
148+
//
149+
150+
waveOutReset ( hWaveOut );
151+
}
152+
else if( dwWait == WAIT_OBJECT_0 + 2 ) {
153+
//
154+
// close
155+
//
156+
157+
waveOutReset ( hWaveOut );
158+
waveOutUnprepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
159+
160+
break;
161+
}
162+
}
163+
}
164+
165+
waveOutClose ( hWaveOut );
166+
167+
free( waveHeader.lpData );
185168
}
169+
}
186170

187-
return 0;
171+
return 0;
188172
}
189173
#endif

config.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
673673
p_audio_config->achan[channel].octrl[ot].ptt_stop = NULL;
674674
p_audio_config->achan[channel].octrl[ot].ptt_close = NULL;
675675
#else
676+
p_audio_config->achan[channel].octrl[ot].ptt_state = PTT_AUDIO_STATE_STOP;
676677
#endif
677678
}
678679

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

0 commit comments

Comments
 (0)