Hello Tanu, Thanks for the detailed review. I am looking into the changes you have mentioned, will get back to you soon. regards, Dinesh On Wed, May 8, 2013 at 10:52 PM, Tanu Kaskinen <tanu.kaskinen at intel.com> wrote: > Hi Dinesh (is that your first name?), > > Thank you for the patch. I have quite a lot of feedback, but don't take > the criticism personally. > > On Mon, 2013-05-06 at 11:30 +0530, rtdinesh wrote: >> From: DINESH R T <rtdinesh.89 at gmail.com> > > Are you sure you want your name in all-caps? I don't mind it, I just > want to make sure that you're aware that it will look different than > most of the names in "git shortlog -s" output. > >> Extended enable-remixing field with mono-only option which enables remixing only when source/sink is mono. I couldn't simulate the mono scenario in source/sink, so i din't test the code but compiled the code with pulseaduio head. > > Please wrap the commit message at 70-80 characters. > > About testing a mono sink or source: you can load module-null-sink with > argument channels=1 (e.g. "pactl load-module module-null-sink > channels=1"). That will create a mono sink, and its monitor source can > be used as a mono source. You can see the mix matrix for every resampler > in the verbose log. The matrix looks like this: > > D: [pulseaudio] resampler.c: Channel matrix: > D: [pulseaudio] resampler.c: I00 I01 > D: [pulseaudio] resampler.c: +------------ > D: [pulseaudio] resampler.c: O00 | 0.500 0.500 > > I00 and I01 are the input channels and O00 is the output channel (here > I'm playing a stereo stream to a mono sink). > >> >> --- >> src/daemon/daemon-conf.c | 26 ++++++++++++++++++++++---- >> src/daemon/daemon-conf.h | 2 +- >> src/daemon/main.c | 2 +- >> src/pulse/sample.c | 28 ++++++++++++++++++++++++++++ >> src/pulse/sample.h | 19 +++++++++++++++++++ >> src/pulsecore/core.c | 2 +- >> src/pulsecore/core.h | 2 +- >> src/pulsecore/resampler.c | 29 ++++++++++++++++++++++++++--- >> src/pulsecore/resampler.h | 3 ++- >> src/pulsecore/sink-input.c | 8 +++++--- >> src/pulsecore/source-output.c | 8 +++++--- >> 11 files changed, 111 insertions(+), 18 deletions(-) >> >> diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c >> index 2c43cf9..45976b1 100644 >> --- a/src/daemon/daemon-conf.c >> +++ b/src/daemon/daemon-conf.c >> @@ -84,7 +84,7 @@ static const pa_daemon_conf default_conf = { >> .log_meta = FALSE, >> .log_time = FALSE, >> .resample_method = PA_RESAMPLER_AUTO, >> - .disable_remixing = FALSE, >> + .remixing_option = PA_DISABLE_REMIXING, > > This changes the default. The old default "disable_remixing = FALSE" > enables remixing. > >> .disable_lfe_remixing = TRUE, >> .config_file = NULL, >> .use_pid_file = TRUE, >> @@ -511,6 +511,24 @@ static int parse_nice_level(pa_config_parser_state *state) { >> return 0; >> } >> >> + >> + > > Extra empty lines. > >> +static int parse_enable_remixing(pa_config_parser_state *state) { >> + pa_daemon_conf *c; >> + pa_remixing_option_t f; >> + >> + pa_assert(state); >> + >> + c = state->data; >> + >> + if ((f = pa_parse_remixing(state->rvalue)) < 0) { > > This causes a compiler warning, because pa_parse_remixing() is not > declared before it's being used here. Please fix all compiler warnings > before submitting patches. > >> + pa_log(_("[%s:%u] Invalid remixing option '%s'."), state->filename, state->lineno, state->rvalue); >> + return -1; >> + } >> + >> + c->remixing_option = f; >> + return 0; >> +} > > Missing empty line. > >> static int parse_rtprio(pa_config_parser_state *state) { >> #if !defined(OS_IS_WIN32) && defined(HAVE_SCHED_H) >> pa_daemon_conf *c; >> @@ -600,8 +618,8 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { >> { "deferred-volume-extra-delay-usec", >> pa_config_parse_int, &c->deferred_volume_extra_delay_usec, NULL }, >> { "nice-level", parse_nice_level, c, NULL }, >> - { "disable-remixing", pa_config_parse_bool, &c->disable_remixing, NULL }, >> - { "enable-remixing", pa_config_parse_not_bool, &c->disable_remixing, NULL }, >> + { "disable-remixing", parse_enable_remixing, &c->remixing_option, NULL }, >> + { "enable-remixing", parse_enable_remixing, &c->remixing_option, NULL }, > > You can't use the same code to parse both disable-remixing and > enable-remixing, the two options are supposed to have opposite results. > > Handling disable-remixing is a bit tricky, because I don't think > "mono-only" makes sense there. The disable-remixing option is supported > only as legacy, so the only goal is to stay compatible with old > configuration files. Therefore, we should parse it as a boolean > (pa_config_parse_bool() can't be used here, though, because > c->remixing_option is not a boolean). > > Also, on the "enable-remixing" line there's a tab character that > shouldn't be there. > >> { "disable-lfe-remixing", pa_config_parse_bool, &c->disable_lfe_remixing, NULL }, >> { "enable-lfe-remixing", pa_config_parse_not_bool, &c->disable_lfe_remixing, NULL }, >> { "load-default-script-file", pa_config_parse_bool, &c->load_default_script_file, NULL }, >> @@ -790,7 +808,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { >> pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); >> pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); >> pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); >> - pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing)); >> + pa_strbuf_printf(s, "enable-remixing = %s\n", pa_remixing_option_to_string(c->remixing_option)); > > This causes compiler warnings too: > > daemon/daemon-conf.c: In function ?pa_daemon_conf_dump?: > daemon/daemon-conf.c:811:5: warning: implicit declaration of function ?pa_remixing_option_to_string? [-Wimplicit-function-declaration] > daemon/daemon-conf.c:811:5: warning: format ?%s? expects argument of type ?char *?, but argument 3 has type ?int? [-Wformat] > >> pa_strbuf_printf(s, "enable-lfe-remixing = %s\n", pa_yes_no(!c->disable_lfe_remixing)); >> pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); >> pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); >> diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h >> index faf2540..da42cfc 100644 >> --- a/src/daemon/daemon-conf.h >> +++ b/src/daemon/daemon-conf.h >> @@ -68,7 +68,6 @@ typedef struct pa_daemon_conf { >> system_instance, >> no_cpu_limit, >> disable_shm, >> - disable_remixing, >> disable_lfe_remixing, >> load_default_script_file, >> disallow_exit, >> @@ -84,6 +83,7 @@ typedef struct pa_daemon_conf { >> realtime_priority, >> nice_level, >> resample_method; >> + pa_remixing_option_t remixing_option; > > I think "remixing_mode" would be slightly more descriptive name for the > variable, and similarly pa_remixing_mode_t for the enum type. > >> char *script_commands, *dl_search_path, *default_script_file; >> pa_log_target_t log_target; >> pa_log_level_t log_level; >> diff --git a/src/daemon/main.c b/src/daemon/main.c >> index c18524f..6f8c160 100644 >> --- a/src/daemon/main.c >> +++ b/src/daemon/main.c >> @@ -1026,7 +1026,7 @@ int main(int argc, char *argv[]) { >> c->resample_method = conf->resample_method; >> c->realtime_priority = conf->realtime_priority; >> c->realtime_scheduling = !!conf->realtime_scheduling; >> - c->disable_remixing = !!conf->disable_remixing; >> + c->remixing_option = conf->remixing_option; >> c->disable_lfe_remixing = !!conf->disable_lfe_remixing; >> c->deferred_volume = !!conf->deferred_volume; >> c->running_as_daemon = !!conf->daemonize; >> diff --git a/src/pulse/sample.c b/src/pulse/sample.c >> index b613612..cbb2da7 100644 >> --- a/src/pulse/sample.c >> +++ b/src/pulse/sample.c >> @@ -157,6 +157,18 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) { >> >> return table[f]; >> } >> +const char *pa_remixing_option_to_string(pa_remixing_option_t f) { > > I don't think sample.c is the right place for this function. I suggest > that you put this in resampler.c instead. > > "f" as an argument name seems pretty random. Please use "o" or "option" > instead (or "m" or "mode", if pa_remixing_option_t gets renamed to > pa_remixing_mode_t). > >> + static const char* const table[]= { >> + [PA_DISABLE_REMIXING] = "NO", >> + [PA_ENABLE_REMIXING] = "YES", >> + [PA_MONO_ONLY] = "MONO-ONLY" > > I'd prefer lower-case strings. > >> + }; >> + >> + if (f < 0 || f >= PA_REMIXING_MAX) >> + return NULL; > > You can replace this with an assertion, because it's a bug in our own > code if the argument is ever invalid. > >> + >> + return table[f]; >> +} >> >> char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { >> pa_assert(s); >> @@ -244,6 +256,22 @@ pa_sample_format_t pa_parse_sample_format(const char *format) { >> return PA_SAMPLE_INVALID; >> } >> >> + >> +pa_remixing_option_t pa_parse_remixing(const char *format){ > > Move this to resampler.c too. And rename it to pa_parse_remixing_mode. > > The argument name seems to be copy-pasted from somewhere else; it > doesn't make sense in this context. > >> + pa_assert(format); >> + if (strcasecmp(format, "mono-only") == 0) >> + return PA_MONO_ONLY; >> + else if (strcasecmp(format, "yes") == 0) >> + return PA_ENABLE_REMIXING; >> + else if (strcasecmp(format,"true") == 0) >> + return PA_ENABLE_REMIXING; >> + else if(strcasecmp(format, "no") == 0) >> + return PA_DISABLE_REMIXING; >> + else if(strcasecmp(format, "false") == 0) >> + return PA_DISABLE_REMIXING; > > It would be simpler to first try pa_parse_boolean(), and if that fails, > then use strcasecmp(mode, "mono-only"). > >> + >> + return PA_REMIXING_INVALID; > > Instead of returning INVALID, please return -1 to indicate an error. The > function can take a pa_remixing_mode_t pointer as an argument for > returning the actual mode. > >> +} >> int pa_sample_format_is_le(pa_sample_format_t f) { >> pa_assert(f >= PA_SAMPLE_U8); >> pa_assert(f < PA_SAMPLE_MAX); >> diff --git a/src/pulse/sample.h b/src/pulse/sample.h >> index 9067951..65272a0 100644 >> --- a/src/pulse/sample.h >> +++ b/src/pulse/sample.h >> @@ -180,6 +180,21 @@ typedef enum pa_sample_format { >> /**< An invalid value */ >> } pa_sample_format_t; >> >> +/* Remixing Options */ > > This isn't a very useful comment. If you don't have anything non-obvious > to say, don't write a comment at all. > >> +typedef enum pa_remixing_option{ > > This can be moved to resampler.h, and as I already mentioned, I'd prefer > pa_remixing_mode as the name. > > Also, missing space before {. > >> + /* ENable Remixing */ > > No tabs, please. "Remixing" shouldn't start with upper-case R. > >> + PA_ENABLE_REMIXING=0, > > Enumeration values should have proper prefixes, for example, > PA_REMIXING_MODE_ENABLE (PA_REMIXING_MODE_ is the prefix). > >> + /* Enable Remix if input/output/both is mono-only */ > > s/Remix/remixing/ > > Extra space after "both". > >> + PA_MONO_ONLY=1, >> + /* Disable Remixing */ >> + PA_DISABLE_REMIXING=2, >> + /*Upper limit of valid remixing type */ >> + PA_REMIXING_MAX=4, > > Why 4? This isn't a flag enumeration, so you don't have to specify any > values yourself. > >> + >> + PA_REMIXING_INVALID = -1 > > This is not necessary. > >> +}pa_remixing_option_t; > > Missing space after }. > >> + >> + >> #ifdef WORDS_BIGENDIAN >> /** Signed 16 Bit PCM, native endian */ >> #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE >> @@ -244,6 +259,10 @@ typedef enum pa_sample_format { >> #define PA_SAMPLE_S24BE PA_SAMPLE_S24BE >> #define PA_SAMPLE_S24_32LE PA_SAMPLE_S24_32LE >> #define PA_SAMPLE_S24_32BE PA_SAMPLE_S24_32BE >> + >> +#define PA_ENABLE_REMIXING PA_ENABLE_REMIXING >> +#define PA_DISABLE_REMIXING PA_DISABLE_REMIXING >> +#define PA_MONO_ONLY PA_MONO_ONLY > > These won't be needed after moving the enumeration to resampler.h > (sample.h is part of the public API, which requires some special > treatment). > >> /** \endcond */ >> >> /** A sample format and attribute specification */ >> diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c >> index 2ca50c2..330fe04 100644 >> --- a/src/pulsecore/core.c >> +++ b/src/pulsecore/core.c >> @@ -138,7 +138,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) { >> c->running_as_daemon = FALSE; >> c->realtime_scheduling = FALSE; >> c->realtime_priority = 5; >> - c->disable_remixing = FALSE; >> + c->remixing_option = PA_DISABLE_REMIXING; > > This changes the default again from enabled to disabled. > >> c->disable_lfe_remixing = FALSE; >> c->deferred_volume = TRUE; >> c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 1; >> diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h >> index a8cff5c..0f14878 100644 >> --- a/src/pulsecore/core.h >> +++ b/src/pulsecore/core.h >> @@ -174,11 +174,11 @@ struct pa_core { >> pa_bool_t disallow_exit:1; >> pa_bool_t running_as_daemon:1; >> pa_bool_t realtime_scheduling:1; >> - pa_bool_t disable_remixing:1; >> pa_bool_t disable_lfe_remixing:1; >> pa_bool_t deferred_volume:1; >> >> pa_resample_method_t resample_method; >> + pa_remixing_option_t remixing_option; > > I'd prefer remixing_mode as the variable name here too. > >> int realtime_priority; >> >> pa_server_type_t server_type; >> diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c >> index bc45f06..53f4b03 100644 >> --- a/src/pulsecore/resampler.c >> +++ b/src/pulsecore/resampler.c >> @@ -203,7 +203,6 @@ pa_resampler* pa_resampler_new( >> pa_resample_flags_t flags) { >> >> pa_resampler *r = NULL; >> - > > No good reason to remove this empty line. The convention is to have an > empty line between the function's variable declarations and the initial > assertions. > >> pa_assert(pool); >> pa_assert(a); >> pa_assert(b); >> @@ -700,7 +699,7 @@ static void calc_map_table(pa_resampler *r) { >> m->map_table_f[oc][ic] = 1.0f; >> } >> } >> - } else { >> + }else { > > Don't do that. > >> >> /* OK, we shall do the full monty: upmixing and downmixing. Our >> * algorithm is relatively simple, does not do spacialization, delay >> @@ -770,11 +769,35 @@ static void calc_map_table(pa_resampler *r) { >> ic_unconnected_left = 0, >> ic_unconnected_right = 0, >> ic_unconnected_center = 0, >> - ic_unconnected_lfe = 0; >> + ic_unconnected_lfe = 0, >> + c; >> bool ic_unconnected_center_mixed_in = 0; >> + bool input_is_mono_only = true; >> + bool output_is_mono_only = true; >> >> pa_assert(remix); >> >> + if(r->flags & PA_RESAMPLER_MONO_ONLY){ >> + >> + for (c = 0; c < r->i_cm.channels; c++) { >> + if (r->i_cm.map[c] != PA_CHANNEL_POSITION_MONO) { >> + input_is_mono_only = false; >> + break; >> + } >> + } >> + >> + for (c = 0; c < r->o_cm.channels; c++) { >> + if (r->o_cm.map[c] != PA_CHANNEL_POSITION_MONO) { >> + output_is_mono_only = false; >> + break; >> + } >> + } >> + >> + if ((!input_is_mono_only) || (!output_is_mono_only)) >> + return; >> + } >> + >> + >> for (ic = 0; ic < n_ic; ic++) { >> if (on_left(r->i_cm.map[ic])) >> ic_left++; >> diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h >> index 742de6a..1d09ff4 100644 >> --- a/src/pulsecore/resampler.h >> +++ b/src/pulsecore/resampler.h >> @@ -52,7 +52,8 @@ typedef enum pa_resample_flags { >> PA_RESAMPLER_VARIABLE_RATE = 0x0001U, >> PA_RESAMPLER_NO_REMAP = 0x0002U, /* implies NO_REMIX */ >> PA_RESAMPLER_NO_REMIX = 0x0004U, >> - PA_RESAMPLER_NO_LFE = 0x0008U >> + PA_RESAMPLER_NO_LFE = 0x0008U, >> + PA_RESAMPLER_MONO_ONLY = 0x0010U > > I think it would be better to not have another flag here, because it's > mutually exclusive with PA_RESAMPLER_NO_REMIX. pa_resampler_new() > interface could be changed so that it takes a remixing mode as a > parameter, and then stores a boolean in pa_resampler that indicates > whether remixing should be done or not. Then the NO_REMIX flag could be > removed too. > > This also allows the code that you added to calc_map_table() to be moved > to pa_resampler_new(). calc_map_table() is complicated enough already as > it is. > > -- > Tanu > > --------------------------------------------------------------------- > Intel Finland Oy > Registered Address: PL 281, 00181 Helsinki > Business Identity Code: 0357606 - 4 > Domiciled in Helsinki > > This e-mail and any attachments may contain confidential material for > the sole use of the intended recipient(s). Any review or distribution > by others is strictly prohibited. If you are not the intended > recipient, please contact the sender and delete all copies.