Skip to content

Commit be31422

Browse files
committed
effect: Add NO_DITHER flag.
1 parent bca5323 commit be31422

File tree

5 files changed

+27
-8
lines changed

5 files changed

+27
-8
lines changed

dsp.c

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of dsp.
33
*
4-
* Copyright (c) 2013-2024 Michael Barbour <[email protected]>
4+
* Copyright (c) 2013-2025 Michael Barbour <[email protected]>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -38,9 +38,9 @@
3838
(((x) == 0) ? (in_codecs.head == NULL || input_mode == INPUT_MODE_SEQUENCE) ? DEFAULT_FS : in_codecs.head->fs : (x))
3939
#define CHOOSE_INPUT_CHANNELS(x) \
4040
(((x) == 0) ? (in_codecs.head == NULL || input_mode == INPUT_MODE_SEQUENCE) ? DEFAULT_CHANNELS : in_codecs.head->channels : (x))
41-
#define SHOULD_DITHER(in, out, has_effects) \
41+
#define SHOULD_DITHER(in, out, chain_dither) \
4242
(force_dither != -1 && ((out)->hints & CODEC_HINT_CAN_DITHER) && \
43-
(force_dither == 1 || ((out)->prec < 24 && ((has_effects) || (in)->prec > (out)->prec || !((in)->hints & CODEC_HINT_CAN_DITHER)))))
43+
(force_dither == 1 || ((out)->prec < 24 && ((chain_dither) || (in)->prec > (out)->prec || !((in)->hints & CODEC_HINT_CAN_DITHER)))))
4444
#define TIME_FMT "%.2zd:%.2zd:%05.2lf"
4545
#define TIME_FMT_ARGS(frames, fs) \
4646
((frames) != -1) ? (frames) / (fs) / 3600 : 0, \
@@ -625,6 +625,7 @@ static void handle_tstp(int is_paused)
625625
if (init_out_codec(&out_p, &stream, -1, write_buf_blocks) == NULL) \
626626
cleanup_and_exit(1); \
627627
} \
628+
chain_dither = effects_chain_needs_dither(&chain); \
628629
} while (0)
629630

630631
#define REALLOC_BUFS \
@@ -639,7 +640,8 @@ static void handle_tstp(int is_paused)
639640

640641
int main(int argc, char *argv[])
641642
{
642-
int is_paused = 0, do_dither = 0, chain_start, chain_argc, term_sig, err;
643+
int is_paused = 0, do_dither = 0, term_sig, err;
644+
int chain_start, chain_argc, chain_dither;
643645
int read_buf_blocks = 0;
644646
double in_time = 0.0;
645647
struct codec *c = NULL;
@@ -753,11 +755,12 @@ int main(int argc, char *argv[])
753755
int buf_len = 0;
754756
REALLOC_BUFS;
755757
dither_mult = tpdf_dither_get_mult(out_codec->prec);
758+
chain_dither = effects_chain_needs_dither(&chain);
756759

757760
while (in_codecs.head != NULL) {
758761
ssize_t r, pos = 0;
759762
int k = 0;
760-
do_dither = SHOULD_DITHER(in_codecs.head, out_codec, chain.head != NULL);
763+
do_dither = SHOULD_DITHER(in_codecs.head, out_codec, chain_dither);
761764
LOG_FMT(LL_VERBOSE, "info: dither %s", (do_dither) ? "on" : "off" );
762765
print_io_info(in_codecs.head, LL_NORMAL, "input");
763766
print_progress(in_codecs.head, pos, is_paused, 1);
@@ -826,7 +829,7 @@ int main(int argc, char *argv[])
826829
}
827830
else REOPEN_OUTPUT;
828831
REALLOC_BUFS;
829-
do_dither = SHOULD_DITHER(in_codecs.head, out_codec, chain.head != NULL);
832+
do_dither = SHOULD_DITHER(in_codecs.head, out_codec, chain_dither);
830833
LOG_FMT(LL_VERBOSE, "info: dither %s", (do_dither) ? "on" : "off" );
831834
break;
832835
case 'v':

effect.c

+11
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,17 @@ ssize_t get_effects_chain_max_out_frames(struct effects_chain *chain, ssize_t in
401401
return frames;
402402
}
403403

404+
int effects_chain_needs_dither(struct effects_chain *chain)
405+
{
406+
struct effect *e = chain->head;
407+
while (e != NULL) {
408+
if (!(e->flags & EFFECT_FLAG_NO_DITHER))
409+
return 1;
410+
e = e->next;
411+
}
412+
return 0;
413+
}
414+
404415
sample_t * run_effects_chain(struct effect *e, ssize_t *frames, sample_t *buf1, sample_t *buf2)
405416
{
406417
sample_t *ibuf = buf1, *obuf = buf2, *tmp;

effect.h

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct effect_info {
3232
enum {
3333
EFFECT_FLAG_PLOT_MIX = 1<<0,
3434
EFFECT_FLAG_OPT_REORDERABLE = 1<<1,
35+
EFFECT_FLAG_NO_DITHER = 1<<2, /* does not modify the signal such that dither is useful */
3536
};
3637

3738
struct effect {
@@ -72,6 +73,7 @@ void append_effect(struct effects_chain *, struct effect *);
7273
int build_effects_chain(int, const char *const *, struct effects_chain *, struct stream_info *, const char *);
7374
ssize_t get_effects_chain_buffer_len(struct effects_chain *, ssize_t, int);
7475
ssize_t get_effects_chain_max_out_frames(struct effects_chain *, ssize_t);
76+
int effects_chain_needs_dither(struct effects_chain *);
7577
sample_t * run_effects_chain(struct effect *, ssize_t *, sample_t *, sample_t *);
7678
double get_effects_chain_delay(struct effects_chain *);
7779
void reset_effects_chain(struct effects_chain *);

remix.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,15 @@ struct effect * remix_effect_init(const struct effect_info *ei, const struct str
138138

139139
state = calloc(1, sizeof(struct remix_state));
140140
state->channel_selectors = calloc(out_channels, sizeof(char *));
141-
int use_run_1a = 1, use_run_4 = 1;
141+
int use_run_1a = 1, use_run_4 = 1, set_no_dither = 1;
142142
for (int k = 0, i = 0, ch = 0; k < out_channels; ++k, ++ch) {
143143
state->channel_selectors[k] = NEW_SELECTOR(istream->channels);
144144
if (ch >= istream->channels || GET_BIT(channel_selector, ch)) {
145145
if (i < n_selectors) {
146146
if (strcmp(argv[i+1], ".") != 0 && parse_selector_masked(argv[i+1], state->channel_selectors[k], channel_selector, istream->channels))
147147
goto fail;
148148
const int n_sel = num_bits_set(state->channel_selectors[k], istream->channels);
149+
if (n_sel > 1) set_no_dither = 0;
149150
if (n_sel != 1) use_run_1a = 0;
150151
if (n_sel > 4) use_run_4 = 0;
151152
++i;
@@ -170,6 +171,7 @@ struct effect * remix_effect_init(const struct effect_info *ei, const struct str
170171
e->istream.channels = istream->channels;
171172
e->ostream.channels = out_channels;
172173
e->flags |= EFFECT_FLAG_PLOT_MIX;
174+
if (set_no_dither) e->flags |= EFFECT_FLAG_NO_DITHER;
173175
if (use_run_1a) {
174176
state->fast_sel.s1 = calloc(out_channels, sizeof(int));
175177
for (int k = 0; k < out_channels; ++k) {

stats.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of dsp.
33
*
4-
* Copyright (c) 2014-2024 Michael Barbour <[email protected]>
4+
* Copyright (c) 2014-2025 Michael Barbour <[email protected]>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -127,6 +127,7 @@ struct effect * stats_effect_init(const struct effect_info *ei, const struct str
127127
e->name = ei->name;
128128
e->istream.fs = e->ostream.fs = istream->fs;
129129
e->istream.channels = e->ostream.channels = istream->channels;
130+
e->flags |= EFFECT_FLAG_NO_DITHER;
130131
e->run = stats_effect_run;
131132
e->plot = stats_effect_plot;
132133
e->destroy = stats_effect_destroy;

0 commit comments

Comments
 (0)