Add function vol2attn to return an attenuation for a given volume. Needed in alsa as well as in player.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Utility routines. This file is part of Shairport.
|
||||
* Copyright (c) James Laird 2013
|
||||
* The volume to attenuation function vol2attn copyright (c) Mike Brady 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
@@ -173,3 +174,51 @@ uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Given a volume (0 to -30) and high and low attenuations available in the mixer in dB, return an attenuation depending on the volume and the function's transfer function
|
||||
// See http://tangentsoft.net/audio/atten.html for data on good attenuators.
|
||||
// We want a smooth attenuation function, like, for example, the ALPS RK27 Potentiometer transfer functions referred to at the link above.
|
||||
|
||||
double vol2attn(double vol, long max_db, long min_db) {
|
||||
|
||||
// We use a little coordinate geometry to build a transfer function from the volume passed in to the device's dynamic range.
|
||||
// The x axis is the "volume in" which will be from -30 to 0. The y axis will be the "volume out" which will be from the bottom of the range to the top.
|
||||
// We build the transfer function from one or more lines. We characterise each line with two numbers:
|
||||
// the first is where on x the line starts when y=0 (from 0 to -30); the second is where on y the line stops when when x is -30.
|
||||
// thus, if the line was characterised as {0,-30}, it would be an identity transfer.
|
||||
// Assuming, for example, a dynamic range of lv=-70 to hv=0
|
||||
// Typically we'll use three lines -- a three order transfer function
|
||||
// First: {0,25} giving a gentle slope
|
||||
// Second: {-17,-25-(lv+25)/2} giving a faster slope from y=0 at x=-17 to y=-50 at x=-30
|
||||
// Third: {-23,lv} giving a fast slope from y=0 at x=-23 to y=-70 at x=-30
|
||||
|
||||
#define order 3
|
||||
|
||||
double vol_setting = max_db;
|
||||
|
||||
if ((vol<=0.0) && (vol>=-30.0)) {
|
||||
long range_db = max_db-min_db; // this will be a positive nunmber
|
||||
// debug(1,"Volume min %ddB, max %ddB, range %ddB.\n",min_db,max_db,range_db);
|
||||
double first_slope = -2500.0; // this is the slope of the attenuation at the high end -- 25dB for the full rotation.
|
||||
if (-range_db>first_slope)
|
||||
first_slope = range_db;
|
||||
double lines[order][2] = {{0,first_slope},{-17,first_slope-(range_db+first_slope)/2},{-23,-range_db}};
|
||||
int i;
|
||||
for (i=0;i<order;i++) {
|
||||
if (vol<=lines[i][0]) {
|
||||
double tvol = lines[i][1]*(vol-lines[i][0])/(-30-lines[i][0]);
|
||||
// debug(1,"On line %d, end point of %f, input vol %f yields output vol %f.\n",i,lines[i][1],vol,tvol);
|
||||
if (tvol<vol_setting)
|
||||
vol_setting=tvol;
|
||||
}
|
||||
}
|
||||
vol_setting+=max_db;
|
||||
} else if (vol!=-144.0) {
|
||||
debug(1,"Volume request value %f is out of range: should be from 0.0 to -30.0 or -144.0.\n",vol);
|
||||
} else {
|
||||
vol_setting = min_db; // for safety, return the lowest setting...
|
||||
}
|
||||
// debug(1,"returning an attenuation of %f.\n",vol_setting);
|
||||
return vol_setting;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@ char *base64_enc(uint8_t *input, int length);
|
||||
#define RSA_MODE_KEY (1)
|
||||
uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode);
|
||||
|
||||
// given a volume (0 to -30) and high and low attenuations in dB*100 (e.g. 0 to -6000 for 0 to -60 dB), return an attenuation depending on the transfer function
|
||||
double vol2attn(double vol, long max_db, long min_db);
|
||||
|
||||
extern shairport_cfg config;
|
||||
|
||||
void shairport_shutdown(int retval);
|
||||
|
||||
Reference in New Issue
Block a user