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