1 // portaudio functions for butt
2 //
3 // Copyright 2007-2018 by Daniel Noethen.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or (at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <math.h>
21 
22 #include <string.h>
23 #include <pthread.h>
24 #include <samplerate.h>
25 
26 #ifdef WIN32
27  #include <windows.h>
28 #endif
29 
30 #include "gettext.h"
31 #include "config.h"
32 
33 #include "butt.h"
34 #include "cfg.h"
35 #include "port_audio.h"
36 #include "parseconfig.h"
37 #include "lame_encode.h"
38 #include "aac_encode.h"
39 #include "shoutcast.h"
40 #include "icecast.h"
41 #include "strfuncs.h"
42 #include "wav_header.h"
43 #include "ringbuffer.h"
44 #include "vu_meter.h"
45 #include "flgui.h"
46 #include "fl_funcs.h"
47 #include "dsp.hpp"
48 
49 int pa_frames = 0;
50 
51 char* encode_buf;
52 short *pa_pcm_buf;
53 int buf_index;
54 int buf_pos;
55 int framepacket_size;
56 
57 bool try_to_connect;
58 bool pa_new_frames;
59 bool reconnect;
60 bool silence_detected;
61 bool signal_detected;
62 
63 int num_of_input_channels;
64 
65 bool next_file;
66 FILE *next_fd;
67 
68 struct ringbuf rec_rb;
69 struct ringbuf stream_rb;
70 
71 SRC_STATE *srconv_state_stream = NULL;
72 SRC_STATE *srconv_state_record = NULL;
73 SRC_DATA srconv_stream;
74 SRC_DATA srconv_record;
75 
76 pthread_t rec_thread;
77 pthread_t stream_thread;
78 pthread_mutex_t stream_mut, rec_mut;
79 pthread_cond_t  stream_cond, rec_cond;
80 
81 PaStream *stream;
82 
83 static DSPEffects* dsp = NULL;
84 
snd_init(void)85 int snd_init(void)
86 {
87     char info_buf[256];
88 
89     PaError p_err;
90     if((p_err = Pa_Initialize()) != paNoError)
91     {
92         snprintf(info_buf, sizeof(info_buf),
93 				_("PortAudio init failed:\n%s\n"),
94 				Pa_GetErrorText(p_err));
95 
96         ALERT(info_buf);
97         return 1;
98     }
99 
100     if (pa_frames == 0) {
101         pa_frames = 2400; // 50ms * 48000Hz
102     }
103 
104     srconv_stream.data_in = (float*)malloc(2*pa_frames * 64 * sizeof(float));
105     srconv_record.data_in = (float*)malloc(2*pa_frames * 64 * sizeof(float));
106 
107     srconv_stream.data_out = (float*)malloc(2*pa_frames * 64 * sizeof(float));
108     srconv_record.data_out = (float*)malloc(2*pa_frames * 64 * sizeof(float));
109 
110     reconnect = false;
111     buf_index = 0;
112     silence_detected = false;
113     return 0;
114 }
115 
snd_reinit(void)116 void snd_reinit(void)
117 {
118     snd_close();
119     if (snd_init() == 0)
120         snd_open_stream();
121 }
122 
snd_open_stream(void)123 int snd_open_stream(void)
124 {
125 
126     int samplerate;
127     char info_buf[256];
128 
129     PaDeviceIndex pa_dev_id;
130     PaStreamParameters pa_params;
131     PaError pa_err;
132     const PaDeviceInfo *pa_dev_info;
133 
134     if(cfg.audio.dev_count == 0)
135     {
136         print_info(_("ERROR: no sound device with input channels found"), 1);
137         return 1;
138     }
139 
140 
141     pa_frames = round((cfg.audio.buffer_ms/1000.0)*cfg.audio.samplerate);
142 
143     snd_reset_samplerate_conv(SND_STREAM);
144     snd_reset_samplerate_conv(SND_REC);
145 
146     samplerate = cfg.audio.samplerate;
147 
148     pa_dev_id = cfg.audio.pcm_list[cfg.audio.dev_num]->dev_id;
149 
150     pa_dev_info = Pa_GetDeviceInfo(pa_dev_id);
151     if(pa_dev_info == NULL)
152     {
153         snprintf(info_buf, 127, _("Error getting device Info (%d)"), pa_dev_id);
154         print_info(info_buf, 1);
155         return 1;
156     }
157 
158     num_of_input_channels = pa_dev_info->maxInputChannels;
159     if (num_of_input_channels == 1)
160     {
161         cfg.audio.left_ch = 1;
162         cfg.audio.right_ch = 1;
163     }
164     else if ((cfg.audio.left_ch > num_of_input_channels) || (cfg.audio.right_ch > num_of_input_channels))
165     {
166         cfg.audio.left_ch = 1;
167         cfg.audio.right_ch = 2;
168     }
169 
170     framepacket_size = pa_frames * cfg.audio.channel;
171 
172     pa_pcm_buf = (short*)malloc(16 * framepacket_size * sizeof(short));
173     encode_buf = (char*)malloc(16 * framepacket_size * sizeof(char));
174 
175     rb_init(&rec_rb, 16 * framepacket_size * sizeof(short));
176     rb_init(&stream_rb, 16 * framepacket_size * sizeof(short));
177 
178     pa_params.device = pa_dev_id;
179     pa_params.channelCount = pa_dev_info->maxInputChannels;
180     pa_params.sampleFormat = paInt16;
181     pa_params.suggestedLatency = pa_dev_info->defaultHighInputLatency;
182     pa_params.hostApiSpecificStreamInfo = NULL;
183 
184 
185     pa_err = Pa_IsFormatSupported(&pa_params, NULL, samplerate);
186     if(pa_err != paFormatIsSupported)
187     {
188         if(pa_err == paInvalidSampleRate)
189         {
190             snprintf(info_buf, sizeof(info_buf),
191                     _("Samplerate not supported: %dHz\n"
192                     "Using default samplerate: %dHz"),
193                     samplerate, (int)pa_dev_info->defaultSampleRate);
194             print_info(info_buf, 1);
195 
196             if(Pa_IsFormatSupported(&pa_params, NULL,
197                pa_dev_info->defaultSampleRate) != paFormatIsSupported)
198             {
199                 print_info("FAILED", 1);
200                 return 1;
201             }
202             else
203             {
204                 samplerate = (int)pa_dev_info->defaultSampleRate;
205                 cfg.audio.samplerate = samplerate;
206                 update_samplerates();
207             }
208         }
209         else
210         {
211             snprintf(info_buf, sizeof(info_buf), _("PA: Format not supported: %s\n"),
212                     Pa_GetErrorText(pa_err));
213             print_info(info_buf, 1);
214             return 1;
215         }
216     }
217 
218     int flag = cfg.audio.disable_dithering == 0 ? paNoFlag : paDitherOff;
219     pa_err = Pa_OpenStream(&stream, &pa_params, NULL, samplerate, pa_frames, flag, snd_callback, NULL);
220 
221     if(pa_err != paNoError)
222     {
223         printf(_("error opening sound device: \n%s\n"), Pa_GetErrorText(pa_err));
224         return 1;
225     }
226 
227     if (dsp != NULL)
228     {
229         delete dsp;
230         dsp = NULL;
231     }
232 
233     dsp = new DSPEffects(pa_frames, cfg.audio.channel, samplerate);
234 
235 
236     Pa_StartStream(stream);
237     return 0;
238 }
239 
240 
241 //this function is called by PortAudio when new audio data arrived
snd_callback(const void * input,void * output,unsigned long frameCount,const PaStreamCallbackTimeInfo * timeInfo,PaStreamCallbackFlags statusFlags,void * userData)242 int snd_callback(const void *input,
243                  void *output,
244                  unsigned long frameCount,
245                  const PaStreamCallbackTimeInfo* timeInfo,
246                  PaStreamCallbackFlags statusFlags,
247                  void *userData)
248 {
249     int samplerate_out;
250     bool convert_stream = false;
251     bool convert_record = false;
252 
253     char stream_buf[16 * pa_frames*2 * sizeof(short)];
254     char record_buf[16 * pa_frames*2 * sizeof(short)];
255 
256     short *pcm_input = (short*)input;
257 
258     for (int i = 0; i < frameCount; i++)
259     {
260         if (cfg.audio.channel == 1)
261         {
262             if (num_of_input_channels == 1)
263             {
264                 pa_pcm_buf[i] = pcm_input[i];
265             }
266             else
267             {
268                 float left_sample, right_sample;
269                 short mono_sample;
270                 left_sample = (float)pcm_input[num_of_input_channels*i+(cfg.audio.left_ch-1)];
271                 right_sample = (float)pcm_input[num_of_input_channels*i+(cfg.audio.right_ch-1)];
272                 mono_sample = (short)(round((left_sample+right_sample)/2.0));
273                 pa_pcm_buf[i] = mono_sample;
274             }
275         }
276         else {
277             if (num_of_input_channels == 1)
278             {
279                 pa_pcm_buf[2*i] = pcm_input[i];
280                 pa_pcm_buf[2*i+1] = pcm_input[i];
281             }
282             else
283             {
284                 pa_pcm_buf[2*i] = pcm_input[num_of_input_channels*i+(cfg.audio.left_ch-1)];
285                 pa_pcm_buf[2*i+1] = pcm_input[num_of_input_channels*i+(cfg.audio.right_ch-1)];
286             }
287         }
288     }
289     samplerate_out = cfg.audio.samplerate;
290 
291     if(dsp->hasToProcessSamples())
292     {
293         dsp->processSamples(pa_pcm_buf);
294     }
295 
296     if (streaming)
297     {
298         if ((!strcmp(cfg.audio.codec, "opus")) && (cfg.audio.samplerate != 48000))
299         {
300             convert_stream = true;
301             samplerate_out = 48000;
302         }
303 
304         if (convert_stream == true)
305         {
306             srconv_stream.end_of_input = 0;
307             srconv_stream.src_ratio = (float)samplerate_out/cfg.audio.samplerate;
308             srconv_stream.input_frames = frameCount;
309             srconv_stream.output_frames = frameCount*cfg.audio.channel * (srconv_stream.src_ratio+1) * sizeof(float);
310 
311             src_short_to_float_array((short*)pa_pcm_buf, (float*)srconv_stream.data_in, frameCount*cfg.audio.channel);
312 
313             //The actual resample process
314             src_process(srconv_state_stream, &srconv_stream);
315 
316             src_float_to_short_array(srconv_stream.data_out, (short*)stream_buf, srconv_stream.output_frames_gen*cfg.audio.channel);
317 
318             rb_write(&stream_rb, (char*)stream_buf, srconv_stream.output_frames_gen*sizeof(short)*cfg.audio.channel);
319         }
320         else
321             rb_write(&stream_rb, (char*)pa_pcm_buf, frameCount*sizeof(short)*cfg.audio.channel);
322 
323         pthread_cond_signal(&stream_cond);
324     }
325 
326     if(recording)
327     {
328 
329         if ((!strcmp(cfg.rec.codec, "opus")) && (cfg.audio.samplerate != 48000))
330         {
331             convert_record = true;
332             samplerate_out = 48000;
333         }
334 
335         if (convert_record == true)
336         {
337             srconv_record.end_of_input = 0;
338             srconv_record.src_ratio = (float)samplerate_out/cfg.audio.samplerate;
339             srconv_record.input_frames = frameCount;
340             srconv_record.output_frames = frameCount*cfg.audio.channel * (srconv_record.src_ratio+1) * sizeof(float);
341 
342             src_short_to_float_array((short*)pa_pcm_buf, (float*)srconv_record.data_in, frameCount*cfg.audio.channel);
343 
344             //The actual resample process
345             src_process(srconv_state_record, &srconv_record);
346 
347             src_float_to_short_array(srconv_record.data_out, (short*)record_buf, srconv_record.output_frames_gen*cfg.audio.channel);
348 
349             rb_write(&rec_rb, (char*)record_buf, srconv_record.output_frames_gen*sizeof(short)*cfg.audio.channel);
350 
351         }
352         else
353             rb_write(&rec_rb, (char*)pa_pcm_buf, frameCount*sizeof(short)*cfg.audio.channel);
354 
355         pthread_cond_signal(&rec_cond);
356     }
357 
358     //tell snd_update_vu() that there is new audio data
359     pa_new_frames = 1;
360 
361     return 0;
362 }
363 
364 
snd_start_stream(void)365 void snd_start_stream(void)
366 {
367     pthread_mutex_init(&stream_mut, NULL);
368     pthread_cond_init (&stream_cond, NULL);
369 
370     kbytes_sent = 0;
371     streaming = 1;
372 
373     pthread_create(&stream_thread, NULL, snd_stream_thread, NULL);
374 }
375 
376 
snd_stream_thread(void * data)377 void *snd_stream_thread(void *data)
378 {
379     int sent;
380     int rb_bytes_read;
381 	int encode_bytes_read = 0;
382     int bytes_to_read;
383 
384     char *enc_buf = (char*)malloc(stream_rb.size * sizeof(char)*10);
385     char *audio_buf = (char*)malloc(stream_rb.size * sizeof(char)*10);
386 
387     int (*xc_send)(char *buf, int buf_len) = NULL;
388 
389     static int new_stream = 0;
390 
391 
392     if(cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
393         xc_send = &sc_send;
394     else //Icecast
395         xc_send = &ic_send;
396 
397     while(connected)
398     {
399         pthread_cond_wait(&stream_cond, &stream_mut);
400         if(!connected)
401             break;
402 
403         if(!strcmp(cfg.audio.codec, "opus"))
404         {
405             // Read always chunks of 960 frames from the audio ringbuffer to be
406             // compatible with OPUS
407             bytes_to_read = 960 * sizeof(short)*cfg.audio.channel;
408 
409             while ((rb_filled(&stream_rb)) >= bytes_to_read)
410             {
411                 // Read always chunks of 960 frames from the audio ringbuffer to be
412                 bytes_to_read = 960 * sizeof(short)*cfg.audio.channel;
413                 rb_read_len(&stream_rb, audio_buf, bytes_to_read);
414 
415                 encode_bytes_read = opus_enc_encode(&opus_stream, (short*)audio_buf,
416                         enc_buf, bytes_to_read/(2*cfg.audio.channel));
417 
418                 if((sent = xc_send(enc_buf, encode_bytes_read)) == -1)
419                 {
420                     connected = 0;
421                 }
422                 else
423                     kbytes_sent += encode_bytes_read/1024.0;
424             }
425         }
426 #ifdef HAVE_LIBFDK_AAC
427         else if(!strcmp(cfg.audio.codec, "aac"))
428         {
429             bytes_to_read = aac_stream.info.frameLength * cfg.audio.channel * sizeof(short);
430             while ((rb_filled(&stream_rb)) >= bytes_to_read)
431             {
432                 rb_read_len(&stream_rb, audio_buf, bytes_to_read);
433 
434                 encode_bytes_read = aac_enc_encode(&aac_stream, (short*)audio_buf, enc_buf,
435                                                    bytes_to_read/(2*cfg.audio.channel), stream_rb.size*10);
436 
437                 if((sent = xc_send(enc_buf, encode_bytes_read)) == -1)
438                 {
439                     connected = 0;
440                 }
441                 else
442                     kbytes_sent += encode_bytes_read/1024.0;
443 
444             }
445         }
446 #endif
447         else // ogg, mp3 and flac need more data than opus in order to compress the audio data
448         {
449             if(rb_filled(&stream_rb) < framepacket_size*sizeof(short))
450                 continue;
451 
452             rb_bytes_read = rb_read(&stream_rb, audio_buf);
453             if(rb_bytes_read == 0)
454                 continue;
455 
456             if(!strcmp(cfg.audio.codec, "mp3"))
457                 encode_bytes_read = lame_enc_encode(&lame_stream, (short*)audio_buf, enc_buf,
458                         rb_bytes_read/(2*cfg.audio.channel), stream_rb.size*10);
459 
460             if(!strcmp(cfg.audio.codec, "ogg"))
461                 encode_bytes_read = vorbis_enc_encode(&vorbis_stream, (short*)audio_buf,
462                         enc_buf, rb_bytes_read/(2*cfg.audio.channel));
463 
464             if(!strcmp(cfg.audio.codec, "flac"))
465             {
466                 encode_bytes_read = flac_enc_encode_stream(&flac_stream, (short*)audio_buf, (uint8_t*)enc_buf,
467                                                             rb_bytes_read/sizeof(short)/cfg.audio.channel,
468                                                             cfg.audio.channel, new_stream);
469 
470                 if (flac_stream.state == FLAC_STATE_UPDATE_META_DATA)
471                     flac_enc_init_ogg_stream(&flac_stream);
472 
473                 if (encode_bytes_read == 0)
474                     continue;
475             }
476 
477             if((sent = xc_send(enc_buf, encode_bytes_read)) == -1)
478                 connected = 0;
479             else
480                 kbytes_sent += encode_bytes_read/1024.0;
481         }
482     }
483 
484     free(enc_buf);
485     free(audio_buf);
486 
487     return NULL;
488 }
489 
snd_stop_stream(void)490 void snd_stop_stream(void)
491 {
492     connected = 0;
493     streaming = 0;
494 
495     pthread_cond_signal(&stream_cond);
496 
497     pthread_mutex_destroy(&stream_mut);
498     pthread_cond_destroy(&stream_cond);
499 
500 
501     print_info(_("disconnected\n"), 0);
502 }
503 
504 
505 
snd_start_rec(void)506 void snd_start_rec(void)
507 {
508     next_file = 0;
509 
510     kbytes_written = 0;
511     recording = 1;
512 
513     pthread_mutex_init(&rec_mut, NULL);
514     pthread_cond_init (&rec_cond, NULL);
515 
516     pthread_create(&rec_thread, NULL, snd_rec_thread, NULL);
517 
518     print_info(_("recording to:"), 0);
519     print_info(cfg.rec.path, 0);
520 }
521 
snd_stop_rec(void)522 void snd_stop_rec(void)
523 {
524     record = 0;
525     recording = 0;
526 
527 
528     pthread_cond_signal(&rec_cond);
529 
530     pthread_mutex_destroy(&rec_mut);
531     pthread_cond_destroy(&rec_cond);
532 
533     print_info(_("recording stopped"), 0);
534 }
535 
536 //The recording stuff runs in its own thread
537 //this prevents dropouts in the recording in case the
538 //bandwidth is smaller than the selected streaming bitrate
snd_rec_thread(void * data)539 void* snd_rec_thread(void *data)
540 {
541     int rb_bytes_read;
542     int bytes_to_read;
543     int ogg_header_written;
544     int opus_header_written;
545     int enc_bytes_read;
546 
547     char *enc_buf = (char*)malloc(rec_rb.size * sizeof(char)*10);
548     char *audio_buf = (char*)malloc(rec_rb.size * sizeof(char)*10);
549 
550     ogg_header_written = 0;
551     opus_header_written = 0;
552 
553     while(record)
554     {
555         pthread_cond_wait(&rec_cond, &rec_mut);
556 
557         if(next_file == 1)
558         {
559             if(!strcmp(cfg.rec.codec, "flac")) // The flac encoder closes the file
560                 flac_enc_close(&flac_rec);
561             else
562                 fclose(cfg.rec.fd);
563 
564             cfg.rec.fd = next_fd;
565             next_file = 0;
566             if(!strcmp(cfg.rec.codec, "ogg"))
567             {
568                 vorbis_enc_reinit(&vorbis_rec);
569                 ogg_header_written = 0;
570             }
571             if(!strcmp(cfg.rec.codec, "opus"))
572             {
573                 opus_enc_reinit(&opus_rec);
574                 opus_header_written = 0;
575             }
576             if(!strcmp(cfg.rec.codec, "flac"))
577             {
578                 flac_enc_reinit(&flac_rec);
579                 flac_enc_init_FILE(&flac_rec, cfg.rec.fd);
580             }
581         }
582 
583         // Opus and aac need  special treatments
584         // The encoders need a predefined count of frames
585         // Therefore we don't feed the encoder with all data we have in the
586         // ringbuffer at once
587         if(!strcmp(cfg.rec.codec, "opus"))
588         {
589             bytes_to_read = 960 * sizeof(short)*cfg.audio.channel;
590             while ((rb_filled(&rec_rb)) >= bytes_to_read)
591             {
592                 rb_read_len(&rec_rb, audio_buf, bytes_to_read);
593 
594                 if(!opus_header_written)
595                 {
596                     opus_enc_write_header(&opus_rec);
597                     opus_header_written = 1;
598                 }
599 
600                 enc_bytes_read = opus_enc_encode(&opus_rec, (short*)audio_buf,
601                         enc_buf, bytes_to_read/(2*cfg.audio.channel));
602                 kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0;
603             }
604         }
605 #ifdef HAVE_LIBFDK_AAC
606         else if(!strcmp(cfg.rec.codec, "aac"))
607         {
608 
609             bytes_to_read = aac_rec.info.frameLength * cfg.audio.channel * sizeof(short);
610             while ((rb_filled(&rec_rb)) >= bytes_to_read)
611             {
612                 rb_read_len(&rec_rb, audio_buf, bytes_to_read);
613 
614                 enc_bytes_read = aac_enc_encode(&aac_rec, (short*)audio_buf,
615                         enc_buf, bytes_to_read/(2*cfg.audio.channel), rec_rb.size * sizeof(char)*10);
616                 kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0;
617             }
618         }
619 #endif
620         else
621         {
622 
623             if(rb_filled(&rec_rb) < framepacket_size*sizeof(short))
624                 continue;
625 
626             rb_bytes_read = rb_read(&rec_rb, audio_buf);
627             if(rb_bytes_read == 0)
628                 continue;
629 
630 
631             if(!strcmp(cfg.rec.codec, "mp3"))
632             {
633 
634                 enc_bytes_read = lame_enc_encode(&lame_rec, (short*)audio_buf, enc_buf,
635                         rb_bytes_read/(2*cfg.audio.channel), rec_rb.size*10);
636                 kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0;
637             }
638 
639             if(!strcmp(cfg.rec.codec, "ogg"))
640             {
641                 if(!ogg_header_written)
642                 {
643                     vorbis_enc_write_header(&vorbis_rec);
644                     ogg_header_written = 1;
645                 }
646 
647                 enc_bytes_read = vorbis_enc_encode(&vorbis_rec, (short*)audio_buf,
648                         enc_buf, rb_bytes_read/(2*cfg.audio.channel));
649                 kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0;
650             }
651 
652             if(!strcmp(cfg.rec.codec, "flac"))
653             {
654                 flac_enc_encode(&flac_rec, (short*)audio_buf, rb_bytes_read/sizeof(short)/cfg.audio.channel, cfg.audio.channel);
655                 kbytes_written = flac_enc_get_bytes_written()/1024.0;
656             }
657 
658 
659             if(!strcmp(cfg.rec.codec, "wav"))
660             {
661                 //This does permanently update the WAV header
662                 //so in case of a crash we still have a valid WAV file
663                 wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, 16);
664                 kbytes_written += fwrite(audio_buf, sizeof(char), rb_bytes_read, cfg.rec.fd)/1024.0;
665             }
666         }
667     }
668 
669     if(!strcmp(cfg.rec.codec, "flac"))  // The flac encoder closes the file
670         flac_enc_close(&flac_rec);
671     else
672         fclose(cfg.rec.fd);
673 
674     free(enc_buf);
675     free(audio_buf);
676 
677     return NULL;
678 }
679 
680 
snd_update_vu(void)681 void snd_update_vu(void)
682 {
683     int i;
684     static int lpeak = 0;
685     static int rpeak = 0;
686     static int call_cnt = 0;
687     short *p;
688     float decay = 0.5;
689     static double lavg = 0;
690     static double ravg = 0;
691 
692     p = pa_pcm_buf;
693     for(i = 0; i < framepacket_size; i += cfg.audio.channel)
694     {
695         if(abs(p[i]) > lpeak)
696             lpeak = abs(p[i]);
697         if(abs(p[i+(cfg.audio.channel-1)]) > rpeak)
698             rpeak = abs(p[i+(cfg.audio.channel-1)]);
699     }
700 
701     int mean_peak = lpeak/2 + rpeak/2;
702     float mean_peak_dB = 20*log10(mean_peak/32768.0);
703 
704     if (mean_peak_dB < -cfg.audio.silence_level)
705         silence_detected = true;
706     else
707         silence_detected = false;
708 
709     if (mean_peak_dB > -cfg.audio.signal_level)
710         signal_detected = true;
711     else
712         signal_detected = false;
713 
714     lavg = (decay * lpeak) + (1.0-decay) * lavg;
715     ravg = (decay * rpeak) + (1.0-decay) * ravg;
716 
717     // Update the vu meter UI only every second call of this function.
718     // This reduces the CPU usage by not missing any samples
719     if (call_cnt == 1)
720     {
721         vu_meter((short)round(lavg), (short)round(ravg));
722         call_cnt = 0;
723     }
724     else
725     {
726         call_cnt++;
727         lpeak = 0;
728         rpeak = 0;
729     }
730 
731     pa_new_frames = 0;
732 }
733 
snd_get_devices(int * dev_count)734 snd_dev_t **snd_get_devices(int *dev_count)
735 {
736 	int i, j;
737     int devcount, sr_count, dev_num;
738     bool sr_supported = 0;
739     const PaDeviceInfo *p_di;
740     char info_buf[256];
741     PaStreamParameters pa_params;
742 
743     int sr[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
744 
745     snd_dev_t **dev_list;
746 
747 
748     dev_list = (snd_dev_t**)malloc(100*sizeof(snd_dev_t*));
749 
750 	//100 sound devices should be enough
751     for(i = 0; i < 100; i++)
752         dev_list[i] = (snd_dev_t*)malloc(sizeof(snd_dev_t));
753 
754     dev_list[0]->name = (char*) malloc(strlen(_("Default PCM device (default)"))+1);
755     strcpy(dev_list[0]->name, _("Default PCM device (default)"));
756     dev_list[0]->dev_id = Pa_GetDefaultInputDevice();
757 
758     dev_num = 1;
759 
760 
761     devcount = Pa_GetDeviceCount();
762     if(devcount < 0)
763     {
764         snprintf(info_buf, sizeof(info_buf), "PaError: %s", Pa_GetErrorText(devcount));
765         print_info(info_buf, 1);
766     }
767 
768     for(i = 0; i < devcount && i < 100; i++)
769     {
770         sr_count = 0;
771         p_di = Pa_GetDeviceInfo(i);
772         if(p_di == NULL)
773         {
774             snprintf(info_buf, sizeof(info_buf), _("Error getting device Info (%d)"), i);
775             print_info(info_buf, 1);
776             continue;
777         }
778 
779 
780         //Save only devices which have input Channels
781         if(p_di->maxInputChannels <= 0)
782             continue;
783 
784 
785         const PaHostApiInfo *pa_hostapi = Pa_GetHostApiInfo(p_di->hostApi);
786         pa_params.device = i;
787         pa_params.channelCount = p_di->maxInputChannels;
788         pa_params.sampleFormat = paInt16;
789         pa_params.suggestedLatency = p_di->defaultHighInputLatency;
790         pa_params.hostApiSpecificStreamInfo = NULL;
791 
792         //add the supported samplerates to the device structure
793         for(j = 0; j < sizeof(sr)/sizeof(sr[0]); j++)
794         {
795             if(Pa_IsFormatSupported(&pa_params, NULL, sr[j]) == paFormatIsSupported)
796             {
797                 dev_list[dev_num]->sr_list[sr_count] = sr[j];
798                 sr_count++;
799                 sr_supported = 1;
800             }
801         }
802         //Go to the next device if this one doesn't support at least one of our samplerates
803         if(!sr_supported)
804             continue;
805 
806         dev_list[dev_num]->num_of_sr = sr_count;
807 
808         //Mark the end of the samplerate list for this device with a 0
809         dev_list[dev_num]->sr_list[sr_count] = 0;
810 
811         dev_list[dev_num]->name = (char*) malloc(strlen(p_di->name)+strlen(pa_hostapi->name)+10);
812         dev_list[dev_num]->dev_id = i;
813         dev_list[dev_num]->num_of_channels = p_di->maxInputChannels;
814         snprintf(dev_list[dev_num]->name, strlen(p_di->name)+strlen(pa_hostapi->name)+10, "%d: %s [%s]", dev_num, p_di->name, pa_hostapi->name);
815 
816 
817         //copy the sr_list from the device where the
818         //virtual default device points to
819         if(dev_list[0]->dev_id == dev_list[dev_num]->dev_id)
820         {
821             memcpy(dev_list[0]->sr_list, dev_list[dev_num]->sr_list,
822                     sizeof(dev_list[dev_num]->sr_list));
823 
824             dev_list[0]->num_of_sr = sr_count;
825             dev_list[0]->num_of_channels = p_di->maxInputChannels;
826         }
827 
828 
829         //We need to escape every '/' in the device name
830         //otherwise FLTK will add a submenu for every '/' in the dev list
831         strrpl(&dev_list[dev_num]->name, (char*)"/", (char*)"\\/", MODE_ALL);
832 
833         dev_num++;
834     }//for(i = 0; i < devcount && i < 100; i++)
835 
836     if(dev_num == 1)
837         *dev_count = 0;
838     else
839         *dev_count = dev_num;
840 
841     return dev_list;
842 }
843 
snd_reset_samplerate_conv(int rec_or_stream)844 void snd_reset_samplerate_conv(int rec_or_stream)
845 {
846     int error;
847 
848     if (rec_or_stream == SND_STREAM)
849     {
850         if (srconv_state_stream != NULL)
851         {
852             src_delete(srconv_state_stream);
853             srconv_state_stream = NULL;
854         }
855 
856         srconv_state_stream = src_new(cfg.audio.resample_mode, cfg.audio.channel, &error);
857         if (srconv_state_stream == NULL)
858         {
859             print_info(_("ERROR: Could not initialize samplerate converter"), 0);
860         }
861     }
862 
863     if (rec_or_stream == SND_REC)
864     {
865         if (srconv_state_record != NULL)
866         {
867             src_delete(srconv_state_record);
868             srconv_state_record = NULL;
869         }
870 
871 
872         srconv_state_record = src_new(cfg.audio.resample_mode, cfg.audio.channel, &error);
873         if (srconv_state_record == NULL)
874         {
875             print_info(_("ERROR: Could not initialize samplerate converter"), 0);
876         }
877     }
878 }
879 
snd_get_device_name(int id)880 char *snd_get_device_name(int id)
881 {
882     const PaDeviceInfo *pa_dev_info;
883 
884     pa_dev_info = Pa_GetDeviceInfo(id);
885     if(pa_dev_info == NULL)
886         return NULL;
887     else
888         return strdup(pa_dev_info->name); // Make sure it will be free'd on the caller side
889 }
890 
snd_get_number_of_channels(int id)891 int snd_get_number_of_channels(int id)
892 {
893     const PaDeviceInfo *pa_dev_info;
894 
895     pa_dev_info = Pa_GetDeviceInfo(id);
896     if(pa_dev_info == NULL)
897         return 0;
898     else
899         return pa_dev_info->maxInputChannels;
900 }
901 
snd_close(void)902 void snd_close(void)
903 {
904     Pa_StopStream(stream);
905     Pa_CloseStream(stream);
906     Pa_Terminate();
907 
908     free((void*)srconv_stream.data_in);
909     free(srconv_stream.data_out);
910 
911     free((void*)srconv_record.data_in);
912     free(srconv_record.data_out);
913 
914     free(pa_pcm_buf);
915     free(encode_buf);
916 }
917 
918 
919