Home | History | Annotate | Download | only in server
      1 /* Copyright 2016 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <syslog.h>
      7 
      8 #include "cras_ramp.h"
      9 
     10 
     11 /*
     12  * State of cras_ramp:
     13  *   CRAS_RAMP_STATE_IDLE: No ramping is started, or a ramping is already done.
     14  *   CRAS_RAMP_STATE_UP: Ramping up from 0 to 1.
     15  *   CRAS_RAMP_STATE_DOWN: Ramping down from certain scaler to 0.
     16  */
     17 enum CRAS_RAMP_STATE {
     18 	CRAS_RAMP_STATE_IDLE,
     19 	CRAS_RAMP_STATE_UP,
     20 	CRAS_RAMP_STATE_DOWN,
     21 };
     22 
     23 /*
     24  * Struct to hold ramping information.
     25  * Members:
     26  *   state: Current state. One of CRAS_RAMP_STATE.
     27  *   ramped_frames: Number of frames that have passed after starting ramping.
     28  *   duration_frames: The targeted number of frames for whole ramping duration.
     29  *   increment: The scaler increment that should be added to scaler for
     30  *              every frame.
     31  *   start_scaler: The initial scaler.
     32  *   cb: Callback function to call after ramping is done.
     33  *   cb_data: Data passed to cb.
     34  */
     35 struct cras_ramp {
     36 	enum CRAS_RAMP_STATE state;
     37 	int ramped_frames;
     38 	int duration_frames;
     39 	float increment;
     40 	float start_scaler;
     41 	void (*cb)(void *data);
     42 	void *cb_data;
     43 };
     44 
     45 void cras_ramp_destroy(struct cras_ramp* ramp)
     46 {
     47 	free(ramp);
     48 }
     49 
     50 struct cras_ramp* cras_ramp_create()
     51 {
     52 	struct cras_ramp* ramp;
     53 	ramp = (struct cras_ramp*)malloc(sizeof(*ramp));
     54 	if (ramp == NULL) {
     55 		return NULL;
     56 	}
     57 	cras_ramp_reset(ramp);
     58 	return ramp;
     59 }
     60 
     61 int cras_ramp_reset(struct cras_ramp *ramp) {
     62 	ramp->state = CRAS_RAMP_STATE_IDLE;
     63 	ramp->ramped_frames = 0;
     64 	ramp->duration_frames = 0;
     65 	ramp->increment = 0;
     66 	ramp->start_scaler = 1.0;
     67 	return 0;
     68 }
     69 
     70 int cras_ramp_start(struct cras_ramp *ramp, int is_up, int duration_frames,
     71 		    cras_ramp_cb cb, void *cb_data)
     72 {
     73 	struct cras_ramp_action action;
     74 
     75 	/* Get current scaler position so it can serve as new start scaler. */
     76 	action = cras_ramp_get_current_action(ramp);
     77 	if (action.type == CRAS_RAMP_ACTION_INVALID)
     78 		return -EINVAL;
     79 
     80         /* Set initial scaler to current scaler so ramping up/down can be
     81          * smoothly switched. */
     82 	if (is_up) {
     83 		ramp->state = CRAS_RAMP_STATE_UP;
     84 		if (action.type == CRAS_RAMP_ACTION_NONE)
     85 			ramp->start_scaler = 0;
     86 		else
     87 			ramp->start_scaler = action.scaler;
     88 		ramp->increment = (1 - ramp->start_scaler) / duration_frames;
     89 	} else {
     90 		ramp->state = CRAS_RAMP_STATE_DOWN;
     91 		if (action.type == CRAS_RAMP_ACTION_NONE)
     92 			ramp->start_scaler = 1;
     93 		else
     94 			ramp->start_scaler = action.scaler;
     95 
     96 		ramp->increment = -ramp->start_scaler / duration_frames;
     97 	}
     98 	ramp->ramped_frames = 0;
     99 	ramp->duration_frames = duration_frames;
    100 	ramp->cb = cb;
    101 	ramp->cb_data = cb_data;
    102 	return 0;
    103 }
    104 
    105 struct cras_ramp_action cras_ramp_get_current_action(const struct cras_ramp *ramp)
    106 {
    107 	struct cras_ramp_action action;
    108 
    109 	if (ramp->ramped_frames < 0) {
    110 		action.type = CRAS_RAMP_ACTION_INVALID;
    111 		action.scaler = 1.0;
    112 		action.increment = 0.0;
    113 		return action;
    114 	}
    115 
    116 	switch (ramp->state) {
    117 	case CRAS_RAMP_STATE_IDLE:
    118 		action.type = CRAS_RAMP_ACTION_NONE;
    119 		action.scaler = 1.0;
    120 		action.increment = 0.0;
    121 		break;
    122 	case CRAS_RAMP_STATE_DOWN:
    123 		action.type = CRAS_RAMP_ACTION_PARTIAL;
    124 		action.scaler = ramp->start_scaler +
    125 				ramp->ramped_frames * ramp->increment;
    126 		action.increment = ramp->increment;
    127 		break;
    128 	case CRAS_RAMP_STATE_UP:
    129 		action.type = CRAS_RAMP_ACTION_PARTIAL;
    130 		action.scaler = ramp->start_scaler +
    131 				ramp->ramped_frames * ramp->increment;
    132 		action.increment = ramp->increment;
    133 		break;
    134 	}
    135 	return action;
    136 }
    137 
    138 int cras_ramp_update_ramped_frames(
    139 		struct cras_ramp *ramp, int num_frames)
    140 {
    141 	if (ramp->state == CRAS_RAMP_STATE_IDLE)
    142 		return -EINVAL;
    143 	ramp->ramped_frames += num_frames;
    144 	if (ramp->ramped_frames >= ramp->duration_frames) {
    145 		ramp->state = CRAS_RAMP_STATE_IDLE;
    146 		if (ramp->cb)
    147 			ramp->cb(ramp->cb_data);
    148 	}
    149 	return 0;
    150 }
    151