@@ -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 ;
0 commit comments