Skip to content

Commit c265ce3

Browse files
singalsulgirdwood
authored andcommitted
Audio: PCM converter: Add support for A-law sample type
This patch adds to the PCM converter functions pcm_convert_alaw_to_s32() and pcm_convert_s32_to_alaw(). The function audio_stream_fmt_conversion() is also updated to check the sample type and depth to set up correctly conversion for A-law. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent fbf8849 commit c265ce3

6 files changed

Lines changed: 93 additions & 2 deletions

File tree

src/audio/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ config FORMAT_U8
180180
help
181181
Support unsigned 8 bit processing data format
182182

183+
config FORMAT_A_LAW
184+
bool "Support A-law"
185+
help
186+
Support 8 bit A-law processing data format.
187+
183188
config FORMAT_S16LE
184189
bool "Support S16LE"
185190
default y
@@ -228,6 +233,12 @@ config PCM_CONVERTER_FORMAT_U8
228233
help
229234
Support 8 bit processing data format without sign
230235

236+
config PCM_CONVERTER_FORMAT_A_LAW
237+
bool "Support A-law"
238+
select MATH_A_LAW_CODEC
239+
help
240+
Support 8 bit A-law data format.
241+
231242
config PCM_CONVERTER_FORMAT_S16LE
232243
bool "Support S16LE"
233244
default y

src/audio/pcm_converter/pcm_converter_generic.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <sof/audio/buffer.h>
2323
#include <sof/audio/format.h>
24+
#include <sof/math/a_law.h>
2425
#include <rtos/bit.h>
2526
#include <sof/common.h>
2627
#include <sof/compiler_attributes.h>
@@ -93,6 +94,66 @@ static int pcm_convert_s32_to_u8(const struct audio_stream *source,
9394
}
9495
#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
9596

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

98159
static int pcm_convert_s16_to_s24(const struct audio_stream *source,
@@ -555,6 +616,13 @@ const struct pcm_func_map pcm_func_map[] = {
555616
{ SOF_IPC_FRAME_U8, SOF_IPC_FRAME_S32_LE, pcm_convert_u8_to_s32 },
556617
{ SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_U8, pcm_convert_s32_to_u8 },
557618
#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
619+
#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW
620+
{ SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_A_LAW, just_copy },
621+
#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW */
622+
#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE
623+
{ SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_S32_LE, pcm_convert_alaw_to_s32 },
624+
{ SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_A_LAW, pcm_convert_s32_to_alaw },
625+
#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */
558626
#if CONFIG_PCM_CONVERTER_FORMAT_S16LE
559627
{ SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, just_copy },
560628
#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE */

src/include/module/audio/format.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static inline uint32_t get_sample_bytes(enum sof_ipc_frame fmt)
2222
case SOF_IPC_FRAME_S24_3LE:
2323
return 3;
2424
case SOF_IPC_FRAME_U8:
25+
case SOF_IPC_FRAME_A_LAW:
2526
return 1;
2627
default:
2728
return 4;
@@ -37,6 +38,7 @@ static inline uint32_t get_sample_bitdepth(enum sof_ipc_frame fmt)
3738
case SOF_IPC_FRAME_S24_3LE:
3839
return 24;
3940
case SOF_IPC_FRAME_U8:
41+
case SOF_IPC_FRAME_A_LAW:
4042
return 8;
4143
default:
4244
return 32;

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 {

src/include/sof/audio/audio_stream.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,13 @@ static inline void audio_stream_fmt_conversion(enum ipc4_bit_depth depth,
10281028
*valid_fmt = SOF_IPC_FRAME_U8;
10291029
#endif /* CONFIG_FORMAT_U8 */
10301030

1031+
#ifdef CONFIG_FORMAT_A_LAW
1032+
if (type == IPC4_TYPE_A_LAW && depth == 8) {
1033+
*frame_fmt = SOF_IPC_FRAME_A_LAW;
1034+
*valid_fmt = SOF_IPC_FRAME_A_LAW;
1035+
}
1036+
#endif
1037+
10311038
if (valid == 24) {
10321039
#ifdef CONFIG_FORMAT_S24_3LE
10331040
if (depth == 24) {

0 commit comments

Comments
 (0)