1 // ----------------------------------------------------------------------------
2 //
3 //      sound.h
4 //
5 // Copyright (C) 2006-2007
6 //              Dave Freese, W1HKJ
7 //
8 // Copyright (C) 2007-2009
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 #ifndef _SOUND_H
28 #define _SOUND_H
29 
30 #include <iostream>
31 
32 #include <string>
33 #include <cstring>
34 #include <climits>
35 
36 #  include <sndfile.h>
37 
38 #include <samplerate.h>
39 
40 #define SCBLOCKSIZE 512
41 
42 
43 class SndException : public std::exception
44 {
45 public:
46 	SndException(int err_ = 0)
err(err_)47 		: err(err_), msg(std::string("Sound error: ") + err_to_str(err_))
48 	{ }
SndException(const char * msg_)49 	SndException(const char* msg_)
50 		: err(1), msg(msg_)
51 	{ }
SndException(int err_,const std::string & msg_)52 	SndException(int err_, const std::string& msg_) : err(err_), msg(msg_) { }
~SndException()53 	virtual ~SndException() throw() { }
54 
what(void)55 	const char*	what(void) const throw() { return msg.c_str(); }
error(void)56 	int		error(void) const { return err; }
57 
58 protected:
err_to_str(int e)59 	const char* err_to_str(int e) { return strerror(e); }
60 
61 	int		err;
62 	std::string	msg;
63 };
64 
65 
66 class SoundBase {
67 protected:
68 	int		sample_frequency;
69 	int		txppm;
70 	int		rxppm;
71 
72 	// for interface to the samplerate resampling library
73 	SRC_STATE	*tx_src_state;
74 	SRC_STATE	*rx_src_state;
75 	double		*wrt_buffer;
76 
77 	SNDFILE* ofCapture;
78 	SNDFILE* ifPlayback;
79 	SNDFILE* ofGenerate;
80 
81 // 2 channel writes
82 	SRC_STATE	*writ_src_state_left;
83 	SRC_STATE	*writ_src_state_right;
84 	SRC_DATA	*writ_src_data_left;
85 	SRC_DATA	*writ_src_data_right;
86 
87 	float		*src_write_buffer_left;
88 	float		*src_write_buffer_right;
89 
90 // 1 channel reads
91 	SRC_STATE	*play_src_state;
92 	SRC_DATA	*play_src_data;
93 
94 	float		*src_rd_out_buffer;
95 	float		*src_rd_inp_buffer;
96 	float		*out_pointer;
97 
98 	double		req_sample_rate;
99 
100 	SF_INFO		play_info;
101 
102 	float modem_wr_sr;
103 	float modem_play_sr;
104 
105 	bool   new_playback;
106 	sf_count_t  read_file(SNDFILE* file, float* buf, size_t count);
107 	void	write_file(SNDFILE* file, float* buf_left, float *buf_right, size_t count);
108 	void	write_file(SNDFILE* file, double* buf_left, double *buf_right, size_t count);
109 
110 public:
111 	SoundBase();
112 	virtual ~SoundBase();
113 	virtual int	Open(int mode, int freq = 8000) = 0;
114 	virtual void    Close(unsigned dir = UINT_MAX) = 0;
115 	virtual void    Abort(unsigned dir = UINT_MAX) = 0;
116 	virtual size_t	Write(double *, size_t) = 0;
117 	virtual size_t	Write_stereo(double *, double *, size_t) = 0;
118 	virtual size_t	resample_write(float *buf, size_t count) = 0;
119 	virtual size_t	Read(float *, size_t) = 0;
120 	virtual void    flush(unsigned dir = UINT_MAX) = 0;
121 	virtual bool	must_close(int dir = 0) = 0;
122 
123 	int		startCapture(std::string fname, int format);
124 	void	stopCapture();
125 
126 	int		startPlayback(std::string fname, int format);
127 	void	stopPlayback();
128 
129 	int		startGenerate(std::string fname, int format);
130 	void	stopGenerate();
131 
132 	int		AudioMP3(std::string fname);
133 	int		AudioWAV(std::string fname);
134 	int		Audio(std::string fname);
135 };
136 
137 
138 #if USE_OSS
139 
140 class SoundOSS : public SoundBase {
141 private:
142 	std::string	device;
143 	int		device_fd;
144 	int		version;
145 	int		capability_mask;
146 	int		format_mask;
147 	int		channels;
148 	int		play_format;
149 	int		mode;
150 	bool	formatok;
151 	unsigned char	*cbuff;
152 
153 	SRC_DATA	*rx_src_data;
154 	SRC_DATA	*tx_src_data;
155 	float		*snd_buffer;
156 	float		*src_buffer;
157 
158 	void	getVersion();
159 	void	getCapabilities();
160 	void	getFormats();
161 	void	setfragsize();
162 	void	Channels(int);
163 	void	Frequency(int);
164 	void	Format(int);
165 	int		BufferSize(int);
166 	bool	wait_till_finished();
167 	bool	reset_device();
168 
169 public:
170 	SoundOSS(const char *dev = "/dev/dsp");
171 	~SoundOSS();
172 	int		Open(int mode, int freq = 8000);
173 	void	Close(unsigned dir = UINT_MAX);
174 	void	Abort(unsigned dir = UINT_MAX) { Close(dir); }
175 	size_t		Write(double *, size_t);
176 	size_t		Write_stereo(double *, double *, size_t);
177 	size_t		resample_write(float *buf, size_t count);
178 	size_t		Read(float *, size_t);
179 	bool		must_close(int dir = 0) { return true; }
180 	void		flush(unsigned dir = UINT_MAX) { wait_till_finished(); }
181 
182 private:
Fd()183 	int		Fd() { return device_fd; }
Frequency()184 	int		Frequency() { return sample_frequency;};
Version()185 	int		Version() {return version;};
Capabilities()186 	int		Capabilities() {return capability_mask;};
Formats()187 	int		Formats() { return format_mask;};
Channels()188 	int		Channels() { return channels;};
Format()189 	int		Format() { return play_format;};
FormatOK()190 	bool	FormatOK() { return formatok;};
191 };
192 
193 #endif // USE_OSS
194 
195 
196 #if USE_PORTAUDIO
197 #  include <pthread.h>
198 #  include <semaphore.h>
199 #  include <vector>
200 #  include <portaudio.h>
201 #  include "ringbuffer.h"
202 
203 class SoundPort : public SoundBase
204 {
205 public:
206         typedef std::vector<const PaDeviceInfo*>::const_iterator device_iterator;
207         static void	initialize(void);
208         static void	terminate(void);
209         static const std::vector<const PaDeviceInfo*>& devices(void);
210         static void devices_info(std::string& in, std::string& out);
211 	static const std::vector<double>& get_supported_rates(const std::string& name, unsigned dir);
212 
213 public:
214         SoundPort(const char *in_dev, const char *out_dev);
215         ~SoundPort();
216 	int 		Open(int mode, int freq = 8000);
217 	void 		Close(unsigned dir = UINT_MAX);
218 	void 		Abort(unsigned dir = UINT_MAX);
219 	size_t 		Write(double *buf, size_t count);
220 	size_t		Write_stereo(double *bufleft, double *bufright, size_t count);
221 	size_t 		Read(float *buf, size_t count);
222 	bool		must_close(int dir = 0);
223 	void		flush(unsigned dir = UINT_MAX);
224 
225 private:
226         void		src_data_reset(unsigned dir);
227         static long	src_read_cb(void* arg, float** data);
228         size_t          resample_write(float* buf, size_t count);
229 	device_iterator name_to_device(std::string& name, unsigned dir);
230         void 		init_stream(unsigned dir);
231         void 		start_stream(unsigned dir);
232         void 		pause_stream(unsigned dir);
233         bool		stream_active(unsigned dir);
234         bool		full_duplex_device(const PaDeviceInfo* dev);
235         double		find_srate(unsigned dir);
236 	static void	probe_supported_rates(const device_iterator& idev);
237         void		pa_perror(int err, const char* str = 0);
238         static void	init_hostapi_ext(void);
239         static PaStreamCallback stream_process;
240         static PaStreamFinishedCallback stream_stopped;
241 
242 private:
243         static bool                             pa_init;
244 	static std::vector<const PaDeviceInfo*> devs;
245         float* 					fbuf;
246 		float*					src_buffer;
247 	SRC_DATA	*tx_src_data;
248 
249         enum {
250                 spa_continue = paContinue, spa_complete = paComplete,
251                 spa_abort = paAbort, spa_drain, spa_pause
252         };
253         struct stream_data {
254                 std::string device;
255                 device_iterator idev;
256 
257                 PaStream* stream;
258                 PaStreamParameters params;
259 
260                 unsigned frames_per_buffer;
261                 double dev_sample_rate;
262                 double src_ratio;
263 
264                 sem_t* rwsem;
265 		pthread_mutex_t* cmutex;
266 		pthread_cond_t* ccond;
267                 int state;
268                 ringbuffer<float>* rb;
269 		size_t blocksize;
270                 size_t advance;
271         } sd[2];
272 };
273 
274 class SndPortException : public SndException
275 {
276 public:
277 	SndPortException(int err_ = 0)
278 		: SndException(err_, std::string("PortAudio error: ") + err_to_str(err_))
279 	{ }
SndPortException(const char * msg_)280 	SndPortException(const char* msg_) : SndException(msg_) { }
281 protected:
err_to_str(int e)282 	const char* err_to_str(int e) { return Pa_GetErrorText(e); }
283 };
284 
285 #endif // USE_PORTAUDIO
286 
287 
288 #if USE_PULSEAUDIO
289 #  include <pulse/simple.h>
290 #  include <pulse/error.h>
291 extern "C" { const char* pa_get_library_version(void); };
292 
293 class SoundPulse : public SoundBase
294 {
295 public:
296 	SoundPulse(const char* dev);
297 	virtual ~SoundPulse();
298 
299 	int	Open(int mode, int freq = 8000);
300 	void    Close(unsigned dir = UINT_MAX);
301 	void    Abort(unsigned dir = UINT_MAX);
302 	size_t	Write(double* buf, size_t count);
303 	size_t	Write_stereo(double* bufleft, double* bufright, size_t count);
304 	size_t	Read(float *buf, size_t count);
305 	bool	must_close(int dir = 0) { return false; }
306 	void	flush(unsigned dir = UINT_MAX);
307 
308 private:
309 	void	src_data_reset(int mode);
310         static long	src_read_cb(void* arg, float** data);
311 	size_t	resample_write(float* buf, size_t count);
312 
313 private:
314 	struct stream_data {
315 		pa_simple*	stream;
316 		pa_sample_spec	stream_params;
317 		pa_buffer_attr  buffer_attrs;
318 		pa_stream_direction_t dir;
319 		double		src_ratio;
320 		size_t		blocksize;
321 	} sd[2];
322 
323 	SRC_DATA* tx_src_data;
324 	float* fbuf;
325 	float* rbuf;
326 	float* snd_buffer;
327 	float* src_buffer;
328 };
329 
330 class SndPulseException : public SndException
331 {
332 public:
333 	SndPulseException(int err_ = 0)
334 		: SndException(err_, std::string("PulseAudio error: ") + err_to_str(err_))
335 	{ }
SndPulseException(const char * msg_)336 	SndPulseException(const char* msg_) : SndException(msg_) { }
337 protected:
err_to_str(int e)338 	const char* err_to_str(int e) { return pa_strerror(e); }
339 };
340 
341 #endif // USE_PULSEAUDIO
342 
343 
344 class SoundNull : public SoundBase
345 {
346 public:
347 	int	Open(int mode, int freq = 44100) { sample_frequency = freq; return 0; }
Close(unsigned)348 	void    Close(unsigned) { }
Abort(unsigned)349 	void    Abort(unsigned) { }
350 	size_t	Write(double* buf, size_t count);
351 	size_t	Write_stereo(double* bufleft, double* bufright, size_t count);
352 	size_t	Read(float *buf, size_t count);
resample_write(float * buf,size_t count)353 	size_t	resample_write(float* buf, size_t count){return 0;};
354 	bool	must_close(int dir = 0) { return false; }
355 	void	flush(unsigned);
356 };
357 
358 namespace SND_SUPPORT {
359 	bool format_supported(int format);
360 	void get_file_params(std::string def_fname, std::string &fname, int &format, bool check);
361 	void tag_file(SNDFILE *sndfile, const char *title);
362 };
363 
364 
365 #endif // SOUND_H
366