1 /* Copyright (c) 2012 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 <stddef.h>
7 #include <stdlib.h>
8 #include <sys/param.h>
9 
10 #include "cras_util.h"
11 #include "cras_volume_curve.h"
12 
13 /* Simple curve with configurable max volume and volume step. */
14 struct stepped_curve {
15 	struct cras_volume_curve curve;
16 	long max_vol;
17 	long step;
18 };
19 
get_dBFS_step(const struct cras_volume_curve * curve,size_t volume)20 static long get_dBFS_step(const struct cras_volume_curve *curve, size_t volume)
21 {
22 	const struct stepped_curve *c = (const struct stepped_curve *)curve;
23 	return c->max_vol - (c->step * (MAX_VOLUME - volume));
24 }
25 
26 /* Curve that has each step explicitly called out by value. */
27 struct explicit_curve {
28 	struct cras_volume_curve curve;
29 	long dB_values[NUM_VOLUME_STEPS];
30 };
31 
get_dBFS_explicit(const struct cras_volume_curve * curve,size_t volume)32 static long get_dBFS_explicit(const struct cras_volume_curve *curve,
33 			      size_t volume)
34 {
35 	const struct explicit_curve *c = (const struct explicit_curve *)curve;
36 
37 	/* Limit volume to (0, MAX_VOLUME). */
38 	volume = MIN(MAX_VOLUME, MAX(0, volume));
39 	return c->dB_values[volume];
40 }
41 
42 /*
43  * Exported Interface.
44  */
45 
cras_volume_curve_create_default()46 struct cras_volume_curve *cras_volume_curve_create_default()
47 {
48 	/* Default to max volume of 0dBFS, and a step of 0.5dBFS. */
49 	return cras_volume_curve_create_simple_step(0, 50);
50 }
51 
cras_volume_curve_create_simple_step(long max_volume,long volume_step)52 struct cras_volume_curve *cras_volume_curve_create_simple_step(
53 		long max_volume,
54 		long volume_step)
55 {
56 	struct stepped_curve *curve;
57 	curve = (struct stepped_curve *)calloc(1, sizeof(*curve));
58 	if (curve == NULL)
59 		return NULL;
60 	curve->curve.get_dBFS = get_dBFS_step;
61 	curve->max_vol = max_volume;
62 	curve->step = volume_step;
63 	return &curve->curve;
64 }
65 
cras_volume_curve_create_explicit(long dB_values[NUM_VOLUME_STEPS])66 struct cras_volume_curve *cras_volume_curve_create_explicit(
67 		long dB_values[NUM_VOLUME_STEPS])
68 {
69 	struct explicit_curve *curve;
70 	curve = (struct explicit_curve *)calloc(1, sizeof(*curve));
71 	if (curve == NULL)
72 		return NULL;
73 	curve->curve.get_dBFS = get_dBFS_explicit;
74 	memcpy(curve->dB_values, dB_values, sizeof(curve->dB_values));
75 	return &curve->curve;
76 }
77 
cras_volume_curve_destroy(struct cras_volume_curve * curve)78 void cras_volume_curve_destroy(struct cras_volume_curve *curve)
79 {
80 	free(curve);
81 }
82