Skip to content

Commit b921e20

Browse files
committed
Audio: PCM converter: Add support for A-law
WIP - still the actual sample converter missing. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 49bbb3e commit b921e20

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

src/audio/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ config FORMAT_U8
174174
help
175175
Support unsigned 8 bit processing data format
176176

177+
config FORMAT_A_LAW
178+
bool "Support A-law"
179+
default n
180+
help
181+
Support 8 bit A-law processing data format.
182+
177183
config FORMAT_S16LE
178184
bool "Support S16LE"
179185
default y
@@ -222,6 +228,12 @@ config PCM_CONVERTER_FORMAT_U8
222228
help
223229
Support 8 bit processing data format without sign
224230

231+
config PCM_CONVERTER_FORMAT_A_LAW
232+
bool "Support A-law"
233+
default n
234+
help
235+
Support 8 bit A-law data format.
236+
225237
config PCM_CONVERTER_FORMAT_S16LE
226238
bool "Support S16LE"
227239
default y

src/audio/pcm_converter/pcm_converter_generic.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,66 @@ static int pcm_convert_s32_to_u8(const struct audio_stream *source,
9393
}
9494
#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
9595

96+
#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE
97+
static int pcm_convert_alaw_to_s32(const struct audio_stream *source,
98+
uint32_t ioffset, struct audio_stream *sink,
99+
uint32_t ooffset, uint32_t samples, uint32_t chmap)
100+
{
101+
uint8_t *src = audio_stream_get_rptr(source);
102+
int32_t *dst = audio_stream_get_wptr(sink);
103+
uint32_t processed;
104+
uint32_t nmax, i, n;
105+
106+
src += ioffset;
107+
dst += ooffset;
108+
for (processed = 0; processed < samples; processed += n) {
109+
src = audio_stream_wrap(source, src);
110+
dst = audio_stream_wrap(sink, dst);
111+
n = samples - processed;
112+
nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_U8_SAMPLES;
113+
n = MIN(n, nmax);
114+
nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES;
115+
n = MIN(n, nmax);
116+
for (i = 0; i < n; i++) {
117+
*dst = (INT8_MIN + *src) << 24;
118+
src++;
119+
dst++;
120+
}
121+
}
122+
123+
return samples;
124+
}
125+
126+
static int pcm_convert_s32_to_alaw(const struct audio_stream *source,
127+
uint32_t ioffset, struct audio_stream *sink,
128+
uint32_t ooffset, uint32_t samples, uint32_t chmap)
129+
{
130+
int32_t *src = audio_stream_get_rptr(source);
131+
uint8_t *dst = audio_stream_get_wptr(sink);
132+
uint32_t processed;
133+
uint32_t nmax, i, n;
134+
135+
src += ioffset;
136+
dst += ooffset;
137+
for (processed = 0; processed < samples; processed += n) {
138+
src = audio_stream_wrap(source, src);
139+
dst = audio_stream_wrap(sink, dst);
140+
n = samples - processed;
141+
nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES;
142+
n = MIN(n, nmax);
143+
nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_U8_SAMPLES;
144+
n = MIN(n, nmax);
145+
for (i = 0; i < n; i++) {
146+
*dst = sat_int8(Q_SHIFT_RND(*src, 24, 0)) - INT8_MIN;
147+
src++;
148+
dst++;
149+
}
150+
}
151+
152+
return samples;
153+
}
154+
#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
155+
96156
#if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE
97157

98158
static int pcm_convert_s16_to_s24(const struct audio_stream *source,
@@ -555,6 +615,13 @@ const struct pcm_func_map pcm_func_map[] = {
555615
{ SOF_IPC_FRAME_U8, SOF_IPC_FRAME_S32_LE, pcm_convert_u8_to_s32 },
556616
{ SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_U8, pcm_convert_s32_to_u8 },
557617
#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
618+
#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW
619+
{ SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_A_LAW, just_copy },
620+
#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW */
621+
#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE
622+
{ SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_S32_LE, pcm_convert_alaw_to_s32 },
623+
{ SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_A_LAW, pcm_convert_s32_to_alaw },
624+
#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
558625
#if CONFIG_PCM_CONVERTER_FORMAT_S16LE
559626
{ SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, just_copy },
560627
#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE */

src/include/module/ipc/stream.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ enum sof_ipc_frame {
2222
SOF_IPC_FRAME_S24_3LE,
2323
SOF_IPC_FRAME_S24_4LE_MSB,
2424
SOF_IPC_FRAME_U8,
25-
SOF_IPC_FRAME_S16_4LE /* 16-bit in 32-bit container */
25+
SOF_IPC_FRAME_S16_4LE, /* 16-bit in 32-bit container */
26+
SOF_IPC_FRAME_A_LAW,
2627
};
2728

2829
#endif /* __MODULE_IPC_STREAM_H__ */

src/include/module/ipc4/base-config.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ enum ipc4_sample_type {
9797
IPC4_TYPE_LSB_INTEGER = 1, /**< integer with Least Significant Byte first */
9898
IPC4_TYPE_SIGNED_INTEGER = 2,
9999
IPC4_TYPE_UNSIGNED_INTEGER = 3,
100-
IPC4_TYPE_FLOAT = 4
100+
IPC4_TYPE_FLOAT = 4,
101+
IPC4_TYPE_A_LAW = 5,
102+
IPC4_TYPE_MU_LAW = 6,
101103
};
102104

103105
enum ipc4_stream_type {

0 commit comments

Comments
 (0)