static void sink_subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = (struct userdata *)userdata; if (t == PA_SUBSCRIPTION_EVENT_CHANGE) { pa_sink *sink = PA_SINK(pa_idxset_get_by_index(c->sinks, idx)); if (sink) { if (u->master_sink == sink) { const pa_cvolume *vol = pa_sink_get_volume(sink, 0, 0); int aep_step; u->linear_q15_master_volume_L = lrint(pa_sw_volume_to_linear(vol->values[0]) * 32767.0); if (vol->channels == 1) u->linear_q15_master_volume_R = lrint(pa_sw_volume_to_linear(vol->values[0]) * 32767.0); else u->linear_q15_master_volume_R = lrint(pa_sw_volume_to_linear(vol->values[1]) * 32767.0); aep_step = voice_pa_vol_to_aep_step(u, vol->values[0]); if (voice_cmt_ul_is_active_iothread(u) || (u->voip_source && PA_SOURCE_IS_LINKED(u->voip_source->state) && pa_source_used_by(u->voip_source))) { if (aep_step <= 0) { voice_update_aep_volume(0); voice_update_sidetone_gain(0); } else { voice_update_aep_volume(aep_step - 1); voice_update_sidetone_gain(aep_step - 1); } } xprot_change_volume(u->xprot, u->linear_q15_master_volume_L, u->linear_q15_master_volume_R); } } } }
double pa_sw_volume_to_dB(pa_volume_t v) { pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), PA_DECIBEL_MININFTY); if (v <= PA_VOLUME_MUTED) return PA_DECIBEL_MININFTY; return linear_to_dB(pa_sw_volume_to_linear(v)); }
static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { unsigned channel, nchannels, padding; pa_assert(linear); pa_assert(volume); nchannels = volume->channels; for (channel = 0; channel < nchannels; channel++) linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]); for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) linear[channel] = linear[padding]; }
static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { unsigned channel, nchannels, padding; pa_assert(linear); pa_assert(volume); nchannels = volume->channels; for (channel = 0; channel < nchannels; channel++) linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) linear[channel] = linear[padding]; }
int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_volume_t v; for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { double dB = pa_sw_volume_to_dB(v); double f = pa_sw_volume_to_linear(v); printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n", v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); } return 0; }
/** * @brief Callback function called when the information on the * context's sink is retrieved. * @param ctx Context which operation has succeeded * @param info Structure containing the sink's information * @param this_gen pulse_driver_t pointer for the PulseAudio output * instance. * * This function saves the volume field of the passed structure to the * @c cvolume variable of the output instance and send an update volume * event to the frontend. */ static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info, int is_last, void *userdata) { pulse_driver_t *const this = (pulse_driver_t *) userdata; if (is_last < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n", pa_strerror(pa_context_errno(this->context))); return; } if (!info) return; this->cvolume = info->volume; this->swvolume = pa_cvolume_avg(&info->volume); #if PA_PROTOCOL_VERSION >= 11 /* PulseAudio 0.9.7 and newer */ this->muted = info->mute; #else this->muted = pa_cvolume_is_muted (&this->cvolume); #endif /* send update volume event to frontend */ xine_event_t event; xine_audio_level_data_t data; xine_stream_t *stream; xine_list_iterator_t ite; data.right = data.left = (int) (pa_sw_volume_to_linear(this->swvolume)*100); data.mute = this->muted; event.type = XINE_EVENT_AUDIO_LEVEL; event.data = &data; event.data_length = sizeof(data); pthread_mutex_lock(&this->xine->streams_lock); for(ite = xine_list_front(this->xine->streams); ite; ite = xine_list_next(this->xine->streams, ite)) { stream = xine_list_get_value(this->xine->streams, ite); event.stream = stream; xine_event_send(stream, &event); } pthread_mutex_unlock(&this->xine->streams_lock); }
static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { unsigned k, channel; float linear[PA_CHANNELS_MAX + VOLUME_PADDING]; pa_assert(streams); pa_assert(spec); pa_assert(volume); calc_linear_float_volume(linear, volume); for (k = 0; k < nstreams; k++) { for (channel = 0; channel < spec->channels; channel++) { pa_mix_info *m = streams + k; m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]); } } }
static void gst_pulsesrc_source_output_info_cb (pa_context * c, const pa_source_output_info * i, int eol, void *userdata) { GstPulseSrc *psrc; psrc = GST_PULSESRC_CAST (userdata); if (!i) goto done; /* If the index doesn't match our current stream, * it implies we just recreated the stream (caps change) */ if (i->index == psrc->source_output_idx) { psrc->volume = pa_sw_volume_to_linear (pa_cvolume_max (&i->volume)); psrc->mute = i->mute; } done: pa_threaded_mainloop_signal (psrc->mainloop, 0); }
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) { return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b)); }
int main(int argc, char *argv[]) { pa_volume_t v; pa_cvolume cv; float b; pa_channel_map map; pa_volume_t md = 0; unsigned mdn = 0; if (!getenv("MAKE_CHECK")) pa_log_set_level(PA_LOG_DEBUG); pa_log("Attenuation of sample 1 against 32767: %g dB", 20.0*log10(1.0/32767.0)); pa_log("Smallest possible attenuation > 0 applied to 32767: %li", lrint(32767.0*pa_sw_volume_to_linear(1))); for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { double dB = pa_sw_volume_to_dB(v); double f = pa_sw_volume_to_linear(v); pa_log_debug("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i", v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); } for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { char s[PA_CVOLUME_SNPRINT_MAX], t[PA_SW_CVOLUME_SNPRINT_DB_MAX]; pa_cvolume_set(&cv, 2, v); pa_log_debug("Volume: %3i [%s] [%s]", v, pa_cvolume_snprint(s, sizeof(s), &cv), pa_sw_cvolume_snprint_dB(t, sizeof(t), &cv)); } map.channels = cv.channels = 2; map.map[0] = PA_CHANNEL_POSITION_LEFT; map.map[1] = PA_CHANNEL_POSITION_RIGHT; for (cv.values[0] = PA_VOLUME_MUTED; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096) for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096) { char s[PA_CVOLUME_SNPRINT_MAX]; pa_log_debug("Volume: [%s]; balance: %2.1f", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map)); } for (cv.values[0] = PA_VOLUME_MUTED+4096; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096) for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096) for (b = -1.0f; b <= 1.0f; b += 0.2f) { char s[PA_CVOLUME_SNPRINT_MAX]; pa_cvolume r; float k; pa_log_debug("Before: volume: [%s]; balance: %2.1f", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map)); r = cv; pa_cvolume_set_balance(&r, &map,b); k = pa_cvolume_get_balance(&r, &map); pa_log_debug("After: volume: [%s]; balance: %2.1f (intended: %2.1f) %s", pa_cvolume_snprint(s, sizeof(s), &r), k, b, k < b-.05 || k > b+.5 ? "MISMATCH" : ""); } for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 51) { double l = pa_sw_volume_to_linear(v); pa_volume_t k = pa_sw_volume_from_linear(l); double db = pa_sw_volume_to_dB(v); pa_volume_t r = pa_sw_volume_from_dB(db); pa_volume_t w; pa_assert(k == v); pa_assert(r == v); for (w = PA_VOLUME_MUTED; w < PA_VOLUME_NORM*2; w += 37) { double t = pa_sw_volume_to_linear(w); double db2 = pa_sw_volume_to_dB(w); pa_volume_t p, p1, p2; double q, qq; p = pa_sw_volume_multiply(v, w); qq = db + db2; p2 = pa_sw_volume_from_dB(qq); q = l*t; p1 = pa_sw_volume_from_linear(q); if (p2 > p && p2 - p > md) md = p2 - p; if (p2 < p && p - p2 > md) md = p - p2; if (p1 > p && p1 - p > md) md = p1 - p; if (p1 < p && p - p1 > md) md = p - p1; if (p1 != p || p2 != p) mdn++; } } pa_log("max deviation: %lu n=%lu", (unsigned long) md, (unsigned long) mdn); pa_assert(md <= 1); pa_assert(mdn <= 251); return 0; }