CMSIS-DSP: Add MFCC to SDFTools

Python and C++ nodes available.
New examples 5 and 6 are shwoing how to use MFCC in SDF in both cases.
pull/19/head
Christophe Favergeon 4 years ago
parent d25b745082
commit 6ab9125272

@ -9,4 +9,10 @@ examples/build/bin_example2
examples/build/bin_dsp/
examples/build/bin_example3/
*.pyd
examples/build/localcreate.bat
examples/build/input_example3.txt
examples/build/bin_example6/
examples/build/input_example6.txt
examples/build/output_example3.txt
examples/build/output_example6.txt

@ -173,3 +173,23 @@ Here is a list of the nodes supported by default. More can be easily added:
- [Example 3 : Working example with CMSIS-DSP and FFT](documentation/example3.md)
- [Example 4 : Same as example 3 but with the CMSIS-DSP Python wrapper](documentation/example4.md)
Examples 5 and 6 are showing how to use the CMSIS-DSP MFCC with a synchronous data flow.
## Building the examples
The script `create.bat` or `create.sh` in folder `examples/build` must be changed to use the path to the root CMSIS-DSP folder.
Then, those scripts can be used to create a make using cmake.
After those steps, typing `make` will build the C examples.
To run the first one for example you'll have to type (from `build` folder): `bin_example1\example1`
For the python examples, you need to go to the example folder (for instance `example4`). In the folder, type `python main.py`.
If the dataflow is changed for any Python example, from the corresponding example folder you'll have to type `python graph.py` to regenerate the schedule. And you'll have to type `dot -Tpdf -o test.pdf test.dot` in the Python examples to regenerate the graph picture.
For the C++ examples, the make is taking care of regenerating the schedule and the dot graph when `graph.py` is edited.

@ -20,12 +20,14 @@ It is much more complex:
- The node HALF representing a constant is introduced (constant arrays are also supported)
- The two streams are added using a CMSIS-DSP function
- Then we have a sliding buffer
- A block representing a MFCC
- A block representing a MFCC (a fake MFCC)
- Another sliding buffer
- An a block representing TensorFlow Lite for Micro
- An a block representing TensorFlow Lite for Micro (a fake TFLite node)
Note that those blocks (MFCC, TFLite) are doing nothing in this example. It is just to illustrate a more complex example that someone may want to experiment with for keyword spotting.
Examples 5 and 6 are showing how to use the CMSIS-DSP MFCC.
The new features compared to `example1` are:
- Delay

@ -47,3 +47,4 @@ add_subdirectory(${DSP}/Source bin_dsp)
add_subdirectory(example1 bin_example1)
add_subdirectory(example2 bin_example2)
add_subdirectory(example3 bin_example3)
add_subdirectory(example6 bin_example6)

@ -32,6 +32,7 @@ class StereoSource(GenericSource):
def typeName(self):
return "StereoSource"
# This is a fake TFLite node just for illustration
class TFLite(GenericSink):
def __init__(self,name):
GenericSink.__init__(self,name)
@ -41,6 +42,8 @@ class TFLite(GenericSink):
def typeName(self):
return "TFLite"
# This is a fake MFCC just to illustrate how it could be used in a graph.
# For a real MFCC example, look at example5
class MFCC(GenericNode):
def __init__(self,name,inLength):
GenericNode.__init__(self,name)

@ -35,8 +35,8 @@ using namespace std;
#include <cstdio>
#include "arm_math.h"
#include "FileSink.h"
#include "FileSource.h"
#include "host/FileSink.h"
#include "host/FileSource.h"
#include "CFFT.h"
#include "ICFFT.h"

@ -3,8 +3,6 @@
#define HALF 0.5
extern const float32_t HANN[256];
extern arm_cfft_instance_f32 CFFT1;
extern arm_cfft_instance_f32 ICFFT1;
#endif

@ -1,16 +0,0 @@
cmake_minimum_required (VERSION 3.14)
include(CMakePrintHelpers)
project(Example3)
add_executable(example3 main.cpp custom.cpp)
sdf(example3)
add_sdf_dir(example3)
target_include_directories(example3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(example3 PRIVATE CMSISDSP)
file(COPY input_example3.txt DESTINATION ${CMAKE_BINARY_DIR})

@ -28,8 +28,8 @@
from sdf.schedule.simu import *
from custom import *
from sdf.nodes.py.FileSink import *
from sdf.nodes.py.FileSource import *
from sdf.nodes.py.host.FileSink import *
from sdf.nodes.py.host.FileSource import *
from sdf.nodes.py.CFFT import *
from sdf.nodes.py.ICFFT import *
from sdf.nodes.py.ToComplex import *

@ -0,0 +1,45 @@
###########################################
# Project: CMSIS DSP Library
# Title: appnodes.py
# Description: Application nodes for Example 4
#
# $Date: 29 July 2021
# $Revision: V1.10.0
#
# Target Processor: Cortex-M and Cortex-A cores
# -------------------------------------------------------------------- */
#
# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################
from sdf.schedule.simu import *
from custom import *
# Host only nodes
from sdf.nodes.py.host.NumpySink import *
from sdf.nodes.py.host.WavSource import *
# Embedded nodes
from sdf.nodes.py.StereoToMono import *
from sdf.nodes.py.MFCC import *

@ -0,0 +1,4 @@
import numpy as np

@ -0,0 +1,46 @@
"""
=================================================
Animated image using a precomputed list of images
=================================================
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
# ims is a list of lists, each row is a list of artists to draw in the
# current frame; here we are just animating one artist, the image, in
# each frame
ims = []
for i in range(60):
x += np.pi / 15.
y += np.pi / 20.
im = ax.imshow(f(x, y), animated=True)
if i == 0:
ax.imshow(f(x, y)) # show an initial one first
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
# To save the animation, use e.g.
#
# ani.save("movie.mp4")
#
# or
#
# writer = animation.FFMpegWriter(
# fps=15, metadata=dict(artist='Me'), bitrate=1800)
# ani.save("movie.mp4", writer=writer)
plt.show()

@ -0,0 +1,60 @@
import sys
import numpy as np
sys.path.append("../..")
from sdf import *
from sharedconfig import *
q15Type = CType(Q15)
### The feature computed by the graph is one second of MFCCs.
### So the nbMFCCOutputs is computed from this and with the additional
### assumption that it must be even.
### Because the MFCC slising window is sliding by half a second
### each time (half number of MFCCs)
src=WavSource("src",NBCHANNELS*AUDIO_INTERRUPT_LENGTH)
src.addLiteralArg("test_stereo.wav")
toMono=StereoToMono("toMono",q15Type,AUDIO_INTERRUPT_LENGTH)
slidingAudio=SlidingBuffer("audioWin",q15Type,FFTSize,AudioOverlap)
slidingMFCC=SlidingBuffer("mfccWin",q15Type,numOfDctOutputs*nbMFCCOutputs,numOfDctOutputs*nbMFCCOutputs>>1)
mfcc=MFCC("mfcc",q15Type,FFTSize,numOfDctOutputs)
mfcc.addVariableArg("mfccConfig")
sink=NumpySink("sink",q15Type,nbMFCCOutputs * numOfDctOutputs)
sink.addVariableArg("dispbuf")
g = Graph()
g.connect(src.o, toMono.i)
g.connect(toMono.o, slidingAudio.i)
g.connect(slidingAudio.o, mfcc.i)
g.connect(mfcc.o,slidingMFCC.i)
g.connect(slidingMFCC.o,sink.i)
print("Generate graphviz and code")
sched = g.computeSchedule()
print("Schedule length = %d" % sched.scheduleLength)
print("Memory usage %d bytes" % sched.memory)
#
conf=Configuration()
conf.debugLimit=12
conf.pyOptionalArgs="mfccConfig,dispbuf"
sched.pythoncode(".",config=conf)
with open("test.dot","w") as f:
sched.graphviz(f)

@ -0,0 +1,56 @@
import sched as s
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.animation as animation
import cmsisdsp as dsp
import numpy as np
import cmsisdsp.fixedpoint as f
import cmsisdsp.mfcc as mfcc
import scipy.signal as sig
from cmsisdsp.datatype import F32,Q31,Q15
from sharedconfig import *
import cmsisdsp.datatype as dt
mfccq15=dsp.arm_mfcc_instance_q15()
windowQ15 = dt.convert(sig.hamming(FFTSize, sym=False),Q15)
filtLen,filtPos,packedFiltersQ15 = mfcc.melFilterMatrix(Q15,freq_min, freq_high, numOfMelFilters,sample_rate,FFTSize)
dctMatrixFiltersQ15 = mfcc.dctMatrix(Q15,numOfDctOutputs, numOfMelFilters)
status=dsp.arm_mfcc_init_q15(mfccq15,FFTSize,numOfMelFilters,numOfDctOutputs,
dctMatrixFiltersQ15,
filtPos,filtLen,packedFiltersQ15,windowQ15)
#DISPBUF = np.zeros(nbMFCCOutputs*numOfDctOutputs)
DISPBUF=[]
print("Start")
nb,error = s.scheduler(mfccq15,DISPBUF)
print("Nb sched = %d" % nb)
fig, ax = plt.subplots()
# The test signal is 5 second long
# MFCC are slided by 0.5 second by the last window
# Each sink entry is a one second of MFCC
ims = []
for i in range(10):
mfccdata = (1<<8)*f.Q15toF32(DISPBUF[i])
mfccdata=mfccdata.reshape((nbMFCCOutputs,numOfDctOutputs))
mfccdata= np.swapaxes(mfccdata, 0 ,1)
if i==0:
ax.imshow(mfccdata, vmin=-10, vmax=10,interpolation='nearest',cmap=cm.coolwarm ,origin='lower')
im=ax.imshow(mfccdata, vmin=-10, vmax=10,interpolation='nearest', animated=True,cmap=cm.coolwarm ,origin='lower')
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=500, blit=True,
repeat_delay=500)
#ani.save("mfcc.mp4")
plt.show()

@ -0,0 +1,947 @@
#
# Generated with CMSIS-DSP SDF Scripts.
# The generated code is not covered by CMSIS-DSP license.
#
# The support classes and code is covered by CMSIS-DSP license.
#
import sys
# To find SDF module
sys.path.append("../..")
import numpy as np
import cmsisdsp as dsp
from sdf.schedule.simu import *
from appnodes import *
from custom import *
DEBUGSCHED=False
#
# FIFO buffers
#
FIFOSIZE0=384
buf0=np.zeros(FIFOSIZE0,dtype=np.int16)
FIFOSIZE1=768
buf1=np.zeros(FIFOSIZE1,dtype=np.int16)
FIFOSIZE2=1024
buf2=np.zeros(FIFOSIZE2,dtype=np.int16)
FIFOSIZE3=377
buf3=np.zeros(FIFOSIZE3,dtype=np.int16)
FIFOSIZE4=754
buf4=np.zeros(FIFOSIZE4,dtype=np.int16)
def scheduler(mfccConfig,dispbuf):
sdfError=0
nbSchedule=0
debugCounter=12
#
# Create FIFOs objects
#
fifo0=FIFO(FIFOSIZE0,buf0)
fifo1=FIFO(FIFOSIZE1,buf1)
fifo2=FIFO(FIFOSIZE2,buf2)
fifo3=FIFO(FIFOSIZE3,buf3)
fifo4=FIFO(FIFOSIZE4,buf4)
#
# Create node objects
#
audioWin = SlidingBuffer(1024,256,fifo1,fifo2);
mfcc = MFCC(1024,13,fifo2,fifo3,mfccConfig);
mfccWin = SlidingBuffer(754,377,fifo3,fifo4);
sink = NumpySink(754,fifo4,dispbuf);
src = WavSource(384,fifo0,"test_stereo.wav");
toMono = StereoToMono(384,192,fifo0,fifo1);
while((sdfError==0) and (debugCounter > 0)):
nbSchedule = nbSchedule + 1
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = src.run()
if sdfError < 0:
break
sdfError = toMono.run()
if sdfError < 0:
break
sdfError = audioWin.run()
if sdfError < 0:
break
sdfError = mfcc.run()
if sdfError < 0:
break
sdfError = mfccWin.run()
if sdfError < 0:
break
sdfError = sink.run()
if sdfError < 0:
break
debugCounter = debugCounter - 1
return(nbSchedule,sdfError)

@ -0,0 +1,25 @@
import sys
import numpy as np
FS=16000
NBCHANNELS=2 # stereo
# You can try with 120
AUDIO_INTERRUPT_LENGTH = 192
# MFCC Description
sample_rate = 16000
FFTSize = 1024
AudioOverlap = 256
numOfDctOutputs = 13
freq_min = 64
freq_high = sample_rate / 2
numOfMelFilters = 20
# NB MFCC Outputs to cover one second of signal with the window overlap
nbMFCCOutputs = int(np.floor((sample_rate - FFTSize) / AudioOverlap))
if nbMFCCOutputs%2 == 1:
nbMFCCOutputs = nbMFCCOutputs + 1

@ -0,0 +1,66 @@
digraph structs {
node [shape=plaintext]
rankdir=LR
edge [arrowsize=0.5]
fontname="times"
audioWin [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">audioWin<BR/>(SlidingBuffer)</TD>
</TR>
</TABLE>>];
mfcc [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">mfcc<BR/>(MFCC)</TD>
</TR>
</TABLE>>];
mfccWin [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">mfccWin<BR/>(SlidingBuffer)</TD>
</TR>
</TABLE>>];
sink [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">sink<BR/>(NumpySink)</TD>
</TR>
</TABLE>>];
src [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">src<BR/>(WavSource)</TD>
</TR>
</TABLE>>];
toMono [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">toMono<BR/>(StereoToMono)</TD>
</TR>
</TABLE>>];
src:i -> toMono:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >384</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >384</FONT>>,label="q15(384)"]
toMono:i -> audioWin:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >768</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >192</FONT>>,label="q15(768)"]
audioWin:i -> mfcc:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >1024</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >1024</FONT>>,label="q15(1024)"]
mfcc:i -> mfccWin:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >377</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >13</FONT>>,label="q15(377)"]
mfccWin:i -> sink:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >754</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >754</FONT>>,label="q15(754)"]
}

@ -0,0 +1,44 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: AppNodes.h
* Description: Application nodes for Example 6
*
* $Date: 29 July 2021
* $Revision: V1.10.0
*
* Target Processor: Cortex-M and Cortex-A cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _APPNODES_H_
#define _APPNODES_H_
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#include <cstdio>
#include "arm_math.h"
#include "host/FileSink.h"
#include "host/FileSource.h"
#include "MFCC.h"
#endif

@ -0,0 +1,17 @@
cmake_minimum_required (VERSION 3.14)
include(CMakePrintHelpers)
project(Example6)
add_executable(example6 main.cpp mfccConfigData.c)
sdf(example6)
add_sdf_dir(example6)
target_include_directories(example6 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(example6 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated)
target_link_libraries(example6 PRIVATE CMSISDSP)
file(COPY input_example6.txt DESTINATION ${CMAKE_BINARY_DIR})

@ -0,0 +1,4 @@
#ifndef _CUSTOM_H_
#endif

@ -0,0 +1,106 @@
/*
Generated with CMSIS-DSP SDF Scripts.
The generated code is not covered by CMSIS-DSP license.
The support classes and code is covered by CMSIS-DSP license.
*/
#include "arm_math.h"
#include "custom.h"
#include "GenericNodes.h"
#include "AppNodes.h"
#include "scheduler.h"
/***********
FIFO buffers
************/
#define FIFOSIZE0 256
#define FIFOSIZE1 256
#define FIFOSIZE2 13
#define FIFOSIZE3 26
#define BUFFERSIZE0 256
float32_t buf0[BUFFERSIZE0]={0};
#define BUFFERSIZE1 256
float32_t buf1[BUFFERSIZE1]={0};
#define BUFFERSIZE2 13
float32_t buf2[BUFFERSIZE2]={0};
#define BUFFERSIZE3 26
float32_t buf3[BUFFERSIZE3]={0};
uint32_t scheduler(int *error,arm_mfcc_instance_f32 *mfccConfig)
{
int sdfError=0;
uint32_t nbSchedule=0;
int32_t debugCounter=1;
/*
Create FIFOs objects
*/
FIFO<float32_t,FIFOSIZE0,0> fifo0(buf0);
FIFO<float32_t,FIFOSIZE1,1> fifo1(buf1);
FIFO<float32_t,FIFOSIZE2,1> fifo2(buf2);
FIFO<float32_t,FIFOSIZE3,0> fifo3(buf3);
/*
Create node objects
*/
SlidingBuffer<float32_t,256,128> audioWin(fifo0,fifo1);
MFCC<float32_t,256,float32_t,13> mfcc(fifo1,fifo2,mfccConfig);
SlidingBuffer<float32_t,26,13> mfccWin(fifo2,fifo3);
FileSink<float32_t,13> sink(fifo3,"output_example6.txt");
FileSource<float32_t,192> src(fifo0,"input_example6.txt");
while((sdfError==0) && (debugCounter > 0))
{
sdfError = src.run();
CHECKERROR;
sdfError = audioWin.run();
CHECKERROR;
sdfError = mfcc.run();
CHECKERROR;
sdfError = mfccWin.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
sdfError = src.run();
CHECKERROR;
sdfError = audioWin.run();
CHECKERROR;
sdfError = mfcc.run();
CHECKERROR;
sdfError = mfccWin.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
sdfError = audioWin.run();
CHECKERROR;
sdfError = mfcc.run();
CHECKERROR;
sdfError = mfccWin.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
sdfError = sink.run();
CHECKERROR;
debugCounter--;
nbSchedule++;
}
*error=sdfError;
return(nbSchedule);
}

@ -0,0 +1,25 @@
/*
Generated with CMSIS-DSP SDF Scripts.
The generated code is not covered by CMSIS-DSP license.
The support classes and code is covered by CMSIS-DSP license.
*/
#ifndef _SCHED_H_
#define _SCHED_H_
#ifdef __cplusplus
extern "C"
{
#endif
extern uint32_t scheduler(int *error,arm_mfcc_instance_f32 *mfccConfig);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,57 @@
import sys
import numpy as np
sys.path.append("../..")
from sdf import *
from sharedconfig import *
floatType = CType(F32)
### The feature computed by the graph is one second of MFCCs.
### So the nbMFCCOutputs is computed from this and with the additional
### assumption that it must be even.
### Because the MFCC slising window is sliding by half a second
### each time (half number of MFCCs)
src=FileSource("src",NBCHANNELS*AUDIO_INTERRUPT_LENGTH)
src.addLiteralArg("input_example6.txt")
slidingAudio=SlidingBuffer("audioWin",floatType,FFTSize,FFTSize>>1)
slidingMFCC=SlidingBuffer("mfccWin",floatType,2*numOfDctOutputs,numOfDctOutputs)
mfcc=MFCC("mfcc",floatType,FFTSize,numOfDctOutputs)
mfcc.addVariableArg("mfccConfig")
sink=FileSink("sink",numOfDctOutputs)
sink.addLiteralArg("output_example6.txt")
g = Graph()
g.connect(src.o, slidingAudio.i)
g.connect(slidingAudio.o, mfcc.i)
g.connect(mfcc.o,slidingMFCC.i)
g.connect(slidingMFCC.o,sink.i)
print("Generate graphviz and code")
sched = g.computeSchedule()
print("Schedule length = %d" % sched.scheduleLength)
print("Memory usage %d bytes" % sched.memory)
#
conf=Configuration()
conf.debugLimit=1
conf.cOptionalArgs="arm_mfcc_instance_f32 *mfccConfig"
sched.ccode("generated",config=conf)
with open("test.dot","w") as f:
sched.graphviz(f)

@ -0,0 +1,256 @@
0.65507051
-0.94647589
0.00627239
0.14151286
-0.10863318
-0.36370327
0.05777126
-0.11915792
0.50183546
-0.31461335
0.66440771
0.05389963
0.39690544
0.25424852
-0.17045277
0.09649268
0.87357385
-0.44666372
-0.02637822
-0.10055151
-0.14610252
-0.05981251
-0.02999124
0.60923213
0.10530095
0.35684248
0.21845946
0.47845017
-0.60206979
0.25186908
-0.27410056
-0.07080467
-0.05109539
-0.2666572
0.25483105
-0.86459185
0.07733397
-0.58535444
0.06230904
-0.04161475
-0.17467296
0.77721125
-0.01728161
-0.32141218
0.36674466
-0.17932843
0.78486115
0.12469579
-0.94796877
0.05536031
0.32627676
0.46628512
-0.02585836
-0.51439834
0.21387904
0.16319442
-0.01020818
-0.77161183
0.07754634
-0.24970455
0.2368003
0.35167963
0.14620137
-0.02415204
0.91086167
-0.02434647
-0.3968239
-0.04703925
-0.43905103
-0.34834965
0.33728158
0.15138992
-0.43218885
0.26619718
0.07177906
0.33393581
-0.50306915
-0.63101084
-0.08128395
-0.06569788
0.84232797
-0.32436751
0.02528537
-0.3498329
0.41859931
0.07794887
0.4571989
0.24290963
0.08437417
-0.01371585
-0.00103008
0.83978697
-0.29001237
0.14438743
0.11943318
-0.25576402
0.25151083
0.07886626
0.11565781
-0.01582203
0.1310246
-0.5553611
-0.37950665
0.44179691
0.08460877
0.30646419
0.48927934
-0.21240309
0.36844264
0.49686615
-0.81617664
0.52221472
-0.05188992
-0.03929655
-0.47674501
-0.54506781
0.30711148
0.10049337
-0.47549213
0.59106713
-0.62276051
-0.35182917
0.14612027
0.56142168
-0.01053732
0.35782179
-0.27220781
-0.03672346
-0.11282222
0.3364912
-0.22352515
-0.04245287
0.56968605
-0.14023724
-0.82982905
0.00860008
0.37920345
-0.53749318
-0.12761215
0.08567603
0.47020765
-0.28794812
-0.33888971
0.01850441
0.66848233
-0.26532759
-0.20777571
-0.68342729
-0.41498696
0.00593224
0.02229368
0.75596329
0.29447568
-0.1106449
0.24181939
0.05807497
-0.14343857
0.304988
0.00689148
-0.06264758
0.25864714
-0.22252155
0.28621689
0.17031599
-0.34694027
-0.01625718
0.39834181
0.01259659
-0.28022716
-0.02506168
-0.10276881
0.31733924
0.02787068
-0.09824124
0.45147797
0.14451518
0.17996395
-0.70594978
-0.92943177
0.13649282
-0.5938426
0.50289928
0.19635269
0.16811504
0.05803999
0.0037204
0.13847419
0.30568038
0.3700732
0.21257548
-0.31151753
-0.28836886
0.68743932
-0.11084429
-0.4673766
0.16637754
-0.38992572
0.16505578
-0.07499844
0.04226538
-0.11042177
0.0704542
-0.632819
-0.54898472
0.26498649
-0.59380386
0.93387213
0.06526726
-0.23223558
0.07941394
0.14325166
0.26914661
0.00925575
-0.34282161
-0.51418231
-0.12011075
-0.26676314
-0.09999028
0.03027513
0.22846503
-0.08930338
-0.1867156
0.66297846
0.32220769
-0.06015469
0.04034043
0.09595597
-1.
-0.42933352
0.25069376
-0.26030918
-0.28511861
-0.19931228
0.24408572
-0.3231952
0.45688981
-0.07354078
0.25669449
-0.44202722
0.11928406
-0.32826109
0.52660984
0.03067858
0.11095242
0.19933679
0.03042371
-0.34768682
0.09108447
0.61234556
0.1854931
0.19680502
0.27617564
0.33381827
-0.47358967
0.28714328
-0.27495982

@ -0,0 +1,23 @@
#include <cstdio>
#include <cstdint>
#include "arm_math.h"
#include "scheduler.h"
#include "mfccConfigData.h"
static arm_mfcc_instance_f32 mfcc;
int main(int argc, char const *argv[])
{
int error;
printf("Start\n");
arm_mfcc_init_f32(&mfcc,
256,20,13,mfcc_dct_coefs_config1_f32,
mfcc_filter_pos_config1_f32,mfcc_filter_len_config1_f32,
mfcc_filter_coefs_config1_f32,
mfcc_window_coefs_config1_f32);
uint32_t nb = scheduler(&error,&mfcc);
printf("Nb = %d\n",nb);
return 0;
}

@ -0,0 +1,105 @@
#include "mfccConfigData.h"
const float32_t mfcc_dct_coefs_config1_f32[NB_MFCC_DCT_COEFS_CONFIG1_F32]={
0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,
0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,0.316228f,
0.315253f,0.307490f,0.292156f,0.269628f,0.240461f,0.205374f,0.165229f,0.121015f,0.073822f,0.024811f,
-0.024811f,-0.073822f,-0.121015f,-0.165229f,-0.205374f,-0.240461f,-0.269628f,-0.292156f,-0.307490f,-0.315253f,
0.312334f,0.281761f,0.223607f,0.143564f,0.049469f,-0.049469f,-0.143564f,-0.223607f,-0.281761f,-0.312334f,
-0.312334f,-0.281761f,-0.223607f,-0.143564f,-0.049469f,0.049469f,0.143564f,0.223607f,0.281761f,0.312334f,
0.307490f,0.240461f,0.121015f,-0.024811f,-0.165229f,-0.269628f,-0.315253f,-0.292156f,-0.205374f,-0.073822f,
0.073822f,0.205374f,0.292156f,0.315253f,0.269628f,0.165229f,0.024811f,-0.121015f,-0.240461f,-0.307490f,
0.300750f,0.185874f,0.000000f,-0.185874f,-0.300750f,-0.300750f,-0.185874f,-0.000000f,0.185874f,0.300750f,
0.300750f,0.185874f,0.000000f,-0.185874f,-0.300750f,-0.300750f,-0.185874f,-0.000000f,0.185874f,0.300750f,
0.292156f,0.121015f,-0.121015f,-0.292156f,-0.292156f,-0.121015f,0.121015f,0.292156f,0.292156f,0.121015f,
-0.121015f,-0.292156f,-0.292156f,-0.121015f,0.121015f,0.292156f,0.292156f,0.121015f,-0.121015f,-0.292156f,
0.281761f,0.049469f,-0.223607f,-0.312334f,-0.143564f,0.143564f,0.312334f,0.223607f,-0.049469f,-0.281761f,
-0.281761f,-0.049469f,0.223607f,0.312334f,0.143564f,-0.143564f,-0.312334f,-0.223607f,0.049469f,0.281761f,
0.269628f,-0.024811f,-0.292156f,-0.240461f,0.073822f,0.307490f,0.205374f,-0.121015f,-0.315253f,-0.165229f,
0.165229f,0.315253f,0.121015f,-0.205374f,-0.307490f,-0.073822f,0.240461f,0.292156f,0.024811f,-0.269628f,
0.255834f,-0.097720f,-0.316228f,-0.097720f,0.255834f,0.255834f,-0.097720f,-0.316228f,-0.097720f,0.255834f,
0.255834f,-0.097720f,-0.316228f,-0.097720f,0.255834f,0.255834f,-0.097720f,-0.316228f,-0.097720f,0.255834f,
0.240461f,-0.165229f,-0.292156f,0.073822f,0.315253f,0.024811f,-0.307490f,-0.121015f,0.269628f,0.205374f,
-0.205374f,-0.269628f,0.121015f,0.307490f,-0.024811f,-0.315253f,-0.073822f,0.292156f,0.165229f,-0.240461f,
0.223607f,-0.223607f,-0.223607f,0.223607f,0.223607f,-0.223607f,-0.223607f,0.223607f,0.223607f,-0.223607f,
-0.223607f,0.223607f,0.223607f,-0.223607f,-0.223607f,0.223607f,0.223607f,-0.223607f,-0.223607f,0.223607f,
0.205374f,-0.269628f,-0.121015f,0.307490f,0.024811f,-0.315253f,0.073822f,0.292156f,-0.165229f,-0.240461f,
0.240461f,0.165229f,-0.292156f,-0.073822f,0.315253f,-0.024811f,-0.307490f,0.121015f,0.269628f,-0.205374f,
0.185874f,-0.300750f,-0.000000f,0.300750f,-0.185874f,-0.185874f,0.300750f,0.000000f,-0.300750f,0.185874f,
0.185874f,-0.300750f,-0.000000f,0.300750f,-0.185874f,-0.185874f,0.300750f,-0.000000f,-0.300750f,0.185874f,
};
const float32_t mfcc_window_coefs_config1_f32[NB_MFCC_WIN_COEFS_CONFIG1_F32]={
0.080000f,0.080139f,0.080554f,0.081246f,0.082215f,0.083459f,0.084979f,0.086772f,0.088839f,0.091177f,
0.093786f,0.096663f,0.099807f,0.103217f,0.106890f,0.110823f,0.115015f,0.119464f,0.124165f,0.129117f,
0.134316f,0.139760f,0.145445f,0.151367f,0.157524f,0.163911f,0.170525f,0.177361f,0.184415f,0.191684f,
0.199162f,0.206846f,0.214731f,0.222811f,0.231083f,0.239540f,0.248179f,0.256993f,0.265978f,0.275128f,
0.284438f,0.293901f,0.303513f,0.313267f,0.323157f,0.333179f,0.343325f,0.353589f,0.363966f,0.374448f,
0.385031f,0.395706f,0.406469f,0.417312f,0.428229f,0.439213f,0.450258f,0.461358f,0.472504f,0.483691f,
0.494912f,0.506160f,0.517429f,0.528711f,0.540000f,0.551289f,0.562571f,0.573840f,0.585088f,0.596309f,
0.607496f,0.618642f,0.629742f,0.640787f,0.651771f,0.662688f,0.673531f,0.684294f,0.694969f,0.705552f,
0.716034f,0.726411f,0.736675f,0.746821f,0.756842f,0.766733f,0.776487f,0.786099f,0.795562f,0.804872f,
0.814022f,0.823007f,0.831821f,0.840460f,0.848917f,0.857189f,0.865269f,0.873154f,0.880838f,0.888316f,
0.895585f,0.902639f,0.909475f,0.916089f,0.922476f,0.928633f,0.934555f,0.940240f,0.945684f,0.950883f,
0.955835f,0.960536f,0.964985f,0.969177f,0.973110f,0.976783f,0.980193f,0.983337f,0.986214f,0.988823f,
0.991161f,0.993228f,0.995021f,0.996541f,0.997785f,0.998754f,0.999446f,0.999861f,1.000000f,0.999861f,
0.999446f,0.998754f,0.997785f,0.996541f,0.995021f,0.993228f,0.991161f,0.988823f,0.986214f,0.983337f,
0.980193f,0.976783f,0.973110f,0.969177f,0.964985f,0.960536f,0.955835f,0.950883f,0.945684f,0.940240f,
0.934555f,0.928633f,0.922476f,0.916089f,0.909475f,0.902639f,0.895585f,0.888316f,0.880838f,0.873154f,
0.865269f,0.857189f,0.848917f,0.840460f,0.831821f,0.823007f,0.814022f,0.804872f,0.795562f,0.786099f,
0.776487f,0.766733f,0.756842f,0.746821f,0.736675f,0.726411f,0.716034f,0.705552f,0.694969f,0.684294f,
0.673531f,0.662688f,0.651771f,0.640787f,0.629742f,0.618642f,0.607496f,0.596309f,0.585088f,0.573840f,
0.562571f,0.551289f,0.540000f,0.528711f,0.517429f,0.506160f,0.494912f,0.483691f,0.472504f,0.461358f,
0.450258f,0.439213f,0.428229f,0.417312f,0.406469f,0.395706f,0.385031f,0.374448f,0.363966f,0.353589f,
0.343325f,0.333179f,0.323157f,0.313267f,0.303513f,0.293901f,0.284438f,0.275128f,0.265978f,0.256993f,
0.248179f,0.239540f,0.231083f,0.222811f,0.214731f,0.206846f,0.199162f,0.191684f,0.184415f,0.177361f,
0.170525f,0.163911f,0.157524f,0.151367f,0.145445f,0.139760f,0.134316f,0.129117f,0.124165f,0.119464f,
0.115015f,0.110823f,0.106890f,0.103217f,0.099807f,0.096663f,0.093786f,0.091177f,0.088839f,0.086772f,
0.084979f,0.083459f,0.082215f,0.081246f,0.080554f,0.080139f,};
const uint32_t mfcc_filter_pos_config1_f32[NB_MFCC_NB_FILTER_CONFIG1_F32]={
2,3,5,7,9,11,14,17,20,24,
28,33,38,44,51,59,67,77,88,100,
};
const uint32_t mfcc_filter_len_config1_f32[NB_MFCC_NB_FILTER_CONFIG1_F32]={
3,4,4,4,5,6,6,7,8,9,
10,11,13,15,16,18,21,23,25,28,
};
const float32_t mfcc_filter_coefs_config1_f32[NB_MFCC_FILTER_COEFS_CONFIG1_F32]={
0.663153f,0.706417f,0.118907f,0.293583f,0.881093f,0.568845f,0.051741f,0.431155f,0.948259f,0.563868f,
0.102097f,0.436132f,0.897903f,0.663777f,0.246640f,0.336223f,0.753360f,0.848733f,0.468360f,0.104042f,
0.151267f,0.531640f,0.895958f,0.754478f,0.418519f,0.095146f,0.245522f,0.581481f,0.904854f,0.783449f,
0.482615f,0.191913f,0.216551f,0.517385f,0.808087f,0.910681f,0.638322f,0.374294f,0.118101f,0.089319f,
0.361678f,0.625706f,0.881899f,0.869293f,0.627454f,0.392207f,0.163200f,0.130707f,0.372546f,0.607793f,
0.836800f,0.940111f,0.722642f,0.510517f,0.303479f,0.101291f,0.059889f,0.277358f,0.489483f,0.696521f,
0.898709f,0.903729f,0.710588f,0.521674f,0.336804f,0.155811f,0.096271f,0.289412f,0.478326f,0.663196f,
0.844189f,0.978535f,0.804826f,0.634543f,0.467554f,0.303734f,0.142965f,0.021465f,0.195174f,0.365457f,
0.532446f,0.696266f,0.857035f,0.985135f,0.830139f,0.677876f,0.528253f,0.381178f,0.236568f,0.094340f,
0.014865f,0.169861f,0.322124f,0.471747f,0.618822f,0.763432f,0.905660f,0.954417f,0.816725f,0.681196f,
0.547761f,0.416357f,0.286924f,0.159402f,0.033737f,0.045583f,0.183275f,0.318804f,0.452239f,0.583643f,
0.713076f,0.840598f,0.966263f,0.909875f,0.787764f,0.667357f,0.548606f,0.431467f,0.315895f,0.201850f,
0.089293f,0.090125f,0.212236f,0.332643f,0.451394f,0.568533f,0.684105f,0.798150f,0.910707f,0.978184f,
0.868486f,0.760166f,0.653187f,0.547518f,0.443127f,0.339983f,0.238056f,0.137319f,0.037744f,0.021816f,
0.131514f,0.239834f,0.346813f,0.452482f,0.556873f,0.660017f,0.761944f,0.862681f,0.962256f,0.939305f,
0.841975f,0.745730f,0.650547f,0.556401f,0.463272f,0.371136f,0.279973f,0.189762f,0.100485f,0.012121f,
0.060695f,0.158025f,0.254270f,0.349453f,0.443599f,0.536728f,0.628864f,0.720027f,0.810238f,0.899515f,
0.987879f,0.924653f,0.838062f,0.752330f,0.667442f,0.583381f,0.500130f,0.417674f,0.335998f,0.255088f,
0.174929f,0.095508f,0.016810f,0.075347f,0.161938f,0.247670f,0.332558f,0.416619f,0.499870f,0.582326f,
0.664002f,0.744912f,0.825071f,0.904492f,0.983190f,0.938824f,0.861535f,0.784933f,0.709004f,0.633737f,
0.559120f,0.485144f,0.411795f,0.339065f,0.266942f,0.195416f,0.124479f,0.054119f,0.061176f,0.138465f,
0.215067f,0.290996f,0.366263f,0.440880f,0.514856f,0.588205f,0.660935f,0.733058f,0.804583f,0.875521f,
0.945881f,0.984329f,0.915098f,0.846418f,0.778279f,0.710675f,0.643596f,0.577034f,0.510981f,0.445430f,
0.380372f,0.315802f,0.251710f,0.188091f,0.124938f,0.062243f,};

@ -0,0 +1,61 @@
#ifndef _MFCC_DATA_H_
#define _MFCC_DATA_H_
#include "arm_math_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/*****
DCT COEFFICIENTS FOR THE MFCC
*****/
#define NB_MFCC_DCT_COEFS_CONFIG1_F32 260
extern const float32_t mfcc_dct_coefs_config1_f32[NB_MFCC_DCT_COEFS_CONFIG1_F32];
/*****
WINDOW COEFFICIENTS
*****/
#define NB_MFCC_WIN_COEFS_CONFIG1_F32 256
extern const float32_t mfcc_window_coefs_config1_f32[NB_MFCC_WIN_COEFS_CONFIG1_F32];
/*****
MEL FILTER COEFFICIENTS FOR THE MFCC
*****/
#define NB_MFCC_NB_FILTER_CONFIG1_F32 20
extern const uint32_t mfcc_filter_pos_config1_f32[NB_MFCC_NB_FILTER_CONFIG1_F32];
extern const uint32_t mfcc_filter_len_config1_f32[NB_MFCC_NB_FILTER_CONFIG1_F32];
#define NB_MFCC_FILTER_COEFS_CONFIG1_F32 236
extern const float32_t mfcc_filter_coefs_config1_f32[NB_MFCC_FILTER_COEFS_CONFIG1_F32];
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,20 @@
dct:
config1_f32:
melFilters: 20
dctOutputs: 13
type: "f32"
melfilter:
config1_f32 :
fftlength: 256
fmin: 64
fmax: 8000
samplingRate : 16000
melFilters: 20
type: "f32"
window:
config1_f32:
fftlength: 256
type: "f32"
win: "hamming"

@ -0,0 +1,25 @@
import sys
import numpy as np
FS=16000
NBCHANNELS=1 # stereo
# You can try with 120
AUDIO_INTERRUPT_LENGTH = 192
# MFCC Description
sample_rate = 16000
FFTSize = 256
numOfDctOutputs = 13
freq_min = 64
freq_high = sample_rate / 2
numOfMelFilters = 20
# NB MFCC Outputs to cover one second of signal with the window overlap
nbMFCCOutputs = int(np.floor(sample_rate / (FFTSize >> 1)))
if nbMFCCOutputs%2 == 1:
nbMFCCOutputs = nbMFCCOutputs + 1
print(nbMFCCOutputs)

@ -0,0 +1,57 @@
digraph structs {
node [shape=plaintext]
rankdir=LR
edge [arrowsize=0.5]
fontname="times"
audioWin [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">audioWin<BR/>(SlidingBuffer)</TD>
</TR>
</TABLE>>];
mfcc [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">mfcc<BR/>(MFCC)</TD>
</TR>
</TABLE>>];
mfccWin [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">mfccWin<BR/>(SlidingBuffer)</TD>
</TR>
</TABLE>>];
sink [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">sink<BR/>(FileSink)</TD>
</TR>
</TABLE>>];
src [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">src<BR/>(FileSource)</TD>
</TR>
</TABLE>>];
src:i -> audioWin:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >128</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >192</FONT>>,label="f32(256)"]
audioWin:i -> mfcc:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >256</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >256</FONT>>,label="f32(256)"]
mfcc:i -> mfccWin:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >13</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >13</FONT>>,label="f32(13)"]
mfccWin:i -> sink:i [headlabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >13</FONT>>,taillabel=<<FONT COLOR="blue" POINT-SIZE="12.0" >26</FONT>>,label="f32(26)"]
}

@ -57,6 +57,33 @@ public:
};
#if defined(ARM_FLOAT16_SUPPORTED)
/*
The CMSIS-DSP CFFT F32
*/
template<int inputSize>
class CFFT<float16_t,inputSize,float16_t,inputSize>: public GenericNode<float16_t,inputSize,float16_t,inputSize>
{
public:
CFFT(FIFOBase<float16_t> &src,FIFOBase<float16_t> &dst):GenericNode<float16_t,inputSize,float16_t,inputSize>(src,dst){
arm_status status;
status=arm_cfft_init_f16(&sfft,inputSize>>1);
};
int run(){
float16_t *a=this->getReadBuffer();
float16_t *b=this->getWriteBuffer();
memcpy((void*)b,(void*)a,inputSize*sizeof(float16_t));
arm_cfft_f16(&sfft,b,0,1);
return(0);
};
arm_cfft_instance_f16 sfft;
};
#endif
/*
The CMSIS-DSP CFFT Q15

@ -57,6 +57,34 @@ public:
};
#if defined(ARM_FLOAT16_SUPPORTED)
/*
The CMSIS-DSP ICFFT F32
*/
template<int inputSize>
class ICFFT<float16_t,inputSize,float16_t,inputSize>: public GenericNode<float16_t,inputSize,float16_t,inputSize>
{
public:
ICFFT(FIFOBase<float16_t> &src,FIFOBase<float16_t> &dst):GenericNode<float16_t,inputSize,float16_t,inputSize>(src,dst){
arm_status status;
status=arm_cfft_init_f16(&sifft,inputSize>>1);
};
int run(){
float16_t *a=this->getReadBuffer();
float16_t *b=this->getWriteBuffer();
memcpy((void*)b,(void*)a,inputSize*sizeof(float16_t));
arm_cfft_f16(&sifft,b,1,1);
return(0);
};
arm_cfft_instance_f16 sifft;
};
#endif
/*
The CMSIS-DSP ICFFT Q15

@ -0,0 +1,154 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: MFCC.h
* Description: Node for CMSIS-DSP MFCC
*
* $Date: 06 October 2021
* $Revision: V1.10.0
*
* Target Processor: Cortex-M and Cortex-A cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _MFCC_H_
#define _MFCC_H_
#include <vector>
template<typename IN, int inputSize,typename OUT,int outputSize>
class MFCC;
/*
The MFCC configuration data has to be generated with the script DSP/Scripts/GenMFCCDataForCPP.py.
It is using a yaml file to describe the configuration
*/
/*
The CMSIS-DSP MFCC F32
*/
template<int inputSize,int outputSize>
class MFCC<float32_t,inputSize,float32_t,outputSize>: public GenericNode<float32_t,inputSize,float32_t,outputSize>
{
public:
MFCC(FIFOBase<float32_t> &src,FIFOBase<float32_t> &dst,const arm_mfcc_instance_f32 *config):GenericNode<float32_t,inputSize,float32_t,outputSize>(src,dst){
mfccConfig = config;
#if defined(ARM_MFCC_CFFT_BASED)
memory.resize(2*inputSize);
#else
memory.resize(inputSize + 2);
#endif
};
int run(){
float32_t *a=this->getReadBuffer();
float32_t *b=this->getWriteBuffer();
arm_mfcc_f32(mfccConfig,a,b,memory.data());
return(0);
};
const arm_mfcc_instance_f32 *mfccConfig;
std::vector<float32_t> memory;
};
#if defined(ARM_FLOAT16_SUPPORTED)
/*
The CMSIS-DSP MFCC F16
*/
template<int inputSize,int outputSize>
class MFCC<float16_t,inputSize,float16_t,outputSize>: public GenericNode<float16_t,inputSize,float16_t,outputSize>
{
public:
MFCC(FIFOBase<float16_t> &src,FIFOBase<float16_t> &dst,const arm_mfcc_instance_f16 *config):GenericNode<float16_t,inputSize,float16_t,outputSize>(src,dst){
mfccConfig = config;
#if defined(ARM_MFCC_CFFT_BASED)
memory.resize(2*inputSize);
#else
memory.resize(inputSize + 2);
#endif
};
int run(){
float16_t *a=this->getReadBuffer();
float16_t *b=this->getWriteBuffer();
arm_mfcc_f16(mfccConfig,a,b,memory.data());
return(0);
};
const arm_mfcc_instance_f16 *mfccConfig;
std::vector<float16_t> memory;
};
#endif
/*
The CMSIS-DSP MFCC Q31
*/
template<int inputSize,int outputSize>
class MFCC<q31_t,inputSize,q31_t,outputSize>: public GenericNode<q31_t,inputSize,q31_t,outputSize>
{
public:
MFCC(FIFOBase<q31_t> &src,FIFOBase<q31_t> &dst,const arm_mfcc_instance_q31 *config):GenericNode<q31_t,inputSize,q31_t,outputSize>(src,dst){
mfccConfig = config;
memory.resize(2*inputSize);
};
int run(){
q31_t *a=this->getReadBuffer();
q31_t *b=this->getWriteBuffer();
arm_mfcc_q31(mfccConfig,a,b,memory.data());
return(0);
};
const arm_mfcc_instance_q31 *mfccConfig;
std::vector<q31_t> memory;
};
/*
The CMSIS-DSP MFCC Q15
*/
template<int inputSize,int outputSize>
class MFCC<q15_t,inputSize,q15_t,outputSize>: public GenericNode<q15_t,inputSize,q15_t,outputSize>
{
public:
MFCC(FIFOBase<q15_t> &src,FIFOBase<q15_t> &dst,const arm_mfcc_instance_q15 *config):GenericNode<q15_t,inputSize,q15_t,outputSize>(src,dst){
mfccConfig = config;
memory.resize(2*inputSize);
};
int run(){
q15_t *a=this->getReadBuffer();
q15_t *b=this->getWriteBuffer();
arm_mfcc_q15(mfccConfig,a,b,memory.data());
return(0);
};
const arm_mfcc_instance_q15 *mfccConfig;
std::vector<q15_t> memory;
};
#endif

@ -26,15 +26,15 @@
* limitations under the License.
*/
#ifndef _STEREOTOMONOQ15_H_
#define _STEREOTOMONOQ15_H_
#ifndef _STEREOTOMONO_H_
#define _STEREOTOMONO_H_
template<typename IN, int inputSize,typename OUT,int outputSize>
class StereoToMonoQ15;
class StereoToMono;
template<int inputSize,int outputSize>
class StereoToMonoQ15<q15_t,inputSize,q15_t,outputSize>: public GenericNode<q15_t,inputSize,q15_t,outputSize>
class StereoToMono<q15_t,inputSize,q15_t,outputSize>: public GenericNode<q15_t,inputSize,q15_t,outputSize>
{
public:
StereoToMonoQ15(FIFOBase<q15_t> &src,FIFOBase<q15_t> &dst):
@ -53,4 +53,44 @@ public:
};
template<int inputSize,int outputSize>
class StereoToMono<q31_t,inputSize,q31_t,outputSize>: public GenericNode<q31_t,inputSize,q31_t,outputSize>
{
public:
StereoToMono(FIFOBase<q31_t> &src,FIFOBase<q31_t> &dst):
GenericNode<q31_t,inputSize,q31_t,outputSize>(src,dst){};
int run(){
q31_t *a=this->getReadBuffer();
q31_t *b=this->getWriteBuffer();
for(int i = 0; i<outputSize; i++)
{
b[i] = (a[2*i]>>1) + (a[2*i+1]>>1);
}
return(0);
};
};
template<int inputSize,int outputSize>
class StereoToMono<float32_t,inputSize,float32_t,outputSize>: public GenericNode<float32_t,inputSize,float32_t,outputSize>
{
public:
StereoToMono(FIFOBase<float32_t> &src,FIFOBase<float32_t> &dst):
GenericNode<float32_t,inputSize,float32_t,outputSize>(src,dst){};
int run(){
float32_t *a=this->getReadBuffer();
float32_t *b=this->getWriteBuffer();
for(int i = 0; i<outputSize; i++)
{
b[i] = 0.5f * (a[2*i] + a[2*i+1]);
}
return(0);
};
};
#endif

@ -1,6 +1,6 @@
###########################################
# Project: CMSIS DSP Library
# Title: CFFTF32.py
# Title: CFFTF.py
# Description: Node for CMSIS-DSP cfft
#
# $Date: 30 July 2021
@ -30,7 +30,7 @@ import cmsisdsp as dsp
# The CMSIS-DSP CFFT F32
# The CMSIS-DSP CFFT
class CFFT(GenericNode):
def __init__(self,inputSize,outSize,fifoin,fifoout):
GenericNode.__init__(self,inputSize,outSize,fifoin,fifoout)

@ -1,6 +1,6 @@
###########################################
# Project: CMSIS DSP Library
# Title: ICFFTF32.py
# Title: ICFFT.py
# Description: Node for CMSIS-DSP icfft f32
#
# $Date: 30 July 2021
@ -28,7 +28,7 @@
from sdf.schedule.simu import *
import cmsisdsp as dsp
# CMSIS-DSP ICFFT F32
# CMSIS-DSP ICFFT
class ICFFT(GenericNode):
def __init__(self,inputSize,outSize,fifoin,fifoout):
GenericNode.__init__(self,inputSize,outSize,fifoin,fifoout)

@ -0,0 +1,52 @@
###########################################
# Project: CMSIS DSP Library
# Title: MFCC.py
# Description: Node for CMSIS-DSP MFCC
#
# $Date: 30 July 2021
# $Revision: V1.10.0
#
# Target Processor: Cortex-M and Cortex-A cores
# -------------------------------------------------------------------- */
#
# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################
from sdf.schedule.simu import *
import cmsisdsp as dsp
# The CMSIS-DSP MFCC
class MFCC(GenericNode):
def __init__(self,inputSize,outSize,fifoin,fifoout,mfccConfig):
GenericNode.__init__(self,inputSize,outSize,fifoin,fifoout)
self._config=mfccConfig
self._tmp=np.zeros(2*inputSize,dtype=np.int32)
def run(self):
a=self.getReadBuffer()
b=self.getWriteBuffer()
if self._src.type == np.dtype(np.float):
res=dsp.arm_mfcc_f32(self._config,a,self._tmp)
errorStatus = 0
if self._src.type == np.dtype(np.int32):
errorStatus,res=dsp.arm_mfcc_q31(self._config,a,self._tmp)
if self._src.type == np.dtype(np.int16):
errorStatus,res=dsp.arm_mfcc_q15(self._config,a,self._tmp)
b[:] = res[:]
return(errorStatus)

@ -29,15 +29,21 @@ from sdf.schedule.simu import *
import numpy as np
import cmsisdsp as dsp
class StereoToMonoQ15(GenericNode):
class StereoToMono(GenericNode):
def __init__(self,inputSize,outputSize,fifoin,fifoout):
GenericNode.__init__(self,inputSize,outputSize,fifoin,fifoout)
if fifoin.type == np.dtype(np.float):
self._isFloat=True
else:
self._isFloat=False
def run(self):
i=self.getReadBuffer()
o=self.getWriteBuffer()
# Scaling to avoid saturation
if self._isFloat:
o[:] = 0.5 * (i[::2] + i[1::2])
else:
o[:] = (i[::2]) // 2 + (i[1::2] // 2)
return(0)

@ -40,10 +40,10 @@ class FileSink(GenericSink):
def run(self):
b=self.getReadBuffer()
nextPos = self._bufPos + self._inputSize
if (nextPos < self._buffer.size):
if (nextPos <= self._buffer.size):
# Save output to buffer defined in custom.py
# and used to display result with matplotlib
self._buffer[self._bufPos:nextPos]=b
self._buffer[self._bufPos:self._inputSize ]=b[:]
self._bufPos = nextPos
for sample in b:

@ -0,0 +1,46 @@
###########################################
# Project: CMSIS DSP Library
# Title: NumpySink.py
# Description: Sink node for displaying a buffer in scipy
#
# $Date: 06 August 2021
# $Revision: V1.10.0
#
# Target Processor: Cortex-M and Cortex-A cores
# -------------------------------------------------------------------- */
#
# Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################
from sdf.schedule.simu import *
# Add each new received buffer to a list of buffers
class NumpySink(GenericSink):
def __init__(self,inputSize,fifoin,matplotlibBuffer):
GenericSink.__init__(self,inputSize,fifoin)
self._bufPos=0
self._buffer=matplotlibBuffer
def run(self):
b=self.getReadBuffer()
buf = np.zeros(self._inputSize)
buf[:] = b[:]
self._buffer.append(buf)
return(0)

@ -44,10 +44,10 @@ class WavSink(GenericSink):
def run(self):
b=self.getReadBuffer()
nextPos = self._bufPos + self._inputSize
if (nextPos < self._buffer.size):
if (nextPos <= self._buffer.size):
# Save output to buffer defined in custom.py
# and used to display result with matplotlib
self._buffer[self._bufPos:nextPos]=b
self._buffer[self._bufPos:self._inputSize]=b[:]
self._bufPos = nextPos
for sample in b:

@ -30,11 +30,14 @@ import wave
# It is assuming the input is a stereo file
# It is not yet customizable in this version
# Pad with zero when end of file is reached
class WavSource(GenericSource):
"Read a stereo wav with 16 bits encoding"
def __init__(self,outputSize,fifoout,name):
GenericSource.__init__(self,outputSize,fifoout)
self._file=wave.open(name, 'rb')
#print(self._file.getnchannels())
#print(self._file.getnframes())
def run(self):
@ -42,13 +45,13 @@ class WavSource(GenericSource):
# Stereo file so chunk must be divided by 2
frame=np.frombuffer(self._file.readframes(self._outputSize//2),dtype=np.int16)
if frame.size > 0:
a[:frame.size] = frame
a[frame.size:] = 0
return(0)
else:
return(-1)
a[:]=0
return(0)
def __del__(self):
self._file.close()

@ -141,7 +141,7 @@ class SlidingBuffer(GenericNode):
a=self.getReadBuffer()
b=self.getWriteBuffer()
b[:self._overlap] = self._memory
b[self._overlap:self._windowSize]=a
b[self._overlap:self._windowSize]=a[:self._windowSize-self._overlap]
self._memory[:self._overlap] = a[self._windowSize-(self._overlap<<1):self._windowSize-self._overlap]
return(0)

@ -104,6 +104,43 @@ class ToReal(GenericNode):
def typeName(self):
return "ToReal"
class NullSink(GenericSink):
def __init__(self,name,theType,inLength):
GenericSink.__init__(self,name)
self.addInput("i",theType,inLength)
@property
def typeName(self):
return "NullSink"
class StereoToMono(GenericNode):
def __init__(self,name,theType,outLength):
GenericNode.__init__(self,name)
self.addInput("i",theType,2*outLength)
self.addOutput("o",theType,outLength)
@property
def typeName(self):
return "StereoToMono"
class MFCC(GenericNode):
def __init__(self,name,theType,inLength,outLength):
GenericNode.__init__(self,name)
self.addInput("i",theType,inLength)
self.addOutput("o",theType,outLength)
@property
def typeName(self):
return "MFCC"
#############################
#
# Host only Nodes
#
class FileSource(GenericSource):
def __init__(self,name,inLength):
GenericSource.__init__(self,name)
@ -124,29 +161,9 @@ class FileSink(GenericSink):
def typeName(self):
return "FileSink"
class NullSink(GenericSink):
def __init__(self,name,theType,inLength):
GenericSink.__init__(self,name)
self.addInput("i",theType,inLength)
@property
def typeName(self):
return "NullSink"
class StereoToMonoQ15(GenericNode):
def __init__(self,name,outLength):
GenericNode.__init__(self,name)
q15Type=CType(Q15)
self.addInput("i",q15Type,2*outLength)
self.addOutput("o",q15Type,outLength)
@property
def typeName(self):
return "StereoToMonoQ15"
#############################
#
# Python only Nodes
# Python and host only Nodes
#
@ -170,3 +187,12 @@ class WavSink(GenericSink):
def typeName(self):
return "WavSink"
class NumpySink(GenericSink):
def __init__(self,name,theType,inLength):
GenericSink.__init__(self,name)
self.addInput("i",theType,inLength)
@property
def typeName(self):
return "NumpySink"

@ -41,7 +41,7 @@ def {{config.schedName}}({{optionalargs()}}):
sdfError=0
nbSchedule=0
{% if config.debug %}
debugCounter={{config.debugLimit}};
debugCounter={{config.debugLimit}}
{% endif %}
#

@ -45,7 +45,7 @@ parser = argparse.ArgumentParser(description='Generate MFCC Data for CPP')
parser.add_argument('-n', nargs='?',type = str, default="mfccdata", help="mfcc file name")
parser.add_argument('-d', nargs='?',type = str, default="Testing/Source/Tests", help="mfcc c file directory")
parser.add_argument('-i', nargs='?',type = str, default="Testing/Include/Tests", help="mfcc h file directory")
parser.add_argument('others', nargs=argparse.REMAINDER)
parser.add_argument('others', help="yaml configuration file", nargs=argparse.REMAINDER)
args = parser.parse_args()

@ -69,13 +69,17 @@
@return none
@par Description
The number of input samples if the FFT length used
The number of input samples is the FFT length used
when initializing the instance data structure.
The temporary buffer has a 2*fft length.
The source buffer is modified by this function.
The function may saturate. If the FFT length is too
big and the number of MEL filters too small then the fixed
point computations may saturate.
*/
arm_status arm_mfcc_q15(

@ -69,13 +69,17 @@
@return none
@par Description
The number of input samples if the FFT length used
The number of input samples is the FFT length used
when initializing the instance data structure.
The temporary buffer has a 2*fft length.
The source buffer is modified by this function.
The function may saturate. If the FFT length is too
big and the number of MEL filters too small then the fixed
point computations may saturate.
*/

Loading…
Cancel
Save