Tools: Topology1: Add MFCC component

This patch adds basic macros needed for MFCC in testbench and in
developmemnt topologies for hda-generic-2ch and up2. The
configuration blob in this matches the reference Matlab code
as configured to match Pytorch default MFCC.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This commit is contained in:
Seppo Ingalsuo 2022-06-02 18:57:08 +03:00 committed by Liam Girdwood
parent 5b63f446d2
commit e2d73e236a
7 changed files with 384 additions and 1 deletions

View File

@ -240,7 +240,8 @@ done
# for processing algorithms
ALG_SINGLE_MODE_TESTS=(asrc eq-fir eq-iir src dcblock drc multiband-drc tdfb
tdfb_line4_28mm_pm90deg_48khz tdfb_circular8_100mm_pm30deg_48khz)
tdfb_line4_28mm_pm90deg_48khz tdfb_circular8_100mm_pm30deg_48khz
mfcc)
ALG_SINGLE_SIMPLE_TESTS=(test-capture test-playback)
ALG_MULTI_MODE_TESTS=(crossover)
ALG_MULTI_SIMPLE_TESTS=(test-playback)

View File

@ -42,6 +42,7 @@ set(TPLGS
# The topologies those are built from topology in the parent directory
set(TPLGS_UP
"sof-apl-pcm512x\;sof-apl-pcm512x-tdfb_28mm-4ch\;-DFSYNC=48000\;-DDMIC_PCM_CHANNELS=2\;-DDMIC_DAI_CHANNELS=4\;-DDMIC16K_PCM_CHANNELS=2\;-DDMIC16K_DAI_CHANNELS=4\;-DDMIC16KPROC=tdfb-eq-iir-volume\;-DDMIC16KPROC_FILTER1=tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_16khz.m4\;-DDMICPROC=tdfb-eq-iir-volume\;-DDMICPROC_FILTER1=tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_48khz.m4\;-DDMICPROC_FILTER2=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER2=eq_iir_coef_highpass_40hz_20db_16khz.m4"
"sof-apl-pcm512x\;sof-apl-pcm512x-mfcc-2ch\;-DFSYNC=48000\;-DCHANNELS=2\;-DDMIC16KPROC=eq-iir-mfcc\;-DDMICPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_16khz.m4"
"sof-cml-rt1011-rt5682\;sof-cml-eq-rt1011-rt5682\;-DPLATFORM=cml\;-DPPROC=eq-iir-eq-fir-volume"
"sof-cml-rt5682\;sof-cml-eq-fir-loud-rt5682\;-DPLATFORM=cml\;-DHSEARPROC=eq-iir-volume\;-DPIPELINE_FILTER1=eq_iir_coef_loudness.m4\;-DHSMICPROC=eq-fir-volume\;-DPIPELINE_FILTER2=eq_fir_coef_loudness.m4\;-DDMICPROC=eq-iir-volume\;-DDMIC16KPROC=eq-iir-volume"
"sof-cml-rt5682\;sof-cml-eq-fir-rt5682\;-DPLATFORM=cml\;-DHSMICPROC=eq-fir-volume\;-DDMICPROC=eq-iir-volume\;-DDMIC16KPROC=eq-iir-volume"
@ -57,6 +58,7 @@ set(TPLGS_UP
"sof-hda-generic\;sof-hda-generic-2ch-multiband-drc\;-DCHANNELS=2\;-DHSPROC=multiband-drc\;-DDMICPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_16khz.m4\;-DDYNAMIC=1"
"sof-hda-generic\;sof-hda-generic-drc\;-DCHANNELS=0\;-DHSPROC=drc\;-DDYNAMIC=1"
"sof-hda-generic\;sof-hda-generic-2ch-drc\;-DCHANNELS=2\;-DHSPROC=drc\;-DDMICPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_16khz.m4\;-DDYNAMIC=1"
"sof-hda-generic\;sof-hda-generic-2ch-mfcc\;-DCHANNELS=2\;-DHSPROC=volume\;-DDMICPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_16khz.m4\;-DDYNAMIC=1\;-DDMIC16KPROC=eq-iir-mfcc"
"sof-tgl-rt711-rt1308\;sof-tgl-sdw-max98373-rt5682-dmic4ch-ampref\;-DCHANNELS=4\;-DEXT_AMP\;-DEXT_AMP_REF\;-DDMICPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_48khz.m4\;-DDMIC16KPROC_FILTER1=eq_iir_coef_highpass_40hz_20db_16khz.m4\;-DPLATFORM=tgl"
)

View File

@ -0,0 +1,65 @@
divert(-1)
dnl Define macro for MFCC widget
DECLARE_SOF_RT_UUID("mfcc", mfcc_uuid, 0xdb10a773, 0x1aa4, 0x4cea,
0xa2, 0x1f, 0x2d, 0x57, 0xa5, 0xc9, 0x82, 0xeb)
dnl N_MFCC(name)
define(`N_MFCC', `MFCC'PIPELINE_ID`.'$1)
dnl W_MFCC(name, format, periods_sink, periods_source, core, kcontrols_list)
define(`W_MFCC',
`SectionVendorTuples."'N_MFCC($1)`_tuples_uuid" {'
` tokens "sof_comp_tokens"'
` tuples."uuid" {'
` SOF_TKN_COMP_UUID' STR(mfcc_uuid)
` }'
`}'
`SectionData."'N_MFCC($1)`_data_uuid" {'
` tuples "'N_MFCC($1)`_tuples_uuid"'
`}'
`SectionVendorTuples."'N_MFCC($1)`_tuples_w" {'
` tokens "sof_comp_tokens"'
` tuples."word" {'
` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3)
` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4)
` SOF_TKN_COMP_CORE_ID' STR($5)
` }'
`}'
`SectionData."'N_MFCC($1)`_data_w" {'
` tuples "'N_MFCC($1)`_tuples_w"'
`}'
`SectionVendorTuples."'N_MFCC($1)`_tuples_str" {'
` tokens "sof_comp_tokens"'
` tuples."string" {'
` SOF_TKN_COMP_FORMAT' STR($2)
` }'
`}'
`SectionData."'N_MFCC($1)`_data_str" {'
` tuples "'N_MFCC($1)`_tuples_str"'
`}'
`SectionVendorTuples."'N_MFCC($1)`_tuples_str_type" {'
` tokens "sof_process_tokens"'
` tuples."string" {'
` SOF_TKN_PROCESS_TYPE' "MFCC"
` }'
`}'
`SectionData."'N_MFCC($1)`_data_str_type" {'
` tuples "'N_MFCC($1)`_tuples_str_type"'
`}'
`SectionWidget."'N_MFCC($1)`" {'
` index "'PIPELINE_ID`"'
` type "effect"'
` no_pm "true"'
` data ['
` "'N_MFCC($1)`_data_uuid"'
` "'N_MFCC($1)`_data_w"'
` "'N_MFCC($1)`_data_str"'
` "'N_MFCC($1)`_data_str_type"'
` ]'
` bytes ['
$6
` ]'
`}')
divert(0)dnl

View File

@ -0,0 +1,20 @@
# Exported MFCC configuration 30-Sep-2022
CONTROLBYTES_PRIV(DEF_MFCC_PRIV,
` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,'
` 0x68,0x00,0x00,0x00,0x00,0x80,0x01,0x03,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x80,0x3e,0x00,0x00,'
` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,'
` 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,'
` 0xc3,0x35,0x00,0x2c,0xff,0xff,0x00,0x00,'
` 0x90,0x01,0xa0,0x00,0x00,0x00,0x14,0x00,'
` 0x0d,0x00,0x17,0x00,0x00,0x00,0x00,0x64,'
` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,'
` 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00"'
)

View File

@ -0,0 +1,119 @@
# Capture EQ MFCC Pipeline and PCM, 16 kHz
#
# Pipeline Endpoints for connection are :-
#
# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0
# Include topology builder
include(`utils.m4')
include(`buffer.m4')
include(`pcm.m4')
include(`dai.m4')
include(`pipeline.m4')
include(`bytecontrol.m4')
include(`eq_iir.m4')
include(`mfcc.m4')
#
# Controls
#
define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID))
define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID))
# define filter. mfcc_config.m4 is set by default
ifdef(`DMIC16KPROC_FILTER2', , `define(DMIC16KPROC_FILTER2, `mfcc/mfcc_config.m4')')
include(DMIC16KPROC_FILTER2)
# MFCC Bytes control with max value of 255
define(DEF_MFCC_PARAM, concat(`mfcc_param_', PIPELINE_ID))
C_CONTROLBYTES(DEF_MFCC_PARAM, PIPELINE_ID,
CONTROLBYTES_OPS(bytes,
258 binds the mixer control to bytes get/put handlers, 258, 258),
CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers,
258, 258),
, , ,
CONTROLBYTES_MAX(, 1024),
,
DEF_MFCC_PRIV)
# By default, use 40 Hz highpass response with +0 dB gain for 16khz
# TODO: need to implement middle level macro handler per pipeline
ifdef(`DMIC16KPROC_FILTER1', , `define(DMIC16KPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_16khz.m4)')
define(DEF_EQIIR_PRIV, DMIC16KPROC_FILTER1)
include(DMIC16KPROC_FILTER1)
define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID))
# EQ Bytes control with max value of 255
C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID,
CONTROLBYTES_OPS(bytes,
258 binds the mixer control to bytes get/put handlers,
258, 258),
CONTROLBYTES_EXTOPS(
258 binds the mixer control to bytes get/put handlers,
258, 258),
, , ,
CONTROLBYTES_MAX(, 1024),
,
DEF_EQIIR_PRIV)
#
# Components and Buffers
#
# Host "Highpass Capture" PCM
# with 0 sink and 2 source periods
W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE)
# "MFCC 0" has 2 source period and 2 sink periods
W_MFCC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE,
LIST(` ', "DEF_MFCC_PARAM"))
# "EQ 0" has 2 sink period and x source periods
W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE,
LIST(` ', "DEF_EQIIR_COEF"))
# Capture Buffers
W_BUFFER(0, COMP_BUFFER_SIZE(2,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP)
W_BUFFER(1, COMP_BUFFER_SIZE(2,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP)
W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP)
#
# Pipeline Graph
#
# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0
P_GRAPH(pipe-eq-iir-mfcc-capture-16khz, PIPELINE_ID,
LIST(` ',
`dapm(N_PCMC(PCM_ID), N_BUFFER(0))',
`dapm(N_BUFFER(0), N_MFCC(0))',
`dapm(N_MFCC(0), N_BUFFER(1))',
`dapm(N_BUFFER(1), N_EQ_IIR(0))',
`dapm(N_EQ_IIR(0), N_BUFFER(2))'))
#
# Pipeline Source and Sinks
#
indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2))
indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID)
#
# PCM Configuration
#
PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000,
PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536)
undefine(`DEF_EQIIR_COEF')
undefine(`DEF_EQIIR_PRIV')
undefine(`DEF_MFCC_PARAM')
undefine(`DEF_MFCC_CONFIG')
undefine(`DEF_MFCC_PRIV')

View File

@ -0,0 +1,88 @@
# Capture EQ Pipeline and PCM, 48 kHz
#
# Pipeline Endpoints for connection are :-
#
# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <-- sink DAI0
# Include topology builder
include(`utils.m4')
include(`buffer.m4')
include(`pcm.m4')
include(`dai.m4')
include(`pipeline.m4')
include(`bytecontrol.m4')
include(`mfcc.m4')
#
# Controls
#
define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID))
define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID))
# By default, use 40 Hz highpass response with 0 dB gain
# TODO: need to implement middle level macro handler per pipeline
ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `mfcc/mfcc_config.m4')')
include(PIPELINE_FILTER1)
# EQ Bytes control with max value of 255
C_CONTROLBYTES(DEF_MFCC_CONFIG, PIPELINE_ID,
CONTROLBYTES_OPS(bytes,
258 binds the mixer control to bytes get/put handlers,
258, 258),
CONTROLBYTES_EXTOPS(
258 binds the mixer control to bytes get/put handlers,
258, 258),
, , ,
CONTROLBYTES_MAX(, 1024),
,
DEF_MFCC_PRIV)
#
# Components and Buffers
#
# Host "MFCC Capture" PCM
# with 0 sink and 2 source periods
W_PCM_CAPTURE(PCM_ID, MFCC Capture, 0, 2, SCHEDULE_CORE)
# "EQ 0" has 2 sink period and x source periods
W_MFCC(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE,
LIST(` ', "DEF_MFCC_CONFIG"))
# Capture Buffers
W_BUFFER(0, COMP_BUFFER_SIZE(2,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP)
W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP)
#
# Pipeline Graph
#
# host PCM_C <-- B0 <--MFCC 0 <-- B1 <-- sink DAI0
P_GRAPH(pipe-eq-iir-capture, PIPELINE_ID,
LIST(` ',
`dapm(N_PCMC(PCM_ID), N_BUFFER(0))',
`dapm(N_BUFFER(0), N_MFCC(0))',
`dapm(N_MFCC(0), N_BUFFER(1))'))
#
# Pipeline Source and Sinks
#
indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1))
indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), MFCC Capture PCM_ID)
#
# PCM Configuration
#
PCM_CAPABILITIES(MFCC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE,
PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS,
2, 16, 192, 16384, 65536, 65536)
undefine(`DEF_MFCC_CONFIG')
undefine(`DEF_MFCC_PRIV')

View File

@ -0,0 +1,88 @@
# Low Latency mfcc pipeline and PCM
#
# Pipeline Endpoints for connection are :-
#
# host PCM_P --> B0 --> MFCC 0 --> B1 --> sink DAI0
# Include topology builder
include(`utils.m4')
include(`buffer.m4')
include(`pcm.m4')
include(`dai.m4')
include(`bytecontrol.m4')
include(`pipeline.m4')
include(`mfcc.m4')
#
# Controls
#
define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID))
define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID))
# define filter. mfcc_config.m4 is set by default
ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `mfcc/mfcc_config.m4')')
include(PIPELINE_FILTER1)
# MFCC Bytes control with max value of 255
define(MY_CONTROLBYTES, concat(`MFCC_CONTROLBYTES_', PIPELINE_ID))
C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID,
CONTROLBYTES_OPS(bytes,
258 binds the mixer control to bytes get/put handlers, 258, 258),
CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers,
258, 258),
, , ,
CONTROLBYTES_MAX(, 1024),
,
DEF_MFCC_PRIV)
#
# Components and Buffers
#
# Host "MFCC Playback" PCM
# with 2 sink and 0 source periods
W_PCM_PLAYBACK(PCM_ID, MFCC Playback, 2, 0, SCHEDULE_CORE)
# "MFCC 0" has x sink period and 2 source periods
W_MFCC(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE,
LIST(` ', "MY_CONTROLBYTES"))
# Playback Buffers
W_BUFFER(0, COMP_BUFFER_SIZE(2,
COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)),
PLATFORM_HOST_MEM_CAP)
W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS,
COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS,
COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)),
PLATFORM_DAI_MEM_CAP)
#
# Pipeline Graph
#
# host PCM_P --> B0 --> MFCC 0 --> B1 --> sink DAI0
P_GRAPH(pipe-mfcc-playback, PIPELINE_ID,
LIST(` ',
`dapm(N_BUFFER(0), N_PCMP(PCM_ID))',
`dapm(N_MFCC(0), N_BUFFER(0))',
`dapm(N_BUFFER(1), N_MFCC(0))'))
#
# Pipeline Source and Sinks
#
indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1))
indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), MFCC Playback PCM_ID)
#
# PCM Configuration
#
PCM_CAPABILITIES(MFCC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT),
PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS,
2, 16, 192, 16384, 65536, 65536)
undefine(`MY_CONTROLBYTES')
undefine(`DEF_MFCC_CONFIG')
undefine(`DEF_MFCC_PRIV')