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