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