summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-11-22 19:19:01 +0000
committerAidan MacDonald <amachronic@protonmail.com>2023-01-22 15:43:00 -0500
commitdc839639620352c5fa9b63db6679126ec5bcfba8 (patch)
treec551d2e6586b0439003a8c0bba66e0d349cc680d
parent66519000f47cfb5c58be68ab2335b7cbc0bce35b (diff)
downloadrockbox-dc839639620352c5fa9b63db6679126ec5bcfba8.tar.gz
rockbox-dc839639620352c5fa9b63db6679126ec5bcfba8.zip
Add helpers for converting to/from normalized (perceptual) volume
These routines were taken from alsamixer and converted to fixed point for Rockbox. Change-Id: I64e8bf08da02b1e6e3ef10fdc78254bf8e87ff20
-rw-r--r--apps/misc.c102
-rw-r--r--apps/misc.h8
-rw-r--r--docs/LICENSES22
3 files changed, 132 insertions, 0 deletions
diff --git a/apps/misc.c b/apps/misc.c
index e17df02bff..d4c7108d28 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -1664,3 +1664,105 @@ int core_load_bmp(const char * filename, struct bitmap *bm, const int bmformat,
1664 return handle; 1664 return handle;
1665} 1665}
1666#endif /* ndef __PCTOOL__ */ 1666#endif /* ndef __PCTOOL__ */
1667
1668/*
1669 * Normalized volume routines adapted from alsamixer volume_mapping.c
1670 */
1671/*
1672 * Copyright (c) 2010 Clemens Ladisch <clemens@ladisch.de>
1673 *
1674 * Permission to use, copy, modify, and/or distribute this software for any
1675 * purpose with or without fee is hereby granted, provided that the above
1676 * copyright notice and this permission notice appear in all copies.
1677 *
1678 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1679 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1680 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1681 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1682 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1683 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1684 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1685 */
1686/*
1687 * "The mapping is designed so that the position in the interval is proportional
1688 * to the volume as a human ear would perceive it (i.e., the position is the
1689 * cubic root of the linear sample multiplication factor). For controls with
1690 * a small range (24 dB or less), the mapping is linear in the dB values so
1691 * that each step has the same size visually. Only for controls without dB
1692 * information, a linear mapping of the hardware volume register values is used
1693 * (this is the same algorithm as used in the old alsamixer)."
1694 */
1695
1696#define NVOL_FRACBITS 16
1697#define NVOL_UNITY (1L << NVOL_FRACBITS)
1698#define NVOL_FACTOR (600L << NVOL_FRACBITS)
1699
1700#define NVOL_MAX_LINEAR_DB_SCALE (240L << NVOL_FRACBITS)
1701
1702#define nvol_div(x,y) fp_div((x), (y), NVOL_FRACBITS)
1703#define nvol_mul(x,y) fp_mul((x), (y), NVOL_FRACBITS)
1704#define nvol_exp10(x) fp_exp10((x), NVOL_FRACBITS)
1705#define nvol_log10(x) fp_log10((x), NVOL_FRACBITS)
1706
1707static bool use_linear_dB_scale(long min_vol, long max_vol)
1708{
1709 /*
1710 * Alsamixer uses a linear scale for small ranges.
1711 * Commented out so perceptual volume works as advertised on all targets.
1712 */
1713 /*
1714 return max_vol - min_vol <= NVOL_MAX_LINEAR_DB_SCALE;
1715 */
1716
1717 (void)min_vol;
1718 (void)max_vol;
1719 return false;
1720}
1721
1722long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm)
1723{
1724 long norm, min_norm;
1725
1726 vol <<= NVOL_FRACBITS;
1727 min_vol <<= NVOL_FRACBITS;
1728 max_vol <<= NVOL_FRACBITS;
1729 max_norm <<= NVOL_FRACBITS;
1730
1731 if (use_linear_dB_scale(min_vol, max_vol))
1732 {
1733 norm = nvol_div(vol - min_vol, max_vol - min_vol);
1734 }
1735 else
1736 {
1737 min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR));
1738 norm = nvol_exp10(nvol_div(vol - max_vol, NVOL_FACTOR));
1739 norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm);
1740 }
1741
1742 return nvol_mul(norm, max_norm) >> NVOL_FRACBITS;
1743}
1744
1745long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm)
1746{
1747 long vol, min_norm;
1748
1749 norm <<= NVOL_FRACBITS;
1750 min_vol <<= NVOL_FRACBITS;
1751 max_vol <<= NVOL_FRACBITS;
1752 max_norm <<= NVOL_FRACBITS;
1753
1754 vol = nvol_div(norm, max_norm);
1755
1756 if (use_linear_dB_scale(min_vol, max_vol))
1757 {
1758 vol = nvol_mul(vol, max_vol - min_vol) + min_vol;
1759 }
1760 else
1761 {
1762 min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR));
1763 vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm;
1764 vol = nvol_mul(nvol_log10(vol), NVOL_FACTOR) + max_vol;
1765 }
1766
1767 return vol >> NVOL_FRACBITS;
1768}
diff --git a/apps/misc.h b/apps/misc.h
index 403a8c53ac..72b8735c8a 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -238,4 +238,12 @@ int core_load_bmp(const char *filename, struct bitmap *bm, const int bmformat,
238 ssize_t *buf_reqd, struct buflib_callbacks *ops); 238 ssize_t *buf_reqd, struct buflib_callbacks *ops);
239#endif 239#endif
240 240
241/* Convert a volume (in tenth dB) in the range [min_vol, max_vol]
242 * to a normalized linear value in the range [0, max_norm]. */
243long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm);
244
245/* Inverse of to_normalized_volume(), returns the volume in tenth dB
246 * for the given normalized volume. */
247long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm);
248
241#endif /* MISC_H */ 249#endif /* MISC_H */
diff --git a/docs/LICENSES b/docs/LICENSES
index d340d3961b..4d676c82c0 100644
--- a/docs/LICENSES
+++ b/docs/LICENSES
@@ -143,3 +143,25 @@ From: https://github.com/cnSchwarzer/bsdiff-win
143 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 143 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
144 * POSSIBILITY OF SUCH DAMAGE. 144 * POSSIBILITY OF SUCH DAMAGE.
145 */ 145 */
146
147*************************************************************************
148In: apps/misc.c, to_normalized_volume and from_normalized_volume
149From: https://git.alsa-project.org/?p=alsa-utils.git
150 alsamixer/volume_mapping.c
151*************************************************************************
152
153/*
154 * Copyright (c) 2010 Clemens Ladisch <clemens@ladisch.de>
155 *
156 * Permission to use, copy, modify, and/or distribute this software for any
157 * purpose with or without fee is hereby granted, provided that the above
158 * copyright notice and this permission notice appear in all copies.
159 *
160 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
161 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
162 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
163 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
164 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
165 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
166 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167 */