Skip to content

Commit 6b91a55

Browse files
andrula-songlgirdwood
authored andcommitted
Audio: Fix the peak volume calculation error in volume component
Fix the peak volume calculation error in volume component, calculate the maximum absolute value of input as peak volume as close source firmware did. Signed-off-by: Andrula Song <andrula.song@intel.com>
1 parent 5efc08d commit 6b91a55

File tree

9 files changed

+903
-110
lines changed

9 files changed

+903
-110
lines changed

src/audio/module_adapter/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ if(NOT CONFIG_LIBRARY)
66
endif()
77

88
if(CONFIG_COMP_VOLUME)
9-
add_local_sources(sof module/volume/volume_generic.c module/volume/volume_hifi3.c module/volume/volume.c)
9+
add_local_sources(sof
10+
module/volume/volume_generic.c
11+
module/volume/volume_hifi3.c
12+
module/volume/volume_generic_with_peakvol.c
13+
module/volume/volume_hifi3_with_peakvol.c
14+
module/volume/volume.c)
1015
endif()
1116

1217
if(CONFIG_CADENCE_CODEC)

src/audio/module_adapter/module/volume/volume.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,12 @@ static int volume_init(struct processing_module *mod)
550550
uint32_t channels_count;
551551
uint8_t channel_cfg;
552552
uint8_t channel;
553-
uint32_t instance_id;
553+
uint32_t instance_id = IPC4_INST_ID(dev_comp_id(dev));
554554

555+
if (instance_id >= IPC4_MAX_PEAK_VOL_REG_SLOTS) {
556+
comp_err(dev, "instance_id %u out of array bounds.", instance_id);
557+
return -EINVAL;
558+
}
555559
channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count;
556560
if (channels_count > SOF_IPC_MAX_CHANNELS || !channels_count) {
557561
comp_err(dev, "volume_init(): Invalid channels count %u", channels_count);
@@ -573,6 +577,17 @@ static int volume_init(struct processing_module *mod)
573577
return -ENOMEM;
574578
}
575579

580+
/* malloc memory to store temp peak volume 4 times to ensure the address
581+
* is 8-byte aligned for multi-way xtensa intrinsic operations.
582+
*/
583+
cd->peak_vol = rmalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, vol_size);
584+
if (!cd->peak_vol) {
585+
rfree(cd->vol);
586+
rfree(cd);
587+
comp_err(dev, "volume_init(): Failed to allocate %d for peak_vol", vol_size);
588+
return -ENOMEM;
589+
}
590+
576591
md->private = cd;
577592

578593
for (channel = 0; channel < channels_count ; channel++) {
@@ -592,12 +607,6 @@ static int volume_init(struct processing_module *mod)
592607

593608
init_ramp(cd, vol->config[0].curve_duration, target_volume[0]);
594609

595-
instance_id = IPC4_INST_ID(dev_comp_id(dev));
596-
if (instance_id >= IPC4_MAX_PEAK_VOL_REG_SLOTS) {
597-
comp_err(dev, "instance_id %u out of array bounds.", instance_id);
598-
return -EINVAL;
599-
}
600-
601610
cd->mailbox_offset = offsetof(struct ipc4_fw_registers, peak_vol_regs);
602611
cd->mailbox_offset += instance_id * sizeof(struct ipc4_peak_volume_regs);
603612

@@ -650,6 +659,7 @@ static int volume_free(struct processing_module *mod)
650659
/* clear mailbox */
651660
memset_s(&regs, sizeof(regs), 0, sizeof(regs));
652661
mailbox_sw_regs_write(cd->mailbox_offset, &regs, sizeof(regs));
662+
rfree(cd->peak_vol);
653663
#endif
654664

655665
comp_dbg(mod->dev, "volume_free()");

src/audio/module_adapter/module/volume/volume_generic.c

Lines changed: 20 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
/**
1010
* \file
11-
* \brief Volume generic processing implementation
11+
* \brief Volume generic processing implementation without peak volume detection
1212
* \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n
1313
* Keyon Jie <yang.jie@linux.intel.com>\n
1414
* Tomasz Lauda <tomasz.lauda@linux.intel.com>
@@ -21,21 +21,24 @@
2121
#include <ipc/stream.h>
2222
#include <stddef.h>
2323
#include <stdint.h>
24+
#include <stdlib.h>
2425

2526
LOG_MODULE_DECLARE(volume_generic, CONFIG_SOF_LOG_LEVEL);
2627

2728
#include <sof/audio/volume.h>
2829

2930
#ifdef CONFIG_GENERIC
3031

32+
#if (!CONFIG_COMP_PEAK_VOL)
33+
3134
#if CONFIG_FORMAT_S24LE
3235
/**
3336
* \brief Volume s24 to s24 multiply function
3437
* \param[in] x input sample.
3538
* \param[in] vol gain.
3639
* \return output sample.
3740
*
38-
* Volume multiply for 24 bit input and 24 bit bit output.
41+
* Volume multiply for 24 bit input and 24 bit output.
3942
*/
4043
static inline int32_t vol_mult_s24_to_s24(int32_t x, int32_t vol)
4144
{
@@ -46,7 +49,7 @@ static inline int32_t vol_mult_s24_to_s24(int32_t x, int32_t vol)
4649
* \brief Volume processing from 24/32 bit to 24/32 bit.
4750
* \param[in,out] dev Volume base component device.
4851
* \param[in,out] sink Destination buffer.
49-
* \param[in,out] source Source buffer.
52+
* \param[in,out] source Input buffer.
5053
* \param[in] frames Number of frames to process.
5154
*
5255
* Copy and scale volume from 24/32 bit source buffer
@@ -64,43 +67,29 @@ static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_bu
6467
int nmax, n, i, j;
6568
const int nch = source->channels;
6669
int remaining_samples = frames * nch;
67-
#if CONFIG_COMP_PEAK_VOL
68-
int32_t tmp = INT_MIN_FOR_NUMBER_OF_BITS(32);
69-
#endif
7070

7171
x = source->r_ptr;
7272
y = sink->w_ptr;
7373

7474
bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples);
7575
bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples);
7676
while (remaining_samples) {
77-
nmax = VOL_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x));
77+
nmax = audio_stream_samples_without_wrap_s24(source, x);
7878
n = MIN(remaining_samples, nmax);
79-
nmax = VOL_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, y));
79+
nmax = audio_stream_samples_without_wrap_s24(sink, y);
8080
n = MIN(n, nmax);
8181
for (j = 0; j < nch; j++) {
8282
x0 = x + j;
8383
y0 = y + j;
8484
vol = cd->volume[j];
8585
for (i = 0; i < n; i += nch) {
86-
*y0 = vol_mult_s24_to_s24(*x0, vol);
87-
#if CONFIG_COMP_PEAK_VOL
88-
tmp = MAX(*y0, tmp);
89-
#endif
90-
91-
x0 += nch;
92-
y0 += nch;
86+
y0[i] = vol_mult_s24_to_s24(x0[i], vol);
9387
}
94-
#if CONFIG_COMP_PEAK_VOL
95-
cd->peak_regs.peak_meter[j] = tmp;
96-
#endif
9788
}
9889
remaining_samples -= n;
9990
x = audio_stream_wrap(source, x + n);
10091
y = audio_stream_wrap(sink, y + n);
10192
}
102-
/* update peak vol */
103-
peak_vol_update(cd);
10493
}
10594
#endif /* CONFIG_FORMAT_S24LE */
10695

@@ -109,7 +98,7 @@ static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_bu
10998
* \brief Volume processing from 32 bit to 32 bit.
11099
* \param[in,out] dev Volume base component device.
111100
* \param[in,out] sink Destination buffer.
112-
* \param[in,out] source Source buffer.
101+
* \param[in,out] source Input buffer.
113102
* \param[in] frames Number of frames to process.
114103
*
115104
* Copy and scale volume from 32 bit source buffer
@@ -127,18 +116,15 @@ static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_bu
127116
int nmax, n, i, j;
128117
const int nch = source->channels;
129118
int remaining_samples = frames * nch;
130-
#if CONFIG_COMP_PEAK_VOL
131-
int32_t tmp = INT_MIN_FOR_NUMBER_OF_BITS(32);
132-
#endif
133119

134120
x = source->r_ptr;
135121
y = sink->w_ptr;
136122
bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples);
137123
bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples);
138124
while (remaining_samples) {
139-
nmax = VOL_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x));
125+
nmax = audio_stream_samples_without_wrap_s32(source, x);
140126
n = MIN(remaining_samples, nmax);
141-
nmax = VOL_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, y));
127+
nmax = audio_stream_samples_without_wrap_s32(sink, y);
142128
n = MIN(n, nmax);
143129
/* Note: on Xtensa processing one channel volume at time performed slightly
144130
* better than simpler interleaved code version (average 19 us vs. 20 us).
@@ -148,26 +134,14 @@ static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_bu
148134
y0 = y + j;
149135
vol = cd->volume[j];
150136
for (i = 0; i < n; i += nch) {
151-
*y0 = q_multsr_sat_32x32(*x0, vol,
152-
Q_SHIFT_BITS_64(31, VOL_QXY_Y, 31));
153-
#if CONFIG_COMP_PEAK_VOL
154-
tmp = MAX(*y0, tmp);
155-
#endif
156-
157-
x0 += nch;
158-
y0 += nch;
137+
y0[i] = q_multsr_sat_32x32(x0[i], vol,
138+
Q_SHIFT_BITS_64(31, VOL_QXY_Y, 31));
159139
}
160-
#if CONFIG_COMP_PEAK_VOL
161-
cd->peak_regs.peak_meter[j] = tmp;
162-
#endif
163140
}
164141
remaining_samples -= n;
165142
x = audio_stream_wrap(source, x + n);
166143
y = audio_stream_wrap(sink, y + n);
167144
}
168-
169-
/* update peak vol */
170-
peak_vol_update(cd);
171145
}
172146
#endif /* CONFIG_FORMAT_S32LE */
173147

@@ -176,7 +150,7 @@ static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_bu
176150
* \brief Volume processing from 16 bit to 16 bit.
177151
* \param[in,out] dev Volume base component device.
178152
* \param[in,out] sink Destination buffer.
179-
* \param[in,out] source Source buffer.
153+
* \param[in,out] source Input buffer.
180154
* \param[in] frames Number of frames to process.
181155
*
182156
* Copy and scale volume from 16 bit source buffer
@@ -194,44 +168,29 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu
194168
int nmax, n, i, j;
195169
const int nch = source->channels;
196170
int remaining_samples = frames * nch;
197-
#if CONFIG_COMP_PEAK_VOL
198-
int16_t tmp = INT_MIN_FOR_NUMBER_OF_BITS(16);
199-
#endif
200171

201172
x = source->r_ptr;
202173
y = sink->w_ptr;
203-
204174
bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(remaining_samples);
205175
bsink->size += VOL_S16_SAMPLES_TO_BYTES(remaining_samples);
206176
while (remaining_samples) {
207-
nmax = VOL_BYTES_TO_S16_SAMPLES(audio_stream_bytes_without_wrap(source, x));
177+
nmax = audio_stream_samples_without_wrap_s16(source, x);
208178
n = MIN(remaining_samples, nmax);
209-
nmax = VOL_BYTES_TO_S16_SAMPLES(audio_stream_bytes_without_wrap(sink, y));
179+
nmax = audio_stream_samples_without_wrap_s16(sink, y);
210180
n = MIN(n, nmax);
211181
for (j = 0; j < nch; j++) {
212182
x0 = x + j;
213183
y0 = y + j;
214184
vol = cd->volume[j];
215185
for (i = 0; i < n; i += nch) {
216-
*y0 = q_multsr_sat_32x32_16(*x0, vol,
217-
Q_SHIFT_BITS_32(15, VOL_QXY_Y, 15));
218-
#if CONFIG_COMP_PEAK_VOL
219-
tmp = MAX(*y0, tmp);
220-
#endif
221-
x0 += nch;
222-
y0 += nch;
186+
y0[i] = q_multsr_sat_32x32_16(x0[i], vol,
187+
Q_SHIFT_BITS_32(15, VOL_QXY_Y, 15));
223188
}
224-
#if CONFIG_COMP_PEAK_VOL
225-
cd->peak_regs.peak_meter[j] = tmp;
226-
#endif
227189
}
228190
remaining_samples -= n;
229191
x = audio_stream_wrap(source, x + n);
230192
y = audio_stream_wrap(sink, y + n);
231193
}
232-
233-
/* update peak vol */
234-
peak_vol_update(cd);
235194
}
236195
#endif /* CONFIG_FORMAT_S16LE */
237196

@@ -250,3 +209,4 @@ const struct comp_func_map volume_func_map[] = {
250209
const size_t volume_func_count = ARRAY_SIZE(volume_func_map);
251210

252211
#endif
212+
#endif

0 commit comments

Comments
 (0)