Codebase list squeezelite / d8ad375
add configurable silence delay on rate change in similar manner to dop delay Adrian Smith 10 years ago
6 changed file(s) with 80 addition(s) and 59 deletion(s). Raw diff Collapse all Expand all
5555 #if ALSA
5656 " -p <priority>\t\tSet real time priority of output thread (1-99)\n"
5757 #endif
58 " -r <rates>\t\tSpecify sample rates supported by device, enables output device to be off when squeezelite is started; rates = <maxrate> | <minrate>-<maxrate> | <rate1>,<rate2>,<rate3>\n"
58 " -r <rates>[:<delay>]\tSample rates supported, allows output to be off when squeezelite is started; rates = <maxrate>|<minrate>-<maxrate>|<rate1>,<rate2>,<rate3>; delay = optional delay switching rates in ms\n"
5959 #if RESAMPLE
6060 " -R -u [params]\tResample, params = <recipe>:<flags>:<attenuation>:<precision>:<passband_end>:<stopband_start>:<phase_response>,\n"
6161 " \t\t\t recipe = (v|h|m|l|q)(L|I|M)(s) [E|X], E = exception - resample only if native rate not supported, X = async - resample to max rate for device, otherwise to max sync rate\n"
158158 unsigned stream_buf_size = STREAMBUF_SIZE;
159159 unsigned output_buf_size = 0; // set later
160160 unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 };
161 unsigned rate_delay = 0;
161162 char *resample = NULL;
162163 char *output_params = NULL;
163164 #if LINUX
259260 }
260261 break;
261262 case 'r':
262 if (strstr(optarg,",")) {
263 // parse sample rates and sort them
264 char *r = next_param(optarg, ',');
265 unsigned tmp[MAX_SUPPORTED_SAMPLERATES] = { 0 };
266 int i, j;
267 int last = 999999;
268 for (i = 0; r && i < MAX_SUPPORTED_SAMPLERATES; ++i) {
269 tmp[i] = atoi(r);
270 r = next_param(NULL, ',');
271 }
272 for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
273 int largest = 0;
274 for (j = 0; j < MAX_SUPPORTED_SAMPLERATES; ++j) {
275 if (tmp[j] > largest && tmp[j] < last) {
276 largest = tmp[j];
263 {
264 char *rstr = next_param(optarg, ':');
265 char *dstr = next_param(NULL, ':');
266 if (rstr && strstr(rstr, ",")) {
267 // parse sample rates and sort them
268 char *r = next_param(rstr, ',');
269 unsigned tmp[MAX_SUPPORTED_SAMPLERATES] = { 0 };
270 int i, j;
271 int last = 999999;
272 for (i = 0; r && i < MAX_SUPPORTED_SAMPLERATES; ++i) {
273 tmp[i] = atoi(r);
274 r = next_param(NULL, ',');
275 }
276 for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
277 int largest = 0;
278 for (j = 0; j < MAX_SUPPORTED_SAMPLERATES; ++j) {
279 if (tmp[j] > largest && tmp[j] < last) {
280 largest = tmp[j];
281 }
282 }
283 rates[i] = last = largest;
284 }
285 } else if (rstr) {
286 // optstr is <min>-<max> or <max>, extract rates from test rates within this range
287 unsigned ref[] TEST_RATES;
288 char *str1 = next_param(rstr, '-');
289 char *str2 = next_param(NULL, '-');
290 unsigned max = str2 ? atoi(str2) : (str1 ? atoi(str1) : ref[0]);
291 unsigned min = str1 && str2 ? atoi(str1) : 0;
292 unsigned tmp;
293 int i, j;
294 if (max < min) { tmp = max; max = min; min = tmp; }
295 rates[0] = max;
296 for (i = 0, j = 1; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
297 if (ref[i] < rates[j-1] && ref[i] >= min) {
298 rates[j++] = ref[i];
277299 }
278300 }
279 rates[i] = last = largest;
280301 }
281 } else {
282 // optstr is <min>-<max> or <max>, extract rates from test rates within this range
283 unsigned ref[] TEST_RATES;
284 char *str1 = next_param(optarg, '-');
285 char *str2 = next_param(NULL, '-');
286 unsigned max = str2 ? atoi(str2) : (str1 ? atoi(str1) : ref[0]);
287 unsigned min = str1 && str2 ? atoi(str1) : 0;
288 unsigned tmp;
289 int i, j;
290 if (max < min) { tmp = max; max = min; min = tmp; }
291 rates[0] = max;
292 for (i = 0, j = 1; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
293 if (ref[i] < rates[j-1] && ref[i] >= min) {
294 rates[j++] = ref[i];
295 }
302 if (dstr) {
303 rate_delay = atoi(dstr);
296304 }
297305 }
298306 break;
404412 stream_init(log_stream, stream_buf_size);
405413
406414 if (!strcmp(output_device, "-")) {
407 output_init_stdout(log_output, output_buf_size, output_params, rates);
415 output_init_stdout(log_output, output_buf_size, output_params, rates, rate_delay);
408416 } else {
409417 #if ALSA
410 output_init_alsa(log_output, output_device, output_buf_size, output_params, rates, rt_priority);
418 output_init_alsa(log_output, output_device, output_buf_size, output_params, rates, rate_delay, rt_priority);
411419 #endif
412420 #if PORTAUDIO
413 output_init_pa(log_output, output_device, output_buf_size, output_params, rates);
421 output_init_pa(log_output, output_device, output_buf_size, output_params, rates, rate_delay);
414422 #endif
415423 }
416424
118118
119119 if (output.track_start && !silence) {
120120 if (output.track_start == outputbuf->readp) {
121 unsigned delay = 0;
122 if (output.current_sample_rate != output.next_sample_rate) {
123 delay = output.rate_delay;
124 }
125 IF_DSD(
126 if (output.dop != output.next_dop) {
127 delay = output.dop_delay;
128 }
129 )
121130 frames -= size;
122 IF_DSD(
123 if (output.dop != output.next_dop) {
124 if (output.dop_delay) {
125 // add silence delay in two halves, before and after track start and pcm-dop change
126 if (!output.dop_delay_active) {
127 output.pause_frames = output.current_sample_rate * output.dop_delay / 2000;
128 output.dop_delay_active = true; // first delay - don't process track start
129 break;
130 } else {
131 output.pause_frames = output.next_sample_rate * output.dop_delay / 2000;
132 output.dop_delay_active = false; // second delay - process track start
133 }
134 output.state = OUTPUT_PAUSE_FRAMES;
135 }
131 // add silence delay in two halves, before and after track start and rate or pcm-dop change
132 if (delay) {
133 output.state = OUTPUT_PAUSE_FRAMES;
134 if (!output.delay_active) {
135 output.pause_frames = output.current_sample_rate * delay / 2000;
136 output.delay_active = true; // first delay - don't process track start
137 break;
138 } else {
139 output.pause_frames = output.next_sample_rate * delay / 2000;
140 output.delay_active = false; // second delay - process track start
136141 }
137 output.dop = output.next_dop;
138 )
142 }
139143 LOG_INFO("track start sample rate: %u replay_gain: %u", output.next_sample_rate, output.next_replay_gain);
140144 output.frames_played = 0;
141145 output.track_started = true;
142146 output.current_sample_rate = output.next_sample_rate;
147 IF_DSD(
148 output.dop = output.next_dop;
149 )
143150 if (!output.fade == FADE_ACTIVE || !output.fade_mode == FADE_CROSSFADE) {
144151 output.current_replay_gain = output.next_replay_gain;
145152 }
412419 if (output.error_opening) {
413420 output.current_sample_rate = output.default_sample_rate;
414421 }
415 IF_DSD( output.dop_delay_active = false; )
422 IF_DSD( output.delay_active = false; )
416423 }
417424 output.frames_played = 0;
418425 UNLOCK;
610610
611611 static pthread_t thread;
612612
613 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rt_priority) {
613 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[],
614 unsigned rate_delay, unsigned rt_priority) {
614615
615616 unsigned alsa_buffer = ALSA_BUFFER_TIME;
616617 unsigned alsa_period = ALSA_PERIOD_COUNT;
645646 output.period = alsa_period;
646647 output.start_frames = 0;
647648 output.write_cb = &_write_frames;
649 output.rate_delay = rate_delay;
648650
649651 if (alsa_sample_fmt) {
650652 if (!strcmp(alsa_sample_fmt, "32")) alsa.format = SND_PCM_FORMAT_S32_LE;
368368 return ret;
369369 }
370370
371 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[]) {
371 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay) {
372372 PaError err;
373373 unsigned latency = 0;
374374 int osx_playnice = -1;
390390 output.format = 0;
391391 output.start_frames = 0;
392392 output.write_cb = &_write_frames;
393 output.rate_delay = rate_delay;
393394 pa.stream = NULL;
394395
395396 LOG_INFO("requested latency: %u", output.latency);
118118
119119 static thread_type thread;
120120
121 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[]) {
121 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay) {
122122 loglevel = level;
123123
124124 LOG_INFO("init output stdout");
135135 output.format = S32_LE;
136136 output.start_frames = FRAME_BLOCK * 2;
137137 output.write_cb = &_stdout_write_frames;
138 output.rate_delay = rate_delay;
138139
139140 if (params) {
140141 if (!strcmp(params, "32")) output.format = S32_LE;
523523 fade_dir fade_dir;
524524 fade_mode fade_mode; // set by slimproto
525525 unsigned fade_secs; // set by slimproto
526 unsigned rate_delay;
527 bool delay_active;
526528 #if DSD
527529 bool next_dop; // set in decode thread
528530 bool dop;
529531 bool has_dop; // set in dop_init - output device supports dop
530532 unsigned dop_delay; // set in dop_init - delay in ms switching to/from dop
531 bool dop_delay_active;
532533 #endif
533534 };
534535
543544 #if ALSA
544545 void list_devices(void);
545546 bool test_open(const char *device, unsigned rates[]);
546 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rt_priority);
547 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[],
548 unsigned rate_delay, unsigned rt_priority);
547549 void output_close_alsa(void);
548550 #endif
549551
551553 #if PORTAUDIO
552554 void list_devices(void);
553555 bool test_open(const char *device, unsigned rates[]);
554 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[]);
556 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay);
555557 void output_close_pa(void);
556558 void _pa_open(void);
557559 #endif
558560
559561 // output_stdout.c
560 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[]);
562 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay);
561563 void output_close_stdout(void);
562564
563565 // output_pack.c