Skip to content

Commit a6f8dae

Browse files
fkwasowimwasko
authored andcommitted
kpb: add micselection function
Add micsel function to create a topology with KD without a separate micselector module Signed-off-by: Kwasowiec, Fabiola <fabiola.kwasowiec@intel.com>
1 parent b1822cd commit a6f8dae

File tree

2 files changed

+200
-8
lines changed

2 files changed

+200
-8
lines changed

src/audio/kpb.c

Lines changed: 193 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,168 @@ static int kpb_reset(struct comp_dev *dev)
924924
return ret;
925925
}
926926

927+
#ifdef KPB_HIFI3
928+
#if CONFIG_FORMAT_S16LE
929+
static void kpb_micselect_copy16(struct comp_buffer __sparse_cache *sink,
930+
struct comp_buffer __sparse_cache *source, size_t size,
931+
uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets)
932+
{
933+
struct audio_stream __sparse_cache *istream = &source->stream;
934+
struct audio_stream __sparse_cache *ostream = &sink->stream;
935+
uint16_t ch;
936+
size_t i;
937+
938+
AE_SETCBEGIN0(ostream->addr);
939+
AE_SETCEND0(ostream->end_addr);
940+
941+
buffer_stream_invalidate(source, size);
942+
const ae_int16 *in_ptr = (const ae_int16 *)istream->r_ptr;
943+
ae_int16x4 d16 = AE_ZERO16();
944+
const size_t in_offset = in_channels * sizeof(ae_int16);
945+
const size_t out_offset = micsel_channels * sizeof(ae_int16);
946+
const size_t samples_per_chan = size / (sizeof(uint16_t) * micsel_channels);
947+
ae_int16 *out_ptr;
948+
949+
for (ch = 0; ch < micsel_channels; ch++) {
950+
const ae_int16 *input_data = (const ae_int16 *)(in_ptr) + offsets[ch];
951+
952+
out_ptr = (ae_int16 *)ostream->w_ptr;
953+
out_ptr += ch;
954+
for (i = 0; i < samples_per_chan; i++) {
955+
AE_L16_XP(d16, input_data, in_offset);
956+
AE_S16_0_XC(d16, out_ptr, out_offset);
957+
}
958+
}
959+
}
960+
#endif
961+
#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE
962+
static void kpb_micselect_copy32(struct comp_buffer __sparse_cache *sink,
963+
struct comp_buffer __sparse_cache *source, size_t size,
964+
uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets)
965+
{
966+
struct audio_stream __sparse_cache *istream = &source->stream;
967+
struct audio_stream __sparse_cache *ostream = &sink->stream;
968+
uint16_t ch;
969+
size_t i;
970+
971+
AE_SETCBEGIN0(ostream->addr);
972+
AE_SETCEND0(ostream->end_addr);
973+
974+
buffer_stream_invalidate(source, size);
975+
976+
const ae_int32 *in_ptr = (const ae_int32 *)istream->r_ptr;
977+
ae_int32x2 d32 = AE_ZERO32();
978+
const size_t in_offset = in_channels * sizeof(ae_int32);
979+
const size_t out_offset = micsel_channels * sizeof(ae_int32);
980+
const size_t samples_per_chan = size / (sizeof(uint32_t) * micsel_channels);
981+
ae_int32 *out_ptr;
982+
983+
for (ch = 0; ch < micsel_channels; ch++) {
984+
const ae_int32 *input_data = (const ae_int32 *)(in_ptr) + offsets[ch];
985+
986+
out_ptr = (ae_int32 *)ostream->w_ptr;
987+
out_ptr += ch;
988+
for (i = 0; i < samples_per_chan; i++) {
989+
AE_L32_XP(d32, input_data, in_offset);
990+
AE_S32_L_XC(d32, out_ptr, out_offset);
991+
}
992+
}
993+
}
994+
#endif
995+
#else
996+
static void kpb_micselect_copy16(struct comp_buffer __sparse_cache *sink,
997+
struct comp_buffer __sparse_cache *source, size_t size,
998+
uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets)
999+
{
1000+
struct audio_stream __sparse_cache *istream = &source->stream;
1001+
struct audio_stream __sparse_cache *ostream = &sink->stream;
1002+
1003+
buffer_stream_invalidate(source, size);
1004+
size_t out_samples;
1005+
uint16_t ch;
1006+
1007+
const int16_t *in_data;
1008+
int16_t *out_data;
1009+
const uint32_t samples_per_chan = size / (sizeof(uint16_t) * micsel_channels);
1010+
1011+
for (ch = 0; ch < micsel_channels; ch++) {
1012+
out_samples = 0;
1013+
in_data = (int16_t *)istream->r_ptr;
1014+
out_data = (int16_t *)ostream->w_ptr;
1015+
1016+
for (size_t i = 0; i < samples_per_chan * in_channels; i += in_channels) {
1017+
if (&out_data[out_samples + ch]
1018+
>= (int16_t *)ostream->end_addr) {
1019+
out_data = (int16_t *)ostream->addr;
1020+
out_samples = 0;
1021+
}
1022+
out_data[out_samples + ch] = in_data[i + offsets[ch]];
1023+
out_samples += micsel_channels;
1024+
}
1025+
}
1026+
}
1027+
1028+
static void kpb_micselect_copy32(struct comp_buffer __sparse_cache *sink,
1029+
struct comp_buffer __sparse_cache *source, size_t size,
1030+
uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets)
1031+
{
1032+
struct audio_stream __sparse_cache *istream = &source->stream;
1033+
struct audio_stream __sparse_cache *ostream = &sink->stream;
1034+
1035+
buffer_stream_invalidate(source, size);
1036+
size_t out_samples;
1037+
uint16_t ch;
1038+
const int32_t *in_data;
1039+
int32_t *out_data;
1040+
const uint32_t samples_per_chan = size / (sizeof(uint32_t) * micsel_channels);
1041+
1042+
for (ch = 0; ch < micsel_channels; ch++) {
1043+
out_samples = 0;
1044+
in_data = (int32_t *)istream->r_ptr;
1045+
out_data = (int32_t *)ostream->w_ptr;
1046+
1047+
for (size_t i = 0; i < samples_per_chan * in_channels; i += in_channels) {
1048+
if (&out_data[out_samples + ch]
1049+
>= (int32_t *)ostream->end_addr) {
1050+
out_data = (int32_t *)ostream->addr;
1051+
out_samples = 0;
1052+
}
1053+
out_data[out_samples + ch] = in_data[i + offsets[ch]];
1054+
out_samples += micsel_channels;
1055+
}
1056+
}
1057+
}
1058+
#endif
1059+
static void kpb_micselect_copy(struct comp_dev *dev, struct comp_buffer __sparse_cache *sink_c,
1060+
struct comp_buffer __sparse_cache *source_c, size_t copy_bytes,
1061+
uint32_t channels)
1062+
{
1063+
struct comp_data *kpb = comp_get_drvdata(dev);
1064+
size_t sample_width = kpb->config.sampling_width;
1065+
uint32_t *offsets = kpb->offsets;
1066+
1067+
switch (sample_width) {
1068+
#if CONFIG_FORMAT_S16LE
1069+
case 16:
1070+
kpb_micselect_copy16(sink_c, source_c, copy_bytes,
1071+
channels, kpb->num_of_sel_mic, offsets);
1072+
break;
1073+
#endif /* CONFIG_FORMAT_S16LE */
1074+
#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE
1075+
case 24:
1076+
kpb_micselect_copy32(sink_c, source_c, copy_bytes,
1077+
channels, kpb->num_of_sel_mic, offsets);
1078+
break;
1079+
case 32:
1080+
kpb_micselect_copy32(sink_c, source_c, copy_bytes,
1081+
channels, kpb->num_of_sel_mic, offsets);
1082+
break;
1083+
#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */
1084+
default:
1085+
comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!");
1086+
return;
1087+
}
1088+
}
9271089
/**
9281090
* \brief Copy real time input stream into sink buffer,
9291091
* and in the same time buffers that input for
@@ -941,7 +1103,7 @@ static int kpb_copy(struct comp_dev *dev)
9411103
struct comp_data *kpb = comp_get_drvdata(dev);
9421104
struct comp_buffer *source, *sink;
9431105
struct comp_buffer __sparse_cache *source_c, *sink_c = NULL;
944-
size_t copy_bytes = 0;
1106+
size_t copy_bytes = 0, produced_bytes = 0;
9451107
size_t sample_width = kpb->config.sampling_width;
9461108
struct draining_data *dd = &kpb->draining_task_data;
9471109
uint32_t avail_bytes;
@@ -997,19 +1159,39 @@ static int kpb_copy(struct comp_dev *dev)
9971159
break;
9981160
}
9991161

1000-
kpb_copy_samples(sink_c, source_c, copy_bytes, sample_width, channels);
1001-
1162+
if (kpb->num_of_sel_mic == 0) {
1163+
kpb_copy_samples(sink_c, source_c, copy_bytes, sample_width, channels);
1164+
} else {
1165+
uint32_t avail = audio_stream_get_avail_bytes(&source_c->stream);
1166+
uint32_t free = audio_stream_get_free_bytes(&sink_c->stream);
1167+
1168+
copy_bytes = MIN(avail, free * channels / kpb->num_of_sel_mic);
1169+
copy_bytes = ROUND_DOWN(copy_bytes, (sample_width >> 3) * channels);
1170+
unsigned int total_bytes_per_sample =
1171+
(sample_width >> 3) * kpb->num_of_sel_mic;
1172+
1173+
produced_bytes = copy_bytes * kpb->num_of_sel_mic / channels;
1174+
produced_bytes = ROUND_DOWN(produced_bytes, total_bytes_per_sample);
1175+
if (!copy_bytes) {
1176+
comp_err(dev, "kpb_copy(): nothing to copy sink->free %d source->avail %d",
1177+
free,
1178+
avail);
1179+
ret = PPL_STATUS_PATH_STOP;
1180+
break;
1181+
}
1182+
kpb_micselect_copy(dev, sink_c, source_c, produced_bytes, channels);
1183+
}
10021184
/* Buffer source data internally in history buffer for future
10031185
* use by clients.
10041186
*/
1005-
if (audio_stream_get_avail_bytes(&source_c->stream) <= kpb->hd.buffer_size) {
1187+
if (copy_bytes <= kpb->hd.buffer_size) {
10061188
ret = kpb_buffer_data(dev, source_c, copy_bytes);
1189+
10071190
if (ret) {
10081191
comp_err(dev, "kpb_copy(): internal buffering failed.");
10091192
break;
1010-
} else {
1011-
ret = PPL_STATUS_PATH_STOP;
10121193
}
1194+
ret = PPL_STATUS_PATH_STOP;
10131195

10141196
/* Update buffered size. NOTE! We only record buffered
10151197
* data up to the size of history buffer.
@@ -1021,7 +1203,11 @@ static int kpb_copy(struct comp_dev *dev)
10211203
comp_err(dev, "kpb_copy(): too much data to buffer.");
10221204
}
10231205

1024-
comp_update_buffer_produce(sink_c, copy_bytes);
1206+
if (kpb->num_of_sel_mic == 0)
1207+
comp_update_buffer_produce(sink_c, copy_bytes);
1208+
else
1209+
comp_update_buffer_produce(sink_c, produced_bytes);
1210+
10251211
comp_update_buffer_consume(source_c, copy_bytes);
10261212

10271213
break;

src/include/sof/math/numbers.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@
2929
__a < 0 ? -1 : \
3030
__a > 0 ? 1 : 0; \
3131
})
32-
32+
#ifndef ROUND_DOWN
33+
#define ROUND_DOWN(size, alignment) ({ \
34+
typeof(size) __size = (size); \
35+
typeof(alignment) __alignment = (alignment); \
36+
__size - (__size % __alignment); \
37+
})
38+
#endif /* !ROUND_DOWN */
3339
int gcd(int a, int b); /* Calculate greatest common divisor for a and b */
3440

3541
/* This is a divide function that returns ceil of the quotient.

0 commit comments

Comments
 (0)