mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-21 08:56:56 -05:00
pulse-server: convert between client cubic volume and linear
This commit is contained in:
parent
2e3556fa12
commit
1ceb902b76
3 changed files with 39 additions and 18 deletions
|
|
@ -283,7 +283,7 @@ static void channel_map_to_positions(const struct channel_map *map, uint32_t *po
|
||||||
pos[i] = channel_pa2id(map->map[i]);
|
pos[i] = channel_pa2id(map->map[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cvolume {
|
struct volume {
|
||||||
uint8_t channels;
|
uint8_t channels;
|
||||||
float values[CHANNELS_MAX];
|
float values[CHANNELS_MAX];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,27 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define VOLUME_MUTED ((uint32_t) 0U)
|
||||||
|
#define VOLUME_NORM ((uint32_t) 0x10000U)
|
||||||
|
#define VOLUME_MAX ((uint32_t) UINT32_MAX/2)
|
||||||
|
|
||||||
|
static inline uint32_t volume_from_linear(float vol)
|
||||||
|
{
|
||||||
|
uint32_t v;
|
||||||
|
if (vol <= 0.0f)
|
||||||
|
v = VOLUME_MUTED;
|
||||||
|
else
|
||||||
|
v = SPA_CLAMP((uint64_t) lround(cbrt(vol) * VOLUME_NORM),
|
||||||
|
VOLUME_MUTED, VOLUME_MAX);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float volume_to_linear(uint32_t vol)
|
||||||
|
{
|
||||||
|
float v = ((float)vol) / VOLUME_NORM;
|
||||||
|
return v * v * v;
|
||||||
|
}
|
||||||
|
|
||||||
struct descriptor {
|
struct descriptor {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t channel;
|
uint32_t channel;
|
||||||
|
|
@ -203,11 +224,11 @@ static int read_volume(struct message *m, float *vol)
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
if ((res = read_u32(m, &v)) < 0)
|
if ((res = read_u32(m, &v)) < 0)
|
||||||
return res;
|
return res;
|
||||||
*vol = ((float)v) / 0x10000U;
|
*vol = volume_to_linear(v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_cvolume(struct message *m, struct cvolume *vol)
|
static int read_cvolume(struct message *m, struct volume *vol)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
@ -336,7 +357,7 @@ static int message_get(struct message *m, ...)
|
||||||
case TAG_CVOLUME:
|
case TAG_CVOLUME:
|
||||||
if (dtag != tag)
|
if (dtag != tag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if ((res = read_cvolume(m, va_arg(va, struct cvolume*))) < 0)
|
if ((res = read_cvolume(m, va_arg(va, struct volume*))) < 0)
|
||||||
return res;
|
return res;
|
||||||
break;
|
break;
|
||||||
case TAG_PROPLIST:
|
case TAG_PROPLIST:
|
||||||
|
|
@ -462,16 +483,16 @@ static void write_channel_map(struct message *m, struct channel_map *map)
|
||||||
static void write_volume(struct message *m, float vol)
|
static void write_volume(struct message *m, float vol)
|
||||||
{
|
{
|
||||||
write_8(m, TAG_VOLUME);
|
write_8(m, TAG_VOLUME);
|
||||||
write_32(m, vol * 0x10000U);
|
write_32(m, volume_from_linear(vol));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_cvolume(struct message *m, struct cvolume *cvol)
|
static void write_cvolume(struct message *m, struct volume *vol)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
write_8(m, TAG_CVOLUME);
|
write_8(m, TAG_CVOLUME);
|
||||||
write_8(m, cvol->channels);
|
write_8(m, vol->channels);
|
||||||
for (i = 0; i < cvol->channels; i ++)
|
for (i = 0; i < vol->channels; i ++)
|
||||||
write_32(m, cvol->values[i] * 0x10000U);
|
write_32(m, volume_from_linear(vol->values[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_props(struct message *m, struct pw_properties *props)
|
static void write_props(struct message *m, struct pw_properties *props)
|
||||||
|
|
@ -545,7 +566,7 @@ static int message_put(struct message *m, ...)
|
||||||
write_channel_map(m, va_arg(va, struct channel_map*));
|
write_channel_map(m, va_arg(va, struct channel_map*));
|
||||||
break;
|
break;
|
||||||
case TAG_CVOLUME:
|
case TAG_CVOLUME:
|
||||||
write_cvolume(m, va_arg(va, struct cvolume*));
|
write_cvolume(m, va_arg(va, struct volume*));
|
||||||
break;
|
break;
|
||||||
case TAG_PROPLIST:
|
case TAG_PROPLIST:
|
||||||
write_props(m, va_arg(va, struct pw_properties*));
|
write_props(m, va_arg(va, struct pw_properties*));
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ struct device {
|
||||||
enum pw_direction direction;
|
enum pw_direction direction;
|
||||||
struct pw_properties *props;
|
struct pw_properties *props;
|
||||||
struct sample_spec ss;
|
struct sample_spec ss;
|
||||||
struct cvolume volume;
|
struct volume volume;
|
||||||
struct channel_map map;
|
struct channel_map map;
|
||||||
bool muted;
|
bool muted;
|
||||||
struct device *monitor;
|
struct device *monitor;
|
||||||
|
|
@ -139,7 +139,7 @@ struct stream {
|
||||||
struct buffer_attr attr;
|
struct buffer_attr attr;
|
||||||
uint32_t frame_size;
|
uint32_t frame_size;
|
||||||
|
|
||||||
struct cvolume volume;
|
struct volume volume;
|
||||||
bool muted;
|
bool muted;
|
||||||
|
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
@ -1178,7 +1178,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
fail_on_suspend = false,
|
fail_on_suspend = false,
|
||||||
relative_volume = false,
|
relative_volume = false,
|
||||||
passthrough = false;
|
passthrough = false;
|
||||||
struct cvolume volume;
|
struct volume volume;
|
||||||
struct pw_properties *props = NULL;
|
struct pw_properties *props = NULL;
|
||||||
uint8_t n_formats = 0;
|
uint8_t n_formats = 0;
|
||||||
struct stream *stream = NULL;
|
struct stream *stream = NULL;
|
||||||
|
|
@ -1413,7 +1413,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
relative_volume = false,
|
relative_volume = false,
|
||||||
passthrough = false;
|
passthrough = false;
|
||||||
uint32_t direct_on_input_idx;
|
uint32_t direct_on_input_idx;
|
||||||
struct cvolume volume;
|
struct volume volume;
|
||||||
struct pw_properties *props = NULL;
|
struct pw_properties *props = NULL;
|
||||||
uint8_t n_formats = 0;
|
uint8_t n_formats = 0;
|
||||||
struct stream *stream = NULL;
|
struct stream *stream = NULL;
|
||||||
|
|
@ -1795,7 +1795,7 @@ static int do_set_stream_volume(struct client *client, uint32_t command, uint32_
|
||||||
uint32_t channel;
|
uint32_t channel;
|
||||||
struct stream *stream;
|
struct stream *stream;
|
||||||
int res;
|
int res;
|
||||||
struct cvolume volume;
|
struct volume volume;
|
||||||
|
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
TAG_U32, &channel,
|
TAG_U32, &channel,
|
||||||
|
|
@ -3146,7 +3146,7 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
||||||
.format = SAMPLE_FLOAT32LE,
|
.format = SAMPLE_FLOAT32LE,
|
||||||
.rate = 44100,
|
.rate = 44100,
|
||||||
.channels = 2, },
|
.channels = 2, },
|
||||||
.volume = (struct cvolume) {
|
.volume = (struct volume) {
|
||||||
.channels = 2,
|
.channels = 2,
|
||||||
.values[0] = 1.0f,
|
.values[0] = 1.0f,
|
||||||
.values[1] = 1.0f, },
|
.values[1] = 1.0f, },
|
||||||
|
|
@ -3169,7 +3169,7 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
||||||
.format = SAMPLE_FLOAT32LE,
|
.format = SAMPLE_FLOAT32LE,
|
||||||
.rate = 44100,
|
.rate = 44100,
|
||||||
.channels = 2, },
|
.channels = 2, },
|
||||||
.volume = (struct cvolume) {
|
.volume = (struct volume) {
|
||||||
.channels = 2,
|
.channels = 2,
|
||||||
.values[0] = 1.0f,
|
.values[0] = 1.0f,
|
||||||
.values[1] = 1.0f, },
|
.values[1] = 1.0f, },
|
||||||
|
|
@ -3191,7 +3191,7 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
||||||
.format = SAMPLE_FLOAT32LE,
|
.format = SAMPLE_FLOAT32LE,
|
||||||
.rate = 44100,
|
.rate = 44100,
|
||||||
.channels = 2, },
|
.channels = 2, },
|
||||||
.volume = (struct cvolume) {
|
.volume = (struct volume) {
|
||||||
.channels = 2,
|
.channels = 2,
|
||||||
.values[0] = 1.0f,
|
.values[0] = 1.0f,
|
||||||
.values[1] = 1.0f, },
|
.values[1] = 1.0f, },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue