• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Struct to hold ramping information.
12  * Members:
13  *   state: Current state. One of CRAS_RAMP_STATE.
14  *   ramped_frames: Number of frames that have passed after starting ramping.
15  *   duration_frames: The targeted number of frames for whole ramping duration.
16  *   increment: The scaler increment that should be added to scaler for
17  *              every frame.
18  *   start_scaler: The initial scaler.
19  *   cb: Callback function to call after ramping is done.
20  *   cb_data: Data passed to cb.
21  */
22 struct cras_ramp {
23 	int active;
24 	int ramped_frames;
25 	int duration_frames;
26 	float increment;
27 	float start_scaler;
28 	float target;
29 	void (*cb)(void *data);
30 	void *cb_data;
31 };
32 
cras_ramp_destroy(struct cras_ramp * ramp)33 void cras_ramp_destroy(struct cras_ramp *ramp)
34 {
35 	free(ramp);
36 }
37 
cras_ramp_create()38 struct cras_ramp *cras_ramp_create()
39 {
40 	struct cras_ramp *ramp;
41 	ramp = (struct cras_ramp *)malloc(sizeof(*ramp));
42 	if (ramp == NULL) {
43 		return NULL;
44 	}
45 	cras_ramp_reset(ramp);
46 	return ramp;
47 }
48 
cras_ramp_reset(struct cras_ramp * ramp)49 int cras_ramp_reset(struct cras_ramp *ramp)
50 {
51 	ramp->active = 0;
52 	ramp->ramped_frames = 0;
53 	ramp->duration_frames = 0;
54 	ramp->increment = 0;
55 	ramp->start_scaler = 1.0;
56 	ramp->target = 1.0;
57 	return 0;
58 }
59 
cras_ramp_start(struct cras_ramp * ramp,int mute_ramp,float from,float to,int duration_frames,cras_ramp_cb cb,void * cb_data)60 int cras_ramp_start(struct cras_ramp *ramp, int mute_ramp, float from, float to,
61 		    int duration_frames, cras_ramp_cb cb, void *cb_data)
62 {
63 	struct cras_ramp_action action;
64 
65 	if (!ramp)
66 		return -EINVAL;
67 
68 	/* if from == to == 0 means we want to mute for duration_frames */
69 	if (from == to && from != 0)
70 		return 0;
71 
72 	/* Get current scaler position so it can serve as new start scaler. */
73 	action = cras_ramp_get_current_action(ramp);
74 	if (action.type == CRAS_RAMP_ACTION_INVALID)
75 		return -EINVAL;
76 
77 	/* Set initial scaler to current scaler so ramping up/down can be
78          * smoothly switched. */
79 	ramp->active = 1;
80 	if (action.type == CRAS_RAMP_ACTION_NONE) {
81 		ramp->start_scaler = from;
82 	} else {
83 		/* If this a mute ramp, we want to match the previous multiplier
84 		 * so that there is not a jump in the audio. Otherwise, we are
85 		 * applying a volume ramp so we need to multiply |from| by the
86 		 * previous scaler so that we can stack volume ramps. */
87 		ramp->start_scaler = action.scaler;
88 		if (!mute_ramp)
89 			ramp->start_scaler *= from;
90 	}
91 	ramp->increment = (to - ramp->start_scaler) / duration_frames;
92 	ramp->target = to;
93 	ramp->ramped_frames = 0;
94 	ramp->duration_frames = duration_frames;
95 	ramp->cb = cb;
96 	ramp->cb_data = cb_data;
97 	return 0;
98 }
99 
100 struct cras_ramp_action
cras_ramp_get_current_action(const struct cras_ramp * ramp)101 cras_ramp_get_current_action(const struct cras_ramp *ramp)
102 {
103 	struct cras_ramp_action action;
104 
105 	if (ramp->ramped_frames < 0) {
106 		action.type = CRAS_RAMP_ACTION_INVALID;
107 		action.scaler = 1.0;
108 		action.increment = 0.0;
109 		action.target = 1.0;
110 	} else if (ramp->active) {
111 		action.type = CRAS_RAMP_ACTION_PARTIAL;
112 		action.scaler = ramp->start_scaler +
113 				ramp->ramped_frames * ramp->increment;
114 		action.increment = ramp->increment;
115 		action.target = ramp->target;
116 	} else {
117 		action.type = CRAS_RAMP_ACTION_NONE;
118 		action.scaler = 1.0;
119 		action.increment = 0.0;
120 		action.target = 1.0;
121 	}
122 	return action;
123 }
124 
cras_ramp_update_ramped_frames(struct cras_ramp * ramp,int num_frames)125 int cras_ramp_update_ramped_frames(struct cras_ramp *ramp, int num_frames)
126 {
127 	if (!ramp->active)
128 		return -EINVAL;
129 	ramp->ramped_frames += num_frames;
130 	if (ramp->ramped_frames >= ramp->duration_frames) {
131 		ramp->active = 0;
132 		if (ramp->cb)
133 			ramp->cb(ramp->cb_data);
134 	}
135 	return 0;
136 }
137