adapter-control: add support for volume ramp time params

- Add support for both native and non-native modes
- Add "examples" in the help text
This commit is contained in:
Ashok Sidipotu 2023-03-24 13:56:27 +05:30 committed by Wim Taymans
parent b0f6c4a8c0
commit 7b91d506f1

View file

@ -46,13 +46,18 @@ static SPA_LOG_IMPL(default_log);
#define MIN_LATENCY 1024 #define MIN_LATENCY 1024
#define CONTROL_BUFFER_SIZE 32768 #define CONTROL_BUFFER_SIZE 32768
#define DEFAULT_SAMPLES (64*1*1024) #define DEFAULT_RAMP_SAMPLES (64*1*1024)
#define DEFAULT_STEP_SAMPLES 200 #define DEFAULT_RAMP_STEP_SAMPLES 200
#define DEFAULT_RAMP_TIME 2000 // 2 seconds
#define DEFAULT_RAMP_STEP_TIME 5000 // 5 milli seconds
#define DEFAULT_DEVICE "hw:0,0" #define DEFAULT_DEVICE "hw:0,0"
#define NON_NATIVE "non-native" #define NON_NATIVE "non-native"
#define NATIVE "native" #define NATIVE "native"
#define DEFAULT_MODE NON_NATIVE #define DEFAULT_MODE NON_NATIVE
#define INVALID -1
struct buffer { struct buffer {
struct spa_buffer buffer; struct spa_buffer buffer;
@ -103,10 +108,10 @@ struct data {
const char *mode; const char *mode;
uint32_t volume_ramp_samples; int32_t volume_ramp_samples;
uint32_t volume_ramp_step_samples; int32_t volume_ramp_step_samples;
uint32_t volume_ramp_time; int32_t volume_ramp_time;
uint32_t volume_ramp_step_time; int32_t volume_ramp_step_time;
bool running; bool running;
pthread_t thread; pthread_t thread;
@ -298,6 +303,30 @@ exit_cleanup:
dlclose(hnd); dlclose(hnd);
return res; return res;
} }
static unsigned int get_ramp_samples(struct data *data)
{
if (data->volume_ramp_samples != INVALID)
return data->volume_ramp_samples;
else if (data->volume_ramp_time != INVALID) {
unsigned int samples = (data->volume_ramp_time * 48000) / 1000;
printf("volume ramp samples calculated from time %d\n", samples);
return samples;
}
return 0;
}
static unsigned int get_ramp_step_samples(struct data *data)
{
if (data->volume_ramp_step_samples != INVALID)
return data->volume_ramp_step_samples;
else if (data->volume_ramp_step_time != INVALID) {
/* 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 int fade_in(struct data *data) static int fade_in(struct data *data)
{ {
@ -306,7 +335,9 @@ static int fade_in(struct data *data)
struct spa_pod_builder b; struct spa_pod_builder b;
struct spa_pod_frame f[1]; struct spa_pod_frame f[1];
void *buffer = data->control_buffer->datas[0].data; void *buffer = data->control_buffer->datas[0].data;
double step_size = ((double) data->volume_ramp_step_samples / (double) data->volume_ramp_samples); unsigned int ramp_samples = get_ramp_samples(data);
unsigned int ramp_step_samples = get_ramp_step_samples(data);
double step_size = ((double) ramp_step_samples / (double) ramp_samples);
uint32_t buffer_size = data->control_buffer->datas[0].maxsize; uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
data->control_buffer->datas[0].chunk[0].size = buffer_size; data->control_buffer->datas[0].chunk[0].size = buffer_size;
@ -314,12 +345,13 @@ static int fade_in(struct data *data)
spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_push_sequence(&b, &f[0], 0);
data->volume_offs = 0; data->volume_offs = 0;
do { do {
// printf("volume level %f offset %d\n", data->volume_accum, data->volume_offs);
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties); spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b, spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0, SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_volume, SPA_POD_Float(data->volume_accum)); SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
data->volume_accum += step_size; data->volume_accum += step_size;
data->volume_offs += data->volume_ramp_step_samples; data->volume_offs += ramp_step_samples;
} while (data->volume_accum < 1.0); } while (data->volume_accum < 1.0);
spa_pod_builder_pop(&b, &f[0]); spa_pod_builder_pop(&b, &f[0]);
} }
@ -328,7 +360,6 @@ static int fade_in(struct data *data)
struct spa_pod *props; struct spa_pod *props;
int res = 0; int res = 0;
uint8_t buffer[1024]; uint8_t buffer[1024];
printf("fading in\n");
spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_add_object(&b, props = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0, SPA_TYPE_OBJECT_Props, 0,
@ -348,7 +379,10 @@ static int fade_out(struct data *data)
if (spa_streq (data->mode, NON_NATIVE)) { if (spa_streq (data->mode, NON_NATIVE)) {
struct spa_pod_builder b; struct spa_pod_builder b;
struct spa_pod_frame f[1]; struct spa_pod_frame f[1];
double step_size = ((double) data->volume_ramp_step_samples / (double) data->volume_ramp_samples); unsigned int ramp_samples = get_ramp_samples(data);
unsigned int ramp_step_samples = get_ramp_step_samples(data);
double step_size = ((double) ramp_step_samples / (double) ramp_samples);
void *buffer = data->control_buffer->datas[0].data; void *buffer = data->control_buffer->datas[0].data;
uint32_t buffer_size = data->control_buffer->datas[0].maxsize; uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
@ -356,14 +390,15 @@ static int fade_out(struct data *data)
spa_pod_builder_init(&b, buffer, buffer_size); spa_pod_builder_init(&b, buffer, buffer_size);
spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_push_sequence(&b, &f[0], 0);
data->volume_offs = data->volume_ramp_step_samples; data->volume_offs = ramp_step_samples;
do { do {
// printf("volume level %f offset %d\n", data->volume_accum, data->volume_offs);
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties); spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b, spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0, SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_volume, SPA_POD_Float(data->volume_accum)); SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
data->volume_accum -= step_size; data->volume_accum -= step_size;
data->volume_offs += data->volume_ramp_step_samples; data->volume_offs += ramp_step_samples;
} while (data->volume_accum > 0.0); } while (data->volume_accum > 0.0);
spa_pod_builder_pop(&b, &f[0]); spa_pod_builder_pop(&b, &f[0]);
} else { } else {
@ -417,11 +452,11 @@ static void do_fade(struct data *data)
static int on_sink_node_ready(void *_data, int status) static int on_sink_node_ready(void *_data, int status)
{ {
struct data *data = _data; struct data *data = _data;
int runway = (data->volume_ramp_samples / 1024); int runway = (get_ramp_samples(data) / 1024);
/* only do fade in/out when buffer count is 0 */ /* only do fade in/out when buffer count is 0 */
if (data->buffer_count == 0) if (data->buffer_count == 0)
do_fade(data); do_fade(data);
/* update buffer count */ /* update buffer count */
data->buffer_count++; data->buffer_count++;
@ -601,11 +636,14 @@ static int make_nodes(struct data *data)
props = spa_pod_builder_add_object(&b, props = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0, SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_volumeRampSamples, SPA_POD_Int(data->volume_ramp_samples), SPA_PROP_volumeRampSamples, SPA_POD_Int(data->volume_ramp_samples),
SPA_PROP_volumeRampStepSamples, SPA_POD_Int(data->volume_ramp_step_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));
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) { 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); printf("can't call volramp set params %d\n", res);
return res; return res;
} }
printf("updated volume ramp params\n");
} }
/* set io buffers on source and sink nodes */ /* set io buffers on source and sink nodes */
data->source_sink_io[0] = SPA_IO_BUFFERS_INIT; data->source_sink_io[0] = SPA_IO_BUFFERS_INIT;
@ -860,14 +898,31 @@ static void show_help(struct data *data, const char *name, bool error)
" -m, --mode Volume Ramp Mode(\"NonNative\"(via Control Port) \"Native\" (via Volume Ramp Params of AudioAdapter plugin)) (default %s)\n" " -m, --mode Volume Ramp Mode(\"NonNative\"(via Control Port) \"Native\" (via Volume Ramp Params of AudioAdapter plugin)) (default %s)\n"
" -s, --ramp-samples SPA_PROP_volumeRampSamples(Samples to ramp the volume over)(default %d)\n" " -s, --ramp-samples SPA_PROP_volumeRampSamples(Samples to ramp the volume over)(default %d)\n"
" -a, --ramp-step-samples SPA_PROP_volumeRampStepSamples(Step or incremental Samples to ramp the volume over)(default %d)\n" " -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)\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)\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, --ramp-scale SPA_PROP_volumeRampScale(the scale or graph to used to ramp the volume)\n"
"examples:\n"
"adapter-control\n"
"-->when invoked with out any params, ramps volume with default values\n"
"adapter-control --ramp-samples=70000, rest of the parameters are defaults\n"
"-->ramps volume over 70000 samples(it is 1.45 seconds)\n"
"adapter-control --alsa-device=hw:0,0 --ramp-samples=70000\n"
"-->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"
"-->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"
"-->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",
name, name,
DEFAULT_DEVICE, DEFAULT_DEVICE,
DEFAULT_MODE, DEFAULT_MODE,
DEFAULT_SAMPLES, DEFAULT_RAMP_SAMPLES,
DEFAULT_STEP_SAMPLES); DEFAULT_RAMP_STEP_SAMPLES,
DEFAULT_RAMP_TIME,
DEFAULT_RAMP_STEP_TIME);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -877,8 +932,10 @@ int main(int argc, char *argv[])
char c; char c;
/* default values*/ /* default values*/
data.volume_ramp_samples = DEFAULT_SAMPLES; data.volume_ramp_samples = DEFAULT_RAMP_SAMPLES;
data.volume_ramp_step_samples = DEFAULT_STEP_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.alsa_device = DEFAULT_DEVICE;
data.mode = DEFAULT_MODE; data.mode = DEFAULT_MODE;
@ -912,15 +969,23 @@ int main(int argc, char *argv[])
break; break;
case 's': case 's':
data.volume_ramp_samples = atoi(optarg); data.volume_ramp_samples = atoi(optarg);
data.volume_ramp_time = INVALID;
data.volume_ramp_step_time = INVALID;
break; break;
case 't': case 't':
data.volume_ramp_time = atoi(optarg); data.volume_ramp_time = atoi(optarg);
data.volume_ramp_samples = INVALID;
data.volume_ramp_step_samples = INVALID;
break; break;
case 'a': case 'a':
data.volume_ramp_step_samples = atoi(optarg); data.volume_ramp_step_samples = atoi(optarg);
data.volume_ramp_step_time = INVALID;
data.volume_ramp_time = INVALID;
break; break;
case 'i': case 'i':
data.volume_ramp_step_time = atoi(optarg); data.volume_ramp_step_time = atoi(optarg);
data.volume_ramp_samples = INVALID;
data.volume_ramp_step_samples = INVALID;
break; break;
default: default:
show_help(&data, argv[0], true); show_help(&data, argv[0], true);
@ -948,8 +1013,12 @@ int main(int argc, char *argv[])
} }
printf("using %s mode\n", data.mode); printf("using %s mode\n", data.mode);
printf("using %d samples with a step size of %d samples\n", if ((data.volume_ramp_samples != INVALID) && (data.volume_ramp_step_samples != INVALID))
data.volume_ramp_samples, data.volume_ramp_step_samples); 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));
spa_loop_control_enter(data.control); spa_loop_control_enter(data.control);
run_async_sink(&data); run_async_sink(&data);