1 // ----------------------------------------------------------------------------
2 //
3 //	sound.cxx
4 //
5 // Copyright (C) 2006-2013
6 //			Dave Freese, W1HKJ
7 //
8 // Copyright (C) 2007-2010
9 //			Stelios Bounanos, M0GLD
10 //
11 // This file is part of fldigi.
12 //
13 // Fldigi is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // Fldigi is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
25 // ----------------------------------------------------------------------------
26 
27 #include <config.h>
28 
29 #include <string>
30 #include <vector>
31 #include <map>
32 #include <sstream>
33 #include <algorithm>
34 #include <iterator>
35 
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cerrno>
39 #include <unistd.h>
40 
41 #include <fcntl.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <semaphore.h>
45 #include <limits.h>
46 
47 #if USE_OSS
48 #  include <sys/ioctl.h>
49 #  if defined(__OpenBSD__)
50 #   include <soundcard.h>
51 #  else
52 #   include <sys/soundcard.h>
53 #  endif
54 #endif
55 #include <math.h>
56 
57 #if HAVE_DLOPEN
58 #  include <dlfcn.h>
59 #endif
60 
61 #include "gettext.h"
62 #include "sound.h"
63 #include "configuration.h"
64 #include "status.h"
65 #include "fileselect.h"
66 #include "trx.h"
67 #include "fl_digi.h"
68 #include "threads.h"
69 #include "timeops.h"
70 #include "ringbuffer.h"
71 #include "debug.h"
72 #include "qrunner.h"
73 #include "icons.h"
74 #include "macros.h"
75 #include "util.h"
76 
77 #include "estrings.h"
78 
79 #include "dr_mp3.h"
80 
81 #define SND_BUF_LEN	 65536
82 #define SND_RW_LEN	(8 * SND_BUF_LEN)
83 
84 #define SNDFILE_CHANNELS 2
85 
86 int sndfile_samplerate[7] = {8000, 11025, 16000, 22050, 24000, 44100, 48000};
87 
88 using namespace std;
89 
90 LOG_FILE_SOURCE(debug::LOG_AUDIO);
91 
92 namespace SND_SUPPORT {
format_supported(int format)93 	bool format_supported(int format) {
94 		SF_INFO info = {
95 			0,
96 			sndfile_samplerate[progdefaults.wavSampleRate],
97 			progdefaults.record_both_channels ? 2 : 1,
98 			format, 0, 0 };
99 		SNDFILE* sndf = sf_open("temp.audio", SFM_WRITE, &info);
100 		sf_close(sndf);
101 		remove("temp.audio");
102 		if (sndf) return true;
103 		return false;
104 	}
105 
get_file_params(std::string def_fname,std::string & fname,int & format,bool check)106 	void get_file_params(std::string def_fname, std::string &fname, int &format, bool check) {
107 		bool isplayback = (def_fname.find("playback") != std::string::npos);
108 		std::string filters;
109 		if (isplayback)
110 			filters = "Audio format\t*.{mp3,wav}\n";
111 		else
112 			filters = "Audio format\t*.wav\n";
113 		format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
114 		int fsel = 0;
115 		const char *fn = 0;
116 		if (isplayback)
117 			fn = FSEL::select(_("Audio file"), filters.c_str(), def_fname.c_str(), &fsel);
118 		else
119 			fn = FSEL::saveas(_("Audio file"), filters.c_str(), def_fname.c_str(), &fsel);
120 		if (!fn || !*fn) {
121 			fname = "";
122 			return;
123 		}
124 		fname = fn;
125 
126 		if (!isplayback && (fname.find(".wav") == std::string::npos))
127 			fname.append(".wav");
128 
129 		if (check) {
130 			FILE *f = fopen(fname.c_str(), "r");
131 			if (f) {
132 				fclose(f);
133 				int ans = fl_choice("Replace %s?", "Yes", "No", 0, fname.c_str());
134 				if ( ans == 1) fname = "";
135 			}
136 		}
137 	}
138 
tag_file(SNDFILE * sndfile,const char * title)139 	void tag_file(SNDFILE *sndfile, const char *title) {
140 		int err;
141 		if ((err = sf_set_string(sndfile, SF_STR_TITLE, title)) != 0) {
142 			LOG_VERBOSE("sf_set_string STR_TITLE: %s", sf_error_number(err));
143 			return;
144 		}
145 		sf_set_string(sndfile, SF_STR_COPYRIGHT, progdefaults.myName.c_str());
146 		sf_set_string(sndfile, SF_STR_SOFTWARE, PACKAGE_NAME "-" PACKAGE_VERSION);
147 		sf_set_string(sndfile, SF_STR_ARTIST, progdefaults.myCall.c_str());
148 		char s[64];
149 		snprintf(s, sizeof(s), "%s freq=%s",
150 			active_modem->get_mode_name(), inpFreq->value());
151 		sf_set_string(sndfile, SF_STR_COMMENT, s);
152 		time_t t = time(0);
153 		struct tm zt;
154 		(void)gmtime_r(&t, &zt);
155 		if (strftime(s, sizeof(s), "%Y-%m-%dT%H:%M:%Sz", &zt) > 0)
156 			sf_set_string(sndfile, SF_STR_DATE, s);
157 	}
158 
159 };
160 
SoundBase()161 SoundBase::SoundBase()
162 		: sample_frequency(0),
163 	  txppm(progdefaults.TX_corr), rxppm(progdefaults.RX_corr),
164 		  tx_src_state(0), rx_src_state(0),
165 		  wrt_buffer(new double[SND_BUF_LEN]),
166 		  ofCapture(0), ifPlayback(0), ofGenerate(0)
167 {
168 	memset(wrt_buffer, 0, SND_BUF_LEN * sizeof(*wrt_buffer));
169 
170 	int err;
171 	writ_src_data_left = new SRC_DATA;
172 	writ_src_data_right = new SRC_DATA;
173 	play_src_data = new SRC_DATA;
174 
175 	writ_src_state_left = src_new(progdefaults.sample_converter, 1, &err);
176 	if (writ_src_state_left == 0)
177 		throw SndException(src_strerror(err));
178 
179 	writ_src_state_right = src_new(progdefaults.sample_converter, 1, &err);
180 	if (writ_src_state_right == 0)
181 		throw SndException(src_strerror(err));
182 
183 	play_src_state = src_new(progdefaults.sample_converter, 1, &err);
184 	if (play_src_state == 0)
185 		throw SndException(src_strerror(err));
186 
187 	if (play_src_state == 0)
188 		throw SndException(src_strerror(err));
189 
190 	src_write_buffer_left = new float [SND_RW_LEN];
191 	if (!src_write_buffer_left)
192 		throw SndException(src_strerror(err));
193 
194 	src_write_buffer_right = new float [SND_RW_LEN];
195 	if (!src_write_buffer_right)
196 		throw SndException(src_strerror(err));
197 
198 	src_rd_inp_buffer = new float [SND_RW_LEN];
199 	if (!src_rd_inp_buffer)
200 		throw SndException(src_strerror(err));
201 
202 	src_rd_out_buffer = new float [SND_RW_LEN];
203 	if (!src_rd_out_buffer)
204 		throw SndException(src_strerror(err));
205 
206 	modem_wr_sr = modem_play_sr = 0;
207 	out_pointer = src_rd_out_buffer;
208 }
209 
~SoundBase()210 SoundBase::~SoundBase()
211 {
212 	delete [] wrt_buffer;
213 
214 	if (ofGenerate)
215 		sf_close(ofGenerate);
216 	if (ofCapture)
217 		sf_close(ofCapture);
218 	if (ifPlayback)
219 		sf_close(ifPlayback);
220 	delete writ_src_data_left;
221 	delete writ_src_data_right;
222 	delete play_src_data;
223 	delete [] src_write_buffer_left;
224 	delete [] src_write_buffer_right;
225 	delete [] src_rd_inp_buffer;
226 	delete [] src_rd_out_buffer;
227 }
228 
stopCapture()229 void SoundBase::stopCapture()
230 {
231 	if (ofCapture) {
232 		int err;
233 		if ((err = sf_close(ofCapture)) != 0)
234 			LOG_ERROR("sf_close error: %s", sf_error_number(err));
235 		ofCapture = 0;
236 	}
237 }
238 
startCapture(std::string fname,int format)239 int SoundBase::startCapture(std::string fname, int format)
240 {
241 	// frames (ignored), freq, channels, format, sections (ignored), seekable (ignored)
242 	SF_INFO info = { 0, sndfile_samplerate[progdefaults.wavSampleRate],
243 		progdefaults.record_both_channels ? 2 : 1,
244 //		SNDFILE_CHANNELS,
245 		format, 0, 0 };
246 	if ((ofCapture = sf_open(fname.c_str(), SFM_WRITE, &info)) == NULL) {
247 		LOG_ERROR("Could not write %s:%s", fname.c_str(), sf_strerror(NULL) );
248 		return 0;
249 	}
250 	if (sf_command(ofCapture, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) != SF_TRUE)
251 		LOG_ERROR("ofCapture update header command failed: %s", sf_strerror(ofCapture));
252 
253 	SND_SUPPORT::tag_file(ofCapture, "Captured audio");
254 
255 	return 1;
256 }
257 
stopGenerate()258 void SoundBase::stopGenerate()
259 {
260 	if (ofGenerate) {
261 		int err;
262 		if ((err = sf_close(ofGenerate)) != 0)
263 			LOG_ERROR("sf_close error: %s", sf_error_number(err));
264 		ofGenerate = 0;
265 	}
266 }
267 
268 //int SoundBase::startGenerate(bool val, std::string fname, int format)
startGenerate(std::string fname,int format)269 int SoundBase::startGenerate(std::string fname, int format)
270 {
271 	SF_INFO info = { 0, sndfile_samplerate[progdefaults.wavSampleRate],
272 		progdefaults.record_both_channels ? 2 : 1,
273 //		SNDFILE_CHANNELS,
274 		format, 0, 0 };
275 	if ((ofGenerate = sf_open(fname.c_str(), SFM_WRITE, &info)) == NULL) {
276 		LOG_ERROR("Could not write %s", fname.c_str());
277 		return 0;
278 	}
279 	if (sf_command(ofGenerate, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) != SF_TRUE)
280 		LOG_ERROR("ofGenerate update header command failed: %s", sf_strerror(ofGenerate));
281 
282 	SND_SUPPORT::tag_file(ofGenerate, "Generated audio");
283 
284 	modem_wr_sr = sample_frequency;
285 
286 	writ_src_data_left->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
287 	src_set_ratio(writ_src_state_left, writ_src_data_left->src_ratio);
288 
289 	writ_src_data_right->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
290 	src_set_ratio(writ_src_state_right, writ_src_data_right->src_ratio);
291 
292 	return 1;
293 }
294 
stopPlayback()295 void SoundBase::stopPlayback()
296 {
297 	if (ifPlayback) {
298 		int err;
299 		if ((err = sf_close(ifPlayback)) != 0)
300 			LOG_ERROR("sf_close error: %s", sf_error_number(err));
301 		ifPlayback = 0;
302 	}
303 	progdefaults.loop_playback = false;
304 }
305 
startPlayback(std::string fname,int format)306 int SoundBase::startPlayback(std::string fname, int format)
307 {
308 	play_info.frames = 0;
309 	play_info.samplerate = 0;
310 	play_info.channels = 0;
311 	play_info.format = 0;
312 	play_info.sections = 0;
313 	play_info.seekable = 0;
314 
315 	if ((ifPlayback = sf_open(fname.c_str(), SFM_READ, &play_info)) == NULL) {
316 		LOG_ERROR("Could not open %s:%s", fname.c_str(), sf_strerror(NULL) );
317 		return 1;
318 	}
319 
320 LOG_VERBOSE
321 ("wav file stats:\n\
322 frames     : %d\n\
323 samplerate : %d\n\
324 channels   : %d\n\
325 format     : %d\n\
326 sections   : %d\n\
327 seekable   : %d",
328 static_cast<unsigned int>(play_info.frames),
329 play_info.samplerate,
330 play_info.channels,
331 play_info.format,
332 play_info.sections,
333 play_info.seekable);
334 
335 	modem_play_sr = sample_frequency;
336 	play_src_data->src_ratio = 1.0 * modem_play_sr / play_info.samplerate;
337 	src_set_ratio(play_src_state, play_src_data->src_ratio);
338 
339 	LOG_VERBOSE("src ratio %f", play_src_data->src_ratio);
340 
341 	new_playback = true;
342 
343 	return 0;
344 }
345 
346 // ---------------------------------------------------------------------
347 // read_file
348 //    can be simplified from the equivalent read audio stream
349 //   source sr is arbitrary, requested is either 8000 or 11025 depending
350 // on the modem in use
351 // read from file and resample until a "count" number of converted samples
352 // is available, or until at the end of the input file
353 // ---------------------------------------------------------------------
354 extern int fmt_auto_record;
355 
read_file(SNDFILE * file,float * buf,size_t count)356 sf_count_t SoundBase::read_file(SNDFILE* file, float* buf, size_t count)
357 {
358 	sf_count_t r = 0, rd_count = 0;
359 	int err = 0;
360 
361 	if (new_playback || modem_play_sr != sample_frequency) {
362 		modem_play_sr = sample_frequency;
363 		play_src_data->src_ratio = 1.0 * modem_play_sr / play_info.samplerate;
364 		src_set_ratio(play_src_state, play_src_data->src_ratio);
365 		LOG_VERBOSE("src ratio %f", play_src_data->src_ratio);
366 		new_playback = true;
367 	}
368 	if (new_playback) {
369 		fmt_auto_record = 1;
370 	}
371 
372 #define RDBLKSIZE 1024
373 	float rdbuf[2 * RDBLKSIZE];
374 	int ch = play_info.channels;
375 	while ( static_cast<size_t>(out_pointer - src_rd_out_buffer) < count) {
376 		memset(src_rd_inp_buffer, 0, RDBLKSIZE * sizeof(float));
377 		if (new_playback) {
378 			new_playback = false;
379 			rd_count = RDBLKSIZE;
380 		}
381 		else {
382 			memset(rdbuf, 0, 2 * RDBLKSIZE * sizeof(float));
383 			rd_count = sf_readf_float(file, rdbuf, RDBLKSIZE);
384 			if (!rd_count) break;
385 			for (int i = 0; i < rd_count; i++)
386 				src_rd_inp_buffer[i] = rdbuf[i * ch];
387 		}
388 
389 		play_src_data->data_in = src_rd_inp_buffer;
390 		play_src_data->input_frames = rd_count;
391 		play_src_data->data_out = out_pointer;
392 		play_src_data->output_frames = SND_RW_LEN - (out_pointer - src_rd_out_buffer);
393 		play_src_data->end_of_input = 0;
394 
395 		if ((err = src_process(play_src_state, play_src_data)) != 0)
396 			throw SndException(src_strerror(err));
397 
398 		out_pointer += play_src_data->output_frames_gen;
399 
400 	}
401 
402 	if ( static_cast<size_t>(out_pointer - src_rd_out_buffer) >= count) {
403 		memcpy(buf, src_rd_out_buffer, count * sizeof(float));
404 		memmove(src_rd_out_buffer, src_rd_out_buffer + count, (SND_RW_LEN - count) * sizeof(float));
405 		out_pointer -= count;
406 		r = count;
407 	}
408 
409 	if (r == 0) {
410 		src_reset (play_src_state);
411 		out_pointer = src_rd_out_buffer;
412 		if (!progdefaults.loop_playback) {
413 			stopPlayback();
414 			bHighSpeed = false;
415 			REQ(reset_mnuPlayback);
416 		} else {
417 			memset(buf, count, sizeof(*buf));
418 			sf_seek(file, 0, SEEK_SET);
419 		}
420 	}
421 	return r;
422 }
423 
424 //----------------------------------------------------------------------
425 // Audio
426 // Adds ability to transmit an audio file using new macro tag:
427 //   <AUDIO:path-filename>
428 //   macro editor opens an OS select file dialog when the tag is
429 //   selected from the pick list.
430 //   suggested use:
431 //     <MODEM:NULL><TX>
432 //     <AUDIO:path-filename-1>
433 //     <AUDIO:path-filename-2>
434 //     <RX><@MODEM:BPSK31>
435 //   or modem type of choice
436 //   Audio file may be either wav or mp3 format, either mono or stereo
437 //   any sample rate
438 //   Returning to Rx stops current and any pending audio playback.  Post
439 //   Tx macro tags are then executed.
440 //   T/R button or Escape key will abort the playback.
441 // Please use responsibly - know and understand your license limitations
442 // for transmitting audio files, especially music and/or copyrighted
443 // material.
444 //----------------------------------------------------------------------
AudioMP3(std::string fname)445 int SoundBase::AudioMP3(std::string fname)
446 {
447 	drmp3_config config;
448 	drmp3_uint64 frame_count;
449 
450 	float* mp3_buffer =  drmp3_open_file_and_read_f32(
451 						fname.c_str(), &config, &frame_count );
452 
453 	if (!mp3_buffer) {
454 		LOG_ERROR("File must be mp3 float format");
455 		return 0;
456 	}
457 
458 	LOG_INFO("\n\
459 MP3 parameters\n\
460       channels: %d\n\
461    sample rate: %d\n\
462    frame count: %ld\n",
463        config.outputChannels,
464        config.outputSampleRate,
465        long(frame_count));
466 
467 	float *buffer = new float[2 * frame_count];
468 	if (!buffer) {
469 		LOG_ERROR("Could not allocate audio buffer");
470 		drmp3_free(mp3_buffer);
471 		return 0;
472 	}
473 	if (config.outputChannels == 2) {
474 		float maxval = 1.0;
475 		for (unsigned int n = 0; n < frame_count; n++) {
476 			buffer[2 * n] = mp3_buffer[2 * n] + mp3_buffer[2 * n + 1];
477 			buffer[2 * n + 1] = 0;
478 			if (fabs(buffer[2 * n]) > maxval) maxval = fabs(buffer[ 2 * n]);
479 		}
480 		for (unsigned int n = 0; n < frame_count; n++)
481 			buffer[2 * n] /= maxval;
482 	} else {
483 		for (unsigned int n = frame_count - 1; n >= 0; n--) {
484 			buffer[2 * n] = mp3_buffer[n];
485 			buffer[2 * n + 1] = 0;
486 		}
487 	}
488 	drmp3_free(mp3_buffer);
489 
490 	double save_sample_rate = req_sample_rate;
491 	req_sample_rate = config.outputSampleRate;
492 
493 	unsigned int n = 0;
494 	int incr = SCBLOCKSIZE;
495 	while (n < frame_count) {
496 		if (active_modem->get_stopflag())  {
497 			Rx_queue_execute();
498 			break;
499 		}
500 		if (n + incr < frame_count)
501 			resample_write(&buffer[n*2], incr);
502 		else
503 			resample_write(&buffer[n*2], frame_count - n);
504 		n += incr;
505 	}
506 
507 	delete [] buffer;
508 	req_sample_rate = save_sample_rate;
509 	return n;
510 
511 }
512 
AudioWAV(std::string fname)513 int SoundBase::AudioWAV(std::string fname)
514 {
515 	SNDFILE *playback;
516 	play_info.frames = 0;
517 	play_info.samplerate = 0;
518 	play_info.channels = 0;
519 	play_info.format = 0;
520 	play_info.sections = 0;
521 	play_info.seekable = 0;
522 
523 	if ((playback = sf_open(fname.c_str(), SFM_READ, &play_info)) == NULL) {
524 		LOG_ERROR("Could not open %s", fname.c_str());
525 		return 0;
526 	}
527 	LOG_INFO("\
528 \nAudio file: %s\
529 \nframes:     %ld\
530 \nsamplerate: %d\
531 \nchannels:   %d",
532 fname.c_str(), (long)play_info.frames, play_info.samplerate, play_info.channels);
533 
534 	int ch = play_info.channels;
535 
536 	if (ch > 2) return 0;
537 
538 	int fsize = play_info.frames * 2;
539 
540 	float *buffer = new float[fsize];
541 	if (!buffer)
542 		return 0;
543 	memset(buffer, 0, fsize * sizeof(*buffer));
544 
545 	int ret = sf_readf_float( playback, buffer, play_info.frames);
546 	if (!ret) {
547 		sf_close(playback);
548 		delete [] buffer;
549 		return 0;
550 	}
551 
552 	double save_sample_rate = req_sample_rate;
553 	req_sample_rate = play_info.samplerate;
554 	if (ch == 1) {
555 		for (long int n = play_info.frames - 1; n >= 0; n--) {
556 			buffer[2 * n] = buffer[n];
557 			buffer[2 * n + 1] = 0;
558 		}
559 	} else {
560 		float maxval = 1.0;
561 		for (long int n = play_info.frames - 1; n >= 0; n--) {
562 			buffer[2 * n] = buffer[2 * n] + buffer[2 * n + 1];
563 			buffer[2 * n + 1] = 0;
564 			if (fabs(buffer[2*n] > maxval)) maxval = fabs(buffer[2*n]);
565 		}
566 		for (long int n = 0; n < play_info.frames; n++)
567 			buffer[2*n] /= maxval;
568 	}
569 
570 	unsigned int n = 0;
571 	int incr = SCBLOCKSIZE;
572 	while (n < play_info.frames) {
573 		if (active_modem->get_stopflag())  {
574 			Rx_queue_execute();
575 			break;
576 		}
577 		if (n + incr < play_info.frames)
578 			resample_write(&buffer[n*2], incr);
579 		else
580 			resample_write(&buffer[n*2], play_info.frames - n);
581 		n += incr;
582 	}
583 
584 	sf_close(playback);
585 	delete [] buffer;
586 	req_sample_rate = save_sample_rate;
587 	return play_info.frames;
588 }
589 
Audio(std::string fname)590 int SoundBase::Audio(std::string fname)
591 {
592 	if (fname.empty())
593 		return 0;
594 	if ((fname.find("mp3") != std::string::npos) ||
595 		(fname.find("MP3") != std::string::npos ))
596 		return AudioMP3(fname);
597 	else
598 		return AudioWAV(fname);
599 }
600 // ---------------------------------------------------------------------
601 // write_file
602 // All sound buffer data is resampled to a specified sample rate
603 //    progdefaults.wavSampleRate
604 // resultant data (left channel only) is written to a wav file
605 //----------------------------------------------------------------------
write_file(SNDFILE * file,float * bufleft,float * bufright,size_t count)606 void SoundBase::write_file(SNDFILE* file, float* bufleft, float* bufright, size_t count)
607 {
608 	bool must_delete = false;
609 	if (bufright == NULL || !progdefaults.record_both_channels) {
610 		bufright = new float[count];
611 		memset(bufright, 0, count * sizeof(float));
612 		must_delete = true;
613 	}
614 
615 	int err;
616 	size_t output_size = count;
617 	float *bufl = bufleft;
618 	float *bufr = bufright;
619 
620 	if (modem_wr_sr != sample_frequency) {
621 		modem_wr_sr = sample_frequency;
622 		writ_src_data_left->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
623 		writ_src_data_left->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
624 		src_set_ratio(writ_src_state_left, writ_src_data_left->src_ratio);
625 
626 		writ_src_data_right->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
627 		writ_src_data_right->src_ratio = 1.0 * sndfile_samplerate[progdefaults.wavSampleRate] / modem_wr_sr;
628 		src_set_ratio(writ_src_state_right, writ_src_data_right->src_ratio);
629 	}
630 	writ_src_data_left->data_in = bufleft;
631 	writ_src_data_left->input_frames = count;
632 	writ_src_data_left->data_out = src_write_buffer_left;
633 	writ_src_data_left->output_frames = SND_RW_LEN;
634 	writ_src_data_left->end_of_input = 0;
635 
636 	writ_src_data_right->data_in = bufright;
637 	writ_src_data_right->input_frames = count;
638 	writ_src_data_right->data_out = src_write_buffer_right;
639 	writ_src_data_right->output_frames = SND_RW_LEN;
640 	writ_src_data_right->end_of_input = 0;
641 
642 	if ((err = src_process(writ_src_state_left, writ_src_data_left)) != 0) {
643 		if (must_delete) {
644 			delete [] bufright;
645 		}
646 		throw SndException(src_strerror(err));
647 	}
648 	if ((err = src_process(writ_src_state_right, writ_src_data_right)) != 0) {
649 		if (must_delete) {
650 			delete [] bufright;
651 		}
652 		throw SndException(src_strerror(err));
653 	}
654 
655 	output_size = writ_src_data_left->output_frames_gen;
656 	bufl = src_write_buffer_left;
657 	bufr = src_write_buffer_right;
658 
659 	if (output_size) {
660 		if (progdefaults.record_both_channels) {
661 			float buffer[2*output_size];
662 			memset(buffer, 0, 2 * output_size * sizeof(float));
663 			for (size_t i = 0; i < output_size; i++) {
664 				buffer[2*i] = bufl[i];//0.9 * bufl[i];
665 				buffer[2*i + 1] = bufr[i];//0.9 * bufr[i];
666 			}
667 			sf_write_float(file, buffer, 2 * output_size);
668 		} else {
669 			sf_write_float(file, bufl, output_size);
670 		}
671 	}
672 
673 		if (must_delete) {
674 			delete [] bufright;
675 		}
676 
677 	return;
678 }
679 
write_file(SNDFILE * file,double * bufleft,double * bufright,size_t count)680 void SoundBase::write_file(SNDFILE* file, double* bufleft, double *bufright, size_t count)
681 {
682 	float *outbuf_l = new float[count];
683 	float *outbuf_r = new float[count];
684 
685 	for (size_t i = 0; i < count; i++) {
686 		outbuf_l[i] = bufleft[i];
687 		outbuf_r[i] = (bufright ? bufright[i] : 0);
688 	}
689 	write_file(file, outbuf_l, outbuf_r, count);
690 	delete [] outbuf_l;
691 	delete [] outbuf_r;
692 	return;
693 }
694 
695 #if USE_OSS
696 
697 #define MAXSC 32767.0f
698 #define maxsc 32000.0
699 
SoundOSS(const char * dev)700 SoundOSS::SoundOSS(const char *dev ) {
701 	device		  = dev;
702 	cbuff		   = 0;
703 	try {
704 		Open(O_RDONLY);
705 		getVersion();
706 		getCapabilities();
707 		getFormats();
708 		Close();
709 	}
710 	catch (const SndException& e) {
711 		LOG_ERROR("device %s error: %s", device.c_str(), e.what());
712 	}
713 
714 	snd_buffer = new float [2 * SND_BUF_LEN];
715 	src_buffer = new float [2 * SND_BUF_LEN];
716 	cbuff	 = new unsigned char [4 * SND_BUF_LEN];
717 
718 	memset(snd_buffer, 0, 2 * SND_BUF_LEN * sizeof(*snd_buffer));
719 	memset(src_buffer, 0, 2 * SND_BUF_LEN * sizeof(*src_buffer));
720 	memset(cbuff,	 0, 4 * SND_BUF_LEN * sizeof(*cbuff));
721 
722 	tx_src_data = new SRC_DATA;
723 	rx_src_data = new SRC_DATA;
724 
725 	int err;
726 	rx_src_state = src_new(progdefaults.sample_converter, 2, &err);
727 	if (rx_src_state == 0)
728 		throw SndException(src_strerror(err));
729 
730 	tx_src_state = src_new(progdefaults.sample_converter, 2, &err);
731 	if (tx_src_state == 0)
732 		throw SndException(src_strerror(err));
733 
734 	rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6);
735 	src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6));
736 
737 	tx_src_data->src_ratio = 1.0 + txppm/1e6;
738 	src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
739 }
740 
~SoundOSS()741 SoundOSS::~SoundOSS()
742 {
743 	Close();
744 
745 	delete tx_src_data;
746 	delete rx_src_data;
747 
748 	if (rx_src_state)
749 		src_delete(rx_src_state);
750 	if (tx_src_state)
751 		src_delete(tx_src_state);
752 
753 	delete [] snd_buffer;
754 	delete [] src_buffer;
755 	delete [] cbuff;
756 }
757 
setfragsize()758 void SoundOSS::setfragsize()
759 {
760 	int sndparam;
761 // Try to get ~100ms worth of samples per fragment
762 	sndparam = (int)log2(sample_frequency * 0.1);
763 // double since we are using 16 bit samples
764 	sndparam += 1;
765 // Unlimited amount of buffers for RX, four for TX
766 	if (mode == O_RDONLY)
767 		sndparam |= 0x7FFF0000;
768 	else
769 		sndparam |= 0x00040000;
770 
771 	if (ioctl(device_fd, SNDCTL_DSP_SETFRAGMENT, &sndparam) < 0)
772 		throw SndException(errno);
773 }
774 
Open(int md,int freq)775 int SoundOSS::Open(int md, int freq)
776 {
777 	Close();
778 
779 	mode = md;
780 	try {
781 		int oflags = md;
782 #	   ifdef HAVE_O_CLOEXEC
783 			oflags = oflags | O_CLOEXEC;
784 #	   endif
785 
786 #ifdef __FreeBSD__
787 /*
788  * In FreeBSD sound devices e.g. /dev/dsp0.0 can only be open once
789  * whereas /dev/dsp0 can be open multiple times. fldigi tries
790  * to open /dev/dsp0.0 multiple times which fails. Also see man 4 sound.
791  * "For specific sound card access, please instead use /dev/dsp or /dev/dsp%d"
792  * This is a hack. XXX - db VA3DB
793  */
794 		char *fixed_name;
795 		char *p;
796 		/* Look for a '.' if found, blow it away */
797 		fixed_name = strdup(device.c_str());
798 		p = strchr(fixed_name, '.');
799 		if(p != NULL)
800 			*p = '\0';
801 		device_fd = fl_open(fixed_name, oflags, 0);
802 		free(fixed_name);
803 #else
804 		device_fd = fl_open(device.c_str(), oflags, 0);
805 #endif
806 		if (device_fd == -1)
807 			throw SndException(errno);
808 
809 		Format(AFMT_S16_LE);	// default: 16 bit little endian
810 		Channels(2);			//		2 channels
811 		Frequency(freq);
812 		setfragsize();
813 	}
814 	catch (...) {
815 		throw;
816 	}
817 	return 0;
818 }
819 
Close(unsigned dir)820 void SoundOSS::Close(unsigned dir)
821 {
822 	if (device_fd == -1)
823 		return;
824 	close(device_fd);
825 	device_fd = -1;
826 }
827 
getVersion()828 void SoundOSS::getVersion()
829 {
830 	version = 0;
831 
832 	if (ioctl(device_fd, OSS_GETVERSION, &version) == -1) {
833 		version = -1;
834 		throw SndException("OSS Version");
835 	}
836 }
837 
getCapabilities()838 void SoundOSS::getCapabilities()
839 {
840 	capability_mask = 0;
841 	if (ioctl(device_fd, SNDCTL_DSP_GETCAPS, &capability_mask) == -1) {
842 		capability_mask = 0;
843 		throw SndException("OSS capabilities");
844 	}
845 }
846 
getFormats()847 void SoundOSS::getFormats()
848 {
849 	format_mask = 0;
850 	if (ioctl(device_fd, SNDCTL_DSP_GETFMTS, &format_mask) == -1) {
851 		format_mask = 0;
852 		throw SndException("OSS formats");
853 	}
854 }
855 
Format(int format)856 void SoundOSS::Format(int format)
857 {
858 	play_format = format;
859 	if (ioctl(device_fd, SNDCTL_DSP_SETFMT, &play_format) == -1) {
860 		device_fd = -1;
861 		formatok = false;
862 		throw SndException("Unsupported snd card format");
863 	}
864 	formatok = true;
865 }
866 
Channels(int nuchannels)867 void SoundOSS::Channels(int nuchannels)
868 {
869 	channels = nuchannels;
870 	if (ioctl(device_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
871 		device_fd = -1;
872 		throw "Snd card channel request failed";
873 	}
874 }
875 
Frequency(int frequency)876 void SoundOSS::Frequency(int frequency)
877 {
878 	sample_frequency = frequency;
879 	if (ioctl(device_fd, SNDCTL_DSP_SPEED, &sample_frequency) == -1) {
880 		device_fd = -1;
881 		throw SndException("Cannot set frequency");
882 	}
883 }
884 
BufferSize(int seconds)885 int SoundOSS::BufferSize( int seconds )
886 {
887 	int bytes_per_channel = 0;
888 	switch (play_format) {
889 		case AFMT_MU_LAW:
890 		case AFMT_A_LAW:
891 		case AFMT_IMA_ADPCM:
892 			bytes_per_channel = 0; /* format not supported by this program */
893 			break;
894 		case AFMT_S16_BE:
895 		case AFMT_U16_LE:
896 		case AFMT_U16_BE:
897 		case AFMT_MPEG:
898 		case AFMT_S16_LE:
899 			bytes_per_channel = 2;
900 			break;
901 		case AFMT_U8:
902 		case AFMT_S8:
903 			bytes_per_channel = 1;
904 			break;
905 	}
906   return seconds * sample_frequency * bytes_per_channel * channels;
907 }
908 
wait_till_finished()909 bool SoundOSS::wait_till_finished()
910 {
911 	if (ioctl(device_fd, SNDCTL_DSP_POST, (void*)1) == -1 )
912 		return false;
913 	if (ioctl(device_fd, SNDCTL_DSP_SYNC, (void*)0) == -1)
914 		return false; /* format (or ioctl()) not supported by device */
915 	return true; /* all sound has been played */
916 }
917 
reset_device()918 bool SoundOSS::reset_device()
919 {
920 	if (ioctl(device_fd, SNDCTL_DSP_RESET, 0) == -1) {
921 		device_fd = -1;
922 		return false; /* format (or ioctl()) not supported by device */
923 	}
924 	return 1; /* sounddevice has been reset */
925 }
926 
Read(float * buffer,size_t buffersize)927 size_t SoundOSS::Read(float *buffer, size_t buffersize)
928 {
929 	short int *ibuff = (short int *)cbuff;
930 	int numread;
931 
932 	numread = read(device_fd, cbuff, buffersize * 4);
933 	if (numread == -1)
934 		throw SndException(errno);
935 
936 	for (size_t i = 0; i < buffersize * 2; i++)
937 		src_buffer[i] = ibuff[i] / MAXSC;
938 
939 	for (size_t i = 0; i < buffersize; i++)
940 		buffer[i] = src_buffer[2*i + (progdefaults.ReverseRxAudio ? 1 : 0)];
941 
942 	if (ofCapture)
943 		write_file(ofCapture, buffer, NULL, buffersize);
944 	if (ifPlayback) {
945 		read_file(ifPlayback, buffer, buffersize);
946 		return buffersize;
947 	}
948 
949 	if (rxppm != progdefaults.RX_corr) {
950 		rxppm = progdefaults.RX_corr;
951 		rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6);
952 		src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6));
953 	}
954 
955 	if (rxppm == 0)
956 		return buffersize;
957 
958 // process using samplerate library
959 
960 	rx_src_data->data_in = src_buffer;
961 	rx_src_data->input_frames = buffersize;
962 	rx_src_data->data_out = snd_buffer;
963 	rx_src_data->output_frames = SND_BUF_LEN;
964 	rx_src_data->end_of_input = 0;
965 
966 	if ((numread = src_process(rx_src_state, rx_src_data)) != 0)
967 		throw SndException(src_strerror(numread));
968 
969 	numread = rx_src_data->output_frames_gen;
970 
971 	for (int i = 0; i < numread; i++)
972 		buffer[i] = snd_buffer[2*i + (progdefaults.sig_on_right_channel ? 1 : 0)];
973 
974 	return numread;
975 
976 }
977 
Write(double * buf,size_t count)978 size_t SoundOSS::Write(double *buf, size_t count)
979 {
980 	int retval;
981 	short int *wbuff;
982 	unsigned char *p;
983 
984 	if (ofGenerate)
985 		write_file(ofGenerate, buf, NULL, count);
986 
987 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
988 		return count;
989 	}
990 
991 
992 	if (txppm != progdefaults.TX_corr) {
993 		txppm = progdefaults.TX_corr;
994 		tx_src_data->src_ratio = 1.0 + txppm/1e6;
995 		src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
996 	}
997 
998 	if (txppm == 0) {
999 		wbuff = new short int[2*count];
1000 		p = (unsigned char *)wbuff;
1001 		for (size_t i = 0; i < count; i++) {
1002 			wbuff[2*i] = wbuff[2*i+1] = (short int)(buf[i] * maxsc);
1003 		}
1004 		count *= sizeof(short int);
1005 		retval = write(device_fd, p, 2*count);
1006 		delete [] wbuff;
1007 		if (retval == -1)
1008 			throw SndException(errno);
1009 	}
1010 	else {
1011 		float *inbuf;
1012 		inbuf = new float[2*count];
1013 		size_t bufsize;
1014 		for (size_t i = 0; i < count; i++)
1015 			inbuf[2*i] = inbuf[2*i+1] = buf[i];
1016 		tx_src_data->data_in = inbuf;
1017 		tx_src_data->input_frames = count;
1018 		tx_src_data->data_out = src_buffer;
1019 		tx_src_data->output_frames = SND_BUF_LEN;
1020 		tx_src_data->end_of_input = 0;
1021 
1022 		retval = src_process(tx_src_state, tx_src_data);
1023 		delete [] inbuf;
1024 		if (retval != 0)
1025 			throw SndException(src_strerror(retval));
1026 
1027 		bufsize = tx_src_data->output_frames_gen;
1028 		wbuff = new short int[2*bufsize];
1029 		p = (unsigned char *)wbuff;
1030 
1031 		for (size_t i = 0; i < 2*bufsize; i++)
1032 			wbuff[i] = (short int)(src_buffer[i] * maxsc);
1033 		int num2write = bufsize * 2 * sizeof(short int);
1034 
1035 		retval = write(device_fd, p, num2write);
1036 		delete [] wbuff;
1037 		if (retval != num2write)
1038 			throw SndException(errno);
1039 		retval = count;
1040 	}
1041 
1042 	return retval;
1043 }
1044 
resample_write(float * buf,size_t count)1045 size_t SoundOSS::resample_write(float *buf, size_t count)
1046 {
1047 	double *samples = new double[2*count];
1048 	Write(samples, count);
1049 	delete [] samples;
1050 	return 0;
1051 }
1052 
Write_stereo(double * bufleft,double * bufright,size_t count)1053 size_t SoundOSS::Write_stereo(double *bufleft, double *bufright, size_t count)
1054 {
1055 	int retval;
1056 	short int *wbuff;
1057 	unsigned char *p;
1058 
1059 	if (ofGenerate)
1060 		write_file(ofGenerate, bufleft, bufright, count);
1061 
1062 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
1063 		return count;
1064 	}
1065 
1066 	if (txppm != progdefaults.TX_corr) {
1067 		txppm = progdefaults.TX_corr;
1068 		tx_src_data->src_ratio = 1.0 + txppm/1e6;
1069 		src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
1070 	}
1071 
1072 	if (txppm == 0) {
1073 		wbuff = new short int[2*count];
1074 		p = (unsigned char *)wbuff;
1075 		for (size_t i = 0; i < count; i++) {
1076 			if (progdefaults.ReverseAudio) {
1077 				wbuff[2*i+1] = (short int)(bufleft[i] * maxsc);
1078 				wbuff[2*i] = (short int)(bufright[i] * maxsc);
1079 			} else {
1080 				wbuff[2*i] = (short int)(bufleft[i] * maxsc);
1081 				wbuff[2*i+1] = (short int)(bufright[i] * maxsc);
1082 			}
1083 		}
1084 		count *= sizeof(short int);
1085 		retval = write(device_fd, p, 2*count);
1086 		delete [] wbuff;
1087 		if (retval == -1)
1088 			throw SndException(errno);
1089 	}
1090 	else {
1091 		float *inbuf;
1092 		inbuf = new float[2*count];
1093 		size_t bufsize;
1094 		for (size_t i = 0; i < count; i++) {
1095 			if (progdefaults.ReverseAudio) {
1096 				inbuf[2*i+1] = bufleft[i];
1097 				inbuf[2*i] = bufright[i];
1098 			} else {
1099 				inbuf[2*i] = bufleft[i];
1100 				inbuf[2*i+1] = bufright[i];
1101 			}
1102 		}
1103 		tx_src_data->data_in = inbuf;
1104 		tx_src_data->input_frames = count;
1105 		tx_src_data->data_out = src_buffer;
1106 		tx_src_data->output_frames = SND_BUF_LEN;
1107 		tx_src_data->end_of_input = 0;
1108 
1109 		retval = src_process(tx_src_state, tx_src_data);
1110 		delete [] inbuf;
1111 		if (retval != 0)
1112 			throw SndException(src_strerror(retval));
1113 
1114 		bufsize = tx_src_data->output_frames_gen;
1115 		wbuff = new short int[2*bufsize];
1116 		p = (unsigned char *)wbuff;
1117 
1118 		for (size_t i = 0; i < 2*bufsize; i++)
1119 			wbuff[i] = (short int)(src_buffer[i] * maxsc);
1120 
1121 		int num2write = bufsize * 2 * sizeof(short int);
1122 		retval = write(device_fd, p, num2write);
1123 		delete [] wbuff;
1124 		if (retval != num2write)
1125 			throw SndException(errno);
1126 		retval = count;
1127 	}
1128 
1129 	return retval;
1130 }
1131 #endif // USE_OSS
1132 
1133 
1134 #if USE_PORTAUDIO
1135 
1136 bool SoundPort::pa_init = false;
1137 std::vector<const PaDeviceInfo*> SoundPort::devs;
1138 
1139 static ostringstream device_text[2];
1140 static pthread_mutex_t device_mutex = PTHREAD_MUTEX_INITIALIZER;
1141 
1142 map<string, vector<double> > supported_rates[2];
1143 
initialize(void)1144 void SoundPort::initialize(void)
1145 {
1146 	if (pa_init)
1147 		return;
1148 
1149 	init_hostapi_ext();
1150 
1151 	int err;
1152 	if ((err = Pa_Initialize()) != paNoError) {
1153 #if __WIN32__
1154 		LOG_PERROR(win_error_string(err).c_str());
1155 #else
1156 		LOG_PERROR("Portaudio Initialize error");
1157 #endif
1158 		throw SndPortException(err);
1159 	}
1160 	pa_init = true;
1161 
1162 	PaDeviceIndex ndev;
1163 	if ((ndev = Pa_GetDeviceCount()) < 0) {
1164 		LOG_PERROR("Portaudio device count error");
1165 		throw SndPortException(ndev);
1166 	}
1167 	if (ndev == 0) {
1168 		LOG_PERROR("Portaudio, no audio devices");
1169 		throw SndException(ENODEV, "No available audio devices");
1170 	}
1171 
1172 	devs.reserve(ndev);
1173 	for (PaDeviceIndex i = 0; i < ndev; i++)
1174 		devs.push_back(Pa_GetDeviceInfo(i));
1175 }
terminate(void)1176 void SoundPort::terminate(void)
1177 {
1178 	if (!pa_init)
1179 		return;
1180 	static_cast<void>(Pa_Terminate());
1181 	pa_init = false;
1182 	devs.clear();
1183 	supported_rates[0].clear();
1184 	supported_rates[1].clear();
1185 }
devices(void)1186 const std::vector<const PaDeviceInfo*>& SoundPort::devices(void)
1187 {
1188 		return devs;
1189 }
devices_info(string & in,string & out)1190 void SoundPort::devices_info(string& in, string& out)
1191 {
1192 	guard_lock devices_lock(&device_mutex);
1193 	in = device_text[0].str();
1194 	out = device_text[1].str();
1195 }
1196 
get_supported_rates(const string & name,unsigned dir)1197 const vector<double>& SoundPort::get_supported_rates(const string& name, unsigned dir)
1198 {
1199 	return supported_rates[dir][name];
1200 }
1201 
1202 
SoundPort(const char * in_dev,const char * out_dev)1203 SoundPort::SoundPort(const char *in_dev, const char *out_dev)
1204 {
1205 	req_sample_rate = 0;
1206 
1207 	sd[0].device = in_dev;
1208 	sd[0].params.channelCount = 2; // init_stream can change this to 0 or 1
1209 	sd[0].stream = 0;
1210 	sd[0].frames_per_buffer = paFramesPerBufferUnspecified;
1211 	sd[0].dev_sample_rate = 0;
1212 	sd[0].state = spa_continue;
1213 	sd[0].rb = 0;
1214 	sd[0].advance = 0;
1215 
1216 	sd[1].device = out_dev;
1217 	sd[1].params.channelCount = 2;
1218 	sd[1].stream = 0;
1219 	sd[1].frames_per_buffer = paFramesPerBufferUnspecified;
1220 	sd[1].dev_sample_rate = 0;
1221 	sd[1].state = spa_continue;
1222 	sd[1].rb = 0;
1223 	sd[1].advance = 0;
1224 
1225 	sem_t** sems[] = { &sd[0].rwsem, &sd[1].rwsem };
1226 #if USE_NAMED_SEMAPHORES
1227 	char sname[32];
1228 #endif
1229 	for (size_t i = 0; i < sizeof(sems)/sizeof(*sems); i++) {
1230 #if USE_NAMED_SEMAPHORES
1231 		unsigned int un = i;
1232 		snprintf(sname, sizeof(sname), "%u-%u-%s", un, getpid(), PACKAGE_TARNAME);
1233 		if ((*sems[i] = sem_open(sname, O_CREAT | O_EXCL, 0600, 0)) == (sem_t*)SEM_FAILED) {
1234 			pa_perror(errno, sname);
1235 			throw SndException(errno);
1236 		}
1237 #  if HAVE_SEM_UNLINK
1238 		if (sem_unlink(sname) == -1) {
1239 			pa_perror(errno, sname);
1240 			throw SndException(errno);
1241 		}
1242 #  endif
1243 #else
1244 		*sems[i] = new sem_t;
1245 		if (sem_init(*sems[i], 0, 0) == -1) {
1246 #if __WIN32__
1247 		int err = GetLastError();
1248 		LOG_PERROR(win_error_string(err).c_str());
1249 #endif
1250 			pa_perror(errno, "sem_init error");
1251 			throw SndException(errno);
1252 		}
1253 #endif // USE_NAMED_SEMAPHORES
1254 	}
1255 
1256 	for (size_t i = 0; i < 2; i++) {
1257 		sd[i].cmutex = new pthread_mutex_t;
1258 		pthread_mutex_init(sd[i].cmutex, NULL);
1259 		sd[i].ccond = new pthread_cond_t;
1260 		pthread_cond_init(sd[i].ccond, NULL);
1261 	}
1262 
1263 	tx_src_data = new SRC_DATA;
1264 	src_buffer = new float[sd[1].params.channelCount * SND_BUF_LEN];
1265 	fbuf = new float[2 * SND_BUF_LEN];
1266 
1267 	memset(src_buffer, 0, sd[1].params.channelCount * SND_BUF_LEN * sizeof(*src_buffer));
1268 	memset(fbuf, 0, 2 * SND_BUF_LEN * sizeof(*fbuf));
1269 }
1270 
~SoundPort()1271 SoundPort::~SoundPort()
1272 {
1273 	Close();
1274 
1275 	sem_t* sems[] = { sd[0].rwsem, sd[1].rwsem };
1276 	for (size_t i = 0; i < sizeof(sems)/sizeof(*sems); i++) {
1277 #if USE_NAMED_SEMAPHORES
1278 		if (sem_close(sems[i]) == -1)
1279 			LOG_PERROR("sem_close");
1280 #else
1281 		if (sem_destroy(sems[i]) == -1)
1282 			LOG_PERROR("sem_destroy");
1283 		delete sems[i];
1284 #endif
1285 	}
1286 
1287 	for (size_t i = 0; i < 2; i++) {
1288 		if (pthread_mutex_destroy(sd[i].cmutex) == -1) {
1289 			pa_perror(errno, "pthread mutex destroy");
1290 			terminate(); //throw SndException(errno);
1291 		}
1292 		delete sd[i].cmutex;
1293 		if (pthread_cond_destroy(sd[i].ccond) == -1) {
1294 			pa_perror(errno, "pthread cond destroy");
1295 			terminate(); //throw SndException(errno);
1296 		}
1297 		delete sd[i].ccond;
1298 	}
1299 
1300 	delete sd[0].rb;
1301 	delete sd[1].rb;
1302 
1303 	if (rx_src_state)
1304 		src_delete(rx_src_state);
1305 	if (tx_src_state)
1306 		src_delete(tx_src_state);
1307 
1308 	delete tx_src_data;
1309 	delete [] src_buffer;
1310 	delete [] fbuf;
1311 }
1312 
Open(int mode,int freq)1313 int SoundPort::Open(int mode, int freq)
1314 {
1315 	int old_sample_rate = (int)req_sample_rate;
1316 	req_sample_rate = sample_frequency = freq;
1317 
1318 	// do we need to (re)initialise the streams?
1319 	int ret = 1;
1320 	int sr[2] = { progdefaults.in_sample_rate, progdefaults.out_sample_rate };
1321 
1322 	// initialize stream if it is a JACK device, regardless of mode
1323 	device_iterator idev;
1324 	int device_type = 0;
1325 	if (mode == O_WRONLY && (idev = name_to_device(sd[0].device, 0)) != devs.end() &&
1326 		(device_type = Pa_GetHostApiInfo((*idev)->hostApi)->type) == paJACK)
1327 		mode = O_RDWR;
1328 	if (mode == O_RDONLY && (idev = name_to_device(sd[1].device, 1)) != devs.end() &&
1329 		(device_type = Pa_GetHostApiInfo((*idev)->hostApi)->type) == paJACK)
1330 		mode = O_RDWR;
1331 
1332 	size_t start = (mode == O_RDONLY || mode == O_RDWR) ? 0 : 1,
1333 		end = (mode == O_WRONLY || mode == O_RDWR) ? 1 : 0;
1334 	for (size_t i = start; i <= end; i++) {
1335 		if ( !(stream_active(i) && (Pa_GetHostApiInfo((*sd[i].idev)->hostApi)->type == paJACK ||
1336 						old_sample_rate == freq ||
1337 						sr[i] != SAMPLE_RATE_AUTO)) ) {
1338 			Close(i);
1339 			try {
1340 				init_stream(i);
1341 			} catch (const SndException& e) {
1342 				LOG_ERROR("SndException: %s", e.what());
1343 				throw SndPortException(paDeviceUnavailable);
1344 			}
1345 			src_data_reset(i);
1346 
1347 			// reset the semaphore
1348 			while (sem_trywait(sd[i].rwsem) == 0);
1349 			if (errno && errno != EAGAIN) {
1350 				pa_perror(errno, "open failed");
1351 				throw SndException(errno);
1352 			}
1353 			start_stream(i);
1354 
1355 			ret = 0;
1356 		}
1357 		else {
1358 			pause_stream(i);
1359 			src_data_reset(i);
1360 			sd[i].state = spa_continue;
1361 		}
1362 	}
1363 
1364 	static char pa_open_str[500];
1365 	snprintf(pa_open_str, sizeof(pa_open_str),
1366 "\
1367 Port Audio open mode = %s\n\
1368 device type = %s\n\
1369 device name = %s\n\
1370 # input channels %d\n\
1371 # output channels %d",
1372 		mode == O_WRONLY ? "Write" :
1373 		mode == O_RDONLY ? "Read" :
1374 		mode == O_RDWR ? "Read/Write" : "unknown",
1375 		device_type == 0 ? "paInDevelopment" :
1376 		device_type == 1 ? "paDirectSound" :
1377 		device_type == 2 ? "paMME" :
1378 		device_type == 3 ? "paASIO" :
1379 		device_type == 4 ? "paSoundManager" :
1380 		device_type == 5 ? "paCoreAudio" :
1381 		device_type == 7 ? "paOSS" :
1382 		device_type == 8 ? "paALSA" :
1383 		device_type == 9 ? "paAL" :
1384 		device_type == 10 ? "paBeOS" :
1385 		device_type == 11 ? "paWDMKS" :
1386 		device_type == 12 ? "paJACK" :
1387 		device_type == 13 ? "paWASAPI" :
1388 		device_type == 14 ? "paAudioScienceHPI" : "unknown",
1389 		mode == O_WRONLY ? sd[1].device.c_str() :
1390 		mode == O_RDONLY ? sd[0].device.c_str() : "unknown",
1391 		sd[0].params.channelCount,
1392 		sd[1].params.channelCount );
1393 	LOG_INFO( "%s", pa_open_str);
1394 
1395 	return ret;
1396 }
1397 
pause_stream(unsigned dir)1398 void SoundPort::pause_stream(unsigned dir)
1399 {
1400 	if (sd[dir].stream == 0 || !stream_active(dir))
1401 		return;
1402 
1403 	pthread_mutex_lock(sd[dir].cmutex);
1404 		sd[dir].state = spa_pause;
1405 	if (pthread_cond_timedwait_rel(sd[dir].ccond, sd[dir].cmutex, 5.0) == -1 && errno == ETIMEDOUT)
1406 		LOG_ERROR("stream %u wedged", dir);
1407 	pthread_mutex_unlock(sd[dir].cmutex);
1408 }
1409 
Close(unsigned dir)1410 void SoundPort::Close(unsigned dir)
1411 {
1412 	unsigned start, end;
1413 	if (dir == UINT_MAX) {
1414 		start = 0;
1415 		end = 1;
1416 	}
1417 	else
1418 		start = end = dir;
1419 
1420 	for (unsigned i = start; i <= end; i++) {
1421 		if (!stream_active(i))
1422 			continue;
1423 
1424 		pthread_mutex_lock(sd[i].cmutex);
1425 		sd[i].state = spa_complete;
1426 		// first wait for buffers to be drained and for the
1427 		// stop callback to signal us that the stream has
1428 		// been stopped
1429 		if (pthread_cond_timedwait_rel(sd[i].ccond, sd[i].cmutex, 5.0) == -1 &&
1430 			errno == ETIMEDOUT)
1431 			LOG_ERROR("stream %u wedged", i);
1432 		pthread_mutex_unlock(sd[i].cmutex);
1433 		sd[i].state = spa_continue;
1434 
1435 		int err;
1436 		if ((err = Pa_CloseStream(sd[i].stream)) != paNoError)
1437 			pa_perror(err, "Pa_CloseStream");
1438 
1439 		sd[i].stream = 0;
1440 	}
1441 }
1442 
Abort(unsigned dir)1443 void SoundPort::Abort(unsigned dir)
1444 {
1445 	unsigned start, end;
1446 	if (dir == UINT_MAX) {
1447 		start = 0;
1448 		end = 1;
1449 	}
1450 	else
1451 		start = end = dir;
1452 
1453 	int err;
1454 	for (unsigned i = start; i <= end; i++) {
1455 		if (!stream_active(i))
1456 			continue;
1457 		if ((err = Pa_AbortStream(sd[i].stream)) != paNoError)
1458 #if __WIN32__
1459 		LOG_PERROR(win_error_string(err).c_str());
1460 #endif
1461 			pa_perror(err, "Pa_AbortStream");
1462 		sd[i].stream = 0;
1463 	}
1464 }
1465 
1466 
1467 #define WAIT_FOR_COND(cond, s, t) \
1468 do { \
1469 	while (!(cond)) { \
1470 		if (sem_timedwait_rel(s, t) == -1) { \
1471 			if (errno == ETIMEDOUT) { \
1472 				timeout = true;	 \
1473 				break; \
1474 			} else if (errno == EINTR) { \
1475 				continue; \
1476 			} \
1477 			LOG_PERROR("sem_timedwait"); \
1478 			throw SndException(errno); \
1479 		} \
1480 	} \
1481 } while (0)
1482 
1483 
Read(float * buf,size_t count)1484 size_t SoundPort::Read(float *buf, size_t count)
1485 {
1486 	if (ifPlayback) {
1487 		read_file(ifPlayback, buf, count);
1488 		if (!ofCapture) {
1489 			if (!bHighSpeed)
1490 				MilliSleep((long)ceil((1e3 * count) / req_sample_rate));
1491 			return count;
1492 		}
1493 	}
1494 
1495 	if (rxppm != progdefaults.RX_corr)
1496 		rxppm = progdefaults.RX_corr;
1497 
1498 	sd[0].src_ratio = req_sample_rate / (sd[0].dev_sample_rate * (1.0 + rxppm / 1e6));
1499 	src_set_ratio(rx_src_state, sd[0].src_ratio);
1500 
1501 	size_t maxframes = (size_t)floor(sd[0].rb->length() * sd[0].src_ratio / sd[0].params.channelCount);
1502 
1503 	if (unlikely(count > maxframes)) {
1504 		size_t n = 0;
1505 #define PA_TIMEOUT_TRIES 10
1506 		int pa_timeout = PA_TIMEOUT_TRIES;
1507 // possible to lock up in this while block if the Read(...) fails
1508 		while (count > maxframes) {
1509 			n += Read(buf, maxframes);
1510 			buf += maxframes * sd[0].params.channelCount;
1511 			count -= n;//maxframes;
1512 			pa_timeout--;
1513 			if (pa_timeout == 0) {
1514 #if __WIN32__
1515 				int err = GetLastError();
1516 				LOG_PERROR(win_error_string(err).c_str());
1517 #endif
1518 				pa_perror(1, "Portaudio read error #1");
1519 				throw SndException("Portaudio read error 1");
1520 			}
1521 		}
1522 		if (count > 0)
1523 			n += Read(buf, count);
1524 		return n;
1525 	}
1526 
1527 	float* rbuf = fbuf;
1528 	if (req_sample_rate != sd[0].dev_sample_rate || rxppm != 0) {
1529 		long r;
1530 		size_t n = 0;
1531 		sd[0].blocksize = SCBLOCKSIZE;
1532 		while (n < count) {
1533 			if  ((r = src_callback_read(rx_src_state, sd[0].src_ratio,
1534 							count - n, rbuf + n * sd[0].params.channelCount)) == 0) {
1535 				pa_perror(2, "Portaudio read error #2");
1536 				throw SndException("Portaudio read error 2");
1537 			}
1538 			n += r;
1539 		}
1540 	}
1541 	else {
1542 		bool timeout = false;
1543 		WAIT_FOR_COND( (sd[0].rb->read_space() >= count * sd[0].params.channelCount / sd[0].src_ratio), sd[0].rwsem,
1544 				   (MAX(1.0, 2 * count * sd[0].params.channelCount / sd->dev_sample_rate)) );
1545 		if (timeout) {
1546 			pa_perror(3, "Portaudio read error #3");
1547 			throw SndException("Portaudio read error 3");
1548 		}
1549 		ringbuffer<float>::vector_type vec[2];
1550 		sd[0].rb->get_rv(vec);
1551 		if (vec[0].len >= count * sd[0].params.channelCount) {
1552 			rbuf = vec[0].buf;
1553 			sd[0].advance = vec[0].len;
1554 		}
1555 		else
1556 			sd[0].rb->read(rbuf, count * sd[0].params.channelCount);
1557 	}
1558 	if (sd[0].advance) {
1559 		sd[0].rb->read_advance(sd[0].advance);
1560 		sd[0].advance = 0;
1561 	}
1562 
1563 	// transfer active input channel; left == 0, right == 1
1564 	size_t n;
1565 	for (size_t i = 0; i < count; i++) {
1566 		n = sd[0].params.channelCount * i;
1567 		if (sd[0].params.channelCount == 2)
1568 			n += progdefaults.ReverseRxAudio;
1569 		buf[i] = rbuf[n];
1570 	}
1571 
1572 	if (ofCapture)
1573 		write_file(ofCapture, buf, NULL, count);
1574 
1575 	return count;
1576 }
1577 
Write(double * buf,size_t count)1578 size_t SoundPort::Write(double *buf, size_t count)
1579 {
1580 	if (ofGenerate)
1581 		write_file(ofGenerate, buf, NULL, count);
1582 
1583 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
1584 		return count;
1585 	}
1586 
1587 // copy input to both channels if right channel enabled
1588 	for (size_t i = 0; i < count; i++)
1589 		if (progdefaults.sig_on_right_channel)
1590 			fbuf[sd[1].params.channelCount * i] = fbuf[sd[1].params.channelCount * i + 1] = buf[i];
1591 		else if (progdefaults.ReverseAudio) {
1592 				fbuf[sd[1].params.channelCount * i + 1] = buf[i];
1593 				fbuf[sd[1].params.channelCount * i] = 0;
1594 		} else {
1595 				fbuf[sd[1].params.channelCount * i] = buf[i];
1596 				fbuf[sd[1].params.channelCount * i + 1] = 0;
1597 		}
1598 
1599 	return resample_write(fbuf, count);
1600 }
1601 
Write_stereo(double * bufleft,double * bufright,size_t count)1602 size_t SoundPort::Write_stereo(double *bufleft, double *bufright, size_t count)
1603 {
1604 	if (sd[1].params.channelCount != 2)
1605 		return Write(bufleft, count);
1606 
1607 	if (ofGenerate)
1608 		write_file(ofCapture, bufleft, bufright, count);
1609 
1610 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
1611 		return count;
1612 	}
1613 
1614 // interleave into fbuf
1615 	for (size_t i = 0; i < count; i++) {
1616 		if (progdefaults.ReverseAudio) {
1617 			fbuf[sd[1].params.channelCount * i + 1] = bufleft[i];
1618 			fbuf[sd[1].params.channelCount * i] = bufright[i];
1619 		} else {
1620 			fbuf[sd[1].params.channelCount * i] = bufleft[i];
1621 			fbuf[sd[1].params.channelCount * i + 1] = bufright[i];
1622 		}
1623 	}
1624 
1625 	return resample_write(fbuf, count);
1626 }
1627 
1628 
resample_write(float * buf,size_t count)1629 size_t SoundPort::resample_write(float* buf, size_t count)
1630 {
1631 	size_t maxframes = (size_t)floor((sd[1].rb->length() / sd[1].params.channelCount) / tx_src_data->src_ratio);
1632 	maxframes /= 2; // don't fill the buffer
1633 
1634 	if (unlikely(count > maxframes)) {
1635 		size_t n = 0;
1636 #define PA_TIMEOUT_TRIES 10
1637 		int pa_timeout = PA_TIMEOUT_TRIES;
1638 // possible to lock up in this while block if the resample_write(...) fails
1639 		while (count > maxframes) {
1640 			n += resample_write(buf, maxframes);
1641 			buf += sd[1].params.channelCount * maxframes;
1642 			count -= maxframes;
1643 			pa_timeout--;
1644 			if (pa_timeout == 0) {
1645 				pa_perror(1, "Portaudio write error #1");
1646 				throw SndException("Portaudio write error 1");
1647 			}
1648 		}
1649 		if (count > 0)
1650 			n += resample_write(buf, count);
1651 		return n;
1652 	}
1653 
1654 	assert(count * sd[1].params.channelCount * tx_src_data->src_ratio <= sd[1].rb->length());
1655 
1656 	ringbuffer<float>::vector_type vec[2];
1657 	sd[1].rb->get_wv(vec);
1658 	float* wbuf = buf;
1659 	if (req_sample_rate != sd[1].dev_sample_rate || progdefaults.TX_corr != 0) {
1660 		if (vec[0].len >= sd[1].params.channelCount * (size_t)ceil(count * tx_src_data->src_ratio))
1661 			wbuf = vec[0].buf; // direct write in the rb
1662 		else
1663 			wbuf = src_buffer;
1664 
1665 		if (txppm != progdefaults.TX_corr)
1666 			txppm = progdefaults.TX_corr;
1667 
1668 		tx_src_data->src_ratio = sd[1].dev_sample_rate * (1.0 + txppm / 1e6) / req_sample_rate;
1669 		src_set_ratio(tx_src_state, tx_src_data->src_ratio);
1670 
1671 		tx_src_data->data_in = buf;
1672 		tx_src_data->input_frames = count;
1673 		tx_src_data->data_out = wbuf;
1674 		tx_src_data->output_frames = (wbuf == vec[0].buf ? vec[0].len : SND_BUF_LEN);
1675 		tx_src_data->end_of_input = 0;
1676 		int r;
1677 		if ((r = src_process(tx_src_state, tx_src_data)) != 0) {
1678 			pa_perror(2, "Portaudio write error #2");
1679 			throw SndException("Portaudio write error 2");
1680 		}
1681 		if (tx_src_data->output_frames_gen == 0) // input was too small
1682 			return count;
1683 
1684 		count = tx_src_data->output_frames_gen;
1685 		if (wbuf == vec[0].buf) { // advance write pointer and return
1686 			sd[1].rb->write_advance(sd[1].params.channelCount * count);
1687 			sem_trywait(sd[1].rwsem);
1688 			return count;
1689 		}
1690 	}
1691 
1692 	// if we didn't do a direct resample into the rb, or didn't resample at all,
1693 	// we must now copy buf into the ringbuffer, possibly waiting for space first
1694 	bool timeout = false;
1695 	WAIT_FOR_COND( (sd[1].rb->write_space() >= sd[1].params.channelCount * count), sd[1].rwsem,
1696 				   (MAX(1.0, 2 * sd[1].params.channelCount * count / sd[1].dev_sample_rate)) );
1697 	if (timeout) {
1698 		pa_perror(3, "Portaudio write error #3");
1699 		throw SndException("Portaudio write error 3");
1700 	}
1701 
1702 	sd[1].rb->write(wbuf, sd[1].params.channelCount * count);
1703 
1704 	return count;
1705 }
1706 
flush(unsigned dir)1707 void SoundPort::flush(unsigned dir)
1708 {
1709 	unsigned start, end;
1710 	if (dir == UINT_MAX) {
1711 		start = 0;
1712 		end = 1;
1713 	}
1714 	else
1715 		start = end = dir;
1716 
1717 	for (unsigned i = start; i <= end; i++) {
1718 		if (!stream_active(i))
1719 			continue;
1720 
1721 		pthread_mutex_lock(sd[i].cmutex);
1722 		sd[i].state = spa_drain;
1723 		if (pthread_cond_timedwait_rel(sd[i].ccond, sd[i].cmutex, 5.0) == -1
1724 			&& errno == ETIMEDOUT)
1725 			LOG_ERROR("stream %u wedged", i);
1726 		pthread_mutex_unlock(sd[i].cmutex);
1727 		sd[i].state = spa_continue;
1728 	}
1729 }
1730 
src_data_reset(unsigned dir)1731 void SoundPort::src_data_reset(unsigned dir)
1732 {
1733 	size_t rbsize;
1734 
1735 	int err;
1736 	if (dir == 0) {
1737 		if (rx_src_state)
1738 			src_delete(rx_src_state);
1739 		rx_src_state = src_callback_new(src_read_cb, progdefaults.sample_converter,
1740 										sd[0].params.channelCount, &err, &sd[0]);
1741 		if (!rx_src_state) {
1742 			pa_perror(err, src_strerror(err));
1743 			throw SndException(src_strerror(err));
1744 		}
1745 		sd[0].src_ratio = req_sample_rate / (sd[0].dev_sample_rate * (1.0 + rxppm / 1e6));
1746 	}
1747 	else if (dir == 1) {
1748 		if (tx_src_state)
1749 			src_delete(tx_src_state);
1750 		tx_src_state = src_new(progdefaults.sample_converter, sd[1].params.channelCount, &err);
1751 		if (!tx_src_state) {
1752 			pa_perror(err, src_strerror(err));
1753 			throw SndException(src_strerror(err));
1754 		}
1755 		tx_src_data->src_ratio = sd[1].dev_sample_rate * (1.0 + txppm / 1e6) / req_sample_rate;
1756 	}
1757 
1758 	rbsize = 2 * MAX(ceil2(
1759 					(unsigned)(2 * sd[dir].params.channelCount * SCBLOCKSIZE *
1760 					MAX(req_sample_rate, sd[dir].dev_sample_rate) /
1761 					MIN(req_sample_rate, sd[dir].dev_sample_rate))),
1762 					8192);
1763 	stringstream info;
1764 	info << "rbsize = " << rbsize;
1765 	LOG_VERBOSE("%s", info.str().c_str());
1766 	if (sd[dir].rb) delete sd[dir].rb;
1767 	sd[dir].rb = new ringbuffer<float>(rbsize);
1768 }
1769 
src_read_cb(void * arg,float ** data)1770 long SoundPort::src_read_cb(void* arg, float** data)
1771 {
1772 	struct stream_data* sd = reinterpret_cast<stream_data*>(arg);
1773 
1774 	// advance read pointer for previous read
1775 	if (sd->advance) {
1776 		sd->rb->read_advance(sd->advance);
1777 		sd->advance = 0;
1778 	}
1779 
1780 	// wait for data
1781 	bool timeout = false;
1782 	WAIT_FOR_COND( (sd->rb->read_space() >= (size_t)sd[0].params.channelCount * SCBLOCKSIZE), sd->rwsem,
1783 				   (MAX(1.0, 2 * sd[0].params.channelCount * SCBLOCKSIZE / sd->dev_sample_rate)) );
1784 	if (timeout) {
1785 		*data = 0;
1786 		return 0;
1787 	}
1788 
1789 	ringbuffer<float>::vector_type vec[2];
1790 	sd->rb->get_rv(vec);
1791 
1792 	*data = vec[0].buf;
1793 	sd->advance = vec[0].len;
1794 
1795 	return vec[0].len / sd[0].params.channelCount;
1796 }
1797 
name_to_device(std::string & name,unsigned dir)1798 SoundPort::device_iterator SoundPort::name_to_device(std::string &name, unsigned dir)
1799 {
1800 	device_iterator i;
1801 	for (i = devs.begin(); i != devs.end(); ++i)
1802 		if (name == (*i)->name && (dir ? (*i)->maxOutputChannels : (*i)->maxInputChannels))
1803 			break;
1804 	return i;
1805 }
1806 
init_stream(unsigned dir)1807 void SoundPort::init_stream(unsigned dir)
1808 {
1809 	const char* dir_str[2] = { "input", "output" };
1810 	PaDeviceIndex idx = paNoDevice;
1811 
1812 	LOG_DEBUG("looking for device \"%s\"", sd[dir].device.c_str());
1813 
1814 	if ((sd[dir].idev = name_to_device(sd[dir].device, dir)) != devs.end())
1815 		idx = sd[dir].idev - devs.begin();
1816 	if (idx == paNoDevice) { // no match
1817 		LOG_ERROR("Could not find device \"%s\", using default device", sd[dir].device.c_str());
1818 		PaDeviceIndex def = (dir == 0 ? Pa_GetDefaultInputDevice() : Pa_GetDefaultOutputDevice());
1819 		if (def == paNoDevice) {
1820 			pa_perror(paDeviceUnavailable, "Portaudio device unavailable");
1821 			throw SndPortException(paDeviceUnavailable);
1822 		}
1823 		sd[dir].idev = devs.begin() + def;
1824 		idx = def;
1825 	}
1826 	else if (sd[dir].idev == devs.end()) // if we only found a near-match point the idev iterator to it
1827 		sd[dir].idev = devs.begin() + idx;
1828 
1829 	const PaHostApiInfo* host_api = Pa_GetHostApiInfo((*sd[dir].idev)->hostApi);
1830 	int max_channels = dir ? (*sd[dir].idev)->maxOutputChannels :
1831 		(*sd[dir].idev)->maxInputChannels;
1832 	if ((host_api->type == paALSA || host_api->type == paOSS) && max_channels == 0) {
1833 		pa_perror(EBUSY, "Portaudio device busy");
1834 		throw SndException(EBUSY);
1835 	}
1836 
1837 	if (dir == 0) {
1838 		sd[0].params.device = idx;
1839 		sd[0].params.sampleFormat = paFloat32;
1840 		sd[0].params.suggestedLatency = (*sd[dir].idev)->defaultHighInputLatency;
1841 		sd[0].params.hostApiSpecificStreamInfo = NULL;
1842 		if (max_channels < 2)
1843 				sd[0].params.channelCount = max_channels;
1844 		if (max_channels == 0) {
1845 			pa_perror(EBUSY, "Portaudio device cannot open for read");
1846 			throw SndException(EBUSY);
1847 		}
1848 	}
1849 	else {
1850 		sd[1].params.device = idx;
1851 		sd[1].params.sampleFormat = paFloat32;
1852 		if (host_api->type == paMME)
1853 						sd[1].params.suggestedLatency = (*sd[dir].idev)->defaultLowOutputLatency;
1854 				else
1855 						sd[1].params.suggestedLatency = (*sd[dir].idev)->defaultHighOutputLatency;
1856 		sd[1].params.hostApiSpecificStreamInfo = NULL;
1857 		if (max_channels < 2)
1858 			sd[1].params.channelCount = max_channels;
1859 	}
1860 
1861 	const vector<double>& rates = supported_rates[dir][(*sd[dir].idev)->name];
1862 	if (rates.size() <= 1)
1863 		probe_supported_rates(sd[dir].idev);
1864 	ostringstream ss;
1865 	if (rates.size() > 1)
1866 		copy(rates.begin() + 1, rates.end(), ostream_iterator<double>(ss, " "));
1867 	else
1868 		ss << "Unknown";
1869 
1870 	{
1871 	guard_lock devices_lock(&device_mutex);
1872 
1873 	device_text[dir].str("");
1874 		device_text[dir]
1875 		<< "index: " << idx
1876 		<< "\nname: " << (*sd[dir].idev)->name
1877 		<< "\nhost API: " << host_api->name
1878 		<< "\nmax input channels: " << (*sd[dir].idev)->maxInputChannels
1879 		<< "\nmax output channels: " << (*sd[dir].idev)->maxOutputChannels
1880 		<< "\ndefault sample rate: " << (*sd[dir].idev)->defaultSampleRate
1881 		<< "\nsupported sample rates: " << ss.str()
1882 		<< boolalpha
1883 		<< "\ninput only: " << ((*sd[dir].idev)->maxOutputChannels == 0)
1884 		<< "\noutput only: " << ((*sd[dir].idev)->maxInputChannels == 0)
1885 		<< "\nfull duplex: " << full_duplex_device(*sd[dir].idev)
1886 		<< "\nsystem default input: " << (idx == Pa_GetDefaultInputDevice())
1887 		<< "\nsystem default output: " << (idx == Pa_GetDefaultOutputDevice())
1888 		<< "\nhost API default input: " << (idx == host_api->defaultInputDevice)
1889 		<< "\nhost API default output: " << (idx == host_api->defaultOutputDevice)
1890 		<< "\ndefault low input latency: " << (*sd[dir].idev)->defaultLowInputLatency
1891 		<< "\ndefault high input latency: " << (*sd[dir].idev)->defaultHighInputLatency
1892 		<< "\ndefault low output latency: " << (*sd[dir].idev)->defaultLowOutputLatency
1893 		<< "\ndefault high output latency: " << (*sd[dir].idev)->defaultHighOutputLatency
1894 		<< "\n";
1895 	}
1896 
1897 	LOG_VERBOSE("using %s (%d ch) device \"%s\":\n%s", dir_str[dir], sd[dir].params.channelCount,
1898 		sd[dir].device.c_str(), device_text[dir].str().c_str());
1899 
1900 		sd[dir].dev_sample_rate = find_srate(dir);
1901 		if (sd[dir].dev_sample_rate != req_sample_rate)
1902 		LOG_DEBUG("%s: resampling %f <=> %f", dir_str[dir],
1903 			  sd[dir].dev_sample_rate, req_sample_rate);
1904 
1905 		if (progdefaults.PortFramesPerBuffer > 0) {
1906 				sd[dir].frames_per_buffer = progdefaults.PortFramesPerBuffer;
1907 		LOG_DEBUG("%s: frames_per_buffer=%u", dir_str[dir], sd[dir].frames_per_buffer);
1908 	}
1909 }
1910 
start_stream(unsigned dir)1911 void SoundPort::start_stream(unsigned dir)
1912 {
1913 	int err;
1914 
1915 	PaStreamParameters* sp[2];
1916 	sp[dir] = &sd[dir].params;
1917 	sp[!dir] = NULL;
1918 
1919 LOG_INFO("\n\
1920 open pa stream for %s:\n\
1921   samplerate    : %.0f\n\
1922   device number : %d\n\
1923   # channels    : %d\n\
1924   latency       : %f\n\
1925   sample Format : paFloat32",
1926 (dir == 1 ? "write" : "read"),
1927 sd[dir].dev_sample_rate,
1928 sp[dir]->device,
1929 sp[dir]->channelCount,
1930 sp[dir]->suggestedLatency);
1931 
1932 	err = Pa_OpenStream(&sd[dir].stream, sp[0], sp[1],
1933 			sd[dir].dev_sample_rate, sd[dir].frames_per_buffer,
1934 			paNoFlag,
1935 			stream_process, &sd[dir]);
1936 	if (err != paNoError) {
1937 		throw SndPortException(err);
1938 	}
1939 
1940 	if ((err = Pa_SetStreamFinishedCallback(sd[dir].stream, stream_stopped)) != paNoError)
1941 		throw SndPortException(err);
1942 
1943 	if ((err = Pa_StartStream(sd[dir].stream)) != paNoError) {
1944 		pa_perror(err, "Portaudio stream start stream error");
1945 		Close();
1946 		throw SndPortException(err);
1947 	}
1948 }
1949 
1950 
stream_process(const void * in,void * out,unsigned long nframes,const PaStreamCallbackTimeInfo * time_info,PaStreamCallbackFlags flags,void * data)1951 int SoundPort::stream_process(
1952 			const void* in, void* out, unsigned long nframes,
1953 			const PaStreamCallbackTimeInfo *time_info,
1954 			PaStreamCallbackFlags flags, void* data)
1955 {
1956 	struct stream_data* sd = reinterpret_cast<struct stream_data*>(data);
1957 
1958 #ifndef NDEBUG
1959 	struct {
1960 		PaStreamCallbackFlags f;
1961 		const char* s;
1962 	} fa[] = { { paInputUnderflow, "Input underflow" },
1963 			   { paInputOverflow,  "Input overflow" },
1964 			   { paOutputUnderflow, "Output underflow" },
1965 			   { paOutputOverflow, "Output overflow" }
1966 			};
1967 	for (size_t i = 0; i < sizeof(fa)/sizeof(*fa); i++)
1968 		if (flags & fa[i].f)
1969 			LOG_DEBUG("%s", fa[i].s);
1970 #endif
1971 
1972 	if (unlikely(sd->state == spa_abort || sd->state == spa_complete)) // finished
1973 		return sd->state;
1974 
1975 	if (in) {
1976 		switch (sd->state) {
1977 			case spa_continue: // write into the rb, post rwsem if we wrote anything
1978 				if (sd->rb->write(reinterpret_cast<const float*>(in), sd->params.channelCount * nframes))
1979 					sem_post(sd->rwsem);
1980 				break;
1981 			case spa_drain: case spa_pause: // signal the cv
1982 				pthread_mutex_lock(sd->cmutex);
1983 				pthread_cond_signal(sd->ccond);
1984 				pthread_mutex_unlock(sd->cmutex);
1985 		}
1986 	}
1987 	else if (out) {
1988 		float* outf = reinterpret_cast<float*>(out);
1989 		// if we are paused just pretend that the rb was empty
1990 		size_t nread = (sd->state == spa_pause) ? 0 : sd->rb->read(outf, sd->params.channelCount * nframes);
1991 		memset(outf + nread, 0, (sd->params.channelCount * nframes - nread) * sizeof(float)); // fill rest with 0
1992 
1993 		switch (sd->state) {
1994 			case spa_continue: // post rwsem if we read anything
1995 				if (nread > 0)
1996 					sem_post(sd->rwsem);
1997 				break;
1998 			case spa_drain: // signal the cv when we have emptied the buffer
1999 				if (nread > 0)
2000 					break;
2001 			// else fall through
2002 			case spa_pause:
2003 				pthread_mutex_lock(sd->cmutex);
2004 				pthread_cond_signal(sd->ccond);
2005 				pthread_mutex_unlock(sd->cmutex);
2006 				break;
2007 		}
2008 	}
2009 
2010 	return paContinue;
2011 }
2012 
stream_stopped(void * data)2013 void SoundPort::stream_stopped(void* data)
2014 {
2015 	struct stream_data* sd = reinterpret_cast<struct stream_data*>(data);
2016 
2017 	if (sd->rb)
2018 		sd->rb->reset();
2019 	pthread_mutex_lock(sd->cmutex);
2020 	pthread_cond_signal(sd->ccond);
2021 	pthread_mutex_unlock(sd->cmutex);
2022 }
2023 
2024 
stream_active(unsigned dir)2025 bool SoundPort::stream_active(unsigned dir)
2026 {
2027 	if (!sd[dir].stream)
2028 		return false;
2029 
2030 	int err;
2031 	if ((err = Pa_IsStreamActive(sd[dir].stream)) < 0) {
2032 		pa_perror(err, "Portaudio stream active error");
2033 		throw SndPortException(err);
2034 	}
2035 	return err == 1;
2036 }
2037 
full_duplex_device(const PaDeviceInfo * dev)2038 bool SoundPort::full_duplex_device(const PaDeviceInfo* dev)
2039 {
2040 	return dev->maxInputChannels > 0 && dev->maxOutputChannels > 0;
2041 }
2042 
must_close(int dir)2043 bool SoundPort::must_close(int dir)
2044 {
2045 	return Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->type != paJACK;
2046 }
2047 
find_srate(unsigned dir)2048 double SoundPort::find_srate(unsigned dir)
2049 {
2050 	int sr = (dir == 0 ? progdefaults.in_sample_rate : progdefaults.out_sample_rate);
2051 		switch (sr) {
2052 		case SAMPLE_RATE_UNSET: case SAMPLE_RATE_AUTO:
2053 				break;
2054 		case SAMPLE_RATE_NATIVE:
2055 				return (*sd[dir].idev)->defaultSampleRate;
2056 		default:
2057 				return sr;
2058 		}
2059 
2060 	const vector<double>& rates = supported_rates[dir][(*sd[dir].idev)->name];
2061 	for (vector<double>::const_iterator i = rates.begin(); i != rates.end(); i++)
2062 		if (req_sample_rate == *i || (*sd[dir].idev)->defaultSampleRate == *i)
2063 			return *i;
2064 
2065 	pa_perror(0, "Portaudio - no supported sample rate found");
2066 	throw SndException("No supported sample rate found");
2067 }
2068 
probe_supported_rates(const device_iterator & idev)2069 void SoundPort::probe_supported_rates(const device_iterator& idev)
2070 {
2071 	PaStreamParameters params[2];
2072 	params[0].device = params[1].device = idev - devs.begin();
2073 	params[0].channelCount = 2;
2074 	params[1].channelCount = 2;
2075 	params[0].sampleFormat = params[1].sampleFormat = paFloat32;
2076 	params[0].suggestedLatency = (*idev)->defaultHighInputLatency;
2077 	params[1].suggestedLatency = (*idev)->defaultHighOutputLatency;
2078 	params[0].hostApiSpecificStreamInfo = params[1].hostApiSpecificStreamInfo = NULL;
2079 
2080 	supported_rates[0][(*idev)->name].clear();
2081 	supported_rates[1][(*idev)->name].clear();
2082 	supported_rates[0][(*idev)->name].push_back((*idev)->defaultSampleRate);
2083 	supported_rates[1][(*idev)->name].push_back((*idev)->defaultSampleRate);
2084 	extern double std_sample_rates[];
2085 	for (const double* r = std_sample_rates; *r > 0.0; r++) {
2086 		if (Pa_IsFormatSupported(&params[0], NULL, *r) == paFormatIsSupported)
2087 			supported_rates[0][(*idev)->name].push_back(*r);
2088 		if (Pa_IsFormatSupported(NULL, &params[1], *r) == paFormatIsSupported)
2089 			supported_rates[1][(*idev)->name].push_back(*r);
2090 	}
2091 }
2092 
pa_perror(int err,const char * str)2093 void SoundPort::pa_perror(int err, const char* str)
2094 {
2095 	if (str)
2096 	LOG_ERROR("%s: %s", str, Pa_GetErrorText(err));
2097 
2098 	if (err == paUnanticipatedHostError) {
2099 		const PaHostErrorInfo* hosterr = Pa_GetLastHostErrorInfo();
2100 		PaHostApiIndex i = Pa_HostApiTypeIdToHostApiIndex(hosterr->hostApiType);
2101 
2102 		if (i < 0) { // PA failed without setting its "last host error" info. Sigh...
2103 			LOG_ERROR("Host API error info not available");
2104 			if ( ((sd[0].stream && Pa_GetHostApiInfo((*sd[0].idev)->hostApi)->type == paOSS) ||
2105 				(sd[1].stream && Pa_GetHostApiInfo((*sd[1].idev)->hostApi)->type == paOSS)) &&
2106 				errno )
2107 				LOG_ERROR("Possible OSS error %d: %s", errno, strerror(errno));
2108 		}
2109 		else
2110 			LOG_ERROR("%s error %ld: %s", Pa_GetHostApiInfo(i)->name,
2111 				  hosterr->errorCode, hosterr->errorText);
2112 	}
2113 }
2114 
init_hostapi_ext(void)2115 void SoundPort::init_hostapi_ext(void)
2116 {
2117 #if HAVE_DLOPEN && !defined(__WOE32__)
2118 	void* handle = dlopen(NULL, RTLD_LAZY);
2119 	if (!handle)
2120 		return;
2121 
2122 	PaError (*set_jack_client_name)(const char*);
2123 	const char* err = dlerror();
2124 	set_jack_client_name = (PaError (*)(const char*))dlsym(handle, "PaJack_SetClientName");
2125 	if (!(err = dlerror()))
2126 		set_jack_client_name(main_window_title.c_str());
2127 #  ifndef NDEBUG
2128 		else
2129 		LOG_VERBOSE("dlsym(PaJack_SetClientName) error: %s", err);
2130 #  endif
2131 #endif
2132 }
2133 
2134 #endif // USE_PORTAUDIO
2135 
2136 
2137 #if USE_PULSEAUDIO
2138 
SoundPulse(const char * dev)2139 SoundPulse::SoundPulse(const char *dev)
2140 {
2141 	sd[0].stream = 0;
2142 	sd[0].stream_params.channels = 2;
2143 	sd[0].dir = PA_STREAM_RECORD;
2144 	sd[0].stream_params.format = PA_SAMPLE_FLOAT32LE;
2145 	sd[0].buffer_attrs.maxlength = (uint32_t)-1;
2146 	sd[0].buffer_attrs.minreq = (uint32_t)-1;
2147 	sd[0].buffer_attrs.prebuf = (uint32_t)-1;
2148 	sd[0].buffer_attrs.fragsize = SCBLOCKSIZE * sizeof(float);
2149 	sd[0].buffer_attrs.tlength = (uint32_t)-1;
2150 
2151 	sd[1].stream = 0;
2152 	sd[1].dir = PA_STREAM_PLAYBACK;
2153 	sd[1].stream_params.format = PA_SAMPLE_FLOAT32LE;
2154 	sd[1].stream_params.channels = 2;
2155 	sd[1].buffer_attrs.maxlength = (uint32_t)-1;
2156 	sd[1].buffer_attrs.minreq = (uint32_t)-1;
2157 	sd[1].buffer_attrs.prebuf = (uint32_t)-1;
2158 	sd[1].buffer_attrs.fragsize = (uint32_t)-1;
2159 	sd[1].buffer_attrs.tlength = SCBLOCKSIZE * sizeof(float);
2160 
2161 	tx_src_data = new SRC_DATA;
2162 
2163 	snd_buffer = new float[sd[0].stream_params.channels * SND_BUF_LEN];
2164 	rbuf       = new float[sd[0].stream_params.channels * SND_BUF_LEN];
2165 
2166 	src_buffer = new float[sd[1].stream_params.channels * SND_BUF_LEN];
2167 	fbuf       = new float[sd[1].stream_params.channels * SND_BUF_LEN];
2168 
2169 	memset(snd_buffer, 0, sd[0].stream_params.channels * SND_BUF_LEN * sizeof(*snd_buffer));
2170 	memset(rbuf,       0, sd[0].stream_params.channels * SND_BUF_LEN * sizeof(*rbuf));
2171 
2172 	memset(src_buffer, 0, sd[1].stream_params.channels * SND_BUF_LEN * sizeof(*src_buffer));
2173 	memset(fbuf,       0, sd[1].stream_params.channels * SND_BUF_LEN * sizeof(*fbuf));
2174 }
2175 
~SoundPulse()2176 SoundPulse::~SoundPulse()
2177 {
2178 	Close();
2179 
2180 	delete tx_src_data;
2181 	if (rx_src_state)
2182 		src_delete(rx_src_state);
2183 	if (tx_src_state)
2184 		src_delete(tx_src_state);
2185 
2186 	delete [] snd_buffer;
2187 	delete [] src_buffer;
2188 	delete [] fbuf;
2189 	delete [] rbuf;
2190 }
2191 
Open(int dir,int freq)2192 int SoundPulse::Open(int dir, int freq)
2193 {
2194 	const char* server = (progdefaults.PulseServer.length() ?
2195 				  progdefaults.PulseServer.c_str() : NULL);
2196 	char sname[32];
2197 	int err;
2198 
2199 	sample_frequency = freq;
2200 
2201 	src_data_reset(1 << O_RDONLY | 1 << O_WRONLY);
2202 	if ((unsigned)freq != sd[dir].stream_params.rate)
2203 		Close(dir);
2204 
2205 	sd[dir].stream_params.rate = freq;
2206 	snprintf(sname, sizeof(sname), "%s (%u)", (dir ? "playback" : "capture"), getpid());
2207 	setenv("PULSE_PROP_application.icon_name", PACKAGE_TARNAME, 1);
2208 	sd[dir].stream = pa_simple_new(
2209 		server,						// server address
2210 		main_window_title.c_str(),	// application name
2211 		sd[dir].dir,				// playback / record
2212 		NULL,						// device (default)
2213 		sname,						// system description
2214 		&sd[dir].stream_params,		// sample format
2215 		NULL,						// channel map (default)
2216 		&sd[dir].buffer_attrs,		// buffering attributes
2217 		&err);						// return address for error code
2218 	if (!sd[dir].stream)
2219 		throw SndPulseException(err);
2220 
2221 	return 0;
2222 }
2223 
Close(unsigned dir)2224 void SoundPulse::Close(unsigned dir)
2225 {
2226 	if (dir == 1 || dir == UINT_MAX)
2227 		flush(1);
2228 	Abort(dir);
2229 }
2230 
Abort(unsigned dir)2231 void SoundPulse::Abort(unsigned dir)
2232 {
2233 		unsigned start, end;
2234 		if (dir == UINT_MAX) {
2235 				start = 0;
2236 				end = 1;
2237 		}
2238 		else
2239 				start = end = dir;
2240 
2241 		for (unsigned i = start; i <= end; i++) {
2242 				if (sd[i].stream) {
2243 						pa_simple_free(sd[i].stream);
2244 						sd[i].stream = 0;
2245 				}
2246 		}
2247 
2248 }
2249 
flush(unsigned dir)2250 void SoundPulse::flush(unsigned dir)
2251 {
2252 	int err = PA_OK;
2253 	if ((dir == 1 || dir == UINT_MAX) && sd[1].stream) {
2254 		// wait for audio to finish playing
2255 		MilliSleep(SCBLOCKSIZE * 1000 / sd[1].stream_params.rate);
2256 		pa_simple_flush(sd[1].stream, &err);
2257 	}
2258 
2259 	if ((dir == 0 || dir == UINT_MAX) && sd[0].stream) {
2260 		// We need to flush the captured audio that PA has been
2261 		// buffering for us while we were transmitting.  We will use
2262 		// pa_simple_get_latency() which, contrary to the docs, also
2263 		// works for capture streams.  It tells us how much earlier the
2264 		// data that would be returned by pa_simple_read() was actually
2265 		// captured, and we read and discard all that data.
2266 		pa_usec_t t = pa_simple_get_latency(sd[0].stream, &err);
2267 		if (t && err == PA_OK) {
2268 			size_t bytes = pa_usec_to_bytes(t, &sd[0].stream_params);
2269 			while (bytes > SND_BUF_LEN) {
2270 				pa_simple_read(sd[0].stream, snd_buffer, SND_BUF_LEN, &err);
2271 				if (err != PA_OK)
2272 					break;
2273 				bytes -= SND_BUF_LEN;
2274 			}
2275 			if (bytes)
2276 				pa_simple_read(sd[0].stream, snd_buffer, bytes, &err);
2277 		}
2278 	}
2279 }
2280 
Write(double * buf,size_t count)2281 size_t SoundPulse::Write(double* buf, size_t count)
2282 {
2283 	if (ofGenerate)
2284 		write_file(ofGenerate, buf, NULL, count);
2285 
2286 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
2287 		return count;
2288 	}
2289 
2290 // copy input to both channels
2291 	for (size_t i = 0; i < count; i++)
2292 		if (progdefaults.sig_on_right_channel)
2293 			fbuf[sd[1].stream_params.channels * i] = fbuf[sd[1].stream_params.channels * i + 1] = buf[i];
2294 		else if (progdefaults.ReverseAudio) {
2295 			fbuf[sd[1].stream_params.channels * i + 1] = buf[i];
2296 			fbuf[sd[1].stream_params.channels * i] = 0;
2297 		} else {
2298 			fbuf[sd[1].stream_params.channels * i] = buf[i];
2299 			fbuf[sd[1].stream_params.channels * i + 1] = 0;
2300 		}
2301 
2302 	return resample_write(fbuf, count);
2303 }
2304 
Write_stereo(double * bufleft,double * bufright,size_t count)2305 size_t SoundPulse::Write_stereo(double* bufleft, double* bufright, size_t count)
2306 {
2307 	if (sd[1].stream_params.channels != 2)
2308 		return Write(bufleft, count);
2309 
2310 	if (ofGenerate)
2311 		write_file(ofGenerate, bufleft, bufright, count);
2312 
2313 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
2314 		return count;
2315 	}
2316 
2317 	for (size_t i = 0; i < count; i++) {
2318 		if (progdefaults.ReverseAudio) {
2319 			fbuf[sd[1].stream_params.channels * i + 1] = bufleft[i];
2320 			fbuf[sd[1].stream_params.channels * i] = bufright[i];
2321 		} else {
2322 			fbuf[sd[1].stream_params.channels * i] = bufleft[i];
2323 			fbuf[sd[1].stream_params.channels * i + 1] = bufright[i];
2324 		}
2325 	}
2326 
2327 	return resample_write(fbuf, count);
2328 }
2329 
resample_write(float * buf,size_t count)2330 size_t SoundPulse::resample_write(float* buf, size_t count)
2331 {
2332 	int err;
2333 		float *wbuf = buf;
2334 
2335 	if (progdefaults.TX_corr != 0) {
2336 		if (txppm != progdefaults.TX_corr) {
2337 			txppm = progdefaults.TX_corr;
2338 			tx_src_data->src_ratio = 1.0 + txppm / 1e6;
2339 			src_set_ratio(tx_src_state, tx_src_data->src_ratio);
2340 		}
2341 		tx_src_data->data_in = wbuf;
2342 		tx_src_data->input_frames = count;
2343 		tx_src_data->data_out = src_buffer;
2344 		tx_src_data->output_frames = SND_BUF_LEN;
2345 		tx_src_data->end_of_input = 0;
2346 		if ((err = src_process(tx_src_state, tx_src_data)) != 0)
2347 			throw SndException(src_strerror(err));
2348 		if (tx_src_data->output_frames_gen == 0) // input was too small
2349 			return count;
2350 
2351 		wbuf = tx_src_data->data_out;
2352 		count = tx_src_data->output_frames_gen;
2353 	}
2354 
2355 	if (!active_modem) return count;
2356 
2357 	if (pa_simple_write(sd[1].stream, wbuf, count * sd[1].stream_params.channels * sizeof(float), &err) == -1)
2358 		throw SndPulseException(err);
2359 
2360 	return count;
2361 }
2362 
src_read_cb(void * arg,float ** data)2363 long SoundPulse::src_read_cb(void* arg, float** data)
2364 {
2365 	SoundPulse* p = reinterpret_cast<SoundPulse*>(arg);
2366 
2367 	int err;
2368 	int nread = 0;
2369 	if ((nread = pa_simple_read(p->sd[0].stream, p->snd_buffer,
2370 			p->sd[0].stream_params.channels * sizeof(float) * p->sd[0].blocksize, &err)) == -1) {
2371 		LOG_ERROR("%s", pa_strerror(err));
2372 		*data = 0;
2373 		return 0;
2374 	}
2375 
2376 	*data = p->snd_buffer;
2377 	return p->sd[0].blocksize;
2378 }
2379 
Read(float * buf,size_t count)2380 size_t SoundPulse::Read(float *buf, size_t count)
2381 {
2382 	if (ifPlayback) {
2383 		read_file(ifPlayback, buf, count);
2384 		if (!ofCapture) {
2385 			flush(0);
2386 			if (!bHighSpeed)
2387 				MilliSleep((long)ceil((1e3 * count) / sample_frequency));
2388 			return count;
2389 		}
2390 	}
2391 
2392 	size_t n = 0;
2393 	long r = 0;
2394 
2395 	if (progdefaults.RX_corr != 0) {
2396 		if (rxppm != progdefaults.RX_corr) {
2397 			rxppm = progdefaults.RX_corr;
2398 			sd[0].src_ratio = 1.0 / (1.0 + rxppm / 1e6);
2399 			src_set_ratio(rx_src_state, sd[0].src_ratio);
2400 		}
2401 		sd[0].blocksize = SCBLOCKSIZE;
2402 		while (n < count) {
2403 			if ((r = src_callback_read(rx_src_state, sd[0].src_ratio, count - n, rbuf + n)) == 0)
2404 				break;
2405 			n += r;
2406 		}
2407 	}
2408 	else {
2409 		int err;
2410 		if ((r = pa_simple_read(sd[0].stream, rbuf,
2411 				sd[0].stream_params.channels * sizeof(float) * count, &err)) == -1)
2412 			throw SndPulseException(err);
2413 	}
2414 
2415 	// transfer active input channel; left == 0, right == 1
2416 	size_t i = 0;
2417 	if (sd[0].stream_params.channels == 2) n = progdefaults.ReverseRxAudio;
2418 	else n = 0;
2419 	while (i < count) {
2420 		buf[i] = rbuf[n];
2421 		i++;
2422 		n += sd[0].stream_params.channels;
2423 	}
2424 
2425 	if (ofCapture)
2426 		write_file(ofCapture, buf, NULL, count);
2427 
2428 	return count;
2429 }
2430 
src_data_reset(int mode)2431 void SoundPulse::src_data_reset(int mode)
2432 {
2433 		int err;
2434 		if (mode & 1 << O_RDONLY) {
2435 				if (rx_src_state)
2436 						src_delete(rx_src_state);
2437 				rx_src_state = src_callback_new(src_read_cb, progdefaults.sample_converter,
2438 						sd[0].stream_params.channels, &err, this);
2439 				if (!rx_src_state)
2440 						throw SndException(src_strerror(err));
2441 				sd[0].src_ratio = 1.0 / (1.0 + rxppm / 1e6);
2442 		}
2443 		if (mode & 1 << O_WRONLY) {
2444 				if (tx_src_state)
2445 						src_delete(tx_src_state);
2446 				tx_src_state = src_new(progdefaults.sample_converter, sd[1].stream_params.channels, &err);
2447 				if (!tx_src_state)
2448 						throw SndException(src_strerror(err));
2449 				tx_src_data->src_ratio = 1.0 + txppm / 1e6;
2450 		}
2451 }
2452 
2453 #endif // USE_PULSEAUDIO
2454 
2455 
Write(double * buf,size_t count)2456 size_t SoundNull::Write(double* buf, size_t count)
2457 {
2458 	if (ofGenerate)
2459 		write_file(ofGenerate, buf, NULL, count);
2460 
2461 	if (PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST) {
2462 		return count;
2463 	}
2464 
2465 	MilliSleep((long)ceil((1e3 * count) / sample_frequency));
2466 
2467 	return count;
2468 }
2469 
Write_stereo(double * bufleft,double * bufright,size_t count)2470 size_t SoundNull::Write_stereo(double* bufleft, double* bufright, size_t count)
2471 {
2472 	if (ofGenerate)
2473 		write_file(ofGenerate, bufleft, bufright, count);
2474 
2475 	MilliSleep((long)ceil((1e3 * count) / sample_frequency));
2476 
2477 	return count ? count : 1;
2478 }
2479 
Read(float * buf,size_t count)2480 size_t SoundNull::Read(float *buf, size_t count)
2481 {
2482 	if (ifPlayback)
2483 		read_file(ifPlayback, buf, count);
2484 	else
2485 		memset(buf, 0, count * sizeof(*buf));
2486 	if (ofCapture)
2487 		write_file(ofCapture, buf, NULL, count);
2488 	if (!bHighSpeed)
2489 		MilliSleep((long)ceil((1e3 * count) / sample_frequency));
2490 
2491 	return count;
2492 
2493 }
2494 
flush(unsigned)2495 void SoundNull::flush(unsigned)
2496 {
2497 	if (ofGenerate)
2498 		sf_close(ofGenerate);
2499 }
2500 
2501