Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/audio/volume/volume.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static inline int32_t volume_linear_ramp(struct vol_data *cd, int32_t ramp_time,
if (!cd->initial_ramp)
return cd->tvolume[channel];

return cd->rvolume[channel] + ramp_time * cd->ramp_coef[channel];
return sat_int32((int64_t)ramp_time * cd->ramp_coef[channel] + cd->rvolume[channel]);
}
#endif

Expand Down Expand Up @@ -469,7 +469,7 @@ static void set_linear_ramp_coef(struct vol_data *cd, int chan, bool constant_ra
* be some accumulated error in ramp time the longer
* the ramp and the smaller the transition is.
*/
coef = (2 * coef / cd->initial_ramp + 1) >> 1;
coef = ((int64_t)coef * 2 / cd->initial_ramp + 1) >> 1;

/* Scale coefficient by 1/8, round */
coef = ((coef >> 2) + 1) >> 1;
Expand Down
50 changes: 38 additions & 12 deletions src/audio/volume/volume.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,24 @@ struct sof_ipc_ctrl_value_chan;
//** \brief Volume gain Qx.y */
#define COMP_VOLUME_Q8_16 1

//** \brief Volume gain Qx.y integer x number of bits including sign bit. */
#define VOL_QXY_X 8

//** \brief Volume gain Qx.y fractional y number of bits. */
#define VOL_QXY_Y 16

#else

//** \brief Volume gain Qx.y */
#define COMP_VOLUME_Q1_23 1
#define COMP_VOLUME_Q1_31 1

#endif

#if COMP_VOLUME_Q1_31
/** \brief Volume gain Qx.y integer x number of bits including sign bit.
* With Q8.23 format the gain range is -138.47 to +42.14 dB.
*/
#define VOL_QXY_X 1

//** \brief Volume gain Qx.y fractional y number of bits. */
#define VOL_QXY_Y 31

#define VOLUME_Q17_47_SHIFT 0
#elif COMP_VOLUME_Q1_23
/** \brief Volume gain Qx.y integer x number of bits including sign bit.
* With Q8.23 format the gain range is -138.47 to +42.14 dB.
*/
Expand All @@ -62,6 +69,19 @@ struct sof_ipc_ctrl_value_chan;
//** \brief Volume gain Qx.y fractional y number of bits. */
#define VOL_QXY_Y 23

#define VOLUME_Q17_47_SHIFT 8

#elif COMP_VOLUME_Q8_16
//** \brief Volume gain Qx.y integer x number of bits including sign bit. */
#define VOL_QXY_X 8

//** \brief Volume gain Qx.y fractional y number of bits. */
#define VOL_QXY_Y 16

#define VOLUME_Q17_47_SHIFT 15

#else
#error "Need CONFIG_COMP_VOLUME_Qx_y"
#endif

/**
Expand Down Expand Up @@ -92,16 +112,22 @@ struct sof_ipc_ctrl_value_chan;
*/
#define PEAK_16S_32C_ADJUST 16

/**
* \brief Volume maximum value.
* TODO: This should be 1 << (VOL_QX_BITS + VOL_QY_BITS - 1) - 1 but
* the current volume code cannot handle the full Q1.16 range correctly.
*/
#if COMP_VOLUME_Q1_31
/** \brief Volume maximum value. */
#define VOL_MAX INT32_MAX

/** \brief Volume 0dB value. */
#define VOL_ZERO_DB INT32_MAX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's correct and maybe it's just me, but it does look a bit confusing, or at least unclear. Maybe at least a bit larger comment could help. Is this the same value because by convention volume doesn't get positive or do these two macros have different usage?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In IPC4 due to Q1.31 format the max volume and (near) 0 dB gain value are the same since the max linear gain is 0.9999... In IPC3 we used Q-formats those allowed amplification in volume component. I don't want to yet remove the IPC3 gain range since we still have IPC3 in the code. But we can do it later if we remove IPC3 from git main. But I don't think the Q1.31 is a good choice since it can't represent exactly gain 1 and it can't amplify. But that's what we have now.


#else
/** \brief Volume maximum value. */
#define VOL_MAX ((1 << (VOL_QXY_X + VOL_QXY_Y - 1)) - 1)

/** \brief Volume 0dB value. */
#define VOL_ZERO_DB BIT(VOL_QXY_Y)

#endif

/** \brief Volume minimum value. */
#define VOL_MIN 0

Expand Down
102 changes: 50 additions & 52 deletions src/audio/volume/volume_hifi3.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea
struct vol_data *cd = module_get_private_data(mod);
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f32x2 in_sample = AE_ZERO32();
ae_f32x2 out_sample = AE_ZERO32();
ae_f32x2 volume = AE_ZERO32();
ae_f32x2 in_sample;
ae_f32x2 out_sample;
ae_f32x2 volume;
ae_f32x2 *buf;
ae_f32x2 *buf_end;
int i, n, m;
ae_f32x2 *vol;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source)
+ bsource->consumed);
Expand Down Expand Up @@ -114,15 +114,16 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea
/* Multiply the input sample */
#if COMP_VOLUME_Q8_16
out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), AE_SLAI32(in_sample, 8));
out_sample = AE_SLAI32S(out_sample, 8);
#elif COMP_VOLUME_Q1_23
out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8));
#else
#error "Need CONFIG_COMP_VOLUME_Qx_y"
out_sample = AE_SLAI32S(out_sample, 8);
#elif COMP_VOLUME_Q1_31
out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8));
#endif

/* Shift for S24_LE */
out_sample = AE_SLAI32S(out_sample, 8);
out_sample = AE_SRAI32(out_sample, 8);
/* Shift and round for S24_LE */
out_sample = AE_SRAI32R(out_sample, 8);

/* Store the output sample */
AE_SA32X2_IP(out_sample, outu, out);
Expand All @@ -149,9 +150,9 @@ static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod,
{
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f32x2 in_sample = AE_ZERO32();
ae_f32x2 in_sample;
int i, n, m;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source)
+ bsource->consumed);
Expand Down Expand Up @@ -200,16 +201,14 @@ static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_strea
struct vol_data *cd = module_get_private_data(mod);
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f32x2 in_sample = AE_ZERO32();
ae_f32x2 out_sample = AE_ZERO32();
ae_f32x2 volume = AE_ZERO32();
ae_f32x2 in_sample;
ae_f32x2 out_sample;
ae_f32x2 volume;
int i, n, m;
ae_f64 mult0;
ae_f64 mult1;
ae_f32x2 *buf;
ae_f32x2 *buf_end;
ae_f32x2 *vol;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
const int channels_count = audio_stream_get_channels(sink);
const int inc = sizeof(ae_f32x2);
Expand Down Expand Up @@ -249,23 +248,19 @@ static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_strea

/* Load the input sample */
AE_LA32X2_IP(in_sample, inu, in);

#if COMP_VOLUME_Q8_16
/* Q8.16 x Q1.31 << 1 -> Q9.48 */
mult0 = AE_MULF32S_HH(volume, in_sample);
mult0 = AE_SRAI64(mult0, 1); /* Q9.47 */
mult1 = AE_MULF32S_LL(volume, in_sample);
mult1 = AE_SRAI64(mult1, 1);
out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q9.47 -> Q1.31 */
#elif COMP_VOLUME_Q1_23
/* Q1.23 x Q1.31 << 1 -> Q2.55 */
mult0 = AE_MULF32S_HH(volume, in_sample);
mult0 = AE_SRAI64(mult0, 8); /* Q2.47 */
mult1 = AE_MULF32S_LL(volume, in_sample);
mult1 = AE_SRAI64(mult1, 8);
out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */
#if COMP_VOLUME_Q1_31
out_sample = AE_MULFP32X2RS(volume, in_sample);
#else
#error "Need CONFIG_COMP_VOLUME_Qx_y"
/* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is
* Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47
* Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47
*/
ae_f64 mult0 = AE_MULF32R_HH(volume, in_sample);
ae_f64 mult1 = AE_MULF32R_LL(volume, in_sample);

mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT);
mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT);
out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */
#endif
AE_SA32X2_IP(out_sample, outu, out);
}
Expand All @@ -291,9 +286,9 @@ static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod,
{
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f32x2 in_sample = AE_ZERO32();
ae_f32x2 in_sample;
int i, n, m;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
const int channels_count = audio_stream_get_channels(sink);
int samples = channels_count * frames;
Expand Down Expand Up @@ -341,17 +336,17 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu
struct vol_data *cd = module_get_private_data(mod);
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f32x2 volume0 = AE_ZERO32();
ae_f32x2 volume1 = AE_ZERO32();
ae_f32x2 out_sample0 = AE_ZERO32();
ae_f32x2 out_sample1 = AE_ZERO32();
ae_f16x4 in_sample = AE_ZERO16();
ae_f16x4 out_sample = AE_ZERO16();
ae_f32x2 volume0;
ae_f32x2 volume1;
ae_f32x2 out_sample0;
ae_f32x2 out_sample1;
ae_f16x4 in_sample;
ae_f16x4 out_sample;
int i, n, m;
ae_f32x2 *buf;
ae_f32x2 *buf_end;
ae_f32x2 *vol;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source)
+ bsource->consumed);
Expand Down Expand Up @@ -389,25 +384,28 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu
/* load second two volume gain */
AE_L32X2_XC(volume1, vol, inc);

/* Load the input sample */
AE_LA16X4_IP(in_sample, inu, in);

#if COMP_VOLUME_Q1_31
out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample);
out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample);
#else
#if COMP_VOLUME_Q8_16
/* Q8.16 to Q9.23 */
/* Shift Q8.16 to Q9.23
* No need to shift Q1.23, it is OK as such
*/
volume0 = AE_SLAI32S(volume0, 7);
volume1 = AE_SLAI32S(volume1, 7);
#elif COMP_VOLUME_Q1_23
/* No need to shift, Q1.23 is OK as such */
#else
#error "Need CONFIG_COMP_VOLUME_Qx_y"
#endif
/* Load the input sample */
AE_LA16X4_IP(in_sample, inu, in);

/* Multiply the input sample */
out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample);
out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample);

/* Q9.23 to Q1.31 */
out_sample0 = AE_SLAI32S(out_sample0, 8);
out_sample1 = AE_SLAI32S(out_sample1, 8);
#endif

/* store the output */
out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample1);
Expand Down Expand Up @@ -438,9 +436,9 @@ static void vol_passthrough_s16_to_s16(struct processing_module *mod,
{
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;
ae_f16x4 in_sample = AE_ZERO16();
ae_f16x4 in_sample;
int i, n, m;
ae_valign inu = AE_ZALIGN64();
ae_valign inu;
ae_valign outu = AE_ZALIGN64();
ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source)
+ bsource->consumed);
Expand Down
Loading