adapter-control: add support of scale volume ramp param

This commit is contained in:
Ashok Sidipotu 2023-03-28 10:41:04 +05:30 committed by Wim Taymans
parent 8bfafaeca2
commit e75fe4d469

View file

@ -54,10 +54,14 @@ static SPA_LOG_IMPL(default_log);
#define DEFAULT_DEVICE "hw:0,0"
#define LINEAR "linear"
#define CUBIC "cubic"
#define DEFAULT_SCALE SPA_AUDIO_VOLUME_RAMP_LINEAR
#define NON_NATIVE "non-native"
#define NATIVE "native"
#define DEFAULT_MODE NON_NATIVE
#define INVALID -1
struct buffer {
struct spa_buffer buffer;
@ -107,11 +111,12 @@ struct data {
const char *alsa_device;
const char *mode;
enum spa_audio_volume_ramp_scale scale;
int32_t volume_ramp_samples;
int32_t volume_ramp_step_samples;
int32_t volume_ramp_time;
int32_t volume_ramp_step_time;
uint32_t volume_ramp_samples;
uint32_t volume_ramp_step_samples;
uint32_t volume_ramp_time;
uint32_t volume_ramp_step_time;
bool running;
pthread_t thread;
@ -303,13 +308,14 @@ exit_cleanup:
dlclose(hnd);
return res;
}
static unsigned int get_ramp_samples(struct data *data)
{
if (data->volume_ramp_samples != INVALID)
if (data->volume_ramp_samples)
return data->volume_ramp_samples;
else if (data->volume_ramp_time != INVALID) {
else if (data->volume_ramp_time) {
unsigned int samples = (data->volume_ramp_time * 48000) / 1000;
printf("volume ramp samples calculated from time %d\n", samples);
// printf("volume ramp samples calculated from time %d\n", samples);
return samples;
}
return 0;
@ -317,17 +323,26 @@ static unsigned int get_ramp_samples(struct data *data)
static unsigned int get_ramp_step_samples(struct data *data)
{
if (data->volume_ramp_step_samples != INVALID)
if (data->volume_ramp_step_samples)
return data->volume_ramp_step_samples;
else if (data->volume_ramp_step_time != INVALID) {
else if (data->volume_ramp_step_time) {
/* convert the step time which is in nano seconds to seconds */
unsigned int samples = (data->volume_ramp_step_time / 1000) * (48000 / 1000);
// printf("volume ramp samples calculated from time %d\n", samples);
return samples;
}
return 0;
}
static double get_volume_at_scale(struct data *data)
{
if (data->scale == SPA_AUDIO_VOLUME_RAMP_LINEAR)
return data->volume_accum;
else if (data->scale == SPA_AUDIO_VOLUME_RAMP_CUBIC)
return (data->volume_accum * data->volume_accum * data->volume_accum);
return 0.0;
}
static int fade_in(struct data *data)
{
printf("fading in\n");
@ -345,11 +360,11 @@ static int fade_in(struct data *data)
spa_pod_builder_push_sequence(&b, &f[0], 0);
data->volume_offs = 0;
do {
// printf("volume level %f offset %d\n", data->volume_accum, data->volume_offs);
// printf("volume level %f offset %d\n", get_volume_at_scale(data), data->volume_offs);
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
SPA_PROP_volume, SPA_POD_Float(get_volume_at_scale(data)));
data->volume_accum += step_size;
data->volume_offs += ramp_step_samples;
} while (data->volume_accum < 1.0);
@ -392,11 +407,11 @@ static int fade_out(struct data *data)
spa_pod_builder_push_sequence(&b, &f[0], 0);
data->volume_offs = ramp_step_samples;
do {
// printf("volume level %f offset %d\n", data->volume_accum, data->volume_offs);
// printf("volume level %f offset %d\n", get_volume_at_scale(data), data->volume_offs);
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
SPA_PROP_volume, SPA_POD_Float(get_volume_at_scale(data)));
data->volume_accum -= step_size;
data->volume_offs += ramp_step_samples;
} while (data->volume_accum > 0.0);
@ -638,7 +653,8 @@ static int make_nodes(struct data *data)
SPA_PROP_volumeRampSamples, SPA_POD_Int(data->volume_ramp_samples),
SPA_PROP_volumeRampStepSamples, SPA_POD_Int(data->volume_ramp_step_samples),
SPA_PROP_volumeRampTime, SPA_POD_Int(data->volume_ramp_time),
SPA_PROP_volumeRampStepTime, SPA_POD_Int(data->volume_ramp_step_time));
SPA_PROP_volumeRampStepTime, SPA_POD_Int(data->volume_ramp_step_time),
SPA_PROP_volumeRampScale, SPA_POD_Id(data->scale));
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
printf("can't call volramp set params %d\n", res);
return res;
@ -890,6 +906,17 @@ static void run_async_sink(struct data *data)
printf("got error %d\n", res);
}
static char *getscale(uint32_t scale)
{
char *scale_s = NULL;
if (scale == SPA_AUDIO_VOLUME_RAMP_LINEAR)
scale_s = LINEAR;
else if (scale == SPA_AUDIO_VOLUME_RAMP_CUBIC)
scale_s = CUBIC;
return scale_s;
}
static void show_help(struct data *data, const char *name, bool error)
{
fprintf(error ? stderr : stdout, "%s [options] [command]\n"
@ -900,7 +927,7 @@ static void show_help(struct data *data, const char *name, bool error)
" -a, --ramp-step-samples SPA_PROP_volumeRampStepSamples(Step or incremental Samples to ramp the volume over)(default %d)\n"
" -t, --ramp-time SPA_PROP_volumeRampTime(Time to ramp the volume over in msec)(default %d)\n"
" -i, --ramp-step-time SPA_PROP_volumeRampStepTime(Step or incremental Time to ramp the volume over in nano sec)(default %d)\n"
" -c, --ramp-scale SPA_PROP_volumeRampScale(the scale or graph to used to ramp the volume)\n"
" -c, --scale SPA_PROP_volumeRampScale(the scale or graph to used to ramp the volume)(\"linear\" or \"cubic\")(default %s)\n"
"examples:\n"
"adapter-control\n"
"-->when invoked with out any params, ramps volume with default values\n"
@ -910,19 +937,28 @@ static void show_help(struct data *data, const char *name, bool error)
"-->ramps volume on \"hw:0,0\" alsa device over 70000 samples\n"
"adapter-control --alsa-device=hw:0,0 --ramp-samples=70000 --mode=native\n"
"-->ramps volume on \"hw:0,0\" alsa device over 70000 samples in native mode\n"
"make;./builddir/spa/examples/adapter-control --alsa-device=hw:0,0 --ramp-time=1000 --mode=native\n"
"adapter-control --alsa-device=hw:0,0 --ramp-time=1000 --mode=native\n"
"-->ramps volume on \"hw:0,0\" alsa device over 1000 msec in native mode\n"
"make;./builddir/spa/examples/adapter-control --alsa-device=hw:0,0 --ramp-time=1000 --ramp-step-time=5000 --mode=native\n"
"adapter-control --alsa-device=hw:0,0 --ramp-time=1000 --ramp-step-time=5000 --mode=native\n"
"-->ramps volume on \"hw:0,0\" alsa device over 1000 msec in steps of 5000 nano seconds(5 msec)in native mode\n"
"make;./builddir/spa/examples/adapter-control --alsa-device=hw:0,0 --ramp-samples=70000 --ramp-step-samples=200 --mode=native\n"
"-->ramps volume on \"hw:0,0\" alsa device over 70000 samples with a step size of 200 samples in native mode\n",
"adapter-control --alsa-device=hw:0,0 --ramp-samples=70000 --ramp-step-samples=200 --mode=native\n"
"-->ramps volume on \"hw:0,0\" alsa device over 70000 samples with a step size of 200 samples in native mode\n"
"adapter-control --alsa-device=hw:1,0 --scale=linear\n"
"-->ramps volume on \"hw:1,0\" in linear volume scale, one can leave choose to not use the linear scale here as it is the default\n"
"adapter-control --alsa-device=hw:1,0 --ramp-samples=70000 --scale=cubic\n"
"-->ramps volume on \"hw:1,0\" alsa device over 70000 samples deploying cubic volume scale\n"
"adapter-control --alsa-device=hw:1,0 --ramp-samples=70000 --mode=native --scale=cubic\n"
"-->ramps volume on \"hw:1,0\" alsa device over 70000 samples deploying cubic volume scale in native mode\n"
"adapter-control --alsa-device=hw:1,0 --ramp-time=3000 --scale=cubic --mode=native\n"
"-->ramps volume on \"hw:1,0\" alsa device over 3 seconds samples with a step size of 200 samples in native mode\n",
name,
DEFAULT_DEVICE,
DEFAULT_MODE,
DEFAULT_RAMP_SAMPLES,
DEFAULT_RAMP_STEP_SAMPLES,
DEFAULT_RAMP_TIME,
DEFAULT_RAMP_STEP_TIME);
DEFAULT_RAMP_STEP_TIME,
getscale(DEFAULT_SCALE));
}
int main(int argc, char *argv[])
@ -934,10 +970,9 @@ int main(int argc, char *argv[])
/* default values*/
data.volume_ramp_samples = DEFAULT_RAMP_SAMPLES;
data.volume_ramp_step_samples = DEFAULT_RAMP_STEP_SAMPLES;
data.volume_ramp_time = DEFAULT_RAMP_TIME;
data.volume_ramp_step_time = DEFAULT_RAMP_STEP_TIME;
data.alsa_device = DEFAULT_DEVICE;
data.mode = DEFAULT_MODE;
data.scale = DEFAULT_SCALE;
static const struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
@ -947,13 +982,13 @@ int main(int argc, char *argv[])
{ "ramp-time", required_argument, NULL, 't' },
{ "ramp-step-samples", required_argument, NULL, 'a' },
{ "ramp-step-time", required_argument, NULL, 'i' },
{ "scale", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0}
};
setlocale(LC_ALL, "");
while ((c = getopt_long(argc, argv, "hdmstia:", long_options, NULL)) != -1) {
printf("\nhere_we_are %s %s(%u) c=%c \n",__FILE__,__func__,__LINE__, c);
while ((c = getopt_long(argc, argv, "hdmstiac:", long_options, NULL)) != -1) {
switch (c) {
case 'h':
show_help(&data, argv[0], false);
@ -964,28 +999,34 @@ int main(int argc, char *argv[])
else
data.mode = optarg;
break;
case 'c':
if (!spa_streq (optarg, LINEAR) && !spa_streq (optarg, CUBIC))
printf("Invalid Scale(\"%s\"), using default(\"%s\")\n", optarg,
getscale(DEFAULT_SCALE));
else
if (spa_streq (optarg, LINEAR))
data.scale = SPA_AUDIO_VOLUME_RAMP_LINEAR;
else if (spa_streq (optarg, CUBIC))
data.scale = SPA_AUDIO_VOLUME_RAMP_CUBIC;
break;
case 'd':
data.alsa_device = optarg;
break;
case 's':
data.volume_ramp_samples = atoi(optarg);
data.volume_ramp_time = INVALID;
data.volume_ramp_step_time = INVALID;
break;
case 't':
data.volume_ramp_time = atoi(optarg);
data.volume_ramp_samples = INVALID;
data.volume_ramp_step_samples = INVALID;
if (!data.volume_ramp_step_time)
data.volume_ramp_step_time = DEFAULT_RAMP_STEP_TIME;
data.volume_ramp_samples = 0;
data.volume_ramp_step_samples = 0;
break;
case 'a':
data.volume_ramp_step_samples = atoi(optarg);
data.volume_ramp_step_time = INVALID;
data.volume_ramp_time = INVALID;
break;
case 'i':
data.volume_ramp_step_time = atoi(optarg);
data.volume_ramp_samples = INVALID;
data.volume_ramp_step_samples = INVALID;
break;
default:
show_help(&data, argv[0], true);
@ -1013,12 +1054,12 @@ int main(int argc, char *argv[])
}
printf("using %s mode\n", data.mode);
if ((data.volume_ramp_samples != INVALID) && (data.volume_ramp_step_samples != INVALID))
printf("using %d samples with a step size of %d samples to ramp volume\n",
data.volume_ramp_samples, data.volume_ramp_step_samples);
else if ((data.volume_ramp_time != INVALID) && (data.volume_ramp_step_time != INVALID))
printf("using %d msec with a step size of %d msec to ramp volume\n",
data.volume_ramp_time, (data.volume_ramp_step_time/1000));
if (data.volume_ramp_samples && data.volume_ramp_step_samples)
printf("using %d samples with a step size of %d samples to ramp volume at %s scale\n",
data.volume_ramp_samples, data.volume_ramp_step_samples, getscale(data.scale));
else if (data.volume_ramp_time && data.volume_ramp_step_time)
printf("using %d msec with a step size of %d msec to ramp volume at %s scale\n",
data.volume_ramp_time, (data.volume_ramp_step_time/1000), getscale(data.scale));
spa_loop_control_enter(data.control);
run_async_sink(&data);