<!DOCTYPE html>
<!-- vim: set ts=4: -->
< html >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" / >
< meta name = "apple-mobile-web-app-capable" content = "yes" >
< meta name = "mobile-web-app-capable" content = "yes" >
<!--
Modified from original Node-Red source, for audio system visualization
Copyright 2013 IBM Corp.
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
http://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.
*** NODES FOR OPENAUDIO_ARDUINOLIBRARY 1 March 2021 RSL ***
-->
< head >
< title > Audio System Design Tool for Open Audio F32 Library for Teensy< / title >
< link href = "bootstrap/css/bootstrap.min.css" rel = "stylesheet" media = "screen" >
< link href = "jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css" rel = "stylesheet" media = "screen" >
< link rel = "stylesheet" type = "text/css" href = "orion/built-editor.css" / >
< link rel = "stylesheet" type = "text/css" href = "font-awesome/css/font-awesome.min.css" / >
< link rel = "stylesheet" href = "style.css" >
< style >
table.doc {border-spacing:3px; border-collapse:separate; font-size: 80%}
tr.top {background-color:#C0C0C0}
tr.odd {background-color:#F0F0F0}
tr.even {background-color:#E0E0E0}
p.func {padding-bottom:0; margin:0px}
p.desc {padding-left:2em; margin:0px; padding-top:0.2em; padding-bottom:0.8em; font-size:0.75em}
p.exam {padding-left:2em; text-indent:-1.2em; margin:0px; padding-top:0; padding-bottom:0.5em; font-size:0.75em; font-weight:bold}
pre.desc {padding-left:3em; margin:0px; padding-top:0em; padding-bottom:0.8em; font-size:0.75em;
background-color:#FFFFFF; border:0px; line-height:100%;
}
span.indent {padding-left:2em}
span.literal {color: #006699}
span.comment {color: #777755}
span.keyword {color: #cc6600}
span.function {color: #996600}
span.mainfunction {color: #993300; font-weight: bolder}
< / style >
< / head >
< body spellcheck = "false" >
< div class = "navbar navbar-inverse navbar-fixed-top" >
< div class = "navbar-inner" >
< div class = "container-fluid" >
< span class = "brand" > Audio Design Tool for OpenAudio F32 Library for Teensy< / a > < / span >
< div class = "btn-group pull-right" >
< a class = "btn dropdown-toggle" data-toggle = "dropdown" href = "#" > < i class = "icon-align-justify" > < / i > < span class = "caret" > < / span > < / a >
< ul class = "dropdown-menu" >
< li > < a id = "btn-sidebar" tabindex = "-1" href = "#" > < i class = "icon-ok pull-right" > < / i > < i class = "icon-list-alt" > < / i > Sidebar< / a > < / li >
< li class = "divider" > < / li >
<!-- <li><a id="btn - node - status" tabindex=" - 1" href="#"><i class="icon - ok pull - right"></i><i class="icon - info - sign"></i> Node Status</a></li>
< li class = "divider" > < / li >
-->
<!--
< li class = "dropdown-submenu pull-left" > < a tabindex = "-1" href = "#" > < i class = "icon-edit" > < / i > Import from...< / a >
< ul class = "dropdown-menu" >
< li > < a id = "btn-import" tabindex = "-1" href = "#" > < i class = "icon-edit" > < / i > Clipboard...< / a > < / li >
< li id = "flow-menu-parent" class = "dropdown-submenu pull-left" >
< a tabindex = "-1" href = "#" > < i class = "icon-book" > < / i > Library< / a >
< ul class = "dropdown-menu" > < / ul >
< / li >
< / ul >
< / li >
< li id = "li-menu-export" class = "dropdown-submenu disabled pull-left" > < a tabindex = "-1" href = "#" > < i class = "icon-share" > < / i > Export to...< / a >
< ul class = "dropdown-menu" >
< li id = "li-menu-export-clipboard" class = "disabled" > < a id = "btn-export-clipboard" tabindex = "-1" href = "#" > < i class = "icon-share" > < / i > Clipboard...< / a > < / li >
< li id = "li-menu-export-library" class = "disabled" > < a id = "btn-export-library" tabindex = "-1" href = "#" > < i class = "icon-book" > < / i > Library...< / a > < / li >
< / ul >
< / li >
< li class = "divider" > < / li >
-->
<!--
< li > < a id = "btn-config-nodes" tabindex = "-1" href = "#" > < i class = "icon-th-list" > < / i > Configuration nodes...< / a > < / li >
< li class = "divider" > < / li >
-->
<!--
< li class = "dropdown-submenu pull-left" > < a tabindex = "-1" href = "#" > < i class = "icon-th-large" > < / i > Workspaces< / a >
< ul id = "workspace-menu-list" class = "dropdown-menu" >
< li > < a id = "btn-workspace-add" tabindex = "-1" href = "#" > < i class = "icon-plus" > < / i > Add< / a > < / li >
< li > < a id = "btn-workspace-edit" tabindex = "-1" href = "#" > < i class = "icon-edit" > < / i > Rename< / a > < / li >
< li > < a id = "btn-workspace-delete" tabindex = "-1" href = "#" > < i class = "icon-minus" > < / i > Delete< / a > < / li >
< li class = "divider" > < / li >
< / ul >
< / li >
< li class = "divider" > < / li > -->
< li > < a id = "btn-keyboard-shortcuts" tabindex = "-1" href = "#" > < i class = "icon-question-sign" > < / i > Keyboard Shortcuts< / a > < / li >
< li > < a id = "btn-help" tabindex = "-1" href = "http://node-red.github.io/docs" target = "_blank" > < i class = "icon-question-sign" > < / i > Help...< / a > < / li >
< / ul >
< / div >
< div class = "btn-group pull-left" >
< a id = "btn-deploy" class = "btn action-deploy disabled" href = "#" > < i id = "btn-icn-deploy" class = "icon-upload" > < / i > Export< / a >
< a id = "btn-import" class = "btn action-import disabled" href = "#" > < i id = "btn-icn-download" class = "icon-download" > < / i > Import< / a >
< / div >
< / div >
< / div >
< / div >
< div id = "main-container" class = "sidebar-closed" >
< div id = "palette" >
< img src = "img/spin.svg" class = "palette-spinner" / >
< div id = "palette-container" class = "palette-scroll" >
< / div >
< div id = "palette-search" >
< i class = "icon-search" > < / i > < input id = "palette-search-input" type = "text" placeholder = "filter" > < a href = "#" id = "palette-search-clear" > < i class = "icon-remove" > < / i > < / a > < / input >
< / div >
< / div > <!-- /palette -->
< div id = "workspace" >
< ul id = "workspace-tabs" > < / ul >
<!-- <div id="workspace - add - tab"><a id="btn - workspace - add - tab" href="#"><i class="icon - plus"></i></a></div> -->
< div id = "chart" > < / div >
< div id = "workspace-toolbar" >
< div class = "btn-group" >
< a class = "btn btn-small" href = "#" > < i class = "icon-zoom-out" > < / i > < / a >
< a class = "btn btn-small" href = "#" > < i class = "icon-th" > < / i > < / a >
< a class = "btn btn-small" href = "#" > < i class = "icon-zoom-in" > < / i > < / a >
< / div >
< / div >
< / div >
< div id = "chart-zoom-controls" >
< div class = "btn-group" >
< a class = "btn btn-mini" id = "btn-zoom-out" href = "#" > < i class = "icon-zoom-out" > < / i > < / a >
< a class = "btn btn-mini" id = "btn-zoom-zero" href = "#" > < i class = "icon-th" > < / i > < / a >
< a class = "btn btn-mini" id = "btn-zoom-in" href = "#" > < i class = "icon-zoom-in" > < / i > < / a >
< / div >
< / div >
< div id = "sidebar" >
< ul id = "sidebar-tabs" > < / ul >
< div id = "sidebar-content" > < / div >
< / div >
< div id = "sidebar-separator" > < / div >
< / div >
< div id = "notifications" > < / div >
< div id = "dropTarget" > < div > Drop the flow here< / div > < / div >
< div id = "dialog" class = "hide" > < form id = "dialog-form" class = "form-horizontal" > < / form > < / div >
< div id = "node-config-dialog" class = "hide" > < form id = "dialog-config-form" class = "form-horizontal" > < / form > < div class = "form-tips" id = "node-config-dialog-user-count" > < / div > < / div >
< div id = "node-dialog-confirm-deploy" class = "hide" >
< form class = "form-horizontal" >
< div id = "node-dialog-confirm-deploy-config" style = "text-align: center; padding-top: 30px;" >
Some of the nodes are not properly configured. Are you sure you want to deploy?
< / div >
< div id = "node-dialog-confirm-deploy-unknown" style = "text-align: center; padding-top: 10px;" >
The workspace contains some unknown node types:
< ul style = "width: 300px; margin: auto; text-align: left;" id = "node-dialog-confirm-deploy-unknown-list" > < / ul >
Are you sure you want to deploy?
< / div >
< / form >
< / div >
< div id = "node-dialog-error-deploy" class = "hide" >
< form class = "form-horizontal" >
< div id = "node-dialog-error-deploy-noio" style = "text-align: center; padding-top: 10px;" >
< p > The workspace contains no input/output nodes!< / p >
< p > You need an input or an output to export the data!< / p >
< p > Without such a input/output function the exported
code will not run properly!< / p >
< / div >
< / form >
< / div >
< div id = "node-help" class = "modal hide fade" tabindex = "-1" role = "dialog" aria-labelledby = "node-help-label" aria-hidden = "true" >
< div class = "modal-header" >
< h5 id = "node-help-label" > Keyboard Shortcuts < span style = "float: right;" > < a href = "http://node-red.github.io/docs" target = "_blank" > Open help in new window » < / a > < / span > < / h5 >
< / div >
< div class = "modal-body" >
< table >
< tr >
< td > < span class = "help-key" > ?< / span > < / td > < td > Help< / td >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > a< / span > < / td > < td > Select all nodes< / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > Space< / span > < / td > < td > Toggle sidebar< / td >
< td > < span class = "help-key" > Shift< / span > < span class = "help-key" > Click< / span > < / td > < td > Select all connected nodes< / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > z< / span > < / td > < td > Undo< / td >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > Click< / span > < / td > < td > Add/remove node from selection< / td >
< / tr >
< tr >
< td > < / td > < td > < / td >
< td > < span class = "help-key" > Delete< / span > < / td > < td > Delete selected nodes or link< / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > x< / span > < / td > < td > Cut selected nodes< / td >
< td > < / td > < td > < / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > c< / span > < / td > < td > Copy selected nodes< / td >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > v< / span > < / td > < td > Paste nodes< / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > i< / span > < / td > < td > Import nodes< / td >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > e< / span > < / td > < td > Export selected nodes< / td >
< / tr >
< tr >
< td colspan = "2" > < / td >
< / tr >
< tr >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > +< / span > < / td > < td > Zoom in< / td >
< td > < span class = "help-key" > Ctrl< / span > < span class = "help-key" > -< / span > < / td > < td > Zoom out< / td >
< / tr >
< / table >
< / div >
< div class = "modal-footer" >
< button class = "btn" data-dismiss = "modal" aria-hidden = "true" > Close< / button >
< / div >
< / div >
< div id = "node-dialog-library-save-confirm" class = "hide" >
< form class = "form-horizontal" >
< div style = "text-align: center; padding-top: 30px;" >
A < span id = "node-dialog-library-save-type" > < / span > called < span id = "node-dialog-library-save-name" > < / span > already exists. Overwrite?
< / div >
< / form >
< / div >
< div id = "node-dialog-library-save" class = "hide" >
< form class = "form-horizontal" >
< div class = "form-row" >
< label for = "node-dialog-library-save-folder" > < i class = "icon-folder-open" > < / i > Folder< / label >
< input type = "text" id = "node-dialog-library-save-folder" placeholder = "Folder" >
< / div >
< div class = "form-row" >
< label for = "node-dialog-library-save-filename" > < i class = "icon-file" > < / i > Filename< / label >
< input type = "text" id = "node-dialog-library-save-filename" placeholder = "Filename" >
< / div >
< / form >
< / div >
< div id = "node-dialog-library-lookup" class = "hide" >
< form class = "form-horizontal" >
< div class = "form-row" >
< ul id = "node-dialog-library-breadcrumbs" class = "breadcrumb" >
< li class = "active" > < a href = "#" > Library< / a > < / li >
< / ul >
< / div >
< div class = "form-row" >
< div style = "vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;" >
< div id = "node-select-library" style = "border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;" > < ul > < / ul > < / div >
< / div >
< div style = "vertical-align: top; display: inline-block;width: 65%; height: 100%;" >
< div style = "height: 100%; width: 95%;" class = "node-text-editor" id = "node-select-library-text" > < / div >
< / div >
< / div >
< / form >
< / div >
< div id = "node-dialog-rename-workspace" class = "hide" >
< form class = "form-horizontal" >
< div class = "form-row" >
< label for = "node-input-workspace-name" > < i class = "icon-tag" > < / i > Name:< / label >
< input type = "text" id = "node-input-workspace-name" >
< / div >
< / form >
< / div >
< div id = "node-dialog-delete-workspace" class = "hide" >
< form class = "form-horizontal" >
< div style = "text-align: center; padding-top: 30px;" >
Are you sure you want to delete '< span id = "node-dialog-delete-workspace-name" > < / span > '?
< / div >
< / form >
< / div >
< script type = "text/x-red" data-template-name = "export-clipboard-dialog" >
< div class = "form-row" >
< label for = "node-input-export" style = "display: block; width:100%;" > < i class = "icon-share" > < / i > Source Code:< / label >
< textarea readonly style = "font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class = "input-block-level" id = "node-input-export" rows = "12" > < / textarea >
< / div >
< div class = "form-tips" >
< a id = "download-INO" target = "_blank" > Click to Download Zipped Code< / a >
< / div >
< / script >
< script type = "text/x-red" data-template-name = "export-library-dialog" >
< div class = "form-row" >
< label for = "node-input-filename" > < i class = "icon-tag" > < / i > Filename:< / label >
< input type = "text" id = "node-input-filename" placeholder = "Filename" >
< / div >
< / script >
< script type = "text/x-red" data-template-name = "import-dialog" >
< div class = "form-row" >
< label for = "node-input-import" > < i class = "icon-share" > < / i > Nodes:< / label >
< textarea style = "font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class = "input-block-level" id = "node-input-import" rows = "5" placeholder = "Paste nodes here, or lookup in the library. When importing Arduino code, the whole flow will be replaced." > < / textarea >
< / div >
< div class = "form-tips" >
< label for = "node-input-arduino" style = "font-size: 13px; padding: 2px 0px 0px 4px;" >
< input style = "margin-bottom: 4px; margin-right: 4px;" type = "checkbox" id = "node-input-arduino" checked = "checked" class = "input-block-level" / >
Import copied code from the Arduino IDE
< / label >
< / div >
< / script >
< script src = "jquery/js/jquery-1.9.1.js" > < / script >
< script src = "bootstrap/js/bootstrap.min.js" > < / script >
< script src = "jquery/js/jquery-ui-1.10.3.custom.min.js" > < / script >
< script src = "jquery/js/jquery.ui.touch-punch.min.js" > < / script >
< script src = "jszip/dist/jszip.min.js" > < / script >
< script src = "orion/built-editor.min.js" > < / script >
< script src = "red/d3/d3.v3.min.js" > < / script >
< script src = "red/main.js" > < / script >
< script src = "red/ui/state.js" > < / script >
< script src = "red/nodes.js" > < / script >
< script src = "red/storage.js" > < / script >
< script src = "red/history.js" > < / script >
< script src = "red/ui/keyboard.js" > < / script >
< script src = "red/ui/tabs.js" > < / script >
< script src = "red/ui/view.js" > < / script >
< script src = "red/ui/sidebar.js" > < / script >
< script src = "red/ui/palette.js" > < / script >
< script src = "red/ui/tab-info.js" > < / script >
< script src = "red/ui/tab-config.js" > < / script >
< script src = "red/ui/editor.js" > < / script >
< script src = "red/ui/library.js" > < / script >
< script src = "red/ui/notifications.js" > < / script >
< script src = "red/ui/touch/radialMenu.js" > < / script >
<!--
TODO: generate some or all of this automatically from the C++ source
-->
<!--
TODO: add a field for maximum instance count
-->
<!--
TODO: add a field for exclusive to other objects (not allowed if they're used)
-->
<!--
TODO: add "parameters" fields, to replace the form html stuff
-->
< script type = "text/x-red" data-container-name = "NodeDefinitions" >
{"nodes":[
{"type":"AudioAnalyzePhase_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"phaseDet","inputs":"1","output":"0","category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioAnalyzePeak_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"peak","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioAnalyzeRMS_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"rms","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioAnalyzeFFT1024_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT1024","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioAnalyzeFFT256_IQ_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT256iq","inputs":2,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"4"}},
{"type":"AudioAnalyzeFFT1024_IQ_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT1024iq","inputs":2,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"4"}},
{"type":"AudioAnalyzeFFT2048_IQ_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT2048iq","inputs":2,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"4"}},
{"type":"AudioAnalyzeFFT4096_IQ_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT4096iq","inputs":2,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioAnalyzeFFT4096_IQem_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FFT4096IQem","inputs":2,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioAnalyzeToneDetect_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"toneDetect","inputs":"1","output":"0","category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioAnalyzeCTCSS_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"toneCTCSS","inputs":"1","output":"1","category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioCalcEnvelope_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"calcEnvelope","inputs":"1","output":"0","category":"calc-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioCalcGainWDRC_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"calcGainWDRC","inputs":"1","output":"0","category":"calc-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioCalcLevel_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"calcLevel","inputs":"NaN","output":"0","category":"calc-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"}},
{"type":"AudioCalcGainWDRC_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"calcGainWDRC","inputs":"NaN","output":"0","category":"calc-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioConvert_I16toF32","data":{"defaults":{"name":{"value":"new"}},"shortName":"convert_I16toF32","inputs":"0","output":"0","category":"convert-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioConvert_F32toI16","data":{"defaults":{"name":{"value":"new"}},"shortName":"convert_F32toI16","inputs":"1","output":"0","category":"convert-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioEffectCompWDRC_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"compWDRC","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectCompressor_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"compressor","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectDelay_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"delay","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEmpty_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"empty","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectCompressor2_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"compressor2","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectNoiseGate_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"noiseGate","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectFreqShiftFD_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"freqShift","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioEffectGain_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"gain","inputs":"1","output":"0","category":"effect-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilterFIRGeneral_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"filterFIRgeneral","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilterEqualizer_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"filterEqualizer","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilter90Deg_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"filter90deg","inputs":"2","output":"2","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioFilterBiquad_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"biquad","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilterFIR_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"fir","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilterConvolution_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"convFilt","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioLMSDenoiseNotch_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"LMS","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioSpectralDenoise_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"Spectral","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioFilterFreqWeighting_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"freqWeight","inputs":"NaN","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"}},
{"type":"AudioFilterTimeWeighting_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"timeWeight","inputs":"1","output":"0","category":"filter-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMathAdd_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mathAdd","inputs":"2","output":"0","category":"math-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMathMultiply_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mathMultiply","inputs":"2","output":"0","category":"math-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMathOffset_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mathOffset","inputs":"1","output":"0","category":"math-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMathScale_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mathScale","inputs":"1","output":"0","category":"math-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMixer4_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mixer4","inputs":"4","output":"0","category":"mixer-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioMixer8_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"mixer8","inputs":"8","output":"0","category":"mixer-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioPlaySdWav_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"playSdWav","inputs":0,"outputs":2,"category":"play-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioSwitch4_OA_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"switch4","inputs":"1","output":"0","category":"mixer-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"4"}},
{"type":"AudioSwitch8_OA_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"switch8","inputs":"1","output":"0","category":"mixer-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"8"}},
{"type":"FFT_Overlapped_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"blockwiseFFT","inputs":"NaN","output":"0","category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"}},
{"type":"IFFT_Overlapped_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"blockwiseIFFT","inputs":"NaN","output":"0","category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"NaN"}},
{"type":"AudioInputI2S_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"audioInI2S","inputs":"0","output":"0","category":"input-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioOutputI2S_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"audioOutI2S","inputs":"2","output":"0","category":"output-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioInputSPDIF3_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"spdif3","inputs":0,"outputs":2,"category":"input-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AsyncAudioInputSPDIF3_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"spdif_async","inputs":0,"outputs":2,"category":"input-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioInputUSB_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"audioInUSB","inputs":"0","output":"0","category":"input-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioOutputUSB_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"audioOutUSB","inputs":"2","output":"0","category":"output-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioOutputSPDIF3_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"spdif3Out","inputs":2,"outputs":0,"category":"output-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioPlayQueue_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"playQueue","inputs":"0","output":"0","category":"play-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioRecordQueue_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"recordQueue","inputs":"1","output":"0","category":"record-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"AudioSynthNoisePink_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"noisePink","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioSynthWaveformSine_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioSynthSineCosine_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine-cos","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioSynthWaveform_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"waveform","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioSynthNoiseWhite_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"noiseWhite","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioSynthGaussian_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"GaussianWhiteNoise","inputs":"0","output":"0","category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"AudioAlignLR_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"alignLR","inputs":"2","output":"0","category":"input-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"3"}},
{"type":"RadioFMDetector_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FMDetector","inputs":"1","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"radioModulatedGenerator_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"Modulator","inputs":"2","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"radioNoiseBlanker_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"NoiseBlank","inputs":"2","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"radioCESSBtransmit_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"CESSB_Mod","inputs":"1","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"RadioFMDiscriminator_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FMDiscrim","inputs":"1","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"radioBFSKModulator_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"BFSKMod","inputs":"0","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"UART_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"UART","inputs":"1","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"RadioFT8Modulator_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FT8Mod","inputs":"0","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"1"}},
{"type":"RadioFT8Demodulator_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"FT8Demod","inputs":"1","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"0"}},
{"type":"RadioIQMixer_F32","data":{"defaults":{"name":{"value":"new"}},"shortName":"I-QMixer","inputs":"2","output":"0","category":"radio-function","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioControlSGTL5000","data":{"defaults":{"name":{"value":"new"}},"shortName":"sgtl5000","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioControlAK4558","data":{"defaults":{"name":{"value":"new"}},"shortName":"ak4558","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioControlCS4272","data":{"defaults":{"name":{"value":"new"}},"shortName":"cs4272","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioControlWM8731","data":{"defaults":{"name":{"value":"new"}},"shortName":"wm8731","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioControlWM8731master","data":{"defaults":{"name":{"value":"new"}},"shortName":"wm8731m","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioControlCS42448","data":{"defaults":{"name":{"value":"new"}},"shortName":"cs42448","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}}
]}
< / script >
< script type = "text/x-red" data-help-name = "AudioCalcEnvelope_F32" >
< p > AudioCalcEnvelope_F32< / p >
< p > Created: Chip Audette, Feb 2017< / p >
< p > Purpose: This module extracts the envelope of the audio signal.< / p >
< p > Derived From: Core envelope extraction algorithm is from "smooth_env"< / p >
< p > WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro< / p >
< p > As of Feb 2017, CHAPRO license is listed as "Creative Commons?"< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > Used in support of other classes. Deprecated for use in an INO.
See Compressor and Compressor2 for complete, ready to use classes.< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioCalcEnvelope_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioCalcGainWDRC_F32" >
< p > AudioCalcGainWDRC_F32< / p >
< p > Created: Chip Audette, Feb 2017< / p >
< p > Purpose: This module calculates the gain needed for wide dynamic range compression.< / p >
< p > Derived From: Core algorithm is from "WDRC_circuit"< / p >
< p > WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro< / p >
< p > As of Feb 2017, CHAPRO license is listed as "Creative Commons?"< / p >
< p > This processes a single stream of audio data (ie, it is mono)< / p >
< p > Used in support of other classes. Deprecated for use in an INO.
See Compressor and Compressor2 for complete, ready to use classes.< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioCalcGainWDRC_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioCalcLevel_F32" >
< p > Time weighting for sound level meter. Defaults to SLOW< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioCalcLevel_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioCalcGainWDRC_F32" >
< p > AudioCalcGainWDRC_F32: Wide Dynamic Rnage Compressor< / p >
< p > Created: Chip Audette (OpenAudio) Feb 2017< / p >
< p > Derived From: WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro< / p >
< p > As of Feb 2017, CHAPRO license is listed as "Creative Commons?"< / p >
< p > MIT License. Use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioCalcGainWDRC_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioEffectCompWDRC_F32" >
< p > AudioCalcGainWDRC_F32: Wide Dynamic Rnage Compressor< / p >
< p > Created: Chip Audette (OpenAudio) Feb 2017< / p >
< p > Derived From: WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro< / p >
< p > As of Feb 2017, CHAPRO license is listed as "Creative Commons?"< / p >
< p > MIT License. Use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectCompWDRC_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioConvert_I16toF32" >
<!-- ============ AudioConvert_I16toF32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Takes daudio data in conventional Teensy Audio integer format,
and converts it to floating point data suitable for this F32 Audio library.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output F32 format< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > There are no parameters to be modified and this class has no functions.
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > MyAudioEffect_Float
< / p >
< h3 > Notes< / h3 >
< p > This is the Teensy Audio I16 to OpenAudio_F32 data cconverter. The 16-bit signed
integer input can range from -32768 to 32767 in level The floating point (F32)
output scales this same range to -1.0 to 0.9999695 usually called "-1 to +1."
There are no limits of signal range on the floating point side, so -1 to +1
is chosen for convenience. The integer data has a dynamic range that is 8-bits
less than that of the floating point side, so no loss of precision
occurs with this conversion. The integer value 0 converts to the floating point
value, 0.0.< / p >
< p > Only an output is shown for this converter because this Design Tool only follows
the flow of F32 floating point data. Work is in progress to allow
a mix of I16 and F32 in the same Design Tool.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioConvert_I16toF32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioConvert_F32toI16" >
<!-- ============ AudioConvert_F32toI16 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Takes audio data in F32 Audio library floating point format conventional
and converts it to Teensy Audio integer I16 format.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input F32 format< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > There are no parameters to be modified and this class has no functions.
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > MyAudioEffect_Float
< / p >
< h3 > Notes< / h3 >
< p > This is the OpenAudio_F32 to Teensy Audio I16 data cconverter.
The floating point (F32) range must be limited to
a range of -1.0 to 0.9999695, usually called "-1 to +1," or
clipping will occur with this conversion. The 16-bit signed
integer output can only range from -32768 to 32767. Values outside
these limits will be clipped. The integer data will have a dynamic range
that is 8-bits less than that of the floating point side, and so a loss of precision
occurs with this conversion. The floating point vaue 0.0 converts
to an integer value of 0.
value, 0.0.< / p >
< p > Only an input is shown for this converter because this Design Tool only follows
the flow of F32 floating point data. Work is in progress to allow
a mix of I16 and F32 in the same Design Tool.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioConvert_F32toI16" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioFilterEqualizer_F32" >
<!-- ============ AudioFilterEqualizer_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Uses flat-delay FIR filtering to generate a filter with
arbitrary amplitude response.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Equalized Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > equalizerNew< / span > (< strong > uint16_t< / strong > nBands, < strong > float< / strong > *feq, < strong > float< / strong > *adb, < strong > uint16_t< / strong > nFIR, < strong > float< / strong > *cf32f, < strong > float< / strong > kdb);< / p >
< p class = desc > Does the design of the equalizer and enables it for audio updates.
nBands is the number of frequecy bands,
feq points to an array of band tops in Hz,
adb points to an array of dB levels for the bands,
nFIR is the number of FIR coefficients being used and
kdb is the Kaiser window parameter that sets the sidelobe response.
< / p >
< p class = func > < span class = keyword > getResponse< / span > (< strong > uint16_t< / strong > nFreq, < strong > float< / strong > *rdb);< / p >
< p class = desc > Calculates the response of the equalizer in dB at nFreq equally spaced
frequencies. rdb is a pointer to an array of nFreq floats where the response can be put.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestEqualizer1
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestEqualizer1Audio
< / p >
< h3 > Notes< / h3 >
< p > This equalizer is specified by an array of 'nBands' frequency bands
each of of arbitrary frequency span. The first band always starts at
0.0 Hz, and that value is not entered. Each band is specified by the upper
frequency limit to the band.
The last band always ends at half of the sample frequency, which for 44117 Hz
sample frequency would be 22058.5. Each band is specified by its upper
frequency in an .INO supplied array feq[]. The dB level of that band is
specified by a value, in dB, arranged in an .INO supplied array
aeq[]. Thus a trivial bass/treble control might look like:< / p >
< pre class = "desc" >
nBands = 3;
feq[] = {300.0, 1500.0, 22058.5};
float32_t bass = -2.5; // in dB, relative to anything
float32_t treble = 6.0;
aeq[] = {bass, 0.0, treble};
< / pre >
< p > Note that there is much, much more information in the
AudioFilterEqualizer_F32.h file at the OpenAudio_Arduino directory.
This includes more examples.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterEqualizer_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioFilterFIRGeneral_F32" >
<!-- ============ AudioFilterFIRGeneral_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Uses flat-delay FIR filtering to generate Low Pass, High Pass,
Band Pas and Band Reject Filters, do the filtering and compute the
response.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Filtered Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > FIRGeneralNew< / span > (< strong > float< / strong > *adb, < strong > uint16_t< / strong > nFIR, < strong > float< / strong > *cf32f, < strong > float< / strong > kdb, < strong > float< / strong > *pStateArray);< / p >
< p class = desc > Does the design of the filter and enables it for audio updates.
adb points to an array of dB levels for the bands,
nFIR is the number of FIR coefficients being used,
cf32f is a pointer to an INO supplied array where the coefficients will be stored,
nBands is the number of frequecy bands,
feq points to an array of band tops in Hz,
kdb is the Kaiser window parameter that sets the sidelobe response, and
pStateArray is a pointer to an INO supplied 2*nFIR+128 array of floats for working space.
< / p >
< p class = func > < span class = keyword > LoadCoeffs< / span > (< strong > uint16_t< / strong > nFIR, < strong > float< / strong > *cf32, < strong > float< / strong > pStateArray);< / p >
< p class = desc > Loads new filter coefficients that are INO supplied.
nFIR is the number of FIR coefficients being used,
cf32 is a pointer to an array of FIR coefficients (name of array)
pStateArray is a pointer to a 2*nFIR+128 array of floats for working space (name of array)
< / p >
< p class = func > < span class = keyword > getResponse< / span > (< strong > uint16_t< / strong > nFreq, < strong > float< / strong > *rdb);< / p >
< p class = desc > Calculates the response of the equalizer in dB at nFreq equally spaced
frequencies. rdb is a pointer to an array of nFreq floats where the response can be put.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFIRGeneralLarge4
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFIRGeneralLarge5
< / p >
< h3 > Notes< / h3 >
< p > For those new to C, when a pointer to an array is needed in a function call, just
supply the name of the array. See the examples to see how this works.< / p >
< p > The frequency response of the filter is specfied by a series of ideal dB levels.
for instance, 0.0 dB for a pass band and -150.0 dB for a stop band.
IF nFIR is even, the response specification needs nFIR/2 points and if nFIR is odd,
it needs (nFIR+1)/2 points. The "to do" list has macros to specify the common
responses. Meanwhile, see the example INOs for methods of doing this. < / p >
< p > The INO must supply memory that is used by the ARM FIR routine called workspace.
This is an array of float variables that is 2*nFIR+128 in size. The call to design and
use a filter need a pointer to this array, which for C is the name of the array.< / p >
< p > The header file, AudioFilterFIRGeneral_F32.h in the OpenAudio_ArduinoLibrary directory
includes many notes, timing and examples. Be sure to look at those when getting
acquainted with this class.< / p >
< p > FIR filters can be (and are here) implemented to have symmetrical coefficients. This
results in constant delay at all frequencies (linear phase). For some applications this can
be an important feature. Sometimes it is suggested that the FIR should not be
used because of the latency it creates. Note that if constant delay is needed, the FIR
implementation does this with minimum latency.< / p >
< p > AudioFilterFIR_F32 in this OpenAudio_ArduinoLibrary handles 32-bit floating point
data and a maximum of 200 taps. This class requires the INO to provide the working
space and thereby puts no limit on the number of FIR taps (coefficients) being used.
The processor does run out of time, and that limits Teensy 3.6 to about 6000 taps
and Teensy 4.x to about 6000. As a starting spot for huge FIR filters, one might use
1/2 or 1/3 of those numbers.< / p >
< p > It is practical to switch filter coefficient arrays on-the-fly.
See the LoadCoeffs() function. This class is initialized to a 4 coefficient
pass-through filter.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterFIRGeneral_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioFilterConvolution_F32" >
<!-- ============ AudioFilterConvolution_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Convolutional filtering. Faster than a FIR if you want a 512 tap filter.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Filtered Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > initFilter< / span > (< strong > void< / strong > );< / p >
< p class = desc > Without parameters, the initFilter function does not design a filter, but rather
just uses whatever FIR coefficients are in place. These may have been
loaded by way of the getCoeffPtr() function or passThrough(1) may be in place. < / p >
< p class = func > < span class = keyword > initFilter< / span > (< strong > float32_t< / strong > fc,
< strong > float32_t< / strong > Astop, < strong > int< / strong > type, < strong > float32_t< / strong > dfc);< / p >
< p class = desc > Designs filters. fc is the edge frequency in Hz for LPF and HPF
and center frequency for BPF and BRF, Astop is the stopband attenuation in dB.
The parameter dfc is the filter bandwidth (only for bandpass and band reject).
The parameter type sets the filter per the following defines:
< pre class = "desc" >
LOWPASS Low pass with fc cutoff frequency
HIGHPASS High pass with fc cutoff frequency.
BANDPASS Band pass with fc center frequency and dfc pass band width.
BANDREJECT Band reject with fc center frequency and dfc reject band width.
HILBERT Hilbert transform. Not Currently Available
< / pre >
< / p >
< p class = func > < span class = keyword > passThrough< / span > (< strong > int< / strong > stat)< / p >
< p class = desc > passThrough(int stat) allows data for this filter object to be passed through
unchanged with stat=1. The default is stat=0.
< / p >
< p class = func > < span class = keyword > getCoeffPtr< / span > (< strong > void< / strong > );< / p >
< p class = desc > Returns a pointer to the coefficient array. To use this, compute
the coefficients of a 512 tap FIR filter with the desired response. Then
load the 512 float32_t buffer with the coefficients.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestConvolutionFilter_F32
< / p >
< h3 > Notes< / h3 >
< p > See the file AudioFilterConvolution_F32.h, as well as the example file, just above, for many notes,
hints and sample code.< / p > .
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterConvolution_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioLMSDenoiseNotch_F32" >
<!-- ============ AudioLMSDenoiseNotch_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Provides LMS denoise or auto-notch functions.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Filtered Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > initializeLMS< / span > (< strong > uint16_t< / strong > what, < strong > uint16_t< / strong > lengthDataF, < strong > uint16_t< / strong > lengthDataD);< / p >
< p class = desc > The parameter what must be either DENOISE or NOTCH. The lengthDataF buffer should
be a power of 2 between 2 and 128. It will be shifted down to a power of 2, if not. The delay
buffer size, lengthDataD can be any value between 1 and 16.
< / p >
< p class = func > < span class = keyword > setParameters< / span > (< strong > float32_t< / strong > beta, < strong > float32_t< / strong > decay);< / p >
< p class = desc > Sets the gain, beta, that varies the amount of denoise and notching. Adjust
for the desired sound.
< / p >
< p class = func > < span class = keyword > enable< / span > (< strong > bool< / strong > setEnable);< / p >
< p class = desc > The parameter setEnable should be < strong > true< / strong > or < strong > false.< / strong >
If not enabled, the audio is passed through unchanged.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > LMS1.ino
< / p >
< h3 > Notes< / h3 >
< p > This block can be changed at any time between denoise and auto-notching. Thus, usually
only one of these is used in a radio.< / p >
< p > More notes are included in the file AudioLMSDenoiseNotch_F32.h< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioLMSDenoiseNotch_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioSpectralDenoise_F32" >
<!-- ============ AudioSpectralDenoise_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Spectral Noise Reduction< / p >
< p > Remove random noise, such as background noise or machine generated noise, and try
to leave voice intact.< / p >
< p > Spectral NR does not try to remove constant tones or clicks and pops.< / p >
< p > Spectral NR is generally not useful for cleaning up 'pure tone' sources, such as morse code.< / p >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal to be filtered< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Filtered Signal Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setup< / span > (< strong > AudioSettings_F32 & < / strong > settings, < strong > int< / strong > n_fft);< / p >
< p class = desc > Setup the filter. Must be called if parameters not passed in to the
constructor. Can be re-called if other parameters have been changed to have
the changes take effect.
The maximum FFT size is dictated by the underlying FFT_OA code.
< / p >
< p class = func > < span class = keyword > enable< / span > (< strong > bool< / strong > start);< / p >
< p class = desc > Turn on or offthe filter. The filter is enabled by default upon
creation.
< / p >
< p class = func > < span class = keyword > enabled< / span > ();< / p >
< p class = desc > Return the enabled state of the filter.< / p >
< p class = func > < span class = keyword > getAsnr< / span > ();< / p >
< p class = desc > Return the current ASNR value.< / p >
< p class = func > < span class = keyword > setAsnr< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the ASNR value. Active SNR.< / p >
< p class = desc > Call < span class = keyword > setup()< / span > for the change to take effect.< / p >
< p class = func > < span class = keyword > getVADHighFreq< / span > ();< / p >
< p class = desc > Get the VAD band high frequency cutoff value.< / p >
< p class = func > < span class = keyword > setVADHighFreq< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the VAD High Frequency cutoff value. Sets the high
frequency value of the Voice Activity Detector (VAD) window.
< / p >
< p class = desc > Call < span class = keyword > setup()< / span > for the change to take effect.< / p >
< p class = func > < span class = keyword > getVADLowFreq< / span > ();< / p >
< p class = desc > Get the VAD band low frequency value.< / p >
< p class = func > < span class = keyword > setVADLowFreq< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the VAD band low frequency value.< / p >
< p class = desc > Call < span class = keyword > setup()< / span > for the change to take effect.< / p >
< p class = func > < span class = keyword > getNRAlpha< / span > ();< / p >
< p class = desc > get the NRalpha value. NR alpha is the time smoothing constant. It's
range is clipped between 0.9 and 0.9999 in the code. Settings >0.95
generally recommended, or you can get strong reverb and 'watery' effects.
< / p >
< p class = func > < span class = keyword > setNRAlpha< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the NRalpha value.< / p >
< p class = desc > The change takes effect immediately.< / p >
< p class = func > < span class = keyword > getSNRPrioMin< / span > ();< / p >
< p class = desc > Get the SNR prior value.< / p >
< p class = func > < span class = keyword > setSNRPrioMin< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the SNR prior value.< / p >
< p class = desc > The change takes effect immediately.< / p >
< p class = func > < span class = keyword > getNRWidth< / span > ();< / p >
< p class = desc > Get the NR width. Used for the measuring 'span' in the musical note
reduction code.
< / p >
< p class = func > < span class = keyword > setNRWidth< / span > (< strong > int16_t< / strong > value);< / p >
< p class = desc > Set the NR width.< / p >
< p class = desc > The change takes effect immediately.< / p >
< p class = func > < span class = keyword > getPowerThreshold< / span > ();< / p >
< p class = desc > Get the power threshold. Used to limit the effects of the musical
note reduction code.
< / p >
< p class = func > < span class = keyword > setPowerThreshold< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the power threshold.< / p >
< p class = desc > The change takes effect immediately.< / p >
< p class = func > < span class = keyword > getTaxFactor< / span > ();< / p >
< p class = desc > Get the noise output smoothing factor.< / p >
< p class = func > < span class = keyword > setTaxFactor< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the noise output smoothing factor. Typical values are around 0.8.< / p >
< p class = desc > Call < span class = keyword > setup()< / span > for the change to take effect.< / p >
< p class = func > < span class = keyword > getTapFactor< / span > ();< / p >
< p class = desc > Get the speech probability smoothing factor.< / p >
< p class = func > < span class = keyword > setTapFactor< / span > (< strong > float32_t< / strong > value);< / p >
< p class = desc > Set the speech probability smoothing factor. Typical values are around 0.9.< / p >
< p class = desc > Call < span class = keyword > setup()< / span > for the change to take effect.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > SpectralDenoise.ino
< / p >
< h3 > Notes< / h3 >
< p > The defaults work OK, but it is worth experimenting with the adjustable
parameters for your specific situation. Try adjusting NRAlpha, NRWidth and Asnr.
< / p >
< p > The default FFT size is 256. You may wish to make this larger, which will allow
a finer granularity of 'buckets' to potentially improve the noise reduction, but,
will cost both processor time and memory overheads.
< / p >
< p > The maximum FFT size is set by the underlying < strong > FFT_OA< / strong > code, which at
time of writing limits the maximum to 2048.
< / p >
< p > The code is written to account for the < strong > sample_rate_Hz< / strong > passed in with
the audio settings, < strong > but< / strong > , this has not been tested. If you do test,
either with a higher or lower sample rate, please report back and consider fixing
this documentation.
< / p >
< h3 > References< / h3 >
< p > The best reference on how the Spectral code was designed and works can be found on the
< a href = "https://github.com/df8oe/UHSDR/wiki/Noise-reduction" > UHSDR wiki < / a >
< / p >
< / script >
< / div >
< div >
< script type = "text/x-red" data-help-name = "AudioFilter90Deg_F32" >
<!-- ============ AudioFilter90Deg_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Creates two uncoupled paths that almost have the same amplitude gain
but differ in phase by exactly 90 degrees. < / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal Hilbert Filtered< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Input Signal Delayed< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Signal Hilbert Filtered< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Output Signal Delayed< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > (< strong > float< / strong > *pCoeff, < strong > int< / strong > nCoeff);< / p >
< p class = desc > Initializes this block, with pCoeff being a pointer to array of F32 Hilbert Transform coefficients,
and nCoeff being the number of Hilbert transform coefficients (odd).
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverPart1
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverPart2
< / p >
< h3 > Notes< / h3 >
< p > This consists of two uncoupled paths that almost have the same amplitude gain
but differ in phase by exactly 90 degrees.
The number of coefficients is an odd number for the FIR Hilbert transform
as that produces an easily achievable integer sample period delay.< / p >
< p > No default Hilbert Transform is provided, as it is highly application dependent.
The number of coefficients is an odd number with a maximum of 250. The Iowa
Hills program can design such a Hilbert Transform filter.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilter90Deg_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
<!-- ============ AudioEffectCompressor_F32 ========= -->
< script type = "text/x-red" data-help-name = "AudioEffectCompressor_F32" >
< p > AudioEffectCompressor< / p >
< p > Created: Chip Audette, Dec 2016 - Jan 2017< / p >
< p > Purpose; Apply dynamic range compression to the audio stream.< / p >
< p > Assumes floating-point data.< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > MIT License. use at your own risk.< / p >
< p > Note: This help documentation is incomplete. See AudioEffectCompressor2_F32
for a similar block, with documentation. Compressor2 includes up to 5 segments and
look ahead delay, as well.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectCompressor_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
<!-- ============ AudioEffectDelay_F32 ========= -->
< script type = "text/x-red" data-help-name = "AudioEffectDelay_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Delay a signal. Up to 8 separate delay taps can be used.< / p >
< p align = center > < img src = "img/delay.png" > < br > < small > 1 kHz burst, delayed 5.2 ms.< / small > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal Input< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Delay Tap #1< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Delay Tap #2< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Delay Tap #3< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Delay Tap #4< / td > < / tr >
< tr class = odd > < td align = center > Out 4< / td > < td > Delay Tap #5< / td > < / tr >
< tr class = odd > < td align = center > Out 5< / td > < td > Delay Tap #6< / td > < / tr >
< tr class = odd > < td align = center > Out 6< / td > < td > Delay Tap #7< / td > < / tr >
< tr class = odd > < td align = center > Out 7< / td > < td > Delay Tap #8< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > delay< / span > (channel, milliseconds);< / p >
< p class = desc > Set output channel (0 to 7) to delay the signals by
milliseconds. The maximum delay is approx 425 ms. The actual delay
is rounded to the nearest sample. Each channel can be configured for
any delay. There is no requirement to configure the "taps" in increasing
delay order.
< / p >
< p class = func > < span class = keyword > disable< / span > (channel);< / p >
< p class = desc > Disable a channel. The output of this channel becomes
silent. If this channel is the longest delay, memory usage is
automatically reduced to accomodate only the remaining channels used.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > Effects > Delay
< / p >
< h3 > Notes< / h3 >
< p > Memory for the delayed signal is take from the memory pool allocated by
< a href = "http://www.pjrc.com/teensy/td_libs_AudioConnection.html" target = "_blank" > AudioMemory()< / a > .
Each block allows about 3 milliseconds of delay, so AudioMemory
should be increased to allow for the longest delay tap.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectDelay_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioEffectFreqShiftFD_F32" >
<!-- ============ AudioEffectFreqShiftFD_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > This shifts frequencies of entire audio spectrums by use of FFT and IFFT
with bin shifting. < / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Shifted Output Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setup< / span > (< strong > AudioSettings_F32 < / strong > & settings, < strong > int< / strong > N_FFT);< / p >
< p class = desc > Initializes the needed FFTs. Returns the size of FFT achieved
or a negative number if unsuccessful. See example below for determining N_FFT.
< / p >
< p class = func > < span class = keyword > setShift_bins< / span > (< strong > int< / strong > nBins);< / p >
< p class = desc > Sets nBins, the number of FFT bins of frequency shift.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FrequencyShifter_FD_OA
< / p >
< h3 > Notes< / h3 >
< p > Created: Chip Audette (OpenAudio) Aug 2019< / p >
< p > This processing is performed in the frequency domain.
Frequencies can only be shifted by an integer number of bins,
so small frequency shifts are not possible. For example, for
a sample rate of 44.1kHz, and when using N=256, one can only
shift frequencies in multiples of 44.1/256 = 172.3 Hz.< / p >
< p > This processing is performed in the frequency domain where
we take the FFT, shift the bins upward or downward, take
the IFFT, and listen to the results. In effect, this is
single sideband modulation, which will sound very unnatural
(like robot voices!). Maybe you'll like it, or maybe not.
Probably not, unless you like weird. ;) < / p >
< p > You can shift frequencies upward or downward with this algorithm.< / p >
< p > This class supports changes in block size by AudioSettings_F32.< / p >
< p > Also see an I-Q mixing approach with fine tuning in the example: < / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FineFreqShift_OA
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectFreqShiftFD_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioSwitch4_OA_F32" >
<!-- ============ AudioSwitch4_OA_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Switch one input to 4 outputs, which only triggers 1 of the 4
audio processing paths (thus saving computation on paths that you aren't
using). Use with mixer-4 for up to 4 paths of alternate processing.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal 0< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Switch Output Signal 0< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Switch Output Signal 1< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Switch Output Signal 2< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Switch Output Signal 3< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setChannel< / span > (< strong > int< / strong > channel);< / p >
< p class = desc > Selects the output path that will be active, 0 to 7. Returns the selected path, if valid.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > Switches_float
< / p >
< h3 > Notes< / h3 >
< p > If you have two audio paths, like a SSB receiver path and an AM receiver path, you can
shut off the data going to the unused path with this AudioSwitch4_F32 class.
The AudioStream will not supply the packet to the next
object and that, in turn, will cause it to not request a transmission to the next
thing down the chain. The AudioStream routines do not create errors, it turns out,
and you save all the processing time and memory usage for the unused paths.< / p >
< p > There is an 8 output version in the palette, if you need more outputs.< / p >
< p > Created: Chip Audette, OpenAudio, April 2019< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSwitch4_OA_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioSwitch8_OA_F32" >
<!-- ============ AudioSwitch8_OA_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Switch one input to 8 outputs, which only triggers 1 of the 8
audio processing paths (thus saving computation on paths that you aren't
using). Use with mixer-8 for up to 8 paths of alternate processing.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal 0< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Switch Output Signal 0< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Switch Output Signal 1< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Switch Output Signal 2< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Switch Output Signal 3< / td > < / tr >
< tr class = odd > < td align = center > Out 4< / td > < td > Switch Output Signal 4< / td > < / tr >
< tr class = odd > < td align = center > Out 5< / td > < td > Switch Output Signal 5< / td > < / tr >
< tr class = odd > < td align = center > Out 6< / td > < td > Switch Output Signal 6< / td > < / tr >
< tr class = odd > < td align = center > Out 7< / td > < td > Switch Output Signal 7< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setChannel< / span > (< strong > int< / strong > channel);< / p >
< p class = desc > Selects the output path that will be active, 0 to 7. Returns the selected path, if valid.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > Switches_float
< / p >
< h3 > Notes< / h3 >
< p > If you have multiple audio paths, like 5 different demodulators, you can
shut off the data going to the unused paths with this AudioSwitch8_F32 class.
The AudioStream will not supply the packet to the next
object and that, in turn, will cause it to not request a transmission to the next
thing down the chain. The AudioStream routines do not create errors, it turns out,
and you save all the processing time and memory usage for the unused paths.< / p >
< p > There is an 4 output version in the palette, if you need less outputs.< / p >
< p > Created: Chip Audette, OpenAudio, April 2019< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSwitch8_OA_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzePhase_F32" >
<!-- <h2> ============ AudioAnalyzePhase_F32 AudioAnalyzePhase_F32 =========</h2> -->
< h3 > AudioAnalyzePhase_F32< / h3 >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > This block can be used to measure phase between two sinusoid inputs.
The default output IIR filter, 4-cascaded stages of BiQuad,
is suitable for this with a cut-off
frequency of 100 Hz. As an alternative, a linear phase
FIR filter can be set up with the begin function. The built in FIR
LP filter has a cutoff frequency of 4 kHz when used
at a 44.1 kHz sample rate. Any FIR filter can be used
with the setAnalyzeConfig function.
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Reference Sinewave< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Measure Sinewave< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Measured Phase Angle< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setAnalyzePhaseConfig< / span > (< strong > uint16_t< / strong > LPType, < strong > float32_t< / strong > *pCoeffs, < strong > uint16_t< / strong > nCoeffs);< / p >
< p class = desc > < / p >
< p > Changes the output filter from the IIR default, where:
< ul >
< li > LPType is NO_LP_FILTER, IIR_LP_FILTER, FIR_LP_FILTER to select the output filter< / li >
< li > pCoeffs is a pointer to filter coefficients, either IIR or FIR< / li >
< li > nCoeffs is the number of filter coefficients< / li >
< / ul >
< / p >
< p class = func > < span class = keyword > setAnalyzePhaseConfig< / span > (< strong > uint16_t< / strong > LPType, < strong > float32_t< / strong > *pCoeffs, < strong > uint16_t< / strong > nCoeffs, < strong > uint16_t< / strong > pdConfig);< / p >
< p class = desc > Is the same as above, but controls pdConfig which is a bitwiseconfiguration selection selection:< / li >
< pre class = "desc" >
Bit 0: 0=No Limiter (default) 1=Use limiter
Bit 2,1: 00=Use no acos linearizer
01=undefined
10=Fast, math-continuous acos() (default)
11=Accurate acosf()
Bit 3: 0=No scale of multiplier 1=scale to min-max (default)
Bit 4: 0=Output in degrees 1=Output in radians (default)
< / pre >
< / p >
< p class = func > < span class = keyword > showError< / span > (< strong > uint16_t< / strong > e);< / p >
< p class = desc > sets whether error printing comes from update (e=1) or not (e=0)
< / p >
< p > This class supports programmable block size and sample rate via Settings_F32.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > AudioTestAnalyzePhase
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > AudioTestSinCos
< / p >
< h3 > Notes< / h3 >
< p > There are two inputs, 0 and 1 (Left and Right)
There is one output, the phase angle between 0 & 1 expressed in
radians (180 degrees is Pi radians) or degrees. This is a 180-degree
type of phase detector. See RadioIQMixer_F32 for a 360 degree type.
< / p >
< p > < strong > Defaults:< / strong > 100 Hz IIR LP, output is in radians, and this does not need a call to begin().< / p >
< p > A FIR LP is available where linear phase is needed, or NO_LP_FILTER that leaves
harmonics of the input frequency. A limiter is available to remove amplitude effects. Scaling of the output
levels can be done. Many more details are available from AudioAnalyzePhase_F32.h in
the OpenAudio_ArduinoLibrary. < / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzePhase_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div > <!-- Audio Input category -->
< script type = "text/x-red" data-help-name = "AudioEffectNoiseGate_F32" >
<!-- ============ AudioEffectNoiseGate_F32 ======= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Apply envelope controlled threshold to a signal.
Inputs below a given level are removed.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal In< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Gated Signal Out< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setThreshold< / span > (< strong > float < / strong > dBFS);< / p >
< p class = desc > Sets threshold to mute below, in dBFS (relative to full scale input),
such as -40.0.< / p >
< p class = func > < span class = keyword > setOpeningTime< / span > (< strong > float < / strong > tOpen);< / p >
< p class = desc > In units of seconds, such as 0.02.< / p >
< p class = func > < span class = keyword > setClosingTime< / span > (< strong > float < / strong > tClose);< / p >
< p class = desc > In units of seconds, such as 0.05.< / p >
< p class = func > < span class = keyword > setHoldTime< / span > (< strong > float < / strong > tHold);< / p >
< p class = desc > In units of seconds, such as 0.10.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > NoiseGate
< / p >
< h3 > Notes< / h3 >
< p > Created: Max Huster, Feb 2021 < / p >
< p > Purpose: This module mutes the Audio completly, when it's below a given threshold.< / p >
< p > This processes a single stream fo audio data (i.e., it is mono)< / p >
< / script >
< script type = "text/x-red" data-template-name = "_AudioEffectNoiseGate_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div > <!-- Audio Input category -->
< script type = "text/x-red" data-help-name = "AudioEffectCompressor2_F32" >
<!-- ============ AudioEffectCompressor2_F32 ======= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Apply envelope controlled gain to a signal.
Up to five independent "k dB per dB" segments. Includes expansion
(squelch) compression (AGC) and limiting.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal In< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Signal Out< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > ();< / p >
< p class = desc > Enables the compressor using parameters set
by the functon setCompressionCurve().
< / p >
< p class = func > < span class = keyword > setCompressionCurve< / span > (< strong > struct< / strong > compressionCurve*);< / p >
< p class = desc > This defines the compression curve and needs an INO defined structure of type
compressionCurve. That structure is defined in AudioEffectCompressor2_F32.h.
< / p > <!-- ADD INFO HERE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -->
< p class = func > < span class = keyword > getCurrentInputDB< / span > ();< / p >
< p class = desc > Returns the last input level in < strong > float< / strong > dBFS.
< / p >
< p class = func > < span class = keyword > getvInMaxDB< / span > ();< / p >
< p class = desc > Returns the maximum input level in < strong > float< / strong > dBFS.
This is reset upon reading.
< / p >
< p class = func > < span class = keyword > getCurrentGainDB< / span > ();< / p >
< p class = desc > Returns the current gain in < strong > float< / strong > dB.
< / p >
< p class = func > < span class = keyword > setDelayBufferSize< / span > (< strong > int16< / strong > delay);< / p >
< p class = desc > The input envelope detector can run ahead of the input
signal by use of this delay. This give improved transient response. The
parameter "delay" can be any power of 2 such as 64, 128 or 256.
A delay of 256 samples is 256/44100 = 0.0058 sec = 5.8 mSec.
< / p >
< h3 > Macros< / h3 >
< p > These are macros and not functions. They simplify getting a working compressor
and provide their own compressionCurve structure and are called with
a pointer to the compressor object (not to the structure) named "pobject" here.
This means the macro is invoked
without a preceeding object name. These macros replace the begin() function.
See the example program testCompressor2.ino below.< / p >
< p class = func > < span class = keyword > basicCompressorBegin< / span > (pobject, linearInDB, compressionRatio);< / p >
< p class = desc > The compression curve for basicCompressorBegin() has a 3 segments.
It is linear up to an input linearInDB
and then decreases gain according to compressionRatioDB up to an input -10 dB where it
is almost limited, with an increase of output level of 1 dB for a 10 dB increase
in input level. The output level at full input is 1 dB below full output.< / p >
< p class = func > < span class = keyword > limiterBegin< / span > (pointerObject, float marDB, float linearInDB);< / p >
< p class = desc > The compression curve for limiterBegin() has a 2 segments.
It is linear up to an input of linearInDB (typically -15.0f) and
then virtually limits for higher input levels. The output level at
this point is marDB, the margin to prevent clipping, like -2 dB.
This is not a clipper with waveform distortion, but rather decreases
the gain, dB for dB, as the input increases in the limiter region.< / p >
< p class = func > < span class = keyword > squelchCompressorBegin< / span > (pobject, squelchInDB, linearInDB, compressionInDB, compressionRatio);< / p >
< p class = desc > The compression curve for squelchCompressorBegin() has a 3 segments.
and is similar to basicCompression above, except that there is
an expansion region for low levels. So, the call defines the four regions in
terms of the input levels. squelchInDB sets the lowest input level
before the squelching effect starts.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > testCompressor2
< / p >
< h3 > Notes< / h3 >
< p > This is a general purpose audio compressor block (C++ class). It works by determining
the average input of the input signal, and based on a pre-determined curve,
changes the gain going through the block.
A good discussion is the Wikipedia page:
https://en.wikipedia.org/wiki/Dynamic_range_compression
This compressor includes up to 5 dB/dB line segments. allowing
considerable flexibility including:< ul >
< li > Multi segment compression curves, up to 5< / li >
< li > Limiting< / li >
< li > Approximation to "soft knees"< / li >
< li > Expansion for suppressing low-level artifacts< / li >
< li > Anticipation< / li >
< li > Scale offset for use such as hearing-aid audiology< / li >
< / ul >
This is derived from the WDRC compressor. Chip Audette (OpenAudio) Feb 2017
Which was derived From: WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro< / p >
< / script >
< script type = "text/x-red" data-template-name = "_AudioCompressor2_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioEffectEmpty_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > This module does nothing. It passes through the signal with no
changes. If you open up the code, you can copy it to use as a template
to build your own audio processing block.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > Being an empty block, it has no functions.< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio >
< / p >
-->
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectEmpty_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioEffectGain_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Scale the signal by a fixed amount. The gain is applied on a per-block
(as opposed to a per-sample) basis.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal Input< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Result of Input Times Gain< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > There are two functions for setting the gain of this block:< / p >
< p class = func > < span class = keyword > setGain< / span > (gain);< / p >
< p class = desc > Set the gain as a linear value. A value between 0.0 and 1.0
attenuates the signal while a value above 1.0 amplifies the signal. Negative
values will invert the signal.< / p >
< p class = func > < span class = keyword > setGain_dB< / span > (gain_dB);< / p >
< p class = desc > Set the gain using a decibel value (gain_dB = 20*log10(gain)).
A value less than zero attenuates the signal and a value greater than zero
amplifies the signal. Phase inversion is not available.< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio >
< / p >
-->
< / script >
< script type = "text/x-red" data-template-name = "AudioEffectGain_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioFilterBiquad_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Biquadratic cascaded IIR filters, useful for all sorts of
frequency filtering. Up to 4 stages may be cascaded. < / p >
< p align = center > < img src = "img/biquad.png" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal to be filtered< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Filtered Signal Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > ();< / p >
< p class = desc > This < b > required< / b > function initializes
the BiQuad instance using the ARM DSP Math Library. There are no
calling parameters.
< / p >
< p class = func > < span class = keyword > setLowpass< / span > (stage, frequency, Q);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with low pass
response, with the specified corner frequency and Q shape. If Q is
higher that 0.7071, be careful of filter gain (see below).
< / p >
< p class = func > < span class = keyword > setHighpass< / span > (stage, frequency, Q);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with high pass
response, with the specified corner frequency and Q shape. If Q is
higher that 0.7071, be careful of filter gain (see below).
< / p >
< p class = func > < span class = keyword > setBandpass< / span > (stage, frequency, Q);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with band pass
response. The filter has unity gain at the specified frequency. Q
controls the width of frequencies allowed to pass.
< / p >
< p class = func > < span class = keyword > setNotch< / span > (stage, frequency, Q);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with band reject (notch)
response. Q controls the width of rejected frequencies.
< / p >
< p class = func > < span class = keyword > setLowShelf< / span > (stage, frequency, gain, slope);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with low shelf response.
A low shelf filter attenuates or amplifies signals below the specified frequency.
Frequency controls the slope midpoint, gain is in dB and can be both
positive or negative. The slope parameter controls steepness of gain transition.
A slope of 1 yields maximum steepness without overshoot,
lower values yield a less steep slope. See the picture below for a visualization
of the slope parameter's effect.
Be careful with positive gains and slopes higher than 1 as they introduce gain
(see warning below).
< / p >
< / p >
< p class = func > < span class = keyword > setHighShelf< / span > (stage, frequency, gain, slope);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with high shelf response.
A high shelf filter attenuates or amplifies signals above the specified frequency.
Frequency controls the slope midpoint, gain is in dB and can be both
positive or negative. The slope parameter controls steepness of gain transition.
A slope of 1 yields maximum steepness without overshoot,
lower values yield a less steep slope. See the picture below for a visualization
of the slope parameter's effect.
Be careful with positive gains and slopes higher than 1 as they introduce gain
(see warning below).
< / p >
< p align = center > < img src = "img/shelf_filter.png" > < / p >
< p class = func > < span class = keyword > setCoefficients< / span > (stage, array[5]);< / p >
< p class = desc > Configure one stage of the filter (0 to 3) with an arbitrary
filter response. The array of coefficients is in order: B0, B1, B2, A1, A2.
Each coefficient must be less than 2.0 and greater than -2.0. The array
should be type double. < / p >
< p class = func > < span class = keyword > < strong > double* < / strong > getCoefficients< / span > ();< / p >
< p class = desc > Returns a pointer to the array of double precision coefficients. For
up to four stages, each stage is arranged in order B0, B1, B2, A1, A2. This is a
maximum of 20 coefficients with unused stages showing a 1.0 and four zeros. < / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > Effects > Filter
< / p >
< h3 > Notes< / h3 >
< p > Each instance of the Biquad filter class can have 0 to 4 cascaded biquad filters,
with each independent. These can mix filter types, such as Low Pass and High Pass
or they can be multiples of the same type. Note that, in general, cascading identical
Biquad IIR filters will not be the most useful. Check the Internet for discussions
of cascading filters to achieve specific responses, such as Butterworth
or Chebychev.
< / p >
< p > This object implements up to 4 cascaded stages. The four biquads per instance
can each be used, or not used, and the unused
ones will be treated as pass throughs.
< / p >
< p > These IIR filters do not provide flat time delay with frequency as provided
by symmetrical FIR filters. If this is important, the extra complexity of the FIR
type may be justified.< / p >
< p > These IIR filters generally do not have the degrees of freedom that FIR filters easily provide.
That means the response shapes are generally more constrained. This can be overcome
by adding many more biquad sections, with properly chosen frequencies and Qs, but
then it becomes easier to just use the FIR. Thus, most applications where the Biquad IIR
is appropriate will fit into this 4-filter object.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterBiquad_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioFilterFIR_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Finite impulse response filter, useful for all sorts of filtering.
< / p >
< p align = center > < img src = "img/fir_filter.png" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal to be filtered< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Filtered Signal Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > (filter_coeff, filter_length, block_size);< / p >
< p class = desc > Initialize the filter. The filter_coeff must be an array of 32-bit floats (the
filter's impulse response), the filter_length indicates the number of points in the array,
and block_size is the length of the audio block that will be passed to this filtering
object during operation. The filter_coeff array may also be set as
FIR_PASSTHRU (with filter_length = 0), to directly pass the input to output without
filtering.
< / p >
< p class = func > < span class = keyword > end< / span > ();< / p >
< p class = desc > Turn the filter off.
< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > Effects > Filter_FIR
< / p >
-->
< h3 > Known Issues< / h3 >
< p > Your filter's impulse response array must have an even length. If you have
add odd number of taps, you must add an extra zero to increase the length
to an even number.
< / p >
< p > The minimum number of taps is 4. If you use less, add extra zeros to increase
the length to 4.
< / p >
< p > The impulse response must be given in reverse order. Many filters have
symetrical impluse response, making this a non-issue. If your filter has
a non-symetrical response, make sure the data is in reverse time order.
< / p >
< h3 > Notes< / h3 >
< p > FIR filters requires more CPU time than Biquad (IIR), but they can
implement filters with better phase response.
< / p >
< p > The free
< a href = "http://t-filter.engineerjs.com/" target = "_blank" > TFilter Design Tool< / a >
can be used to create the impulse response array. Be sure to choose the desired sampling
frequency (that tool defaults to only 2000 Hz whereas Teensy defaults to 44117) and
for this library the output type should be "float" (32 bit).
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterFIR_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioFilterFreqWeighting_F32" >
< p > Frequency weighting. Defaults to A-Weighting< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterFreqWeighting_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioFilterTimeWeighting_F32" >
< p > Time weighting for sound level meter. Defaults to SLOW< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioFilterTimeWeighting_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMathAdd_F32" >
< p > AudioMathAdd_F32< / p >
< p > Created: Chip Audette, Open Audio, July 2018< / p >
< p > Purpose: Add together two channels (vectors) of audio data on a point-by-point basis< / p >
< p > (like AudioMathMutiply, but addition). Assumes floating-point data.< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMathAdd_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMathMultiply_F32" >
< p > AudioMathMultiply< / p >
< p > Created: Patrick Radius, December 2016< / p >
< p > Purpose: Multiply two channels of audio data. Can be used for example as 'vca' or amplitude modulation.< / p >
< p > Assumes floating-point data.< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMathMultiply_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMathOffset_F32" >
< p > AudioMathOffset_F32< / p >
< p > Created: Chip Audette, Open Audio, June 2018< / p >
< p > Purpose: Add a constant DC value to all audio samples< / p >
< p > Assumes floating-point data.< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMathOffset_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMathScale_F32" >
< p > AudioMathScale_F32< / p >
< p > Created: Chip Audette, Open Audio, June 2018< / p >
< p > Purpose: Multiply all audio samples by a single value (not vector)< / p >
< p > Assumes floating-point data.< / p >
< p > This processes a single stream fo audio data (ie, it is mono)< / p >
< p > MIT License. use at your own risk.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMathScale_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMixer4_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Combine up to 4 audio signals together, each with adjustable gain.
All channels support signal attenuation or amplification.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input signal #1< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Input signal #2< / td > < / tr >
< tr class = odd > < td align = center > In 2< / td > < td > Input signal #3< / td > < / tr >
< tr class = odd > < td align = center > In 3< / td > < td > Input signal #4< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Sum of all inputs< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > gain< / span > (channel, level);< / p >
< p class = desc > Adjust the amplification or attenuation. "channel" must
be 0 to 3. "level" may be any floating point number. A level value of
1.0 passes the signal through directly. Between 0 to 1.0 attenuates the signal, and above
1.0 amplifies it. A level value of 0 shuts the channel
off completely. All 4 channels have separate settings.
< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > SamplePlayer
< / p >
< p class = exam > File > Examples > Audio > Synthesis > PlaySynthMusic
< / p >
< p class = exam > File > Examples > Audio > Analysis > SpectrumAnalyzerBasic
< / p >
< p class = exam > File > Examples > Audio > Analysis > DialTone_Serial
< / p >
< p class = exam > File > Examples > Audio > MemoryAndCpuUsage
< / p >
-->
< h3 > Notes< / h3 >
< p > More than 4 channels may be combined by connecting multiple mixers
in tandem. For example, a 16 channel mixer may be built using 5
mixers, where the fifth mixer combines the outputs of the first 4.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMixer4_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioMixer8_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Combine up to 8 audio signals together, each with adjustable gain.
All channels support signal attenuation or amplification.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input signal #1< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Input signal #2< / td > < / tr >
< tr class = odd > < td align = center > In 2< / td > < td > Input signal #3< / td > < / tr >
< tr class = odd > < td align = center > In 3< / td > < td > Input signal #4< / td > < / tr >
< tr class = odd > < td align = center > In 4< / td > < td > Input signal #5< / td > < / tr >
< tr class = odd > < td align = center > In 5< / td > < td > Input signal #6< / td > < / tr >
< tr class = odd > < td align = center > In 6< / td > < td > Input signal #7< / td > < / tr >
< tr class = odd > < td align = center > In 7< / td > < td > Input signal #8< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Sum of all inputs< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > gain< / span > (channel, level);< / p >
< p class = desc > Adjust the amplification or attenuation. "channel" must
be 0 to 7. "level" may be any floating point number. A level value of
1.0 passes the signal through directly. Between 0 to 1.0 attenuates the signal, and above
1.0 amplifies it. A level value of 0 shuts the channel
off completely. All 4 channels have separate settings.
< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > SamplePlayer
< / p >
< p class = exam > File > Examples > Audio > Synthesis > PlaySynthMusic
< / p >
< p class = exam > File > Examples > Audio > Analysis > SpectrumAnalyzerBasic
< / p >
< p class = exam > File > Examples > Audio > Analysis > DialTone_Serial
< / p >
< p class = exam > File > Examples > Audio > MemoryAndCpuUsage
< / p >
-->
< h3 > Notes< / h3 >
< p > More than 8 channels may be combined by connecting multiple mixers
in tandem. For example, a 16 channel mixer may be built using three
mixers, where the third mixer combines the outputs of the first two.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioMixer8_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "FFT_Overlapped_F32" >
< p > FFT_Overrlapped_F32< / p >
< p > Purpose: Encapsulate the ARM floating point FFT/IFFT functions< / p >
< p > in a way that naturally interfaces to my float32< / p >
< p > extension of the Teensy Audio Library.< / p >
< p > Provides functionality to do overlapped FFT/IFFT where< / p >
< p > each audio block is a fraction (1, 1/2, 1/4) of the< / p >
< p > totaly FFT length. This class handles all of the< / p >
< p > data shuffling to composite the previous data blocks< / p >
< p > with the current data block to provide the full FFT.< / p >
< p > Does similar data shuffling (overlapp-add) for IFFT.< / p >
< p > Created: Chip Audette (openaudio.blogspot.com)< / p >
< p > Jan-Jul 2017< / p >
< p > Typical Usage as FFT:< / p >
< p > //setup the audio stuff< / p >
< p > float sample_rate_Hz = 44100.0; //define sample rate< / p >
< p > int audio_block_samples = 32; //define size of audio blocks< / p >
< p > AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);< / p >
< p > // ... continue creating all of your Audio Processing Blocks ...< / p >
< p > // within a custom audio processing algorithm that you've written< / p >
< p > // you'd create the FFT and IFFT elements< / p >
< p > int NFFT = 128; //define length of FFT that you want (multiple of audio_block_samples)< / p >
< p > FFT_Overrlapped_F32 FFT_obj(audio_settings,NFFT); //Creare FFT object< / p >
< p > FFT_Overrlapped_F32 IFFT_obj(audio_settings,NFFT); //Creare IFFT object< / p >
< p > float complex_2N_buffer[2*NFFT]; //create buffer to hold the FFT output< / p >
< p > // within your own algorithm's "update()" function (which is what< / p >
< p > // is called automatically by the Teensy Audio Libarary approach< / p >
< p > // to audio processing), you can execute the FFT and IFFT< / p >
< p > // First, get the audio and convert to frequency-domain using an FFT< / p >
< p > audio_block_f32_t *in_audio_block = AudioStream_F32::receiveReadOnly_f32();< / p >
< p > FFT_obj.execute(in_audio_block, complex_2N_buffer); //output is in complex_2N_buffer< / p >
< p > AudioStream_F32::release(in_audio_block); //We just passed ownership to FFT_obj, so release it here.< / p >
< p > // Next do whatever processing you'd like on the frequency domain data< / p >
< p > // that is held in complex_2N_buffer< / p >
< p > // Finally, you can convert back to the time domain via IFFT< / p >
< p > audio_block_f32_t *out_audio_block = IFFT_obj.execute(complex_2N_buffer);< / p >
< p > //note that the "out_audio_block" is mananged by IFFT_obj, so don't worry about releasing it.< / p >
< p > License: MIT License< / p >
< / script >
< script type = "text/x-red" data-template-name = "FFT_Overlapped_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "IFFT_Overlapped_F32" >
< p > FFT_Overrlapped_F32< / p >
< p > Purpose: Encapsulate the ARM floating point FFT/IFFT functions< / p >
< p > in a way that naturally interfaces to my float32< / p >
< p > extension of the Teensy Audio Library.< / p >
< p > Provides functionality to do overlapped FFT/IFFT where< / p >
< p > each audio block is a fraction (1, 1/2, 1/4) of the< / p >
< p > totaly FFT length. This class handles all of the< / p >
< p > data shuffling to composite the previous data blocks< / p >
< p > with the current data block to provide the full FFT.< / p >
< p > Does similar data shuffling (overlapp-add) for IFFT.< / p >
< p > Created: Chip Audette (openaudio.blogspot.com)< / p >
< p > Jan-Jul 2017< / p >
< p > Typical Usage as FFT:< / p >
< p > //setup the audio stuff< / p >
< p > float sample_rate_Hz = 44100.0; //define sample rate< / p >
< p > int audio_block_samples = 32; //define size of audio blocks< / p >
< p > AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);< / p >
< p > // ... continue creating all of your Audio Processing Blocks ...< / p >
< p > // within a custom audio processing algorithm that you've written< / p >
< p > // you'd create the FFT and IFFT elements< / p >
< p > int NFFT = 128; //define length of FFT that you want (multiple of audio_block_samples)< / p >
< p > FFT_Overrlapped_F32 FFT_obj(audio_settings,NFFT); //Creare FFT object< / p >
< p > FFT_Overrlapped_F32 IFFT_obj(audio_settings,NFFT); //Creare IFFT object< / p >
< p > float complex_2N_buffer[2*NFFT]; //create buffer to hold the FFT output< / p >
< p > // within your own algorithm's "update()" function (which is what< / p >
< p > // is called automatically by the Teensy Audio Libarary approach< / p >
< p > // to audio processing), you can execute the FFT and IFFT< / p >
< p > // First, get the audio and convert to frequency-domain using an FFT< / p >
< p > audio_block_f32_t *in_audio_block = AudioStream_F32::receiveReadOnly_f32();< / p >
< p > FFT_obj.execute(in_audio_block, complex_2N_buffer); //output is in complex_2N_buffer< / p >
< p > AudioStream_F32::release(in_audio_block); //We just passed ownership to FFT_obj, so release it here.< / p >
< p > // Next do whatever processing you'd like on the frequency domain data< / p >
< p > // that is held in complex_2N_buffer< / p >
< p > // Finally, you can convert back to the time domain via IFFT< / p >
< p > audio_block_f32_t *out_audio_block = IFFT_obj.execute(complex_2N_buffer);< / p >
< p > //note that the "out_audio_block" is mananged by IFFT_obj, so don't worry about releasing it.< / p >
< p > License: MIT License< / p >
< / script >
< script type = "text/x-red" data-template-name = "IFFT_Overlapped_F32 " >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioInputI2S_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receive float32 stereo audio from the
< a href = "http://www.pjrc.com/store/teensy3_audio.html" target = "_blank" > Teensy Audio Board< / a > ,
the < a href = "https://www.tympan.org/" > Tympan Audio Board< / a > ,
or another I2S device.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Constructor< / h3 >
< p > Objects of this class can be created using the typical, minimal constructor using no arguments.
Or, to control the sample rate and block size, the constructor can be passed an AudioSettings_F32
object that has been configured with your desired settings.< / p >
< h3 > Functions< / h3 >
< p > This object has no functions to call from the Arduino sketch. It
simply streams data from the I2S hardware to its 2 output ports.< / p >
< h3 > Hardware< / h3 >
< p > The I2S signals are used in "master" mode, where the Teensy creates
all 3 clock signals and controls all data timing.< / p >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Pin< / th > < th > Signal< / th > < th > Direction< / th > < / tr >
< tr class = odd > < td align = center > 9< / td > < td > BCLK< / td > < td > Output< / td > < / tr >
< tr class = odd > < td align = center > 11< / td > < td > MCLK< / td > < td > Output< / td > < / tr >
< tr class = odd > < td align = center > 22< / td > < td > TX< / td > < td > Output< / td > < / tr >
< tr class = odd > < td align = center > 23< / td > < td > LRCLK< / td > < td > Output< / td > < / tr >
< / table >
< p > Audio from
master mode I2S may be used in the same project as ADC, DAC and
PWM signals, because all remain in sync to Teensy's timing< / p >
< h3 > Examples< / h3 >
< p Most examples use the Audio card with I2S transfer . < / p >
< h3 > Notes< / h3 >
< p > Only one I2S input and one I2S output object may be used. Master
and slave modes may not be mixed (both must be of the same type).< / p >
< p > As of May 2022, the I2S input and output objects can handle 24 or 32-bit
data transfer, if that is supported by the audio hardware device.
No class functions are needed. It is "automagic".< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioInputI2S_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioInputSPDIF3_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receive S/PDIF digital audio, at the rate of the external digital audio source.< / p >
< p > < span style = "color:red" > This input is incompatible with most other inputs and outputs< / span >
which run at a speed controlled by Teensy's internal sample rate.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > pllLocked< / span > ();< / p >
< p class = desc > Returns true if the S/PDIF phase locked loop is tracking
the sample rate of incoming digital audio data.
< / p >
< p class = func > < span class = keyword > sampleRate< / span > ();< / p >
< p class = desc > Returns the sample rate of incoming data, if the PLL has locked,
or returns 0 if the audio sample rate is unknown.
< / p >
< h3 > Hardware< / h3 >
< p >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > T4.x< br > Pin< / th > < th > Signal< / th > < th > Direction< / th > < / tr >
< tr class = odd > < td align = center > 15< / td > < td > S/PDIF Data< / td > < td > Output< / td > < / tr >
< / table >
< / p >
< h3 > Examples< / h3 >
<!-- <p class=exam>File > Examples > Audio > HardwareTesting > PassThroughAsyncSpdif
< / p > -->
< h3 > Notes< / h3 >
< p > This input tries to force the entire audio library to run at the
sample rate of the incoming data. It usually can not be combined
with most other inputs and outputs which run at specific speeds.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioInputSPDIF3_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AsyncAudioInputSPDIF3_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receive S/PDIF digital audio and resample to Teensy's audio sample rate.< / p >
< p > Asynchronous resampling contributed by < a href = "https://github.com/alex6679" > Alex Walch< / a > .< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > getBufferedTime< / span > ();< / p >
< p class = desc > Returns the buffered time in seconds. The buffered time is the duration of the incoming samples which are not resampled yet. The step width of the resampling algorithm is constantly slightly adjusted to keep the buffered time closely to the target latency. The difference between the target latency and the buffered time is typically smaller than 1 microsecond.
< / p >
<!-- <p class=func><span class=keyword>getInputFrequency</span>();</p>
< p class = desc > TODO: documentation needed here
< / p > -->
< p class = func > < span class = keyword > isLocked< / span > ();< / p >
< p class = desc > Returns true if the S/PDIF phase locked loop is tracking
the sample rate of incoming digital audio data.
< / p >
< p class = func > < span class = keyword > getInputFrequency< / span > ();< / p >
< p class = desc > Returns the sample rate of incoming data, if the PLL has locked, or returns 0 if the audio sample rate is unknown.
< / p >
< p class = func > < span class = keyword > getTargetLantency< / span > ();< / p >
< p class = desc > Returns the target latency in seconds. The latency is the time from the moment a sample is received by the Teensy SPDIF hardware receiver until it is transmitted by the asrc intput. The audio samples arrive at the asrc input in chunks of 32 samples per channel. The target latency consists of these 32 samples + some buffer that is needed to compensate for timing variations.
< / p >
< p class = func > < span class = keyword > getAttenuation< / span > ();< / p >
< p class = desc > Returns the actual achieved attenuation of the
anti-aliasing filter. If the input sampling rate is smaller or equal
to 44.1kHz, no low pass filtering is needed and zero is returned.< / p >
< p class = func > < span class = keyword > getHalfFilterLength< / span > ();< / p >
< p class = desc > Returns the half length of the resampling filter. Its complete length is 2*(the returned value)+1.
< / p >
< h3 > Hardware< / h3 >
< p >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > T4.x< br > Pin< / th > < th > Signal< / th > < th > Direction< / th > < / tr >
< tr class = odd > < td align = center > 15< / td > < td > S/PDIF Data< / td > < td > Output< / td > < / tr >
< / table >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > HardwareTesting > PassThroughAsyncSpdif
< / p >
< h3 > Notes< / h3 >
< p > AsyncAudioInputSPDIF3 is not able to clock the audio pipline (never has the 'update_responsibility'). At least 1 other input or output must be used to cause the entire Audio library to update.
< / p >
< p > AsyncAudioInputSPDIF3 can optionally take parameters to alter its resampling behavior.
< / p >
< p > < span class = keyword > AsyncAudioInputSPDIF3_F32< / span > spdif_async1(< i > dither< / i > , < i > noiseshaping< / i > , < i > attenuation< / i > , < i > minHalfFilterLength< / i > , < i > maxHalfFilterLength< / i > );
< / p >
< p class = desc > < i > dither< / i > : triangular shaped dither is added at the transition from 32bit float to 16bit integer if true (default: true)
< / p >
< p class = desc > < i > noiseshaping< / i > : noise shaping is applied at the aforementioned transition if true (default: true)
< / p >
< p class = desc > < i > attenuation< / i > : target attenuation of the anti-aliasing filter (default: 100dB). The attenuation is not reached if a filter longer than 161 is needed.
< / p >
< p class = desc > < i > minHalfFilterLength< / i > : half of the guaranteed resampling filter (internally restricted to 80, default: 20). The filter might be longer if needed to achieve the requested attenuation.
< / p >
< p class = desc > < i > maxHalfFilterLength< / i > : Restricts the maximum length of the resampling filter. The maximum half filter length is 80. This parameter can be used to further restrict the length in order to limit the processor usage.
< / p >
< p > The windowed (Kaiser window) sinc-function is used as resample filter (i.e. to interpolate the incoming signal). The longer the filter, the better the quality of the resampled signal. However, a longer filter has a higher group delay and increases the processor usage. The sinc- filter also serves as anti-aliasing filter if the input sample rate is larger than 44.1kHz. The filter length is automatically increased at high input sample rates to reach the specified attenuation. However its half length is restricted to 80. 32bit floating point arithmetic is used at the resampling stage and the resampled signal is transformed to 16 bit integers afterwards. Here it is possible to apply triangular shaped dither and noise shaping to increase the perceived signal-to-noise-ratio.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AsyncAudioInputSPDIF3_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioOutputI2S_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Transmit float32 stereo audio to the various I2S Codec boards, such as
< a href = "http://www.pjrc.com/store/teensy3_audio.html" target = "_blank" > Teensy Audio Board< / a > .
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Constructor< / h3 >
< p > Objects of this class can be created using the typical, minimal constructor using no arguments.
Or, to control the sample rate and block size, the constructor can be passed an AudioSettings_F32
object that has been configured with your desired settings.< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setGain< / span > (< strong > float < / strong > Gain);< / p >
< p class = desc > Sets the output gain of both left and right channels. Values are unconstrained, but
normally range from 0.0 to 1.0 (default 1.0). A setting of exactly 1.0 results in
no scaling and saves a small amount of processor. < / p >
< h3 > Hardware< / h3 >
< p > A control Codec object, such as the SGTL5000 must be included.< / p >
< p > Audio from
master mode I2S may be used in the same project as ADC, DAC (not T4.x) and
PWM signals, because all remain in sync to Teensy's timing< / p >
<!--
< h3 > Examples< / h3 >
< p > Nearly all the examples use this object. Here are some of the highlights:< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > PassThroughStereo
< / p >
< p class = exam > File > Examples > Audio > SamplePlayer
< / p >
< p class = exam > File > Examples > Audio > Recorder
< / p >
< p class = exam > File > Examples > Audio > WavFilePlayer
< / p >
< p class = exam > File > Examples > Audio > Effects > Chorus
< / p >
< p class = exam > File > Examples > Audio > Synthesis > PlaySynthMusic
< / p >
-->
< h3 > Notes< / h3 >
< p > Only one I2S input and one I2S output object may be used. Master
and slave modes may not be mixed (both must be of the same type).< / p >
< p > Being an "_F32" object, audio is passed into this class using F32 memory
that was allocated using an AudioMemory_F32() call in your sketch's setup()
routine. But, internally, this class still uses some Int16 data handling,
so be sure to also include an AudioMemory() call in addition to AudioMemory_F32()
to allocate the Int16 memory.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioOutputI2S_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioOutputSPDIF3_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Transmit 16 bit stereo audio as Digital S/PDIF by use of the
native S/PDIF port.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > This object has no functions to call from the Arduino sketch. It
simply streams data from its 2 input ports S/PDIF encoded digital
audio on pin 14 (Teensy 4.x).< / p >
< h3 > Hardware< / h3 >
< p > The S/PDIF output signal can be used to drive an optical TOSLINK
cable, or a standard (usually orange) RCA jack.< / p >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Teensy< br > 4.x Pin< / th > < th > Signal< / th > < th > Direction< / th > < / tr >
< tr class = odd > < td align = center > 14< / td > < td > S/PDIF< / td > < td > Output< / td > < / tr >
< / table >
< h3 > Examples< / h3 >
< p > The AudioOutputSPDIF object can be used in place of the AudioOutputI2S object,
< p > used in nearly all the examples. The WavFilePlayer shows how to substitute
output objects for different hardware types.
< / p >
< p class = exam > File > Examples > Audio > WavFilePlayer
< / p >
< h3 > Credits< / h3 >
< p > < a href = "https://github.com/FrankBoesing" target = "_blank" > Frank Boesing< / a >
developed the AudioOutputSPDIF3 code.
< h3 > Notes< / h3 >
< p > Native S/PDIF hardware is used, which is more efficient that use of I2S ports.< / p >
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioOutputSPDIF3_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioAlignLR_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Measure Codec L-R time misalignment at startup and make
time shift corrections during regular operation. ** BETA TEST **< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Right Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Test Signal (Beta)< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > read< / span > (< strong > void< / strong > );< / p >
< p class = desc > This returns a pointer to a < strong > TPinfo< / strong > structure
containing information on the operation of the time alignment. The structure
members are:< / p >
< table class = doc align = center cellpadding = 3 >
< tr class = odd > < td align = center > < strong > uint16_t< / strong > < / td > < td > TPstate< / td > < / tr >
< tr class = odd > < td align = center > < strong > uint32_t< / strong > < / td > < td > nMeas< / td > < / tr >
< tr class = odd > < td align = center > < strong > float32_t< / strong > < / td > < td > xNorm< / td > < / tr >
< tr class = odd > < td align = center > < strong > float32_t< / strong > < / td > < td > xcVal[4]< / td > < / tr >
< tr class = odd > < td align = center > < strong > int16_t< / strong > < / td > < td > neededShift< / td > < / tr >
< tr class = odd > < td align = center > < strong > int16_t< / strong > < / td > < td > TPerror< / td > < / tr >
< tr class = odd > < td align = center > < strong > uint16_t< / strong > < / td > < td > TPsignalHardware< / td > < / tr >
< / table >
< p class = func > < span class = keyword > stateTwinPeaks< / span > (< strong > uint16_t< / strong > TPstate);< / p >
< p class = desc > This process comes up set to TP_IDLE. To start the alignment detection,
use this function to set TPstate to TP_MEASURE. If detection is successful,
the state will automatically move to TP_RUN. Correction of the alignment error will
then continue without requiring any function calls.< / p >
<!--
< p class = func > < span class = keyword > setThreshold< / span > (< strong > float32_t< / strong > TPthreshold);< / p >
< p class = desc > The L-R cross correlation signal must exceed this threshold to indicate
detection. To set this value run the process with any
value for the threshold. Examine the three -1, 0, 1 output data around update #15.
Then set the threshold to about half of maximum positive value of the three.< / p >
-->
< h3 > Examples< / h3 >
< p class = exam > File > Examples > TestTwinPeaks
< / p >
< h3 > Notes< / h3 >
< p > The object construction takes parameters, the first three being
required:
< / p >
< table class = doc align = center cellpadding = 3 >
< tr class = odd > < td align = center > < strong > uint16_t< / strong > < / td > < td > Hardware< / td > < / tr >
< tr class = odd > < td align = center > < strong > uint16_t< / strong > < / td > < td > Pin< / td > < / tr >
< tr class = odd > < td align = center > < strong > bool< / strong > < / td > < td > Invert< / td > < / tr >
< / table >
< p > See AudioAlignLR.h and the example INO for details on the parameters.
A fourth parameter, settings, is optional.< / p >
< p > There are two different methods for generating a test signal. Both
require a small amount of hardware to be contructed. The first, and recommended,
(Hardware=TP_SIGNAL_IO_PIN) method uses a dedicated Teensy digital I/O pin to generate an 11.4 kHz square wave that
is permanently connected by two 10K to 100K resistors to the L& R ADC inputs. The second,
(Hardware=TP_SIGNAL_CODEC), method briefly borrows the
Codec R channel output to produce an 11 kHz square wave that is coupled via analog
switches to the L& R ADC inputs. Both methods seem to work very well. The first method's
hardware is simpler. The third audio output from the AlignLR block is not used for
the first method.< / p >
< p > The resistor values, referred to above, depend on the impedance that
the ADC is being driven from. As a general rule, they should be (very) roughly 200
times the driving point impedance. Too high a value reults in noise in the
measurement. Too low can cause digital noise to get into the audio. It is
also possible to use a pair of NPN transistors, such as a 2N3904, to shunt the resistor
paths to the Codecanalog ground. For that case the resistor would be divided into two
parts, the sum of which equaled the desired resistor value.< / p >
< p > To DO: 1 - See if anybody needs the Codec DAC method.
Remove if not needed.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAlignLR_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioInputUSB_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receive stereo audio from a PC or Mac. Teensy appears as a USB
sound device.< / p >
< p align = center > < img src = "img/usbtype_audio_in.png" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > This object has no functions to call from the Arduino sketch. It
simply streams data from the USB to its 2 output ports.< / p >
<!--
< h3 > Hardware< / h3 >
-->
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > HardwareTesting > PassThroughUSB< / p >
< / p >
< h3 > Notes< / h3 >
< p > Arduino's < b > Tools > USB Type< / b > menu must be set to < b > Audio< / b > .
< / p >
< p align = center > < img src = "img/usbtype_audio.png" > < / p >
< p > USB input & output does not cause the Teensy Audio Library to
update. At least one non-USB input or output object must be
present for the entire library to update properly.< / p >
< p > A known problem exists with USB audio from Macintosh computers.
An imperfect < a href = "https://forum.pjrc.com/threads/34855-Distorted-audio-when-using-USB-input-on-Teensy-3-1?p=110392&viewfull=1#post110392" > workaround
can be enabled by editing usb_audio.cpp< / a > .
Find and uncomment "#define MACOSX_ADAPTIVE_LIMIT".< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioInputUSB_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioOutputUSB_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Send stereo audio to a PC or Mac. Teensy appears as a USB
sound device.< / p >
< p align = center > < img src = "img/usbtype_audio_out.png" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Left Channel< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Right Channel< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p > This object has no functions to call from the Arduino sketch. It
simply streams from it's 2 input ports to the USB.< / p >
<!--
< h3 > Hardware< / h3 >
-->
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > HardwareTesting > WavFilePlayerUSB< / p >
< / p >
< h3 > Notes< / h3 >
< p > Arduino's < b > Tools > USB Type< / b > menu must be set to < b > Audio< / b > .
< / p >
< p align = center > < img src = "img/usbtype_audio.png" > < / p >
< p > USB input & output does not cause the Teensy Audio Library to
update. At least one non-USB input or output object must be
present for the entire library to update properly.< / p >
< p > A known problem exists with USB audio from Macintosh computers.
An imperfect < a href = "https://forum.pjrc.com/threads/34855-Distorted-audio-when-using-USB-input-on-Teensy-3-1?p=110392&viewfull=1#post110392" > workaround
can be enabled by editing usb_audio.cpp< / a > .
Find and uncomment "#define MACOSX_ADAPTIVE_LIMIT".< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioOutputUSB_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioPlaySdWav_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Plays a WAV file, stored on an SD card.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Left Channel Output< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Right Channel Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > play< / span > (filename);< / p >
< p class = desc > Begin playing a WAV file. If a file is already playing,
it is stopped and this file starts playing from the beginning.
No return value.< / p >
< p class = func > < span class = keyword > stop< / span > ();< / p >
< p class = desc > Stop playing. If not playing, this function has no effect.
No return value.< / p >
< p class = func > < span class = keyword > togglePlayPause< / span > ();< / p >
< p class = desc > Used to Pause the playing of a file, or to un-Pause
depending on which applies. No return value. < / p >
< p class = func > < span class = keyword > isPlaying< / span > ();< / p >
< p class = desc > Return true (non-zero) if playing, or false (zero)
when not playing. See the note below about delayed start.< / p >
< p class = func > < span class = keyword > isPaused< / span > ();< / p >
< p class = desc > Return true (non-zero) if paused (see
togglePlayPause above).
< p class = func > < span class = keyword > isStopped< / span > ();< / p >
< p class = desc > Return true (non-zero) if not playing and
not paused.< / p >
< p class = func > < span class = keyword > setSubMult< / span > (subMult* pStruct)
< / span > ();< / p >
< p class = desc > Used if the WAV file is to be run at a lower sample rate
than the audio sample rate. The two rates must be related by an integer.
The calling parameter is a pointer to a structure of type subMult.
That is defined as:
< pre >
struct subMult {
uint16_t rateRatio; // Should be 1 for no rate change, else an integer
uint16_t numCoeffs; // FIR filter
float32_t* firCoeffs; // FIR Filter Coeffs
float32_t* firBufferL; // pointer to 127 + numCoeffs float32_t, left ch
float32_t* firBufferR; // pointer to 127 + numCoeffs float32_t, right ch
};< / pre >
The struct is declared in the INO and this function transmits the selected
information. Note that the FIR filters can be used, even if the rateRatio
is 1. There is no need for this caused by rateRatio = 1, but
the filter function may be useful for other reasons. If the WAV file
and the Audio are both using the same sample rate, this function
is not needed and the rateRatio defaults to 1 and no FIR filters
are involked. The left and right FIR filters use the same coefficients
but need separate firBuffer. For monaural files, the firBufferR pointer can be
a NULL.< / p >
< p class = func > < span class = keyword > getCurrentWavData< / span > ();< / p >
This returns a pointer to a structure containing data about the
WAV file currently selected for play. The structure is:
< pre >
struct wavData {
uint16_t audio_format; // Should be 1 for PCM
uint16_t num_channels; // 1 for mono, 2 for stereo
uint32_t sample_rate; // 44100, 48000, etc
uint16_t bits; // Number of bits per sample, should be 16
};< / pre >
< / p >
< p class = func > < span class = keyword > positionMillis< / span > ();< / p >
< p class = desc > While playing, return the current time offset, in
milliseconds. When not playing, the return from this function
is undefined.
< / p >
< p class = func > < span class = keyword > lengthMillis< / span > ();< / p >
< p class = desc > Return the total length of the current sound clip,
in milliseconds. When not playing, the return from this function
is undefined.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > WavFilePlayer
< p class = exam > File > Examples > Audio > WavFilePlayer2
< / p >
< h3 > Notes< / h3 >
< p > Only 16 bit PCM WAV files are supported. When mono
files are played, both output ports transmit a copy of the
single sound. Of course, stereo WAV files play with the left
channel on port 0 and the right channel on port 1.
< / p >
< p > A brief delay after calling play() will usually occur before
isPlaying() returns true and positionMillis() returns valid
time offset. WAV files have a header at the beginning of the
file, which the audio library must read and parse before
playing can begin.
< / p >
< p > While playing, the audio library accesses the SD card automatically.
If card access is needed for other purposes, you must
< a href = "http://www.pjrc.com/teensy/td_libs_AudioProcessorUsage.html"
target="_blank">use AudioNoInterrupts()< / a >
to prevent AudioPlaySDWav from accessing the SD card while you use it.
Disabling the audio library interrupt for too long may cause audible
dropouts or glitches.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioPlaySdWav_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioPlayQueue_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Play audio data provided by the Arduino sketch. This object provides
functions to allow the sketch code to push data into the audio system.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Sound Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > play< / span > (int16);< / p >
< p class = desc > not yet implemented
< / p >
< p class = func > < span class = keyword > play< / span > (int16[], length);< / p >
< p class = desc > not yet implemented
< / p >
< p class = func > < span class = keyword > getBuffer< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 128 int16. This buffer
is within the audio library memory pool, providing the most efficient
way to input data to the audio system. The buffer is likely to be
populated by previously used data, so the entire 128 words should be
written before calling playBuffer(). Only a single buffer should be
requested at a time. This function may return NULL if no memory is
available.
< / p >
< p class = func > < span class = keyword > playBuffer< / span > ();< / p >
< p class = desc > Transmit the buffer previously obtained from getBuffer().
< / p >
< h3 > Examples< / h3 >
< p > < a href = "http://community.arm.com/groups/embedded/blog/2014/05/23/led-video-panel-at-maker-faire-2014" target = "_blank" > 4320 LED Video+Sound Project< / a >
< / p >
<!--
< p class = exam > File > Examples > Audio >
< / p >
-->
< h3 > Notes< / h3 >
< p > TODO: many caveats....< / p >
< p >
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioPlayQueue_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioRecordQueue_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Record audio data by sending to the Arduino sketch. This object allows
sketch code to receive audio packets.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Sound To Access< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > ();< / p >
< p class = desc > Begin capturing incoming audio to the queue. After calling
begin, readBuffer() and freeBuffer(), or clear() must be used frequently
to prevent the queue from filling up.
< / p >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > Returns the number of audio packets available to read.
< / p >
< p class = func > < span class = keyword > readBuffer< / span > ();< / p >
< p class = desc > Read a single audio packet. A pointer to a 128 sample
array of 16 bit integers is returned. NULL is returned if no packets
are available.
< / p >
< p class = func > < span class = keyword > freeBuffer< / span > ();< / p >
< p class = desc > Release the memory from the previously read packet returned
from readBuffer(). Only a single packet at a time may be read, and
each packet must be freed with this function, to return the memory to
the audio library.
< / p >
< p class = func > < span class = keyword > clear< / span > ();< / p >
< p class = desc > Discard all audio held in the queue.
< / p >
< p class = func > < span class = keyword > end< / span > ();< / p >
< p class = desc > Stop capturing incoming audio into the queue. Data already
captured remains in the queue and may be read with readBuffer().
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > Recorder
< / p >
< h3 > Notes< / h3 >
< p >
Up to 52 packets may be queued by this object, which allows approximately
150 ms of audio to be held in the queue, to allow time for the Arduino
sketch to write data to media or do other high-latency tasks.
The actual packets are taken
from the pool created by AudioMemory().
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioRecordQueue_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioSynthNoisePink_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Create pink noise, using Stefan Stenzel's "New Shade Of Pink" algorithm.
< / p >
<!--
< p align = center > < img src = "img/whitenoise.png" > < / p >
-->
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Pink Noise< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > amplitude< / span > (level);< / p >
< p class = desc > Set the output peak level, from 0 (off) to 1.0.
The default is off. Noise is generated only after setting
to a non-zero level.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > MemoryAndCpuUsage
< / p >
< h3 > Notes< / h3 >
< p > Setting the amplitude to zero causes this object to stop using
CPU time. CPU usage is approx 3% on Teensy 3.1.
< / p >
< p > Stefan Stenzel's
< a href = "http://stenzel.waldorfmusic.de/post/pink/" target = "_blank" > New Shade Of Pink< / a >
algorithm. Stefan's terms of use are "Use for any purpose. If used
in a commercial product, you should give me one."
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthNoisePink_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioSynthWaveformSine_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Create a sine wave signal< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Sine Wave Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > amplitude< / span > (level);< / p >
< p class = desc > < p class = desc > The amplitude, level, is the peak, as in
zero-to-peak. This produces an output ranging from -a to +a.
< / p >
Negative values do a 180-degree phase reversal.
< / p >
< p class = func > < span class = keyword > frequency< / span > (freq);< / p >
< p class = desc > Set the frequency, from 0.0 to half of the sampling
frequency. This is a floating point number and thus not limited to integers.
Values such as 123.456 will be set properly.
< / p >
< p class = func > < span class = keyword > phase< / span > (angle);< / p >
< p class = desc >
Cause the generated waveform to jump to a specific point within
its cycle. Angle is from 0.0 to 360.0 degrees. When multiple objects
are configured,
< a href = "http://www.pjrc.com/teensy/td_libs_AudioProcessorUsage.html" target = "_blank" > AudioNoInterrupts()< / a >
should be used to guarantee all new settings take effect together.
< / p >
< p class = func > < span class = keyword > setSampleRate_Hz< / span > (float &fs_Hz); < / p >
< p class = desc > Sets sample rate for this class only. Default 44.1 kHz.< / p >
< p class = func > < span class = keyword > begin< / span > (void);< / p >
< p class = desc > Defaults to sine running. But, along with the end() function
can be used to turn the wave on and off.
< / p >
< p class = func > < span class = keyword > end< / span > (void);< / p >
< p class = func > < span class = keyword > pureSpectrum< / span > (bool _setPure);< / p >
< p class = desc > The function pureSpectrum(true) enables two stages of
biquad filtering putting the harmonics generally below -135 dBc. This filter
tracks the frequency() entry, and is available above a few hundred Hz,
depending on the sample rate.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > ReceiverPart1
< / p >
< p class = exam > File > Examples > AudioTestPeakRMS
< / p >
< p class = exam > File > Examples > LowpassFilter_FD_OA
< / p >
< h3 > Notes< / h3 >
< p > < / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthWaveformSine_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioSynthSineCosine_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Creates both a sine wave and cosine signals with 90 degree
phase difference. 90 degree difference can be adjusted. Both have the
same adjustable amplitude. < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Sine Wave Output< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Cosine Wave Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > amplitude< / span > (< strong > float < / strong > level);< / p >
< p class = desc > The amplitude, a, is the peak, as in zero-to-peak. This produces outputs
ranging from -a to +a. Both outputs are the same amplitude.
< / p >
< p class = func > < span class = keyword > frequency< / span > (< strong > float < / strong > freq);< / p >
< p class = desc > Set the frequency of the sine and cosine waveforms, in Hz. Both
are the same.< / p >
< p class = func > < span class = keyword > phase< / span > (< strong > float < / strong > angle);< / p >
< p class = desc >
Cause the generated waveform to jump to a specific point within
its cycle. Angle is from 0 to 360 degrees. When multiple objects
are configured,
< a href = "http://www.pjrc.com/teensy/td_libs_AudioProcessorUsage.html" target = "_blank" > AudioNoInterrupts()< / a >
should be used to guarantee all new settings take effect together.< / p >
< p class = func > < span class = keyword > phase_r< / span > (< strong > float < / strong > phr)
< p class = desc > Externally, phase comes in the range (0,2*M_PI) keeping with C math functions
Internally, the full circle is represented as (0.0, 512.0). This is
convenient for finding the entry to the sine table.< / p >
< p class = func > < span class = keyword > phaseS_C_r< / span > (< strong > float < / strong > phsc)
< p class = desc > phaseS_C_r is the number of radians that the cosine output leads the
sine output. The default is M_PI_2 = pi/2 = 1.57079633 radians,
corresponding to 90.00 degrees cosine leading sine.< / p >
< p class = func > < span class = keyword > void simple< / span > (< strong > bool < / strong > s)
< p class = desc > Speed up calculations by setting phaseS_C=90deg, amplitude=1
Note, s=true will override any setting of phaseS_C_r or amplitude.< / p >
< p class = func > < span class = keyword > pureSpectrum< / span > (bool _setPure);< / p >
< p class = desc > The function pureSpectrum(true) enables two stages of
biquad filtering on each output, putting the harmonics generally below -135 dBc.
This filter tracks the frequency() entry, and is available above a few hundred Hz,
depending on the sample rate.
< / p >
< p class = func > < span class = keyword > setSampleRate_Hz< / span > (< strong > float < / strong > fs_Hz)
< p class = desc > Sets sample rate for this class only. Default 44.1 kHz.< / p >
< p class = func > < span class = keyword > setBlockLength< / span > (< strong > uint16_t < / strong > bl)
< p class = desc > Sets block length for this class only. Default 128.< / p >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > MemoryAndCpuUsage
< / p >
< p class = exam > File > Examples > Audio > Analysis > ---
< / p >
< p class = exam > File > Examples > Audio > Analysis > ---
< / p >
< h3 > Notes< / h3 >
< p > < / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthSineCosine_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioSynthWaveform_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Create a waveform: sine, sawtooth, square, triangle, pulse or arbitrary.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Waveform Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > begin< / span > (waveform);< / p >
< p class = desc > Configure the waveform type to create.
< / p >
< p class = func > < span class = keyword > begin< / span > (level, frequency, waveform);< / p >
< p class = desc > Output a waveform, and set the amplitude and frequency.
< / p >
< p class = func > < span class = keyword > frequency< / span > (freq);< / p >
< p class = desc > Change the frequency.
< / p >
< p class = func > < span class = keyword > amplitude< / span > (level);< / p >
< p class = desc > Change the amplitude. Set to 0 to turn the signal off.
< / p >
< p class = func > < span class = keyword > phase< / span > (angle);< / p >
< p class = desc >
Cause the generated waveform to jump to a specific point within
its cycle. Angle is from 0 to 360 degrees. When multiple objects
are configured,
< a href = "http://www.pjrc.com/teensy/td_libs_AudioProcessorUsage.html" target = "_blank" > AudioNoInterrupts()< / a >
should be used to guarantee all new settings take effect together.
< / p >
< p class = func > < span class = keyword > pulseWidth< / span > (amount);< / p >
< p class = desc > Change the width (duty cycle) of the pulse.< / p >
< p class = func > < span class = keyword > arbitraryWaveform< / span > (array, maxFreq);< / p >
< p class = desc >
Configure the waveform to be used with WAVEFORM_ARBITRARY. Array
must be an array of 256 samples. Currently, the data is used
without any filtering, which can cause aliasing with frequencies
above 172 Hz. For higher frequency output, you must bandwidth
limit your waveform data. Someday, "maxFreq" will be used to
do this automatically.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > Synthesis > PlaySynthMusic
< / p >
< p class = exam > File > Examples > Audio > Synthesis > pulseWidth
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > WM8731MikroSine
< / p >
< h3 > Notes< / h3 >
< p > Supported Waveforms:< br >
< ul >
< li > < span class = literal > WAVEFORM_SINE< / span > < / li >
< li > < span class = literal > WAVEFORM_SAWTOOTH< / span > < / li >
< li > < span class = literal > WAVEFORM_SAWTOOTH_REVERSE< / span > < / li >
< li > < span class = literal > WAVEFORM_SQUARE< / span > < / li >
< li > < span class = literal > WAVEFORM_TRIANGLE< / span > < / li >
< li > < span class = literal > WAVEFORM_ARBITRARY< / span > < / li >
< li > < span class = literal > WAVEFORM_PULSE< / span > < / li >
< li > < span class = literal > WAVEFORM_SAMPLE_HOLD< / span > < / li >
< / ul >
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthWaveform_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioSynthGaussian_F32" >
<!-- ============ AudioSynthGaussian_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Generates Gaussian White Noise of known power.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Noise Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > amplitude< / span > (< strong > float< / strong > sd);< / p >
< p class = desc > Sets the amplitude of the noise. This is the 1-sima or standard
deviation level. Since this is Gaussian distributed noise, the same number is also
the RMS level (square root of power).
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestNoiseBlanker1
< / p >
< h3 > Notes< / h3 >
< p > This noise source is a Gaussian distribution with mean of
zero and a standard deviation specified by amplitude(). Default amlitude
is 0.0 (off). Individual samples are fully uncorrelated, meaning that
the spectrum of the noise is flat (White Noise).< / p >
< p > Time requirements for generating a block of 128, Teensy 3.6,
is 121 microseconds and for the Teensy 4.0 is 36 microseconds.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthGaussian_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioSynthNoiseWhite_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Create white noise.
< / p >
< p align = center > < img src = "img/whitenoise.png" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > White Noise< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > amplitude< / span > (level);< / p >
< p class = desc > Set the output peak level, from 0 (off) to 1.0.
The default is off. Noise is generated only after setting
to a non-zero level.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio >
< / p >
< h3 > Notes< / h3 >
< p > Setting the amplitude to zero causes this object to stop using
CPU time to generate random numbers.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioSynthNoiseWhite_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "RadioFMDetector_F32" >
<!-- ============ RadioFMDetector_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > An FM Detector sutable for work at an low frequency such
as 15 kHz. An output low-pass filter is included. A squelch
allows for silencing noise when signals are not present.
For deviations in the 10 kHz range or less. Not for wideband
broadcast FM.
< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > De-modulated Output Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > De-modulated Output Signal, squelched< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > frequency< / span > (< strong > float< / strong > fCenter);< / p >
< p class = desc > < / p >
< p > Sets the center frequency, in Hz.< / p >
< p class = func > < span class = keyword > filterOut< / span > (< strong > float< / strong > *firCoeffs, < strong > uint< / strong > nFIR, < strong > float< / strong > Kdem);< / p >
< p > This sets output filtering where:
< pre class = "desc" >
float32_t* firCoeffs pointer to array of coefficients
uint nFIR is the number of coefficients
float32_t Kdem is the de-emphasis frequency factor
Kdem = 1/(0.5+(tau*fsample))
tau is the de-emphasis time constant,
typically 0.0005 second and fsample
the sample frequency, typically 44117.
< / pre >
< p class = func > < span class = keyword > filterIQ< / span > (< strong > float< / strong > *fir_IQ_Coeffs, < strong > uint< / strong > nFIR_IQ);< / p >
< p > This sets the detector output filtering where:
< pre class = "desc" >
float32_t* fir_IQ_Coeffs is an array of coefficients
uint nFIR_IQ is the number of coefficients, max 60
< / pre >
< p class = func > < span class = keyword > setSquelchThreshold< / span > (< strong > float< / strong > sqThresh);< / p >
< p class = desc > < / p >
< p > Sets the squelch threshold ranging 0.0 to 1.0 where
0.0 always lets audio through.< / p >
< p class = func > < span class = keyword > setSquelchDecay < / span > (< strong > float< / strong > sqDecay);< / p >
< p class = desc > < / p >
< p > Sets the decay rate of the output of the squelch detector. This produces the "squelch tail."
The range is 0.9 (no real tail) to 0.9999 (very slow decay and a long squelch tail.)
The default value is 0.99.< / p >
< p class = func > < span class = keyword > getSquelchLevel< / span > ();< / p >
< p class = desc > < / p >
< p > Returns the current measured squelch level as a < strong > float. < / strong >
Higher levels, towards 1.0, are no signal. A low return value indicates presence of
a signal.< / p >
< p class = func > < span class = keyword > setSquelchFilter< / span > (< strong > float* < / strong > Coefficients);< / p >
< p class = desc > < / p >
< p > This allows changing the 2-section (4-pole) bandpass BiQuad filter used before the
squelch detector. This passes high-frequency noise and attenuates lower frequency voice. The
parameter "Coefficients" points to an array of 10 floating point numbers. A Coefficient value
of NULL restores the default 3 to 5 kHz filter. See the example ReceiverFM.ino for using this.< / p >
< p class = func > < span class = keyword > returnInitializeFMError< / span > ();< / p >
< p > This returns the initialization errors, for debug use.
< pre class = "desc" >
B0001 (value 1) error in IQ FIR Coefficients or qty
B0010 (value 2) error in Output FIR Coefficients or qty
B0100 (value 4) error in de-emphasis constant
B1000 (value 8) errors center frequency to high
< / pre >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverFM
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverPart2
< / p >
< h3 > Notes< / h3 >
< p > This consists of a single input at some frequency, such as 10 to 20 kHz and
an output, such as 0 to 5 kHz. The output level is linearly dependent on the
frequency of the input sine wave frequency, i.e., an it is an FM detector.
The input needs to be band limited below the lower frequency side of the
input, typically 10 kHz. This is not part of this block.< / p >
< p > This uses 430 microseconds for an 128 point update with Teensy 3.6. With the
Teensy 4.x, 97 microseconds is used.< / p >
< P > The output can be FIR filtered using default parameters,
or using coefficients from an array. A separate single pole de-emphasis filer
is included that again can be programmed.< / P >
< p > < strong > Output:< / strong > Float, sensitivity is 2*pi*(f - fCenter)*sample_rate_Hz
For 44117Hz sample rate, this is 0.000142421 per Hz.< / p >
< p > < strong > Accuracy< / strong > The function used is precise. However, the approximations, such
as fastAtan2, slightly limit the accuracy. A 200 point sample of a
14 kHz input had an average error of 0.03 Hz
and a standard deviation of 0.81 Hz.< / p >
< p > The RadioFMDetector_F32.h file has much more information including details
of the arc-tangent method of computation.< / p >
< / script >
< script type = "text/x-red" data-template-name = "RadioFMDetector_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "RadioFMDiscriminator_F32" >
<!-- ============ RadioFMDiscriminator_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > An FM Discriminator suitable for work at an low frequency, such
as 15 kHz. The DSP functionality is the same as that of a classic
2-tuned circuit analog discrimiator. The center frequenct of the tuned circuits
and their Q is programmable. An output low-pass filter is included. A squelch
allows for silencing noise when signals are not present.
For deviations in the 10 kHz range or less. Not for wideband
broadcast FM. No bandpass filtering is supplied for the input signals and noise.
That filtering is often desireable and may be added using AudioFilterFIRGeneral_F32.
< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > De-modulated Output Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > De-modulated Output Signal, squelched< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > initializeFMDiscriminator< / span >
(< strong > float< / strong > f1,< strong > float< / strong > f2,< strong > float< / strong > q1,< strong > float< / strong > q2);< / p >
< p class = desc > < / p >
< p > Designs the discriminator "circuit" where f1 and f2
are the resonant frequencies of the two resonators and q1 and q2 are the associated Q factors.
The Q factors control the width of the peaks at frequencies f1 and f2.< / p >
< p class = func > < span class = keyword > filterOut
< / span > (< strong > float32_t< / strong > *firCoeffs, < strong > uint< / strong > nFIR,
< strong > float32_t< / strong > *firCoeffs,< strong > float32_t< / strong > Kdem);< / p >
< p > This sets output filtering where:
< pre class = "desc" >
float32_t* firCoeffs pointer to array of coefficients
uint nFIR is the number of coefficients
float32_t* fir_State_Out pointer to float32_t array
float32_t Kdem is the de-emphasis frequency factor
Kdem = 1/(0.5+(tau*fsample))
tau is the de-emphasis time constant,
typically 0.0005 second and fsample
the sample frequency, typically 44117.
< / pre >
< p > Calling this function enables the use of a FIR output filter
and will cancel any IIR output filter. firCoeffs points to an INO supplied array
of FIR coefficients. fir_State_Out points to a float32_t storage area, again
supplied by the INO. The size of this array is 128+nFIR. If the block size
in settings has been changed from 128, then that new size should replace 128.< / p >
< p class = func > < span class = keyword > filterOutIIR
< / span > (< strong > float< / strong > frequency, < strong > float32_t< / strong > q, < strong > float32_t< / strong > kdem);< / p >
< p > This sets the detector output filtering where:
< pre class = "desc" >
float32_t frequency is the LPF cutoff in Hz.
float32_t q is the loss factor for the LPF, typically 0.7.
< / pre >
< p > Calling this function enables the use of a IIR output filter
and will cancel any FIR output filter.< / p >
< p class = func > < span class = keyword > setSquelchThreshold< / span > (< strong > float< / strong > sqThresh);< / p >
< p class = desc > < / p >
< p > Sets the squelch threshold ranging 0.0 to 1.0 where
0.0 always lets audio through.< / p >
< p class = func > < span class = keyword > setSquelchDecay < / span > (< strong > float< / strong > sqDecay);< / p >
< p class = desc > < / p >
< p > Sets the decay rate of the output of the squelch detector. This produces the "squelch tail."
The range is 0.9 (no real tail) to 0.9999 (very slow decay and a long squelch tail.)
The default value is 0.99.< / p >
< p class = func > < span class = keyword > getSquelchLevel< / span > ();< / p >
< p class = desc > < / p >
< p > Returns the current measured squelch level as a < strong > float. < / strong >
Higher levels, towards 1.0, are no signal. A low return value indicates presence of
a signal.< / p >
< p class = func > < span class = keyword > setSquelchFilter< / span > (< strong > float* < / strong > Coefficients);< / p >
< p class = desc > < / p >
< p > This allows changing the 2-section (4-pole) bandpass BiQuad filter used before the
squelch detector. This passes high-frequency noise and attenuates lower frequency voice. The
parameter "Coefficients" points to an array of 10 floating point numbers. A Coefficient value
of NULL restores the default 3 to 5 kHz filter. See the example ReceiverFM.ino for using this.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_random
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_snr
< / p >
< h3 > Notes< / h3 >
< p > No input bandpass filtering is included. This may be desireable and should
be provided as a separate FIR filter block. The input level is non-critical
as a limiter is provided at the discriminator input. Limiting is centered on
a 0.0 input level.< / p >
< p > This uses 45 microseconds for an 128 point update with Teensy 4.x.< / p >
< P > The output can be FIR filtered using default parameters,
or using coefficients from an array. A separate single pole de-emphasis filter
is included that again can be programmed.< / P >
< p > Two forms of object creation are possible.
RadioFMDiscriminator_F32() uses default sample rate and block size.
Non-standard values are possible with
RadioFMDiscriminator_F32(AudioSettings_F32 & settings).< / p >
< p > The RadioFMDiscriminator_F32.h file has more information.< / p >
< / script >
< script type = "text/x-red" data-template-name = "RadioFMDiscriminator_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "UART_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receive base-band digital data as audio samples and convert these to digital
0,1 data. Using Universal Asynchronous Receive Transmit (UART) receive
rules, generate data words. These data words are available to the INO
via a 16-word FIFO buffer< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Baseband signal to be digitized< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setUART< / span >
(< strong > uint32_t< / strong > cTauI, < strong > uint32_t< / strong > cTauHalfI,
< strong > uint16_t< / strong > nBits, < strong > uint16_t< / strong > nParity,
< strong > uint16_t< / strong > nStop);< / p >
< p class = desc > This sets the UART parameters. The cTauI is the number of
audio samples for each bit period. This is normally found
as the bit sample rate divided by the UART bit rate. cTauHalfI
is half that number. Both are quantized to integer values.< / p >
< p class = func > < span class = keyword > getNDataBuffer< / span > ();< / p >
< p class = desc > Returns the number of unread data words as uint32_t. < / p >
< p class = func > < span class = keyword > readUartData< / span > ();< / p >
< p class = desc > returns a pointer to the uartData structure.
This increments the index and thus can only be called once per
successful UART output word. If no data is available, a NULL
pointer is returned. The structure is as follows:
< pre class = "desc" >
struct uartData {
uint32_t data;
uint8_t status;
int32_t timeCrossings;
};
< / pre >
< / p >
< p class = func > < span class = keyword > setInputOffset< / span > (< strong > float32_t< / strong > inputOffset);< / p >
< p class = desc > The input is a floating point value, centered on 0.0. One source of this
could be a discriminator base-band output. If the input signal is offset
from zero, it can be corrected with this function. This inputOffset is
added to the input and can be + or - in value.
< / p >
< p class = func > < span class = keyword > setSampleRate_Hz< / span >
(< strong > float32_t< / strong > sampleRate_Hz)< / p >
< p class = desc > Enter sample rate, for this class only, as float32_t.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_random
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_snr
< / p >
< h3 > Notes< / h3 >
< p > This is only the receive portion of the UART. The transmit function is often
best integrated with the transmit modulator. This UART parallels the receive
functions of common devices going back to fully hardware implementations. To support
play with the function, the data words can be any length up to 32 bits.
< / p >
< p > Parity is not yet implemented.< / p >
< / script >
< script type = "text/x-red" data-template-name = "UART_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "radioCESSBtransmit_F32" >
<!-- ============ radioCESSBtransmit_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Converts audio into Weaver SSB and then applies Dave Hershberger, W9GR,
CESSB controlled clipping and
filtering. This prevents the SSB peaks from exceeding a maximum level.
This increases the peak limited average power by 3 or more dB. The output
can be converted to conventional SSB by a RadioIQMixer_F32 object.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Audio Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Weaver SSB I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Weaver SSB Q Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setSampleRate_Hz< / span >
(< strong > float32_t< / strong > fs_Hz bitRate);< / p >
< p class = desc > Specifically, this sets the sample rate, in samples per second,
that is used by CESSB. It also sets other parameters, such as
decimation ratios and filter cutoff frequencies. Thus this function
is < strong > required.< / strong > At this time, the design is centered
on 48000 sps, but can be used with other close values such as
44100 or 50000. The plan is to eventually support 96000 sps if users
are needing it. There is no default value and the CESSB objects will not run if
this function is not called.< / p >
< p class = func > < span class = keyword > getLevels< / span > (< strong > int< / strong > what);< / p >
< p class = desc > Returns a pointer to a structure of type levels. This allows
knowledge of the average and peak levels at both the input and output sides
of the SSB clipper and overshoot compensator. If what==0 the pointer is returned
but no updating is done. That is used to setup the process before data is
available. If what != 0, the contents of the structure are updated and measuring
is reset. The function levelDataCount() below can be used to set the time
between updates. The stucture is part of the object and is defined as:
< pre >
struct levels {
float32_t pwr0; // Average power at input
float32_t peak0; // Peak voltage at input
float32_t pwr1; // Average power at output
float32_t peak1; // Peak voltage at output
uint32_t countP; // Number of averaged samples for pwr0.
};
< / pre > < / p >
< p class = func > < span class = keyword > levelDataCount< / span > ();< / p >
< p class = desc > Returns an uint32_t with the number of averaged samples
of the input power. See getLevels() above. The number of output
samples may differ by an integer factor because of decimation inside
the object.< / p >
< p class = func > < span class = keyword > setGains< / span > (
< strong > float32_t< / strong > gainIn,
< strong > float32_t< / strong > gainCompensate,
< strong > float32_t< / strong > gainOut);< / p >
< p class = desc > These are the controls for the CESSB class. gainIn sets
the amount of clipping by setting the input level to the clipper.
gainCompensate sets the amount of correction applied to prevent
overshoot. A value of 2.0 or slightly less is normally used. gainOut is
for convenience and sets the drive level to the next block. < / p >
< p class = func > < span class = keyword > setSideband< / span > (< strong > bool< / strong > sbReverse);< / p >
< p class = desc > The LSB/USB selection depends on the processing of the
IQ outputs of this class. But, what we can do here is to reverse the
selection by reversing the phase of one of the Weaver LO's. < / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > CESSB
< / p >
< h3 > Notes< / h3 >
< p > The technical description, implementation and test results are in references
listed in the include file for this class,
< a href = "https://github.com/chipaudette/OpenAudio_ArduinoLibrary/blob/master/radioCESSBtransmit_F32.h"
target="_blank">available from Github< / a >
These should be used to understand the details of CESSB. The notes at the top of
that include file has information relating to this Teensy Audio implementation, as well.
< / p >
< p > The first activity for CESSB is to limit or clip the amplitude of the SSB signal. Internally
this always occurs when the envelope of the SSB signal exceeds 1.0. This is all done
with floating point arithmetic so values may exceed 1.0. The input level where this occurs
depends on the setting for gainIn, described above. The maximum level seen ahead of the clipper
is measured by getLevels() as described above. One way to control the input to the CESSB block
is with
< a href = "http://www.janbob.com/electron/OpenAudio_Design_Tool/index.html?info=AudioEffectCompressor2_F32"
target="_blank">Compressor2 Library block.< / a > Note that Compressor2
is not a clipper, but is rather an automatic gain control that uses look-ahead
processing to allow gradual gain changes.
< / p >
< p > The output of the CESSB processing is two sampled data signals representing
Weaver SSB. This uses the in-phase and quadratuere components of the SSB signal
that has been converted to frequencies of -1350 to +1350 Hz. Wow, if that seems
confusing, take a look at the CESSB example and see how this can be translated
into either an Upper Sideband (USB) or a Lower Sideband (LSB) signal. Implemented
in DSP, the Weaver Method of SSB generation has some interesting and good features.
It is worth considering as an alternative to the phasing method, with or without CESSB.
By lowering the input level, this CESSB block can be used as a Weaver Method SSB
generator.< / p >
< p > CESSB as implemented here is intended for voice input, and also filters the voice
to a communications bandwidth of around 2700 Hz.< / p >
< / script >
< script type = "text/x-red" data-template-name = "radioBFSKModulator_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "radioBFSKModulator_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Transmits Binary (2-frequency) Frequency Shift Keyed signals (BFSK).
The data words are supplied by the INO via a 64-word FIFO transmit buffer.
Optional FIR filtering of the input to the modulator is provided.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > BFSK transmit audio or I-F< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setBFSK< / span >
(< strong > float32_t< / strong > bitRate, < strong > uint16_t< / strong > numBits,
< strong > float32_t< / strong > f0, < strong > float32_t< / strong > f1);< / p >
< p class = desc > This sets the BFSK modulator parameters. The bitRate is
obvious, but numBits includes start and stop bits so that to
transmit 8N1 numBits should be 10.
The tone frequencies are in Hz and can be any values up to fs/2.
IMPORTANT: Before calling this initialize function, call any functions
that set filters.< / p >
< p class = func > < span class = keyword > bufferHasSpace< / span > ();< / p >
< p class = desc > Returns a bool value true if another data word can be sent. < / p >
< p class = func > < span class = keyword > sendData< / span > (< strong > uint32_t< / strong > data);< / p >
< p class = desc > Empties the FIFO transmit buffer.< / p >
< p class = func > < span class = keyword > clearBuffer< / span > ();< / p >
< p class = desc > Clears the send buffer. Does not stop a character being sent. No return value.< / p >
< p class = func > < span class = keyword > amplitude< / span > (< strong > float32_t< / strong > a);< / p >
< p class = desc > Sets a, the zero-to-peak amplitude of the transmit signal.
No return value, i.e., void. < / p >
< p class = func > < span class = keyword > setLPF
< / span > (< strong > float32_t*< / strong > FIRdata, < strong > float32_t*< / strong > FIRcoeff, < strong > uint16_t< / strong > numCoeffs);< / p >
< p > This sets output filtering where:
< pre class = "desc" >
float32_t* FIRdata is a pointer to array data storage
float32_t* firCoeffs is a pointer to array of coefficients
uint numCoeffs is the number of FIR filter coefficients
< / pre >
To omit the FIR filter, enter the pointer to the coefficients as NULL.
< p class = func > < span class = keyword > setSampleRate_Hz< / span > (< strong > float32_t< / strong > sampleRate_Hz)< / p >
< p class = desc > Enter sample rate, as float32_t.
It applies to this class only.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_random
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > BFSK_snr
< / p >
< h3 > Notes< / h3 >
< p > This modulator includes a lowpass filter on the input bit data.
This can be very effective in restricting the bandwidth of the BFSK output.
This filter can be None (default) or an arbitrary FIR filter.
< / p >
< p > Parity is not yet implemented.< / p >
< / script >
< script type = "text/x-red" data-template-name = "radioBFSKModulator_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "RadioFT8Modulator_F32" >
<!-- ============ RadioFT8Modulator_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Generates and transmits the eight-tone frequency shift keyed waveform
for the WSJT mode called FT8.
The data is provided by an ASCII string. A subset of possible FT8
messages is supported. All elements of the FT8 waveform are provided
including spectral confinement.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > FT8 transmit audio or I-F< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setSampleRate_Hz< / span >
(< strong > const float32_t< / strong > &fs_Hz); < / p >
< p class = desc > The two values are 48000.0 and 96000.0. < / p >
< p class = func > < span class = keyword > ft8Initialize< / span > ();< / p >
< p class = desc > This computes several filters that are needed.
IMPORTANT: Before calling this initialize function, set the audio sampling rate.< / p >
< p class = func > < span class = keyword > FT8TransmitBusy< / span > ();< / p >
< p class = desc > Returns < strong > bool< / strong > true if transmission is still active (a 12.96 second period).
Returns false if new data can be loaded.< / p >
< p class = func > < span class = keyword > sendData< / span >
(< strong > char*< / strong > data, < strong > int16_t< / strong > i3, < strong > int16_t< / strong > n3,
< strong > int16_t< / strong > specialCase);< / p >
< p class = desc > This defines the data to be sent and also triggers the starting time.
The parameter data takes a string, such as
"K1ABC W9XYZ RR73". The descriptors, i3 and n3 are needed to define all possible FT8 messages.
Because of the current message capability (standard QSO and free text)
the i3 and n3 are not needed. The specialCase are:
specialCase==0 is not special at all. It converts the message to
tones and transmits the 81 tones in FT8 format.
specialCase==1 allows running of the message-to-tone conversion without
starting the transmission of tones. Results are in tones[].
specialCase==2 starts the transmission of tones[]
without doing a message-to-tone conversion as part of the function call. < / p >
< p class = func > < span class = keyword > amplitude< / span > (< strong > float32_t< / strong > a);< / p >
< p class = desc > Sets a, the zero-to-peak amplitude of the transmit signal.
No return value.< / p >
< p class = func > < span class = keyword > frequency< / span > (< strong > float32_t< / strong > f);< / p >
< p class = desc > Sets f, the base, lowest, frequency of the FT8 waveform.
The occupied bandwidth is a few Hz below f and about 50 Hz above f.
No return value.< / p >
< p class = func > < span class = keyword > cancelTransmit< / span > ();< / p >
< p class = desc > Cancels the current transmission, following the current 128 sample period,
if active. This, of course, does not control PTT. No return value.< / p >
< p class = func > < span class = keyword > setSampleRate_Hz< / span > (< strong > float32_t< / strong > sampleRate_Hz)< / p >
< p class = desc > Enter sample rate, as float32_t.
It applies to this class only.
< / p >
< p class = func > < span class = keyword > getPayload< / span > ()< / p >
< p class = desc > Returns pointer to an array of 10 uint8_t holding the 77 bit payload.
< / p >
< p class = func > < span class = keyword > getTones< / span > ()< / p >
< p class = desc > Returns pointer to an array of 81 uint8_t holding the
tones to be transmitted (0, 7).
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FT8Transmit< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FT8Transmit7< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FT8Transmit7HP< / p >
< h3 > Notes< / h3 >
< p > See the library file radioFT8Modulator.h for much more information,
references, sample data, and most importantly, credits to the many contributors
upon which these FT8 library classes are based.< / p >
< p > This class does not provide true (absolute) clock timing. The sendData() function
should be called when it is time for a new 15-sec period transmission.
Audio output will start at the next 128 audio sample period. This
class does not control push-to-talk (PTT).< / p >
< p > This runs on T4.x only. The library class could run on T3.6, say, but the
end-of-receive-period processing would require many compromises to run
there. The reasonable path is to just use T4.0 or T4.1.< / p >
< / script >
< script type = "text/x-red" data-template-name = "RadioFT8Modulator_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "RadioFT8Demodulator_F32" >
<!-- ============ RadioFT8Demodulator_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Receives audio, containing multiple FT8 signals, and bundles them
up into 2048 sample float arrays, ready for an FFT. The system audio
sample rate is decimated to 6400 Hz and high rejection filtering is
provided with a final audio upper limit at 2800 Hz.
The full data array is updated and available every 0.16 second
to support 50% overlap for FFT windowing. The class also includes a
broad-band power detector for noise measurement.
< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > FT8 receive audio< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setSampleRate_Hz< / span >
(< strong > const float32_t< / strong > &fs_Hz); < / p >
< p class = desc > The two values are 48000.0 and 96000.0. < / p >
< p class = func > < span class = keyword > initialize< / span > ();< / p >
< p class = desc > This computes several filters that are needed.< / p >
< p class = func > < span class = keyword > getDataPtr< / span > ()< / p >
< p class = desc > Returns pointer to an array of 2048 float32_t (aka float)
holding latest received audio data. To support windowed FFT's,
this data provides 50% overlap. This means that, even though the
2048 data points require 0.32 seconds to acquire, a new set of data is
available every 0.16 seconds. < / p >
< p class = func > < span class = keyword > startDataCollect< / span > ();< / p >
< p class = desc > Begins a 14.7 second data collection period with 194
2048 float data arrays being made available.
No return value.< / p >
< p class = func > < span class = keyword > cancelDataCollect< / span > ();< / p >
< p class = desc > Cancels the 14.7 second data collection period.
No return value.< / p >
< p class = func > < span class = keyword > receivingData< / span > ();< / p >
< p class = desc > Returns < strong > bool< / strong > true if the 14.7 data collection
is in progress.< / p >
< p class = func > < span class = keyword > powerAvailable< / span > ();< / p >
< p class = desc > See the next function. Returns < strong > bool< / strong >
true if the power measurement is available. < / p >
< p class = func > < span class = keyword > readPower< / span > ();< / p >
< p class = desc > Returns the dB power level < strong > once< / strong >
per 128 samples at the 6.4kHz rate.
This can be used to provide a noise level measurement when signals are not
being transmitted. See the receive example listed below.< / p >
< p > Note that there are other fuctions available to support the W5BAA 128-int
data transfer. The details are in the radioFT8Demodulator_F32.h file.
Use of those functions requires compiling with "#define W5BAA_INTERFACE" in
the .h file.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > FT8Receive
< / p >
< h3 > Notes< / h3 >
< p > See the library file radioFT8Demodulator.h for much more information,
references, sample data, and most importantly, credits to the many contributors
upon which these FT8 library classes are based.< / p >
< p > This class does not provide true (absolute) clock timing.
The startDataCollect() function
should be called when it is time for a new 15-sec receive period.< / p >
< p > This runs on T4.x only. The library class could run on T3.6, say, but the
end-of-receive-period processing would require many compromises to run
there. The reasonable path is to just use T4.0 or T4.1.< / p >
< p > The receive example, along with the corresponding transmit examples
for radioFT8Modulator_F32, are complete basic capabilities, but
do not serve as a ham radio controller. The
< a href = "https://github.com/WB2CBA/W5BAA-FT8-POCKET-TERMINAL"
target="_blank">W5BAA Pocket project< / a >
https://github.com/WB2CBA/W5BAA-FT8-POCKET-TERMINAL
is an example of a complete control app. It does not use this library.< / p >
< / script >
< script type = "text/x-red" data-template-name = "RadioFT8Demodulator_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "radioModulatedGenerator_F32" >
<!-- ============ radioModulatedGenerator_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > A modulator to apply AM, PM or FM to a carrier sine wave. Outputs
can be single waveform, or a pair of waveforms of I and Q form for
external quadrature up conversion. The latter includes corrections for
amplitude and phase errors.
< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > AM Modulating Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > PM or FM Modulating Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Single or I Output Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Q Output Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > frequency< / span > (< strong > float< / strong > fCarrier);< / p >
< p class = desc > < / p >
< p > Sets the center carrier frequency, in Hz.< / p >
< p class = func > < span class = keyword > amplitude< / span > (< strong > float< / strong > ampl);< / p >
< p class = desc > < / p >
< p > Sets the carrier amplitude level. For AM, the peak output will be greater than this
level, reaching twice level at 100% modulation.< / p >
< p class = func > < span class = keyword > phase_r< / span > (< strong > float< / strong > ph);< / p >
< p class = desc > < / p >
< p > Sets the carrier starting phase in radians, 0 to 2*pi. Used with multiple
modulated generators to initialize the relative phase values. Stop interrupts before setting.< / p >
< p class = func > < span class = keyword > doModulation_AM_PM_FM< / span > (< strong > bool< / strong > doAM, < strong > bool< / strong > doPM, < strong > bool< / strong > doFM, < strong > bool< / strong > bothIQ);< / p >
< p class = desc > < / p >
< p > Selects modulation format. PM and FM cannot be used together. Otherwise the selection is flexible.
For instance, AM and PM can be used together for QAM modulation. bothIQ selects whether there is a single
modulated output (false) or a pair of quadrature outputs to drive external hardware (true).< / p >
< p class = func > < span class = keyword > phaseQ_I_r(< / span > (< strong > float< / strong > ph_IQ);< / p >
< p class = desc > < / p >
< p > Used with bothIQ==true to set the relative phase of the outputs. The default
is PI/2 corresponding to 90 degrees. This can correct for phase errors in external hardware.< / p >
< p class = func > < span class = keyword > amplitudeQI(< / span > (< strong > float< / strong > ampl_IQ);< / p >
< p class = desc > < / p >
< p > Used with bothIQ==true to set the relative amplitude of the outputs. The default
is 1.0. This can correct for amplitude errors in external hardware.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > AM_PM_FM.ino
< / p >
< h3 > Notes< / h3 > < p > For AM, 100% AM modulation corresponds
an input of -1.0 to 1.0, regardless of the
carrier amplitude setting. Overmodulation (more that 100%) results in peak
increases beyond twice amplitude, but full abrupt clipping at the
bottom zero point. Clipping on the top would be in an external block,
if desired.< / p >
< p > < pre class = "desc" >
Times: T3.6 update() block of 128 is about 53 microseconds, AM Single output.
T4.x update() block of 128 is about 20 microseconds AM Single output
T4.x update() block of 128 is about 35 microseconds AM I + Q outputs
For T4.x, FM is 1 or 2 microseconds faster than AM.
< / pre >
< / script >
< script type = "text/x-red" data-template-name = "radioModulatedGenerator_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "RadioIQMixer_F32" >
<!-- ============ RadioIQMixer_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > This quadrature mixer block is for both transmit and receive.
It is a basic building block with a pair of mixers along with a sin/cose
LO going to the mixers at the same frequency, but differing in phase
by 90 degrees (programmable). The LO's are included
in the block, but there are no post-mixing filters. Hardware
phase and amplitude error correction is included. < / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input I Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Input Q Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > I In-Phase Out< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Q Quadrature Output< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > frequency< / span > (< strong > float< / strong > fr);< / p >
< p class = desc > Sets Mixer LO frequency in Hz. The default is 1000 Hz.< / p >
< p class = func > < span class = keyword > iqmPhaseS< / span > (< strong > float< / strong > ps);< / p >
< p class = desc > This phase comes in the range (0, 2PI radians) keeping with C math functions.
This function allows multiple mixers to be phase coordinated (stop
interrupts when setting).< / p >
< p class = func > < span class = keyword > phaseS_C_r< / span > (< strong > float< / strong > pc);< / p >
< p class = desc > Sets the number of radians that the cosine LO leads the
sine LO. The default is PI/2 radians. This is used to correct hardware phase unbalance.
Not changeable if doSimple==true. < / p >
< p class = func > < span class = keyword > amplitudeC< / span > (< strong > float< / strong > g);< / p >
< p class = desc > Sets the gain, g, for the I channel.
The Q channel is always 1.0. This is used to correct hardware amplitude unbalance.
Not changeable if doSimple==true. The default is g=1.0.< / p >
< p class = func > < span class = keyword > void useTwoChannel< / span > (< strong > float32_t< / strong > gainOut);< / p >
< p class = desc >
Channel 0 (left) is the in-phase input I for twoCh true of false. Channel 1 (right) is Q for
complex 2-channel input (twoCh==true) and not used for twoChannel==false. Caution, never
use twoCh=false with two inputs. The default is twoCh==false.
< / p >
< p class = func > < span class = keyword > setGainOut< / span > (< strong > float< / strong > g);< / p >
< p class = desc > Sets the gain, g, for both the I and Q channels.
The default value is 1.0. It is available for either doSimple or not doSimple. The reason for this
function is that, is that the I and Q mixers have a gain of 0.5 for either sideband output. This function
can bring the net gain of the object to unity by setting gainOut to 2.0f. It can
also be used as a general gain control.
< / p >
< p class = func > < span class = keyword > useSimple< / span > (< strong > bool< / strong > simple);< / p >
< p class = desc > Faster if true, but no phase/amplitude adjustment. Default is doSimple = true.< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverPart1
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverPart2
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ReceiverSSB
< / p >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > CESSB
< / p >
< h3 > Notes< / h3 >
< p > There is provision for varying
the phase between the sine and cosine oscillators. The relative gain in the
I and Q channels is also programmable. This can be used to correct for errors in the
response of real hardware.< / p >
< P > The output levels are 0.5 times the input level, for each sideband. < / P >
< p > Time: T3.6, For an update of a 128 sample block, doSimple=1, 46 microseconds;
T4.0, For an update of a 128 sample block, doSimple=1, 20 microseconds< / p >
< / script >
< script type = "text/x-red" data-template-name = "RadioIQMixer_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "radioNoiseBlanker_F32" >
<!-- ============ radioNoiseBlanker_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Looks for wideband impulse noise and cuts off the flow of audio when an impulse
is detected. A delay in the audio allows anticipation of impulse noise.
The threshold of impulse detection is adjusted by the averaged
audio level. Parameters are programmable. Single Path or I-Q.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal 0< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Input Signal 1 (optional)< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Output Signal 0 with Blanking< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Output Sig 1 for Input 1< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > setNoiseBlanker< / span > (< strong > float< / strong > threshold, < strong > uint16_t< / strong > nAnticipation, < strong > uint16_t< / strong > nDecay);< / p >
< p class = desc > Sets the three parameters of the noise blanker.
The variable threshold adjusts the minimum level considered to be an impulse.
Anticipation is the number of samples of delay for the signal (1, 125)
and nDecay is the number of samples that are included in the blanked
period after the impulse has dropped below the threshold (1, 10).< / p >
< p class = func > < span class = keyword > enable< / span > (< strong > bool< / strong > e);< / p >
< p class = desc > If e==true the noise blanker is on and if e==false it
is off (default). This is the on/off switch.< / p >
< p class = func > < span class = keyword > useTwoChannel< / span > (< strong > bool< / strong > twoCh);< / p >
< p class = desc > If twoCh==true, input 1 becomes active and is blanked at the same
time as the signal of input 0. This is for I-Q receivers.< / p >
}
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestNoiseBlanker1
< / p >
< h3 > Notes< / h3 >
< p > An intermediate frequency (I-F signal) comes in with occassional
noise pulses. This block watches for
the pulses and turns off the I-F while the pulse exists. In order to
be as smart as possible this looks ahead by a number of samples, nAnticipation.
Likewise, the I-F is left off for nDecay samples after the pulse ends.
Various methods could be to be used to "turn off" the I-F,
including replacement with waveforms.
As of this initial write, zeros are used in the waveform. < / p >
< p > A threshold can be adjusted via setNoiseBlanker(). This is compared with the
average rectified voltage being received. If this is too small, like 1.5
or 2.0, we will be loosing good signals by blanking. If we set it too high, like 20.0,
we will not blank noise pulses. Experiments will find a good setting.
With a sine wave input and no impulse noise, the average rectified signal
should be about 0.637. To catch the top of that requires a threshold of
1/0.637 = 1.57. That would seem to be a very minimal threshold setting.< / p >
< / script >
< script type = "text/x-red" data-template-name = "radioNoiseBlanker_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT1024_F32" >
<!-- ============ AudioAnalyzeFFT1024_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does real input FFT of 1024 points. Output is magnitude
only in formats of RMS (same as I16 version,
power or dBFS (full scale). Output can be bin by bin or by a pointer to
the full output array. Multiple windowing options. Uses half-lenght FFT< / p >
< / div >
< p > March 2021: Streamlined processing and memory useage by going to half-lenght FFT.< / p >
< h3 > Boards Supported< / h3 >
< ul > Teensy 3.5
< li > Teensy 3.6
< li > Teensy 4.0
< li > Teensy 4.1
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Input Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 1023).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 1024 Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 1023). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning1024 (default)
AudioWindowBlackmanHarris1024
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser1024, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > putWindow< / span > (< strong > float< / strong > *pWin);< / p >
< p class = desc > Activates an INO provided window of 256 float numbers. This replaces
any window from WindowFunction(). pWin is a pointer to the window array.
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Sets the number of output powers that arre averaged for a single data set.
This is "non-coherent integration," or averaging. nAverage must be at least
1 with no reasonable upper limit.< / p >
< p class = func > < span class = keyword > getData< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 512 float outputs. This
can save 511 calls to read(). The data remains for about 10 milliseconds.< / p >
< p class = func > < span class = keyword > getWindow< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 1024 float points
that is the windowing function in use.< / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form:< / p >
< pre class = "desc" >
FFT_RMS 0 (default)
FFT_POWER 1
FFT_DBFS 2
< / pre >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT1024
< / p >
< h3 > Notes< / h3 >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by 1024^2/4 = 262144 without windowing.
Windowing loss cuts this down. The RMS level can grow to sqrt(262144)
or 512. The dBFS has been scaled to make this max value 0 dBFS by
removing 54.2 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The following times are for the most time
consuming of the updates, i.e., the "max" value.< / p >
< pre class = "desc" >
T3.6 Windowed, Power Out, 682 uSec
T3.6 Windowed, dBFS out, 834 uSec
T4.0 Windowed, Power Out, 54 uSec
T4.0 Windowed, dBFS Out, 203 uSec
< / pre >
< p > This class was improved in March 2021 by using a single 512-point
FFT to process the 1024 point "real" input to the FFT. This speeds the
process and also reduces the memory requirements for the FFT. Input and output
formats and functions remain unchanged.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT1024_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT256_IQ_F32" >
<!-- ============ AudioAnalyzeFFT256_IQ_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does complex (I-Q) input FFT of 256 points. Output is magnitude
only in formats of RMS (same as I16 version,
power or dBFS (full scale). Output can be bin by bin or by a pointer to
the output array. Multiple windowing options are available.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2< / li >
< li > Teensy 3.5< / li >
< li > Teensy 3.6< / li >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Q Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Overlap 0, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Overlap 0, Q Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Overlap 1, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Overlap 1, Q Signal< / td > < / tr >
< / table >
< p > Note: Audio outputs are not yet implemented. RMS, Power and dBFS outputs via
functions, below, are fully implemented.< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 255).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 256 Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 255). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning256
AudioWindowBlackmanHarris256
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser256, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > putWindow< / span > (< strong > float< / strong > *pWin);< / p >
< p class = desc > Activates an INO provided window of 256 float numbers. This replaces
any window from WindowFunction(). pWin is a pointer to the INO provided window array.
< p class = func > < span class = keyword > getData< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 256 float outputs. This
can save 255 calls to read(). The data remains for about 10 milliseconds.< / p >
< p class = func > < span class = keyword > getWindow< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 256 floating point numbers
that is the windowing function in use. This is mostly for diagnostics,
and not normally needed.< / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form, for example, myFFT.setOutputType(FFT_DBFS); The
options are< / p >
< pre class = "desc" >
FFT_RMS
FFT_POWER
FFT_DBFS
< / pre >
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Selects number of FFT outputs that are power averaged before
becoming available. This "non-coherent integration."< / p >
< p class = func > < span class = keyword > setXAxis< / span > (< strong > uint8_t< / strong > xAxis);< / p >
< p class = desc > Re arranges the output order of the frequencies corresponding
to the various bins. The least significant 2 bit are used. For sin input to
I and cosine input to Q, the following apply:
< pre class = "desc" >
If xAxis=0 f=fs/2 in middle, f=0 on right edge
If xAxis=1 f=fs/2 in middle, f=0 on left edge
If xAxis=2 f=fs/2 on left edge, f=0 in middle
If xAxis=3 f=fs/2 on right edgr, f=0 in middle
< / pre >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT256iq
< / p >
< h3 > Notes< / h3 >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by 256^2/4 = 65536 without windowing.
Windowing loss cuts this down. The RMS level can grow to sqrt(65536)
or 256. The dBFS has been scaled to make this max value 0 dBFS by
removing 42.1 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > The only block size supported by this FFT is 128 which is the normal
default block size.< / p >
<!--
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The following times are for the most time
consuming of the updates, i.e., the "max" value.< / p >
< pre class = "desc" >
T3.6 Windowed, RMS out, - uSec max
T3.6 Windowed, Power Out, - uSec max
T3.6 Windowed, dBFS out, - uSec max
No Window saves 60 uSec on T3.6 for any output.
T4.0 Windowed, RMS Out, - uSec
< / pre >
-->
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT256_IQ_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT1024_IQ_F32" >
<!-- ============ AudioAnalyzeFFT1024_IQ_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does complex (I-Q) input FFT of 1024 points. Output is magnitude
only in formats of RMS (same as I16 version,
power or dBFS (full scale). Output can be bin by bin or by a pointer to
the output array. Multiple windowing options are available.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.5< / li >
< li > Teensy 3.6< / li >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Q Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Overlap 0, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Overlap 0, Q Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Overlap 1, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Overlap 1, Q Signal< / td > < / tr >
< / table >
< p > Note: Audio outputs are not yet implemented. RMS, Power and dBFS outputs via
functions, below, are fully implemented.< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 1023).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 1024 Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 1023). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning1024
AudioWindowBlackmanHarris1024
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser1024, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > putWindow< / span > (< strong > float< / strong > *pWin);< / p >
< p class = desc > Activates an INO provided window of 1024 float numbers. This replaces
any window from WindowFunction(). pWin is a pointer to the INO provided window array.
< p class = func > < span class = keyword > getData< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 1024 float outputs. This
can save 255 calls to read(). The data remains for about 10 milliseconds.< / p >
< p class = func > < span class = keyword > getWindow< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 1024 floating point numbers
that is the windowing function in use. This is mostly for diagnostics,
and not normally needed.< / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form, for example, myFFT.setOutputType(FFT_DBFS); The
options are:
< pre class = "desc" >
FFT_RMS
FFT_POWER
FFT_DBFS
< / pre >
< / p >
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Selects number of FFT outputs that are power averaged before
becoming available. This "non-coherent integration."< / p >
< p class = func > < span class = keyword > setXAxis< / span > (< strong > uint8_t< / strong > xAxis);< / p >
< p class = desc > Re arranges the output order of the frequencies corresponding
to the various bins. The least significant 2 bit are used. For sin input to
I and cosine input to Q, the following apply:
< pre class = "desc" >
If xAxis=0 f=fs/2 in middle, f=0 on right edge
If xAxis=1 f=fs/2 in middle, f=0 on left edge
If xAxis=2 f=fs/2 on left edge, f=0 in middle
If xAxis=3 f=fs/2 on right edgr, f=0 in middle
< / pre >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT1024iq
< / p >
< h3 > Notes< / h3 >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by 1024^2/4 = 262144 without windowing.
Windowing loss cuts this down some. The RMS level can grow to sqrt(262144)
or 512. The dBFS has been scaled to make this max value 0 dBFS by
removing 54.2 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > The only block size supported by this FFT is 128 which is the normal
default block size.< / p >
<!--
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The following times are for the most time
consuming of the updates, i.e., the "max" value.< / p >
< pre class = "desc" >
T3.6 Windowed, RMS out, - uSec max
T3.6 Windowed, Power Out, - uSec max
T3.6 Windowed, dBFS out, - uSec max
No Window saves 60 uSec on T3.6 for any output.
T4.0 Windowed, RMS Out, - uSec
< / pre >
-->
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT1024_IQ_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT2048_IQ_F32" >
<!-- ============ AudioAnalyzeFFT2048_IQ_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does complex (I-Q) input FFT of 2048 points. Output is magnitude
only in formats of RMS (same as I16 version,
power or dBFS (full scale). Output can be bin by bin or by a pointer to
the output array. Multiple windowing options are available.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< p > < strong > Note: Teensy 3.x will NOT compile or run this class.< / strong > < / p >
< ul >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Q Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > Overlap 0, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 1< / td > < td > Overlap 0, Q Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 2< / td > < td > Overlap 1, I Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 3< / td > < td > Overlap 1, Q Signal< / td > < / tr >
< / table >
< p > Note: Audio outputs are not yet implemented. RMS, Power and dBFS outputs via
functions, below, are fully implemented.< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 2047).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 2048 Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 2047). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning2048
AudioWindowBlackmanHarris2048
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser2048, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > putWindow< / span > (< strong > float< / strong > *pWin);< / p >
< p class = desc > Activates an INO provided window of 2048 float numbers. This replaces
any window from WindowFunction(). pWin is a pointer to the INO provided window array.
< p class = func > < span class = keyword > getData< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 2048 float outputs. This
can save 255 calls to read(). The data remains for about 10 milliseconds.< / p >
< p class = func > < span class = keyword > getWindow< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 2048 floating point numbers
that is the windowing function in use. This is mostly for diagnostics,
and not normally needed.< / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form, for example, myFFT.setOutputType(FFT_DBFS); The
options are:
< pre class = "desc" >
FFT_RMS
FFT_POWER
FFT_DBFS
< / pre >
< / p >
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Selects number of FFT outputs that are power averaged before
becoming available. This "non-coherent integration."< / p >
< p class = func > < span class = keyword > setXAxis< / span > (< strong > uint8_t< / strong > xAxis);< / p >
< p class = desc > Re arranges the output order of the frequencies corresponding
to the various bins. The least significant 2 bit are used. For sin input to
I and cosine input to Q, the following apply:
< pre class = "desc" >
If xAxis=0 f=fs/2 in middle, f=0 on right edge
If xAxis=1 f=fs/2 in middle, f=0 on left edge
If xAxis=2 f=fs/2 on left edge, f=0 in middle
If xAxis=3 f=fs/2 on right edgr, f=0 in middle
< / pre >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT2048iq
< / p >
< h3 > Notes< / h3 >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by about a million.
The dBFS has been scaled to make this max value 0 dBFS by
removing 60.2 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > The only block size supported by this FFT is 128 which is the normal
default block size. Any sampling rate can be supported,
within maximum available time constraints.< / p >
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The Teensy 4.x was measured at 987 microseconds
per update with windowing and dBFS output. This can probably run with
96 kHz sample rates, but not 192 kHz.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT2048_IQ_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT4096_IQ_F32" >
<!-- ============ AudioAnalyzeFFT4096_IQ_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does complex (I-Q) input FFT of 4096 points. Output is magnitude
only in formats of RMS, power or dBFS (full scale).
Output can be bin by bin or by a pointer to
the output array. Multiple windowing options are available.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< p > < strong > Note: Teensy 3.x will NOT compile or run this class.< / strong > < / p >
< ul >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Q Input Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 4095).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 4096 Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 4095). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning4096
AudioWindowBlackmanHarris4096
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser4096, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > putWindow< / span > (< strong > float< / strong > *pWin);< / p >
< p class = desc > Activates an INO provided window of 4096 float numbers. This replaces
any window from WindowFunction(). pWin is a pointer to the INO provided window array.
< p class = func > < span class = keyword > getData< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 4096 float outputs. This
can save 255 calls to read(). The data remains for about 10 milliseconds.< / p >
< p class = func > < span class = keyword > getWindow< / span > ();< / p >
< p class = desc > Returns a pointer to an array of 4096 floating point numbers
that is the windowing function in use. This is mostly for diagnostics,
and not normally needed.< / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form, for example, myFFT.setOutputType(FFT_DBFS); The
options are:
< pre class = "desc" >
FFT_RMS
FFT_POWER
FFT_DBFS
< / pre >
< / p >
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Selects number of FFT outputs that are power averaged before
becoming available. This "non-coherent integration."< / p >
< p class = func > < span class = keyword > setXAxis< / span > (< strong > uint8_t< / strong > xAxis);< / p >
< p class = desc > Re arranges the output order of the frequencies corresponding
to the various bins. The least significant 2 bit are used. For sin input to
I and cosine input to Q, the following apply:
< pre class = "desc" >
If xAxis=0 f=fs/2 in middle, f=0 on right edge
If xAxis=1 f=fs/2 in middle, f=0 on left edge
If xAxis=2 f=fs/2 on left edge, f=0 in middle
If xAxis=3 f=fs/2 on right edgr, f=0 in middle
< / pre >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT4096iq
< / p >
< h3 > Notes< / h3 >
< p > < strong > Memory needs - < / strong > As FFTs get bigger they need more memory. This
4096 point FFT needs 64 F32 memories. Be sure to allocate more than this
in your INO sketch. In addition, at linking time, 98 kByte of RAM is added.
The T4.x can support this, but it is a major memory user. < / p >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by about a million.
The dBFS has been scaled to make this max value 0 dBFS by
removing 66.2 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > The only block size supported by this FFT is 128 which is the normal
default block size. Any sampling rate can be supported,
within maximum available time constraints.< / p >
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The Teensy 4.x was measured at 710 microseconds
per update with windowing and dBFS output. This can run with
96 kHz sample rates, but not 192 kHz. By using FFT_POWER output the maximum
processor time per update() is only 510 microseconds and, depending on other
processing, 192 kHz sample rate could be possible.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT4096_IQ_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeFFT4096_IQem_F32" >
<!-- ============ AudioAnalyzeFFT4096_IQem_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Does complex (I-Q) input FFT of 4096 points. Output is magnitude
only in formats of RMS, power or dBFS (full scale).
Output can be bin by bin. Multiple windowing options are available.
This EM version obtains all memory arrays from the INO.< / p >
< / div >
< p > < strong > As of 20 Feb 2022 this is Beta Test and changes may occur in the structure of the calls.< / strong > < / p >
< h3 > Boards Supported< / h3 >
< p > < strong > Note: Teensy 3.x will NOT compile or run this class.< / strong > < / p >
< ul >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > In 1< / td > < td > Q Input Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the FFT is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBin);< / p >
< p class = desc > Returns the output level for the specified nBin (0, 4095).
Bin 0 is DC and the bins are spaced at the sampling frequency divided
by 4096 in Hz.< / p >
< p class = func > < span class = keyword > read< / span > (< strong > int< / strong > nBinFirst, < strong > int< / strong > nBinLast);< / p >
< p class = desc > Returns the power sum for the specified range of bins
numbered (0, 4095). This has the effect of creating a new bin with greater
width.< / p >
< p class = func > < span class = keyword > windowFunction< / span > (< strong > int< / strong > win);< / p >
< p class = desc > Sets the windowing function. Instead of calling by number,
these can be called by the following defined names: < / p >
< pre class = "desc" >
AudioWindowNone
AudioWindowHanning4096
AudioWindowBlackmanHarris4096
< / pre >
< p class = func > < span class = keyword > windowFunction< / span > (AudioWindowKaiser4096, < strong > float< / strong > kdb);< / p >
< p class = desc > Sets the Kaiser window with the first sidelobe kdb
below the peak. The sidelobes continue to drop going away from a sine-wave
carrier. This is a very flexible and useful windowing function. < / p >
< p class = func > < span class = keyword > setOutputType< / span > (< strong > int< / strong > nType);< / p >
< p class = desc > Selects the output form, for example, myFFT.setOutputType(FFT_DBFS); The
options are:
< pre class = "desc" >
FFT_RMS
FFT_POWER
FFT_DBFS
< / pre >
< / p >
< p class = func > < span class = keyword > setNAverage< / span > (< strong > int< / strong > nAverage);< / p >
< p class = desc > Selects number of FFT outputs that are power averaged before
becoming available. This "non-coherent integration."< / p >
< p class = func > < span class = keyword > setXAxis< / span > (< strong > uint8_t< / strong > xAxis);< / p >
< p class = desc > Re arranges the output order of the frequencies corresponding
to the various bins. The least significant 2 bit are used. For sin input to
I and cosine input to Q, the following apply:
< pre class = "desc" >
If xAxis=0 f=0 in middle, f=fs/2 on left edge
If xAxis=1 f=0 in middle, f=fs/2 on right edge
If xAxis=2 f=0 on right edge, f=fs/2 in middle
If xAxis=3 f=0 on left edge, f=fs/2 in middle
< / pre >
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > TestFFT4096iqEM
< / p >
< h3 > Notes< / h3 >
< p > < strong > Memory needs - < / strong > As FFTs get bigger they need more memory. This
4096 point FFT needs 64 F32 memories. Be sure to allocate more than this
in your INO sketch. In addition, at linking time, 58 kByte of .INO supplied
RAM is added without use of power averaging and 74 kBytes if it is used.
The T4.x can support this, but it is a major memory user. < / p >
< p > < strong > Scaling - < / strong >
Full scale for floating point DSP is a nebulous concept. Normally the
full scale is -1.0 to +1.0. This is an unscaled FFT and for a sine
wave centered in frequency on a bin and of FS amplitude, the power
at that center bin will grow by about a million.
The dBFS has been scaled to make this max value 0 dBFS by
removing 66.2 dB. With floating point, the dynamic range is maintained
no matter how it is scaled, but scaling needs to be considered
when building the INO.< / p >
< p > The only block size supported by this FFT is 128 which is the normal
default block size. Any sampling rate can be supported,
within maximum available time constraints.< / p >
< p > For a 44.1 kHz sample rate, it takes 2903 microseconds (uSec) to
collect 128 data points. The sum total of all Audio processing
must be less than this for every update cycle, or overrun will occur
with severe consequences. For the FFT, the processing time used per
udate varies cyclicly. The Teensy 4.x was measured at 710 microseconds
per update with windowing and dBFS output. This can run with
96 kHz sample rates, but not 192 kHz. By using FFT_POWER output the maximum
processor time per update() is only 510 microseconds and, depending on other
processing, 192 kHz sample rate could be possible.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeFFT4096em_IQ_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeToneDetect_F32" >
<!-- ============ AudioAnalyzeToneDetect_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Parallels the Teensy Audio class that detects sine wave tones. Uses the Goertzel
algorithm and has programmable tone detection time.< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2< / li >
< li > Teensy 3.5< / li >
< li > Teensy 3.6< / li >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > frequency< / span > (< strong > float< / strong > freq, < strong > int< / strong > cycles);< / p >
< p class = desc > Sets the frequency fr for tone detection, in Hz, and the number of cycles to be analyzed.< / p >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > returns < strong > bool< / strong > true if the tone detection is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > read< / span > ();< / p >
< p class = desc > Returns the output rms level.< / p >
< p class = func > < span class = keyword > threshold< / span > (< strong > float< / strong > thresh);< / p >
< p class = desc > Sets the threshold for the bool() function. Range of 0.0 to 1.0.< / p >
< p class = func > < span class = keyword > bool< / span > ();< / p >
< p class = desc > Returns true if rms level is above threshold..< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ToneDetect1
< / p >
< h3 > Notes< / h3 >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeToneDetect_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< div >
< script type = "text/x-red" data-help-name = "AudioAnalyzeCTCSS_F32" >
<!-- ============ AudioAnalyzeCTCSS_F32 ========= -->
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Specific to the CTCSS sub-audible tone detection. Uses the Goertzel
algorithm, can be programmed for any tone in the 67 to 254 Hz range.
See analyze_CTCSS_F32.h for much information.
< / p >
< / div >
< h3 > Boards Supported< / h3 >
< ul >
< li > Teensy 3.2< / li >
< li > Teensy 3.5< / li >
< li > Teensy 3.6< / li >
< li > Teensy 4.0< / li >
< li > Teensy 4.1< / li >
< / ul >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > I Input Signal< / td > < / tr >
< tr class = odd > < td align = center > Out 0< / td > < td > O Output Signal< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > initCTCSS< / span > (< strong > void< / strong > );< / p >
< p class = desc > Run this to initialize the CTCSS tone detector This function is < strong > required.< / strong >
< p class = func > < span class = keyword > frequency< / span > (< strong > float< / strong > freq, < strong > int< / strong > tMeas);< / p >
< p class = desc > Sets the frequency freq for tone detection, in Hz between
67.0 and 254.1 Hz, and the number of milliseconds to be analyzed. The defaults are
103.5 Hz and 300 milliseconds. The parameter tMeas is optional.< / p >
< p class = func > < span class = keyword > readTonePower< / span > (< strong > void< / strong > );< / p >
< p class = desc > Returns the power measured for the narrow-band Goertzel tone filter as a < strong > float< / strong > .< / p >
< p class = func > < span class = keyword > readRefPower< / span > (< strong > void< / strong > );< / p >
< p class = desc > Returns the power measured for the 67 to 254 Hz filter as a < strong > float< / strong > . The
tone frequency is notched out for this measurement.< / p >
< p class = func > < span class = keyword > readTonePresent< / span > (< strong > uint16_t< / strong > what);< / p >
< p class = desc > Returns a < strong > bool< / strong > true or false to indicate whether thecurrent reading
is above or below the threshold condition set by "what". Values for < strong > uint16_t< / strong >
parameter "what" are the following pre-defined values:< / p >
< pre class = "desc" >
isAbsThreshold
isRelThreshold
isBothThreshold
< / pre >
< p class = func > < span class = keyword > thresholds< / span > (< strong > float< / strong > levelAbs, < strong > float< / strong > levelRel);< / p >
< p class = desc > The parameter levelAbs sets the threshold for comparing pTone with to estimate the presence
of a CTCSS tone. The parameter levelRel sets a similar threshold on the quotient PowerTone/PowerRef.
Setting either threshold to 0.0f disables that threshold test.< / p >
< p class = func > < span class = keyword > available< / span > (< strong > void< / strong > );< / p >
< p class = desc > returns < strong > bool< / strong > true if the tone detection is complete,
otherwise returns false.< / p >
< p class = func > < span class = keyword > setCTCSS_BP< / span > (< strong > float*< / strong > filterCoeffs);< / p >
< p class = desc > This function sets the IIR coefficients for the 67 to 254 Hz bandpass filter.
Set filterCoeffs to NULL to use pre-determined coefficients for 44, 48,96 or 100 KHz.
Alternatively build your own using info in analyze_CTCSS_F32.h. < / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > ToneDetect3
< / p >
< h3 > Notes< / h3 >
< p > Two outputs are available, TonePower and RefPower. TonePower is the output
of the Goertzel sharply tuned filter and is the conventional CTCSS output
that is compared to a threshold. RefPower measures the power in the entire
67 to 254 Hz sub-audible band, except at the tone frequency. < / p >
< p > Measurements are repeated every tMeas milliseconds, automatically
and decisions of tone presence are updated.< / p >
< p > Each update of an 128-input block takes about 42 uSec on a Teensy 3.6.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeCTCSS_F32" > >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
<!-- ============ AudioAnalyzePeak_F32 ========= -->
< script type = "text/x-red" data-help-name = "AudioAnalyzePeak_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Track the signal peak amplitude. Very useful for simple
audio level response projects, and general troubleshooting.
Almost same class as in Teensy Library but this uses F32 floating point audio input.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal to analyze< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > Returns true each time new peak data is available.
< / p >
< p class = func > < span class = keyword > read< / span > ();< / p >
< p class = desc > Read the highest peak amplitude value since the last read.
< / p >
< p class = func > < span class = keyword > readPeakToPeak< / span > ();< / p >
< p class = desc > Read the highest peak-to-peak amplitude since the last read.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > AudioTestPeakRMS
< / p >
< h3 > Notes< / h3 >
< p > With floating point, F32, audio, there is generally no maximum level that
represents full scale, as there is with Teensy Audio I16. The
exception is at the input and output points where there is
an interface with an integer device. The F32 scaling at these points is set to
-1.0 and +1.0 corresponding to I16 -32768 and 32767.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzePeak_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
<!-- ============ AudioAnalyzeRMS_F32 ========= -->
< script type = "text/x-red" data-help-name = "AudioAnalyzeRMS_F32" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Track the signal RMS amplitude. Useful for
audio level response projects, and general troubleshooting.
Almost same class as in Teensy Library but this uses F32 floating point audio input.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< table class = doc align = center cellpadding = 3 >
< tr class = top > < th > Port< / th > < th > Purpose< / th > < / tr >
< tr class = odd > < td align = center > In 0< / td > < td > Signal to analyze< / td > < / tr >
< / table >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > available< / span > ();< / p >
< p class = desc > Returns true if new RMS data is available.
< / p >
< p class = func > < span class = keyword > read< / span > ();< / p >
< p class = desc > Read the new RMS value.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > OpenAudio_ArduinoLibrary > AudioTestPeakRMS
< / p >
< h3 > Notes< / h3 >
< p > With floating point, F32, audio, there is generally no maximum level that
represents full scale, as there is with Teensy Audio I16. The
exception is at the input and output points where there is
an interface with an integer device. The F32 scaling at these points is set to
-1.0 and +1.0 corresponding to I16 -32768 and 32767.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioAnalyzeRMS_F32" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
<!-- ========== AudioControlSGTL5000 ============= -->
< script type = "text/x-red" data-help-name = "AudioControlSGTL5000" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control the SGTL5000 chip on the
< a href = "http://www.pjrc.com/store/teensy3_audio.html" target = "_blank" > audio shield< / a > .
SGTL5000 is always used in slave mode, where Teensy controls
all I2S timing.
< / p >
< p align = center > < img src = "img/sgtl5000closeup.jpg" > < / p >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate i2s objects
are used to send and receive audio data. I2S master mode objects
must be used, because this object configures the SGTL5000 in slave
mode, where it depends on Teensy to provide all I2S clocks.
This object controls
how the SGTL5000 will use those I2S audio streams.< / p >
< h3 > Functions< / h3 >
< p > These are the most commonly used SGTL5000 functions.< / p >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Start the SGTL5000. This function should be called first.
< / p >
< p class = func > < span class = keyword > volume< / span > (level);< / p >
< p class = desc > Set the headphone volume level. Range is 0 to 1.0, but
0.8 corresponds to the maximum undistorted output for a full scale
signal. Usually 0.5 is a comfortable listening level. The line
level outputs are < em > not< / em > changed by this function.
< / p >
< p class = func > < span class = keyword > inputSelect< / span > (input);< / p >
< p class = desc > Select which input to use: AUDIO_INPUT_LINEIN or AUDIO_INPUT_MIC.
< / p >
< p class = func > < span class = keyword > micGain< / span > (dB);< / p >
< p class = desc > When using the microphone input, set the amplifier gain.
The input number is in decibels, from 0 to 63.
< / p >
< h3 > Signal Levels< / h3 >
< p > The default signal levels should be used for most applications,
but these functions allow you to customize the analog signals.< / p >
< p class = func > < span class = keyword > muteHeadphone< / span > ();< / p >
< p class = desc > Silence the headphone output.
< / p >
< p class = func > < span class = keyword > unmuteHeadphone< / span > ();< / p >
< p class = desc > Turn the headphone output on.
< / p >
< p class = func > < span class = keyword > muteLineout< / span > ();< / p >
< p class = desc > Silence the line level outputs.
< / p >
< p class = func > < span class = keyword > unmuteLineout< / span > ();< / p >
< p class = desc > Turn the line level outputs on.
< / p >
< p class = func > < span class = keyword > lineInLevel< / span > (both);< / p >
< p class = desc style = "padding-bottom:0.2em;" > Adjust the sensitivity of the line-level inputs.
Fifteen settings are possible:
< / p >
< pre class = "desc" >
0: 3.12 Volts p-p
1: 2.63 Volts p-p
2: 2.22 Volts p-p
3: 1.87 Volts p-p
4: 1.58 Volts p-p
5: 1.33 Volts p-p (default)
6: 1.11 Volts p-p
7: 0.94 Volts p-p
8: 0.79 Volts p-p
9: 0.67 Volts p-p
10: 0.56 Volts p-p
11: 0.48 Volts p-p
12: 0.40 Volts p-p
13: 0.34 Volts p-p
14: 0.29 Volts p-p
15: 0.24 Volts p-p
< / pre >
< p class = func > < span class = keyword > lineInLevel< / span > (left, right);< / p >
< p class = desc > Adjust the sensitivity of the line-level inputs, with different
settings for left and right. The same 15 settings are available.
< / p >
< p class = func > < span class = keyword > lineOutLevel< / span > (both);< / p >
< p class = desc style = "padding-bottom:0.2em;" > Adjust the line level output
voltage range. The following settings are possible:
< / p >
< pre class = "desc" >
13: 3.16 Volts p-p
14: 2.98 Volts p-p
15: 2.83 Volts p-p
16: 2.67 Volts p-p
17: 2.53 Volts p-p
18: 2.39 Volts p-p
19: 2.26 Volts p-p
20: 2.14 Volts p-p
21: 2.02 Volts p-p
22: 1.91 Volts p-p
23: 1.80 Volts p-p
24: 1.71 Volts p-p
25: 1.62 Volts p-p
26: 1.53 Volts p-p
27: 1.44 Volts p-p
28: 1.37 Volts p-p
29: 1.29 Volts p-p (default)
30: 1.22 Volts p-p
31: 1.16 Volts p-p
< / pre >
< p class = func > < span class = keyword > lineOutLevel< / span > (left, right);< / p >
< p class = desc > Adjust the line level outout voltage range, with separate
settings for left and right. The same settings (13 to 31) are available.
< / p >
< h3 > Signal Conditioning< / h3 >
< p > Usually these digital signal conditioning features should be left at their
default settings.
< / p >
< p class = func > < span class = keyword > adcHighPassFilterFreeze< / span > ();< / p >
< p class = desc > By default, the analog input (either line-level inputs or mic)
is high-pass filtered, to remove any DC component. This function
freezes the filter, so the current DC component is still substracted, but
the filter stops tracking any DC or low frequency changes.
< / p >
< p class = func > < span class = keyword > adcHighPassFilterDisable< / span > ();< / p >
< p class = desc > Completely disable the analog input filter. DC and sub-audible
low frequencies are allowed to enter the digital signal. This
< a href = "http://openaudio.blogspot.com/2017/03/teensy-audio-board-self-noise.html" > may
reduce noise< / a > in some cases.
< / p >
< p class = func > < span class = keyword > adcHighPassFilterEnable< / span > ();< / p >
< p class = desc > Turn the DC-blocking filter back on, if disabled, or
allows it to resume tracking DC and low frequency changes, if
previously frozen. This is the default setting.
< / p >
< p class = func > < span class = keyword > dacVolume< / span > (both);< / p >
< p class = desc > Normally output volume should be used with volume(), which
changes the analog gain in the headphone amplifier. This function
on the other hand controls digital attenuation before conversion to analog, which
reduces resolution, but allows another fine control of output
signal level. The ranges is 0 to 1.0, with the default (no digital attenuation)
at 1.0.
< / p >
< p class = desc > dacVolume uses zero-crossing detect to avoid clicks, and graceful
ramping is handled by the chip so that a new volume may be set directly in
a single call.
< / p >
< p class = func > < span class = keyword > dacVolume< / span > (left, right);< / p >
< p class = desc > Adjust the digital output volume separately on left and
right channels.
< / p >
< p class = func > < span class = keyword > dacVolumeRamp< / span > ();< / p >
< p class = desc > Enable graceful volume ramping. The dacVolume adjusts gradually using
an exponential curve. Pops or loud clicks are avoided when making large
changes in volume level.
< / p >
< p class = func > < span class = keyword > dacVolumeRampLinear< / span > ();< / p >
< p class = desc > Enable faster volume ramping. A slight click may be heard during a
large volume change.
< / p >
< p class = func > < span class = keyword > dacVolumeRampDisable< / span > ();< / p >
< p class = desc > Do not use any gradual ramping. The zero cross feature still helps
for small changes, but large volume changes may produce a pop or click.
< / p >
< h3 > Audio Processor< / h3 >
< p > The optional digital audio processor is capable of implementing
one or more of: automatic volume control, surround sound control,
bass enhancement, and tonal adjustments (either a
simple tone control, or a parametric equalizer, or a graphic equalizer),
in that order.
< / p >
< p > These signal processing features are implemented in the SGTL5000 chip,
so they do not consume CPU time on Teensy. However, the order of
these processes is fixed in the hardware.
< / p >
< p > It is good practice to mute the outputs before enabling or disabling
the Audio Processor, to avoid clicks or thumps.
< / p >
< p class = func > < span class = keyword > audioPreProcessorEnable< / span > ();< / p >
< p class = desc > Enable the audio processor to pre-process the input
(from either line-level inputs or microphone) before it's sent
to Teensy by I2S.
< / p >
< p class = func > < span class = keyword > audioPostProcessorEnable< / span > ();< / p >
< p class = desc > Enable the audio processor to post-process Teensy's
I2S output before it's turned into analog signals for the
headphones and/or line level outputs.
< / p >
< p class = func > < span class = keyword > audioProcessorDisable< / span > ();< / p >
< p class = desc > Disable the audio processor.
< / p >
< p class = func > < span class = keyword > autoVolumeControl< / span > (maxGain, response, hardLimit, threshold, attack, decay);< / p >
< p class = desc > Configures the auto volume control, which is implemented as a compressor/expander
or hard limiter. < em > maxGain< / em > is the maximum gain that can be applied for expanding, and
can take one of three values: 0 (0dB), 1 (6.0dB) and 2 (12dB). Values greater than 2 are treated
as 2. < em > response< / em > controls the integration time for the compressor and can take
four values: 0 (0ms), 1 (25ms), 2 (50ms) or 3 (100ms). Larger values average the volume
over a longer time, allowing short-term peaks through.
< / p >
< p class = desc > If < em > hardLimit< / em > is 0, a 'soft
knee' compressor is used to progressively compress louder values which are near to or above the
threashold (the louder they are, the greater the compression). If it is 1, a hard compressor
is used (all values above the threashold are the same loudness). The < em > threashold< / em > is specified
as a float in the range 0dBFS to -96dBFS, where -18dBFS is a typical value.
< em > attack< / em > is a float controlling the rate of decrease in gain when the signal is over
threashold, in dB/s. < em > decay< / em > controls how fast gain is restored once the level
drops below threashold, again in dB/s. It is typically set to a longer value than attack.
< / p >
< p class = func > < span class = keyword > autoVolumeEnable< / span > ();< / p >
< p class = desc > Enables auto volume control, using the previously specified settings.
< / p >
< p class = func > < span class = keyword > autoVolumeDisable< / span > ();< / p >
< p class = desc > Disables auto volume control.
< / p >
< p class = func > < span class = keyword > surroundSoundEnable< / span > ();< / p >
< p class = desc > Enable virtual surround processing, to give a broader and
deeper stereo image (even with mono input).
< / p >
< p class = func > < span class = keyword > surroundSoundDisable< / span > ();< / p >
< p class = desc > Disable virtual surround processing. Before disabling, ramp up
the width to maximum to avoid pops.
< / p >
< p class = func > < span class = keyword > surroundSound< / span > (width);< / p >
< p class = desc > Configures virtual surround width from 0 (mono) to 7 (widest).
< / p >
< p class = func > < span class = keyword > surroundSound< / span > (width, select);< / p >
< p class = desc > Configures virtual surround width from 0 (mono) to 7 (widest).
< em > select< / em > may be set to 1 (disable), 2 (mono input) or 3 (stereo input).
< / p >
< p class = func > < span class = keyword > enhanceBassEnable< / span > ();< / p >
< p class = desc > Enable bass enhancement. A mono, low-pass filtered copy of
the original stereo signal has bass levels boosted and is then mixed back into
the stereo signal, which is then optionally high pass filtered (to remove
inaudible subsonic frequencies).
< / p >
< p class = func > < span class = keyword > enhanceBassDisable< / span > ();< / p >
< p class = desc > Disable bass enhancement. Before disabling, ramp down the bass
enhancement level to zero.
< / p >
< p class = func > < span class = keyword > enhanceBass< / span > (lr_lev, bass_lev);< / p >
< p class = desc > Configures the bass enhancement by setting the levels of the
original stereo signal and the bass-enhanced mono level which will be mixed together.
There is no high-pass filter.
< / p >
< p class = desc > When changing bass level, call this function repeatedly to ramp up or down the bass in
steps of 0.5dB, to avoid pops.
< / p >
< p class = func > < span class = keyword > enhanceBass< / span > (lr_lev, bass_lev, hpf_bypass, cutoff);< / p >
< p class = desc > Configures the bass enhancement by setting the levels of the
original stereo signal and the bass-enhanced mono level which will be mixed together.
The high-pass filter may be enabled (0) or bypassed (1). The cutoff frequency is specified
as follows:
< / p >
< pre class = "desc" >
value frequency
0 80Hz
1 100Hz
2 125Hz
3 150Hz
4 175Hz
5 200Hz
6 225Hz
< / pre >
< p class = desc > When changing bass level, call this function repeatedly to ramp up or down the bass in
steps of 0.5dB, to avoid pops.
< / p >
< p class = func > < span class = keyword > eqSelect< / span > (n);< / p >
< p class = desc > Selects the type of frequency control, where < em > n< / em > is
one of< / p >
< p class = desc > < b > FLAT_FREQUENCY (0)< / b > < br >
Equalizers and tone controls disabled, flat frequency response.< / p >
< p class = desc > < b > PARAMETRIC_EQUALIZER (1)< / b > < br >
Enables the 7-band parametric equalizer, thus disabling the
tone controls and graphic equalizer.< / p >
< p class = desc > < b > TONE_CONTROLS (2)< / b > < br >
Enables bass and treble tone controls, disabling the parametric
equalization and graphic equalizer.< / p >
< p class = desc > < b > GRAPHIC_EQUALIZER (3)< / b > < br >
Enables the five-band graphic equalizer, disabling the parametric
equalization and tone controls.< / p >
< p class = func > < span class = keyword > eqBands< / span > (bass, treble);< / p >
< p class = desc > Configures bass and treble tone controls, which are
implemented as one second order low pass filter (bass) in parallel with
one second order high pass filter (treble).
< / p >
< p class = desc > When changing bass or treble level, call this function repeatedly to ramp
up or down the level in steps of 0.04 (=0.5dB) or so, to avoid pops.
< / p >
< p class = func > < span class = keyword > eqBands< / span > (bass, mid_bass, midrange, mid_treble, treble);< / p >
< p class = desc > Configures the graphic equalizer. It is implemented by five parallel,
second order biquad filters with fixed frequencies of 115Hz, 330Hz, 990Hz, 3kHz,
and 9.9kHz. Each band has a range of adjustment from 1.00 (+12dB) to -1.00 (-11.75dB).
< / p >
< p class = func > < span class = keyword > eqBand< / span > (bandNum, n);< / p >
< p class = desc > Configures the gain or cut on one band in the graphic equalizer.
< em > bandnum< / em > can range from 1 to 5; < em > n< / em > is a float in the range 1.00 to -1.00.
< / p >
< p class = desc > When changing a band, call this function repeatedly to ramp up the gain in steps of 0.5dB,
to avoid pops.
< / p >
< p class = func > < span class = keyword > eqFilter< / span > (filterNum, filterParameters);< / p >
< p class = desc > Configurs the parametric equalizer. The number of filters (1 to 7)
is specified along with a pointer to an array of filter coefficients.
The parametric equalizer is implemented using 7 cascaded, second order bi-quad
filters whose frequencies, gain, and Q may be freely configured, but each filter
can only be specified as a set of filter coefficients.
< / p >
< p class = func > < span class = keyword > eqFilterCount< / span > (n);< / p >
< p class = desc > Enables zero or more of the already enabled parametric filters.
< / p >
< h3 > Examples< / h3 >
< p > Nearly all of the Teensy Audio and OpenAudio_ArduinoLibrary (F32 floating point)
library's examples use this object. These examples
for the Teensy Audio Library demonstrate its special features.
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > PassThroughStereo
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > dap_bass_enhance
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > dap_avc_agc
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > balanceDAC
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > balanceHP
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > CalcBiquadToneControlDAP
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > SGTL5000 > VolumeRamp
< / p >
< h3 > Notes< / h3 >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlSGTL5000" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioControlWM8731" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control a WM8731 chip in slave mode, where it receives all clocks from Teensy< / p >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate i2s objects
are used to send and receive audio data. I2S master mode objects
must be used, since this control object configures the WM8731 into
slave mode.
< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Turn on the WS8731.
< / p >
< p class = func > < span class = keyword > disable< / span > ();< / p >
< p class = desc > not implemented
< / p >
< p class = func > < span class = keyword > volume< / span > (level);< / p >
< p class = desc > Set the headphone volume level. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > inputLevel< / span > (level);< / p >
< p class = desc > Adjust the line level input gain. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > inputSelect< / span > (input);< / p >
< p class = desc > Select which input to use: AUDIO_INPUT_LINEIN or AUDIO_INPUT_MIC.
< / p >
<!--
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio >
< / p >
-->
< h3 > Notes< / h3 >
< p > < / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlWM8731" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioControlWM8731master" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control a WM8731 chip in master mode, where it controls all I2S timing.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate i2s objects
are used to send and receive audio data. I2S slave mode objects
must be used, since this control object configures the WM8731 into
master mode.
< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Turn on the WS8731, in I2S Master mode. I2S slave mode
communication must be used by Teensy.
< / p >
< p class = func > < span class = keyword > disable< / span > ();< / p >
< p class = desc > not implemented
< / p >
< p class = func > < span class = keyword > volume< / span > (level);< / p >
< p class = desc > Set the headphone volume level. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > inputLevel< / span > (level);< / p >
< p class = desc > Adjust the line level input gain. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > inputSelect< / span > (input);< / p >
< p class = desc > Select which input to use: AUDIO_INPUT_LINEIN or AUDIO_INPUT_MIC.
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > HardwareTesting > WM8731MikroSine
< / p >
< h3 > Notes< / h3 >
< p > The WM8731 will implement a sample rate of its crystal frequency divided by 256.
To get the 44.1 kHz sample rate the Teensy Audio Library expects, an
11.2896 MHz crystal should be used.
< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlWM8731master" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioControlAK4558" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control the AK4558 chip on the < a href = "https://hackaday.io/project/8567-hifi-audio-codec-module" target = "_blank" > HiFi Audio CODEC Module< / a >
in slave mode, where the Teensy controls all I2S timing.< / p >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate I2S objects
are used to send and receive audio data.
< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Enables the CODEC to work with 44.1 KHz - 16 bit data. This function does not enable the ADC/DAC modules.
< / p >
< p class = func > < span class = keyword > enableIn< / span > ();< / p >
< p class = desc > Enables the ADC module.
< / p >
< p class = func > < span class = keyword > enableOut< / span > ();< / p >
< p class = desc > Enables the DAC module.
< / p >
< p class = func > < span class = keyword > disable< / span > ();< / p >
< p class = desc > Disables the ADC and the DAC modules.
< / p >
< p class = func > < span class = keyword > disableIn< / span > ();< / p >
< p class = desc > Disable the ADC module.
< / p >
< p class = func > < span class = keyword > disableOut< / span > ();< / p >
< p class = desc > Disable the DAC module.
< / p >
< p class = func > < span class = keyword > volume< / span > (level);< / p >
< p class = desc > Accepts a float in range 0.0-1.0 and sets the line output volume accordingly.
< / p >
< p class = func > < span class = keyword > volumeLeft< / span > (level);< / p >
< p class = desc > Accepts a float in range 0.0-1.0 and sets the left line output volume accordingly.
< / p >
< p class = func > < span class = keyword > volumeRight< / span > (level);< / p >
< p class = desc > Accepts a float in range 0.0-1.0 and sets the right line output volume accordingly.
< / p >
< p class = func > < span class = keyword > inputLevel< / span > (level);< / p >
< p class = desc > NOT SUPPORTED BY THE AK4558
< / p >
< p class = func > < span class = keyword > inputSelect< / span > (input);< / p >
< p class = desc > not implemented yet
< / p >
< h3 > Examples< / h3 >
< p class = exam > File > Examples > Audio > HardwareTesting > AK4558 > PassthroughTest
< / p >
< p class = exam > File > Examples > Audio > HardwareTesting > AK4558 > SineOutTest
< / p >
< h3 > Notes< / h3 >
< p > TODO: Implement inputSelect() function to enable mono left, mono right, stereo operation.< / p >
< p > TODO: Implement ADC and DAC filters control.< / p >
< p > TODO: Implement DAC level attenuator attack rate modifier.< / p >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlAK4558" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioControlCS4272" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control the CS4272 chip on the < a href = "https://hackaday.io/project/5912-teensy-super-audio-board" target = "_blank" > Super Audio Board< / a > .
< / p >
< p > TODO: does this control object put the CS4272 into I2S master or slave mode< / p >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate I2S objects
are used to send and receive audio data.
< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Enables the CODEC to work with 44.1 KHz - 16 bit data. This function does not enable the ADC/DAC modules.
< / p >
< p class = func > < span class = keyword > volume< / span > (vol);< / p >
< p class = desc > Set the volume level. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > volume< / span > (left, right);< / p >
< p class = desc > Set the volume level. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > dacVolume< / span > (vol);< / p >
< p class = desc > Set the volume level. Range is 0 to 1.0. TODO: what's the
distinction between volume() and dacVolume()?
< / p >
< p class = func > < span class = keyword > dacVolume< / span > (left, right);< / p >
< p class = desc > Set the volume level. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > muteOutput< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< p class = func > < span class = keyword > unmuteOutput< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< p class = func > < span class = keyword > muteInput< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< p class = func > < span class = keyword > unmuteInput< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< p class = func > < span class = keyword > enableDither< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< p class = func > < span class = keyword > disableDither< / span > ();< / p >
< p class = desc > TODO: description
< / p >
< h3 > Hardware< / h3 >
< p > Pin 2 must be connected to the CS4272 reset. SDA & SCL are used for all control.
< / p >
< h3 > Notes< / h3 >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlCS4272" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< script type = "text/x-red" data-help-name = "AudioControlCS42448" >
< h3 > Summary< / h3 >
< div class = tooltipinfo >
< p > Control the CS42448 chip in TDM mode, for 6 inputs and 8 outputs.
< / p >
< p align = center > < img src = "img/cs42448.jpg" > < / p >
< / div >
< / div >
< h3 > Audio Connections< / h3 >
< p > This object has no audio inputs or outputs. Separate TDM objects
are used to send and receive audio data.
< / p >
< h3 > Functions< / h3 >
< p class = func > < span class = keyword > enable< / span > ();< / p >
< p class = desc > Enables the CS42448 to work in TDM mode.
< / p >
< p class = func > < span class = keyword > volume< / span > (level);< / p >
< p class = desc > Set the volume level for all output channels. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > volume< / span > (channel, level);< / p >
< p class = desc > Set the volume level for a single output. Channel is 1 to 8. Range is 0 to 1.0.
< / p >
< p class = func > < span class = keyword > inputLevel< / span > (level);< / p >
< p class = desc > Set the input gain level for all input channels. Range is 0 to 15.85.
< / p >
< p class = func > < span class = keyword > inputLevel< / span > (channel, level);< / p >
< p class = desc > Set the input gain level for a single input. Channel is 1 to 6. Range is 0 to 15.85.
< / p >
< h3 > Hardware< / h3 >
< p > Tested with this < a href = "https://oshpark.com/shared_projects/2Yj6rFaW" >
CS42448 Circuit Board< / a > .
< / p >
< p align = center > < img src = "img/tdm.jpg" > < / p >
< / div >
< h3 > Notes< / h3 >
< / script >
< script type = "text/x-red" data-template-name = "AudioControlCS42448" >
< div class = "form-row" >
< label for = "node-input-name" > < i class = "fa fa-tag" > < / i > Name< / label >
< input type = "text" id = "node-input-name" placeholder = "Name" >
< / div >
< / script >
< / body >
< / html >