├── .gitmodules
├── LICENSE.txt
├── README.md
├── graphics
├── README.md
├── Tayda-125B-Funbox-v1-template.ai
└── TaydaDrill to Adobe Illustrator xy coord funbox.xlsx
├── hardware
├── README.md
├── funbox_v1
│ ├── funbox.kicad_pcb
│ ├── funbox.kicad_prl
│ ├── funbox.kicad_pro
│ ├── funbox.kicad_sch
│ └── funbox_BOM.csv
├── funbox_v2_midi
│ ├── AudioBuffers.kicad_sch
│ ├── Midi.kicad_sch
│ ├── Midi_InOut.kicad_sch
│ ├── Power.kicad_sch
│ ├── funbox_v2.kicad_pcb
│ ├── funbox_v2.kicad_prl
│ ├── funbox_v2.kicad_pro
│ ├── funbox_v2.kicad_sch
│ ├── funbox_v2_BOM.csv
│ └── funbox_v2_BOM.xml
├── funbox_v3_midi_exp
│ ├── AudioBuffers.kicad_sch
│ ├── GerberSeed_PCBway_Funbox_v3p2.zip
│ ├── Midi.kicad_sch
│ ├── Midi_InOut.kicad_sch
│ ├── Power.kicad_sch
│ ├── funbox_v3.kicad_pcb
│ ├── funbox_v3.kicad_prl
│ ├── funbox_v3.kicad_pro
│ ├── funbox_v3.kicad_sch
│ └── funbox_v3_BOM.csv
└── images
│ ├── funbox_v1_front.jpg
│ ├── funbox_v1_inside.jpg
│ ├── funbox_v1_pcb.jpg
│ ├── funbox_v3_front.jpg
│ ├── funbox_v3_inside.jpg
│ └── funbox_v3_render.jpg
├── include
├── README.md
├── expressionHandler.h
└── funbox.h
├── mod
├── README.md
├── bksheperd_hardware_module
│ ├── guitar_pedal_funbox.cpp
│ └── guitar_pedal_funbox.h
├── daisy_petal.cpp
└── daisy_petal.h
└── software
├── Experiments
├── ChorusVerb
│ ├── Makefile
│ ├── README.md
│ └── chorusverb.cpp
├── DenoiseFFT
│ ├── Makefile
│ ├── README.md
│ ├── denoise.cpp
│ ├── fourier.h
│ ├── shy_fft.h
│ └── wave.h
├── FmSynth
│ ├── Makefile
│ ├── README.md
│ ├── fmsynth.cpp
│ ├── operator.cpp
│ └── operator.h
├── Granular
│ ├── Makefile
│ ├── README.md
│ └── granular.cpp
├── MidiKeys
│ ├── Makefile
│ ├── README.md
│ └── midikeys.cpp
├── NoiseFilterFFT
│ ├── Makefile
│ ├── README.md
│ ├── fourier.h
│ ├── noisefilter.cpp
│ ├── shy_fft.h
│ └── wave.h
├── README.md
└── SpectralReverb
│ ├── Makefile
│ ├── README.md
│ ├── fourier.h
│ ├── shy_fft.h
│ ├── spectralreverb.cpp
│ └── wave.h
├── Jupiter
├── CloudSeed
│ ├── AllpassDiffuser.h
│ ├── AudioLib
│ │ ├── Biquad2.cpp
│ │ ├── Biquad2.h
│ │ ├── Hp1.h
│ │ ├── Lp1.h
│ │ ├── MathDefs.h
│ │ ├── ShaRandom.cpp
│ │ ├── ShaRandom.h
│ │ ├── ValueTables.cpp
│ │ └── ValueTables.h
│ ├── Default.h
│ ├── DelayLine.h
│ ├── Exports.cpp
│ ├── FastSin.cpp
│ ├── FastSin.h
│ ├── Makefile
│ ├── ModulatedAllpass.h
│ ├── ModulatedDelay.h
│ ├── MultitapDiffuser.h
│ ├── Parameter.h
│ ├── ReverbChannel.h
│ ├── ReverbController.h
│ ├── Utils.h
│ ├── Utils
│ │ ├── Sha256.cpp
│ │ └── Sha256.h
│ ├── license.txt
│ └── premake4.lua
├── README.md
└── jupiter
│ ├── Makefile
│ └── jupiter.cpp
├── Mars
├── ImpulseResponse
│ ├── ImpulseResponse.cpp
│ ├── ImpulseResponse.h
│ ├── dsp.cpp
│ ├── dsp.h
│ └── ir_data.h
├── Makefile
├── README.md
├── all_model_data_gru9_4count.h
├── delayline_2tap.h
└── mars.cpp
├── Neptune
├── CloudSeed
│ ├── AllpassDiffuser.h
│ ├── AudioLib
│ │ ├── Biquad2.cpp
│ │ ├── Biquad2.h
│ │ ├── Hp1.h
│ │ ├── Lp1.h
│ │ ├── MathDefs.h
│ │ ├── ShaRandom.cpp
│ │ ├── ShaRandom.h
│ │ ├── ValueTables.cpp
│ │ └── ValueTables.h
│ ├── Default.h
│ ├── DelayLine.h
│ ├── Exports.cpp
│ ├── FastSin.cpp
│ ├── FastSin.h
│ ├── Makefile
│ ├── ModulatedAllpass.h
│ ├── ModulatedDelay.h
│ ├── MultitapDiffuser.h
│ ├── Parameter.h
│ ├── ReverbChannel.h
│ ├── ReverbController.h
│ ├── Utils.h
│ ├── Utils
│ │ ├── Sha256.cpp
│ │ └── Sha256.h
│ ├── license.txt
│ └── premake4.lua
├── README.md
└── neptune
│ ├── Makefile
│ ├── delayline_oct.h
│ ├── delayline_reverse.h
│ └── neptune.cpp
├── Pluto
├── Makefile
├── README.md
├── dsp.h
├── pluto.cpp
├── reverbsc96.cpp
├── reverbsc96.h
└── varSpeedLooper.h
├── README.md
├── Saturn
├── Makefile
├── README.md
├── fourier.h
├── saturn.cpp
├── shy_fft.h
└── wave.h
├── Template
├── README.md
└── template.cpp
├── Uranus
├── Makefile
├── README.md
├── fm_synth_2op.h
├── granularplayermod.cpp
├── granularplayermod.h
├── operator.cpp
├── operator.h
└── uranus.cpp
├── Venus
├── Makefile
├── README.md
├── fourier.h
├── shy_fft.h
├── venus.cpp
└── wave.h
└── images
├── Infographics.pptx
├── earth_infographic.jpg
├── funbox_infographic.jpg
├── jupiter_infographic.jpg
├── mars_infographic.jpg
├── mercury_infographic.jpg
├── neptune_infographic.jpg
├── pluto_infographic.jpg
├── saturn_infographic.jpg
├── uranus_infographic.jpg
└── venus_infographic.jpg
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "libDaisy"]
2 | path = libDaisy
3 | url = https://github.com/electro-smith/libDaisy.git
4 | [submodule "DaisySP"]
5 | path = DaisySP
6 | url = https://github.com/electro-smith/DaisySP.git
7 | [submodule "RTNeural"]
8 | path = RTNeural
9 | url = https://github.com/jatinchowdhury18/RTNeural.git
10 | [submodule "q"]
11 | path = q
12 | url = https://github.com/cycfi/q.git
13 | [submodule "eigen"]
14 | path = eigen
15 | url = https://gitlab.com/libeigen/eigen
16 | [submodule "gcem"]
17 | path = gcem
18 | url = https://github.com/kthohr/gcem.git
19 | [submodule "infra"]
20 | path = infra
21 | url = https://github.com/cycfi/infra.git
22 | [submodule "software/Earth"]
23 | path = software/Earth
24 | url = https://github.com/GuitarML/Earth.git
25 | [submodule "software/Mercury"]
26 | path = software/Mercury
27 | url = https://github.com/GuitarML/Mercury.git
28 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2024 Keith Bloemer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/graphics/README.md:
--------------------------------------------------------------------------------
1 | # Pedal Graphics
--------------------------------------------------------------------------------
/graphics/Tayda-125B-Funbox-v1-template.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/graphics/Tayda-125B-Funbox-v1-template.ai
--------------------------------------------------------------------------------
/graphics/TaydaDrill to Adobe Illustrator xy coord funbox.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/graphics/TaydaDrill to Adobe Illustrator xy coord funbox.xlsx
--------------------------------------------------------------------------------
/hardware/README.md:
--------------------------------------------------------------------------------
1 | # Hardware
2 |
3 | This directory contains the KiCad files for manufacturing the Funbox PCB. Includes schematic, pcb, and generated BOM.
4 | Funbox uses a 125B sized enclosure.
5 |
6 | ## Funbox v1
7 |
8 | VERIFIED WORKING - using OshPark standard board manufacturing
9 |
10 | Funbox v1 uses a 125B enclosure with the following features:
11 | - Stereo In/Out
12 | - 9v power
13 | - 6 potentiometer knobs
14 | - 3 3-way switches On-Off-On
15 | - 2 SPST momentary footswitches
16 | - 2 LEDs
17 | - 2 Dipswitches
18 |
19 | [Tayda Drill Template](https://drill.taydakits.com/box-designs/new?public_key=bXVVdnZXK0pOVWJjZG5YOGtwd282Zz09Cg==)
20 |
21 | 
22 | 
23 | 
24 |
25 |
26 | ## Funbox v2
27 |
28 | Funbox v2 adds MIDI In/Out via two 1/8" TRS jacks and up to a 4 dip switch array, instead of 2.
29 |
30 | [Tayda Drill Template](https://drill.taydakits.com/box-designs/new?public_key=M3BDZTdRSmFWRkF4QXpQUzRORjIwQT09Cg==)
31 |
32 | CURRENTLY UNTESTED
33 |
34 | ## Funbox v3.2
35 |
36 | Funbox v3 replaces the MIDI out jack from version 2 with an Expression Input jack.
37 | Version 3.2 replaces the TL072 Quad Op Amp with a MCP6024 for reduced noise.
38 | Note: Since most Expresion pedals use 1/4" TRS cables, an adapter is required (Female 1/4" to Male 1/8" stereo adapter, or 1/4" to 1/8" TRS cable.)
39 |
40 | [Tayda Drill Template](https://drill.taydakits.com/box-designs/new?public_key=M3BDZTdRSmFWRkF4QXpQUzRORjIwQT09Cg==) (Same as version 2)
41 |
42 | The Gerber files used for ordering from PCBway have been added in GerberSeed_PCBway_Funbox_v3p2.zip (note that other manufacturers may have different Gerber requirements)
43 |
44 | The Funbox v3.2 board is a shared project on OSHPark, click [here](https://oshpark.com/shared_projects/MnthZS4N) to go to the project page for easy ordering.
45 |
46 | VERIFIED WORKING
47 |
48 | Funbox v3 uses a 125B enclosure with the same features a version 1 with the following additions:
49 | - Midi Input from a 1/8 inch TRS jack
50 | - Expression Input from a 1/8 inch TRS jack
51 | - 4 Dipswitches
52 |
53 | 
54 | 
--------------------------------------------------------------------------------
/hardware/funbox_v1/funbox.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 31,
4 | "active_layer_preset": "All Layers",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": false,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 39,
65 | 40
66 | ],
67 | "visible_layers": "fffffff_ffffffff",
68 | "zone_display_mode": 0
69 | },
70 | "meta": {
71 | "filename": "funbox.kicad_prl",
72 | "version": 3
73 | },
74 | "project": {
75 | "files": []
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/hardware/funbox_v1/funbox_BOM.csv:
--------------------------------------------------------------------------------
1 | "Source:","/Users/keithbloemer/Desktop/KiCad/FunBox/funbox.kicad_sch"
2 | "Date:","2024 May 01, Wednesday 12:14:24"
3 | "Tool:","Eeschema 7.0.6-0"
4 | "Generator:","/Applications/KiCad/KiCad.app/Contents/SharedSupport/plugins/bom_csv_grouped_by_value.py"
5 | "Component Count:","61"
6 |
7 | "Collated Components:"
8 |
9 | "Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet","DNP","MANUFACTURER","MAXIMUM_PACKAGE_HEIGHT","PARTREV","STANDARD"
10 | "1","8","9v1, Gnd1, In1, In2, InG1, Out1, Out2, OutG1","~","Connector_Generic:Conn_01x01","TestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mm","~","","","","",""
11 | "2","1","A1","Electrosmith_Daisy_Seed_Rev7","MCU_Module:Electrosmith_Daisy_Seed_Rev4","Module:Electrosmith_Daisy_Seed","https://static1.squarespace.com/static/58d03fdc1b10e3bf442567b8/t/6227e6236f02fb68d1577146/1646781988478/Daisy_Seed_datasheet_v1.0.3.pdf","","","","",""
12 | "3","6","C1, C4, C5, C14, C15, C17","1UF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W6.0mm_P5.00mm","~","","","","",""
13 | "4","2","C2, C11","100","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","",""
14 | "5","2","C3, C16","1NF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","",""
15 | "6","1","C6","100UF","Device:C","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~","","","","",""
16 | "7","4","C7, C8, C9, C10","100NF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","",""
17 | "8","2","C12, C13","2.2nF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","",""
18 | "9","1","D1","1N5817","Diode:1N5817","Diode_THT:D_DO-41_SOD81_P7.62mm_Horizontal","http://www.vishay.com/docs/88525/1n5817.pdf","","","","",""
19 | "10","1","FS1","Foot_Switch_1","Switch:SW_Push","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","",""
20 | "11","1","FS2","Foot_Switch_2","Switch:SW_Push","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","",""
21 | "12","1","LED1","LED_1","Device:LED","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","",""
22 | "13","1","LED2","LED_2","Device:LED","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","",""
23 | "14","6","POT1, POT2, POT3, POT4, POT5, POT6","10K","Device:R_Potentiometer_US","Potentiometer_THT:Pot_RightAngle_LongPin_16mm","~","","","","",""
24 | "15","8","R1, R2, R5, R6, R13, R14, R15, R16","1M","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","",""
25 | "16","4","R3, R8, R9, R12","1K","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","",""
26 | "17","2","R4, R17","100","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","",""
27 | "18","2","R7, R18","100K","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","",""
28 | "19","2","R10, R11","3K3","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","",""
29 | "20","1","S1","DS03-254-02BE","DS03-254-02BE:DS03-254-02BE","Button_Switch_THT:DS03-254-02BE-dip2","","","CUI Inc.","9.93 mm","V1.0","Manufacturer Recommendations"
30 | "21","3","SW1, SW2, SW3","SW_SPDT","Switch:SW_SPDT","Button_Switch_THT:SW_Toggle_SPDT_lugs","~","","","","",""
31 | "22","1","U1","TL074","Amplifier_Operational:TL074","Package_DIP:DIP-14_W7.62mm","http://www.ti.com/lit/ds/symlink/tl071.pdf","","","","",""
32 | "23","1","U2","L7805","Regulator_Linear:L7805","Package_TO_SOT_THT:TO-220-3_Vertical","http://www.st.com/content/ccc/resource/technical/document/datasheet/41/4f/b3/b0/12/d4/47/88/CD00000444.pdf/files/CD00000444.pdf/jcr:content/translations/en.CD00000444.pdf","","","","",""
33 |
--------------------------------------------------------------------------------
/hardware/funbox_v2_midi/funbox_v2.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 0,
4 | "active_layer_preset": "All Layers",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": false,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 39,
65 | 40
66 | ],
67 | "visible_layers": "fffffff_ffffffff",
68 | "zone_display_mode": 0
69 | },
70 | "meta": {
71 | "filename": "funbox_v2.kicad_prl",
72 | "version": 3
73 | },
74 | "project": {
75 | "files": []
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/hardware/funbox_v2_midi/funbox_v2_BOM.csv:
--------------------------------------------------------------------------------
1 | "Source:","/Users/keithbloemer/Desktop/KiCad/FunBox_v2_midi/funbox_v2.kicad_sch"
2 | "Date:","2024 May 17, Friday 12:03:38"
3 | "Tool:","Eeschema 7.0.6-0"
4 | "Generator:","/Applications/KiCad/KiCad.app/Contents/SharedSupport/plugins/bom_csv_grouped_by_value.py"
5 | "Component Count:","70"
6 |
7 | "Collated Components:"
8 |
9 | "Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet","DNP","MANUFACTURER","MAXIMUM_PACKAGE_HEIGHT","PARTREV","STANDARD","Sim.Device","Sim.Pins"
10 | "1","1","A1","Electrosmith_Daisy_Seed_Rev7","MCU_Module:Electrosmith_Daisy_Seed_Rev4","Module:Electrosmith_Daisy_Seed","https://static1.squarespace.com/static/58d03fdc1b10e3bf442567b8/t/6227e6236f02fb68d1577146/1646781988478/Daisy_Seed_datasheet_v1.0.3.pdf","","","","","","",""
11 | "2","2","C1, C2","100","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","","","",""
12 | "3","2","C3, C4","2.2nF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","","","",""
13 | "4","6","C5, C11, C12, C13, C16, C17","1UF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W6.0mm_P5.00mm","~","","","","","","",""
14 | "5","1","C6","100UF","Device:C","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~","","","","","","",""
15 | "6","4","C7, C8, C9, C10","100NF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","","","",""
16 | "7","2","C14, C15","1NF","Device:C","Capacitor_THT:C_Rect_L7.0mm_W2.5mm_P5.00mm","~","","","","","","",""
17 | "8","1","C30","100NF","Device:C","Capacitor_THT:C_Disc_D6.0mm_W2.5mm_P5.00mm","~","","","","","","",""
18 | "9","1","D1","1N5817","Diode:1N5817","Diode_THT:D_DO-41_SOD81_P7.62mm_Horizontal","http://www.vishay.com/docs/88525/1n5817.pdf","","","","","","",""
19 | "10","1","D2","1N4148","Diode:1N4148","Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal","https://assets.nexperia.com/documents/data-sheet/1N4148_1N4448.pdf","","","","","","D","1=K 2=A"
20 | "11","1","FS1","Foot_Switch_1","Switch:SW_Push","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","","","",""
21 | "12","1","FS2","Foot_Switch_2","Switch:SW_Push","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","","","",""
22 | "13","8","In1, In2, In3, InG1, InG2, InG3, Out1, Out2","~","Connector_Generic:Conn_01x01","TestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mm","~","","","","","","",""
23 | "14","1","J6","MIDI IN JACK","Connector_Audio:AudioJack4","Audio_Module:TRRS-PJ-320A","~","","","","","","",""
24 | "15","1","J7","MIDI OUT JACK","Connector_Audio:AudioJack4","Audio_Module:TRRS-PJ-320A","~","","","","","","",""
25 | "16","1","LED1","LED_1","Device:LED","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","","","",""
26 | "17","1","LED2","LED_2","Device:LED","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~","","","","","","",""
27 | "18","6","POT1, POT2, POT3, POT4, POT5, POT6","10K","Device:R_Potentiometer_US","Potentiometer_THT:Pot_RightAngle_LongPin_16mm","~","","","","","","",""
28 | "19","2","R1, R2","3K3","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
29 | "20","4","R3, R4, R8, R9","1K","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
30 | "21","8","R5, R6, R7, R10, R11, R12, R13, R14","1M","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
31 | "22","2","R15, R16","100","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
32 | "23","2","R17, R18","100K","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
33 | "24","1","R30","220R","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
34 | "25","1","R31","470R","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
35 | "26","1","R32","10R","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
36 | "27","1","R33","33R","Device:R","Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal","~","","","","","","",""
37 | "28","1","S1","DS03-254-04BE","DS03-254-04BE:DS03-254-04BE","Button_Switch_THT:DS03-254-04BE-dip4","","","CUI Inc.","9.93 mm","V1.0","Manufacturer Recommendations","",""
38 | "29","3","SW1, SW2, SW3","SW_SPDT","Switch:SW_SPDT","Button_Switch_THT:SW_Toggle_SPDT_lugs","~","","","","","","",""
39 | "30","1","U1","TL074","Amplifier_Operational:TL074","Package_DIP:DIP-14_W7.62mm","http://www.ti.com/lit/ds/symlink/tl071.pdf","","","","","","",""
40 | "31","1","U2","L7805","Regulator_Linear:L7805","Package_TO_SOT_THT:TO-220-3_Vertical","http://www.st.com/content/ccc/resource/technical/document/datasheet/41/4f/b3/b0/12/d4/47/88/CD00000444.pdf/files/CD00000444.pdf/jcr:content/translations/en.CD00000444.pdf","","","","","","",""
41 | "32","1","U5","H11L1","Isolator:H11L1","Package_DIP:DIP-6_W7.62mm","https://www.onsemi.com/pub/Collateral/H11L3M-D.PDF","","","","","","",""
42 |
--------------------------------------------------------------------------------
/hardware/funbox_v3_midi_exp/GerberSeed_PCBway_Funbox_v3p2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/funbox_v3_midi_exp/GerberSeed_PCBway_Funbox_v3p2.zip
--------------------------------------------------------------------------------
/hardware/funbox_v3_midi_exp/funbox_v3.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 37,
4 | "active_layer_preset": "All Layers",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": false,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 39,
65 | 40
66 | ],
67 | "visible_layers": "fffffff_ffffffff",
68 | "zone_display_mode": 0
69 | },
70 | "meta": {
71 | "filename": "funbox_v3.kicad_prl",
72 | "version": 3
73 | },
74 | "project": {
75 | "files": []
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/hardware/funbox_v3_midi_exp/funbox_v3_BOM.csv:
--------------------------------------------------------------------------------
1 | Id,Designator,Footprint,Quantity,Designation,Supplier and ref,
2 | ,,,,,,
3 | 1,R30,R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,1,220 ohm,,
4 | ,,,,,,
5 | 2,"POT4,POT5,POT2,POT1,POT3,POT6",Pot_RightAngle_LongPin_16mm,6,10K,RV16AF-41-15R1-B10K,https://www.taydaelectronics.com/b10k-ohm-linear-taper-potentiometer-round-shaft-pc-mount-l.html
6 | ,,,,,,
7 | 3,"OutR,InG,InL,InR,OutG,OutL,9v,Gnd",TestPoint_THTPad_D2.0mm_Drill1.0mm,8,~,,
8 | ,,,,,,
9 | 4,"C15,C4,C5,C14,C17,C1",C_Rect_L7.0mm_W6.0mm_P5.00mm,6,1UF,,
10 | ,,,,,,
11 | 5,"C13,C12",C_Rect_L7.0mm_W2.5mm_P5.00mm,2,2.2nF,,
12 | ,,,,,,
13 | 6,R31,R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,1,470 ohm,,
14 | ,,,,,,
15 | 7,D2,D_DO-35_SOD27_P7.62mm_Horizontal,1,1N4148,,
16 | ,,,,,,
17 | 8,J7,PJ-320A,1,EXPRESSION,https://www.taydaelectronics.com/pj-320a-3-5-mm-audio-socket-through-hole-pcb-silver-plated.html,
18 | ,,,,,,
19 | 9,"R12,R8,R3,R9",R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,4,1K,,
20 | ,,,,,,
21 | 10,U2,TO-220-3_Vertical,1,L78L05ACZ,https://www.taydaelectronics.com/l78l05acz-l78l05-78l05-5-volts-100ma-voltage-regulator-ic.html,
22 | ,,,,,,
23 | 11,"SW1,SW2,SW3",SW_Toggle_SPDT_lugs,3,SW_SPDT,1MS3T2B1M1QES,https://www.taydaelectronics.com/mini-toggle-switch-1m-series-spdt-on-off-on-short-lever.html
24 | ,,,,,,
25 | 12,"R6,R5,R16,R1,R15,R13,R14,R2",R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,8,1M,,
26 | ,,,,,,
27 | 13,"C8,C9,C7,C10",C_Rect_L7.0mm_W2.5mm_P5.00mm,4,100NF,,
28 | ,,,,,,
29 | 14,C6,CP_Radial_D8.0mm_P3.50mm,1,100UF,,
30 | ,,,,,,
31 | 15,"C11,C2",C_Rect_L7.0mm_W2.5mm_P5.00mm,2,100pF,,
32 | ,,,,,,
33 | 16,LED2,PinHeader_1x02_P2.54mm_Vertical,1,"LED_2 (5mm, color as desired)",732-5017-ND (Digikey),
34 | ,,,,,,
35 | 17,C30,C_Disc_D6.0mm_W2.5mm_P5.00mm,1,100NF,,
36 | ,,,,,,
37 | 18,"R4,R17",R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,2,100 ohm,,
38 | ,,,,,,
39 | 19,LED1,PinHeader_1x02_P2.54mm_Vertical,1,"LED_1 (5mm, color as desired)",732-5017-ND (Digikey),
40 | ,,,,,,
41 | 20,"C16,C3",C_Rect_L7.0mm_W2.5mm_P5.00mm,2,1NF,,
42 | ,,,,,,
43 | 21,"R11,R10",R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,2,3K3,,
44 | ,,,,,,
45 | 22,U1,DIP-14_W7.62mm,1,MCP6024-I/P,Digikey MCP6024-I/P-ND,
46 | ,,,,,,
47 | 23,A1,Electrosmith_Daisy_Seed,1,"Electrosmith_Daisy_Seed_Rev7 (soldered, 65MB memory version)",https://electro-smith.com/products/daisy-seed?variant=45234245140772,
48 | ,,,,,,
49 | 24,D1,D_DO-41_SOD81_P7.62mm_Horizontal,1,1N5817,,
50 | ,,,,,,
51 | 25,U3,DIP-8_W7.62mm,1,MCP6002-I/P,,
52 | ,,,,,,
53 | 26,S1,DS03-254-04BE-dip4,1,DS03-254-04BE,,
54 | ,,,,,,
55 | 27,"R18,R7",R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,2,100K,,
56 | ,,,,,,
57 | 28,FS1,PinHeader_1x02_P2.54mm_Vertical,1,Foot_Switch_1,https://lovemyswitches.com/pro-grade-spst-momentary-foot-switch-normally-open-soft-touch-solder-lug/,
58 | ,,,,,,
59 | 29,J6,PJ-320A,1,MIDI IN,https://www.taydaelectronics.com/pj-320a-3-5-mm-audio-socket-through-hole-pcb-silver-plated.html,
60 | ,,,,,,
61 | 30,FS2,PinHeader_1x02_P2.54mm_Vertical,1,Foot_Switch_2,https://lovemyswitches.com/pro-grade-spst-momentary-foot-switch-normally-open-soft-touch-solder-lug/,
62 | ,,,,,,
63 | 31,U5,DIP-6_W7.62mm,1,H11L1M,https://www.taydaelectronics.com/h11l1-h11l1m-high-speed-optocouplers-output-1-channel.html,
64 | ,,,,,,
65 | 32,R19,R_Axial_DIN0207_L6.3mm_D2.5mm_P7.62mm_Horizontal,1,2M,,
66 |
--------------------------------------------------------------------------------
/hardware/images/funbox_v1_front.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v1_front.jpg
--------------------------------------------------------------------------------
/hardware/images/funbox_v1_inside.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v1_inside.jpg
--------------------------------------------------------------------------------
/hardware/images/funbox_v1_pcb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v1_pcb.jpg
--------------------------------------------------------------------------------
/hardware/images/funbox_v3_front.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v3_front.jpg
--------------------------------------------------------------------------------
/hardware/images/funbox_v3_inside.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v3_inside.jpg
--------------------------------------------------------------------------------
/hardware/images/funbox_v3_render.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/hardware/images/funbox_v3_render.jpg
--------------------------------------------------------------------------------
/include/README.md:
--------------------------------------------------------------------------------
1 | # Include
2 | This contains the funbox.h header along with custom headers for Funbox software.
3 |
4 | ## Contents
5 | - expressionHandler: Expression pedal code for the Funbox v3 board. Remaps knob controls to use with an expression pedal.
6 |
7 | - funbox.h : Include header file for Funbox. Applicable for Funbox version 1, version 2, and version 3. This provides an abstraction for the knobs, switches, and LEDs when writing software for Funbox.```
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/include/funbox.h:
--------------------------------------------------------------------------------
1 | namespace funbox
2 | {
3 | class Funbox
4 | {
5 | public:
6 | enum Sw
7 | {
8 | FOOTSWITCH_1 = 0,
9 | FOOTSWITCH_2 = 1,
10 | SWITCH_1_LEFT = 2,
11 | SWITCH_1_RIGHT = 3,
12 | SWITCH_2_LEFT = 4,
13 | SWITCH_2_RIGHT = 5,
14 | SWITCH_3_LEFT = 6,
15 | SWITCH_3_RIGHT = 7,
16 | SWITCH_DIP_1 = 8,
17 | SWITCH_DIP_2 = 9,
18 | SWITCH_DIP_3 = 10, // On v2/v3 boards only, not v1
19 | SWITCH_DIP_4 = 11 // On v2/v3 boards only, not v1
20 | };
21 |
22 | enum Knob
23 | {
24 | KNOB_1 = 0,
25 | KNOB_2 = 2,
26 | KNOB_3 = 4,
27 | KNOB_4 = 1,
28 | KNOB_5 = 3,
29 | KNOB_6 = 5,
30 | //EXPRESSION = 6 // On v3 board only
31 | };
32 |
33 | enum LED
34 | {
35 | LED_1 = 22,
36 | LED_2 = 23
37 | };
38 |
39 | // Note: MIDI Input is available on v2/v3 board by pin 37, D30
40 | // MIDI Out is available on v2 board by pin 36, D29
41 |
42 | };
43 | }
44 |
--------------------------------------------------------------------------------
/mod/README.md:
--------------------------------------------------------------------------------
1 | # libDaisy Modifications
2 |
3 | Replace these files in libDaisy before building libDaisy. This is required to correctly map the controls for Funbox hardware.
4 | Applicable for Funbox v1, v2, and v3 PCBs.
5 |
6 | INSTRUCTIONS:
7 | ```
8 | # Replace libDaisy/src/daisy_pedal.h with Funbox/mod/daisy_pedal.h
9 | # Replace libDaisy/src/daisy_pedal.cpp with Funbox/mod/daisy_pedal.cpp
10 |
11 | make -C libDaisy
12 | ```
13 |
14 | ## bksheperd hardware module definitions
15 |
16 | These are the hardware definitions for using the bksheperd guitar pedal framework on the Funbox.
17 | Add these two files to the following location in your [DaisySeedProjects](https://github.com/bkshepherd/DaisySeedProjects/tree/main) repo and update
18 | the guitar_pedal.cpp to use this hardware definition.
19 |
20 | Add the guitar_pedal_funbox.h and guitar_pedal_funbox.cpp file to this location to use this extensive guitar effect framework on the Funbox:
21 | https://github.com/bkshepherd/DaisySeedProjects/tree/main/Software/GuitarPedal/Hardware-Modules
22 |
--------------------------------------------------------------------------------
/mod/bksheperd_hardware_module/guitar_pedal_funbox.cpp:
--------------------------------------------------------------------------------
1 | #include "guitar_pedal_funbox.h"
2 |
3 | using namespace bkshepherd;
4 |
5 | static const int s_switchParamCount = 2;
6 | static const PreferredSwitchMetaData s_switchMetaData[s_switchParamCount] = {{sfType: SpecialFunctionType::Bypass, switchMapping: 0},
7 | {sfType: SpecialFunctionType::TapTempo, switchMapping: 1}};
8 |
9 | GuitarPedalFunbox::GuitarPedalFunbox() : BaseHardwareModule()
10 | {
11 | // Setup the Switch Meta Data for this hardware
12 | m_switchMetaDataParamCount = s_switchParamCount;
13 | m_switchMetaData = s_switchMetaData;
14 | }
15 |
16 | GuitarPedalFunbox::~GuitarPedalFunbox()
17 | {
18 |
19 | }
20 |
21 | void GuitarPedalFunbox::Init(bool boost)
22 | {
23 | BaseHardwareModule::Init(boost);
24 |
25 | m_supportsStereo = true;
26 |
27 | Pin knobPins[] = {seed::D16, seed::D17, seed::D18, seed::D19, seed::D20, seed::D21, seed::D15}; // seed::D15, the 7th knobPin is for Expression pedal input
28 | InitKnobs(7, knobPins);
29 |
30 | // Index reference: {0:footswitch1, 1:footswitch2, 2:Switch1Left, 3:Switch1Right, 4:Switch1Left, 5:Switch2Right, 6:Switch3Left, 7:Switch3Right, 8:Dip1, 9:Dip2, 10:Dip3, 11:Dip4}
31 | Pin switchPins[] = {seed::D26, seed::D25, seed::D14, seed::D13, seed::D7, seed::D10, seed::D2, seed::D4, seed::D1, seed::D3, seed::D5, seed::D6};
32 |
33 | InitSwitches(12, switchPins);
34 |
35 | Pin ledPins[] = {seed::D23, seed::D22};
36 | InitLeds(2, ledPins);
37 |
38 | InitMidi(seed::D30, seed::D29);
39 | }
40 |
--------------------------------------------------------------------------------
/mod/bksheperd_hardware_module/guitar_pedal_funbox.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef GUITAR_PEDAL_FUNBOX_H
3 | #define GUITAR_PEDAL_FUNBOX_H /**< & */
4 |
5 | #include "base_hardware_module.h"
6 |
7 | #ifdef __cplusplus
8 |
9 | /** @file guitar_pedal_funbox.h */
10 |
11 | using namespace daisy;
12 |
13 | namespace bkshepherd {
14 |
15 | /**
16 | @brief Helpers and hardware definitions for the Funbox pedal platform by GuitarML.
17 | */
18 | class GuitarPedalFunbox : public BaseHardwareModule
19 | {
20 | public:
21 | GuitarPedalFunbox();
22 | ~GuitarPedalFunbox();
23 | void Init(bool boost = false) override;
24 | };
25 | } // namespace bkshepherd
26 | #endif
27 | #endif
--------------------------------------------------------------------------------
/software/Experiments/ChorusVerb/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = chorusverb
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = chorusverb.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../../libDaisy
18 | DAISYSP_DIR = ../../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/ChorusVerb/README.md:
--------------------------------------------------------------------------------
1 | # ChorusVerb
2 |
3 | Experiment using the DaisySP Chorus and Reverb effects. Features several routing modes, and uses a pitchshifter for different reverb modes.
4 | Getting some interesting sounds, could be successful with some tweaking. The pitchshifted reverb didn't turn out how I hoped.
5 |
6 | Note: I had to modify the pitchshifter class in DaisySP to use a smaller delayline, otherwise the SRAM capacity was exceeded from the Reverb and Pitchshifters.
7 |
8 | ## Controls
9 |
10 | | Control | Description | Comment |
11 | | --- | --- | --- |
12 | | Ctrl 1 | Chorus Depth | |
13 | | Ctrl 2 | Mix | |
14 | | Ctrl 3 | ReverbTime | |
15 | | Ctrl 4 | Chorus Freq | |
16 | | Ctrl 5 | Level | |
17 | | Ctrl 6 | Reverb Damping | |
18 | | 3-Way Switch 1 | Chorus Mode | left=norm, center=stereo spreadFreq, right=stereo spreadDelay |
19 | | 3-Way Switch 2 | Routing Mode | left=Chorus->Reverb, center=parallel, right=Reverb->Chorus |
20 | | 3-Way Switch 3 | Reverb Mode | Left: Normal, Center: Pitchshift up octave, Right: Pitchshift down octave |
21 | | Dip Switch 1 | Mono/Miso | |
22 | | Dip Switch 2 | | |
23 | | FS 1 | Bypass | |
24 | | FS 2 | | |
25 | | LED 1 | Bypass Indicator | |
26 | | LED 2 | | |
27 | | Audio In 1 | Mono In | Ignores Right channel input |
28 | | Audio Out 1 | Stereo Out | Mono/MISO |
29 |
30 |
31 | ## Build
32 |
33 | ChorusVerb runs in Flash memory on the Daisy Seed.
--------------------------------------------------------------------------------
/software/Experiments/DenoiseFFT/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = denoise
3 |
4 | # Sources
5 | CPP_SOURCES = denoise.cpp
6 |
7 | OPT = -O1
8 | #OPT ?= -O3
9 |
10 | # Library Locations
11 | LIBDAISY_DIR = ../../../libDaisy
12 | DAISYSP_DIR = ../../../DaisySP
13 |
14 |
15 | # Core location, and generic Makefile.
16 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
17 | include $(SYSTEM_FILES_DIR)/Makefile
18 |
19 |
20 | # Include funbox.h
21 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/DenoiseFFT/README.md:
--------------------------------------------------------------------------------
1 | # Denoise
2 |
3 | A test using a Short Time Fourier Transform to denoise a signal based on low/high bins and a threshold.
4 | This code adapts the code found here to run on Funbox hardware:
5 | https://github.com/amcerbu/DaisySTFT
6 |
7 | Hoping to open up the door to lots of interesting things you can do with FFTs, on the Daisy Seed.
8 |
9 | ## Controls
10 |
11 | | Control | Description | Comment |
12 | | --- | --- | --- |
13 | | Ctrl 1 | Beta | mix between high and low energy frequency bands |
14 | | Ctrl 2 | Threshold | cutoff for assigning a bin as high or low energy |
15 | | Ctrl 3 | | |
16 | | Ctrl 4 | | |
17 | | Ctrl 5 | | |
18 | | Ctrl 6 | | |
19 | | 3-Way Switch 1 | | |
20 | | 3-Way Switch 2 | | |
21 | | 3-Way Switch 3 | | |
22 | | Dip Switch 1 | | |
23 | | Dip Switch 2 | | |
24 | | FS 1 | Bypass/Engage | |
25 | | FS 2 | | |
26 | | LED 1 | Bypass indicator | |
27 | | LED 2 | | |
28 | | Audio In 1 | Mono out (left copied to right) | |
29 | | Audio Out 1 | | |
30 |
31 |
32 | ## Build
33 |
34 | Denoise runs in Flash memory on the Daisy Seed.
35 |
36 | # NOTES FROM ORIGINAL CODE:
37 |
38 | # DaisySTFT
39 |
40 | ## A minimial short-time Fourier transform example for the Daisy Seed
41 |
42 | As configured, the Seed listens for audio, feeds it to a `Fourier` instance (which handles the buffering, windowing, forward FFT, frequency-domain processing, inverse FFT), and then outputs the processed audio. The example frequency-domain process is defined in the `denoise` method. Try modifying it!
43 |
44 | I've found the program works well when `N = 4096` and `laps = 4` (higher frequency resolution, greater latency), or when `N = 2048` and `laps = 8` (higher time resolution, less latency).
45 |
46 | To compile, make sure you modify the Makefile so that the definitions of `DAISYSP_DIR` and `LIBDAISY_DIR` point to your installations of DaisySP and libDaisy. Then, as usual,
47 |
48 | make clean && make && make program-dfu
--------------------------------------------------------------------------------
/software/Experiments/DenoiseFFT/fourier.h:
--------------------------------------------------------------------------------
1 | // fourier.h
2 | #ifndef FOURIER
3 |
4 | #include "wave.h"
5 |
6 | namespace soundmath
7 | {
8 | template class Fourier
9 | {
10 | public:
11 | void (*processor)(const T* in, T* out);
12 |
13 | // in, middle, out need to be arrays of size (N * laps * 2)
14 | Fourier(void (*processor)(const T*, T*), ShyFFT* fft, Wave* window, size_t laps, T* in, T* middle, T* out)
15 | : processor(processor), in(in), middle(middle), out(out), fft(fft), window(window), laps(laps), stride(N / laps)
16 | {
17 | writepoints = new int[laps * 2];
18 | readpoints = new int[laps * 2];
19 |
20 | memset(writepoints, 0, sizeof(int) * laps * 2);
21 | memset(readpoints, 0, sizeof(int) * laps * 2);
22 |
23 | for (int i = 0; i < 2 * (int)laps; i++) // initialize half of writepoints
24 | writepoints[i] = -i * (int)stride;
25 |
26 | reading = new bool[laps * 2];
27 | writing = new bool[laps * 2];
28 |
29 | memset(reading, false, sizeof(bool) * laps * 2);
30 | memset(writing, true, sizeof(bool) * laps * 2);
31 | }
32 |
33 | ~Fourier()
34 | {
35 | delete [] writepoints;
36 | delete [] readpoints;
37 | delete [] reading;
38 | delete [] writing;
39 | }
40 |
41 | // writes a single sample (with windowing) into the in array
42 | void write(T x)
43 | {
44 | for (size_t i = 0; i < laps * 2; i++)
45 | {
46 | if (writing[i])
47 | {
48 | if (writepoints[i] >= 0)
49 | {
50 | T amp = (*window)((T)writepoints[i] / N);
51 | in[writepoints[i] + N * i] = amp * x;
52 | }
53 | writepoints[i]++;
54 |
55 | if (writepoints[i] == N)
56 | {
57 | writing[i] = false;
58 | reading[i] = true;
59 | readpoints[i] = 0;
60 |
61 | forward(i); // FTs ith in to ith middle buffer
62 | process(i); // user-defined; ought to move info from ith middle to out buffer
63 | backward(i); // IFTs ith out to ith in buffer
64 |
65 | current = i;
66 | }
67 | }
68 | }
69 | }
70 |
71 | inline void forward(const size_t i)
72 | {
73 | fft->Direct((in + i * N), (middle + i * N)); // analysis
74 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
75 | }
76 |
77 | inline void backward(const size_t i)
78 | {
79 | fft->Inverse((out + i * N), (in + i * N)); // synthesis
80 | // arm_rfft_fast_f32(fft, out + i * N, in + i * N, 1);
81 | }
82 |
83 | // executes user-defined callback
84 | inline void process(const size_t i)
85 | {
86 | processor((middle + i * N), (out + i * N));
87 | }
88 |
89 | // read a single reconstructed sample
90 | T read()
91 | {
92 | T accum = 0;
93 |
94 | for (size_t i = 0; i < laps * 2; i++)
95 | {
96 | if (reading[i])
97 | {
98 | T amp = (*window)((T)readpoints[i] / N);
99 | accum += amp * in[readpoints[i] + N * i];
100 |
101 | readpoints[i]++;
102 |
103 | if (readpoints[i] == N)
104 | {
105 | writing[i] = true;
106 | reading[i] = false;
107 | writepoints[i] = 0;
108 | }
109 | }
110 | }
111 |
112 | accum /= N * laps / 2.0;
113 | return accum;
114 | }
115 |
116 |
117 |
118 | private:
119 | T *in, *middle, *out;
120 |
121 | public:
122 | ShyFFT* fft;
123 | Wave* window;
124 |
125 | size_t laps;
126 | size_t stride;
127 |
128 | int* writepoints;
129 | int* readpoints;
130 | bool* reading;
131 | bool* writing;
132 |
133 | int current = 0;
134 | };
135 |
136 |
137 | template class Analyzer
138 | {
139 | public:
140 | int (*processor)(const T* in);
141 |
142 | // in, middle, out need to be arrays of size (N * laps * 2)
143 | Analyzer(int (*processor)(const T*), ShyFFT* fft, size_t laps, T* in, T* middle)
144 | : processor(processor), in(in), middle(middle), fft(fft), laps(laps), stride(N / laps)
145 | {
146 | writepoints = new int[laps];
147 |
148 | memset(writepoints, 0, sizeof(int) * laps);
149 |
150 | for (int i = 0; i < (int)laps; i++) // initialize half of writepoints
151 | writepoints[i] = -i * (int)stride;
152 |
153 | writing = new bool[laps];
154 | memset(writing, true, sizeof(bool) * laps);
155 | }
156 |
157 | ~Analyzer()
158 | {
159 | delete [] writepoints;
160 | delete [] writing;
161 | }
162 |
163 | // writes a single sample (with windowing) into the in array
164 | void write(T x)
165 | {
166 | for (size_t i = 0; i < laps; i++)
167 | {
168 | if (writing[i])
169 | {
170 | if (writepoints[i] >= 0)
171 | {
172 | // T window = halfhann((T)writepoints[i] / N);
173 | T window = hann((T)writepoints[i] / N);
174 | in[writepoints[i] + N * i] = window * x;
175 | }
176 | writepoints[i]++;
177 |
178 | if (writepoints[i] == N)
179 | {
180 | writing[i] = false;
181 |
182 | forward(i); // FTs ith in to ith middle buffer
183 | process(i); // user-defined; ought to move info from ith middle to out buffer
184 | current = i;
185 |
186 | size_t next = (i + 1) % (laps);
187 | writing[next] = true;
188 | writepoints[next] = 0;
189 | }
190 | }
191 | }
192 | }
193 |
194 | inline void forward(const size_t i)
195 | {
196 | fft->Direct((in + i * N), (middle + i * N)); // analysis
197 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
198 | }
199 |
200 | // executes user-defined callback
201 | inline void process(const size_t i)
202 | {
203 | processor((middle + i * N));
204 | }
205 |
206 | private:
207 | T *in, *middle;
208 |
209 | public:
210 | ShyFFT* fft;
211 |
212 | size_t laps;
213 | size_t stride;
214 |
215 | int* writepoints;
216 | bool* writing;
217 |
218 | int current = 0;
219 | };
220 | }
221 |
222 | #define FOURIER
223 | #endif
--------------------------------------------------------------------------------
/software/Experiments/DenoiseFFT/wave.h:
--------------------------------------------------------------------------------
1 | // wave.h // interpolated lookup table
2 | #ifndef WAVE
3 |
4 | #include
5 |
6 | namespace soundmath
7 | {
8 | const int TABSIZE = 2048;
9 |
10 | template class Wave
11 | {
12 | public:
13 | Wave() { }
14 | ~Wave() { }
15 |
16 | Wave(std::function shape, T left = 0, T right = 1, bool periodic = true)
17 | {
18 | this->shape = shape;
19 | this->left = left;
20 | this->right = right;
21 | this->periodic = periodic;
22 |
23 | for (int i = 0; i < TABSIZE; i++)
24 | {
25 | T phase = (T) i / TABSIZE;
26 | table[i] = shape((1 - phase) * left + phase * right);
27 | }
28 |
29 | this->endpoint = shape(right);
30 | }
31 |
32 | #ifdef FUNCTIONAL
33 | T lookup(T input)
34 | {
35 | return shape(input);
36 | }
37 | #else
38 | T lookup(T input)
39 | {
40 | T phase = (input - left) / (right - left);
41 |
42 | // get value at endpoint if input is out of bounds
43 | if (!periodic && (phase < 0 || phase >= 1))
44 | {
45 | if (phase < 0)
46 | return none(0);
47 | else
48 | return endpoint;
49 | }
50 | else
51 | {
52 | phase += 1;
53 | phase -= int(phase);
54 |
55 | int center = (int)(phase * TABSIZE) % TABSIZE;
56 | int after = (center + 1) % TABSIZE;
57 |
58 | T disp = (phase * TABSIZE - center);
59 | disp -= int(disp);
60 |
61 | return linear(center, after, disp);
62 | }
63 | }
64 | #endif
65 |
66 | T operator()(T phase)
67 | {
68 | return lookup(phase);
69 | }
70 |
71 | protected:
72 | T table[TABSIZE];
73 |
74 | private:
75 | T left; // input phases are interpreted as lying in [left, right)
76 | T right;
77 | bool periodic;
78 |
79 | T endpoint; // if (this->periodic == false), provides a value for (*this)(right)
80 |
81 | std::function shape;
82 |
83 | T none(int center)
84 | {
85 | return table[center];
86 | }
87 |
88 | T linear(int center, int after, T disp)
89 | {
90 | return table[center] * (1 - disp) + table[after] * disp;
91 | }
92 |
93 | };
94 | }
95 |
96 | #define WAVE
97 | #endif
--------------------------------------------------------------------------------
/software/Experiments/FmSynth/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = fmsynth
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Ofast
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = fmsynth.cpp
15 | CPP_SOURCES += operator.cpp
16 |
17 | # Library Locations
18 | LIBDAISY_DIR = ../../../libDaisy
19 | DAISYSP_DIR = ../../../DaisySP
20 |
21 | # Core location, and generic Makefile.
22 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
23 | include $(SYSTEM_FILES_DIR)/Makefile
24 |
25 |
26 | # Include funbox.h
27 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/FmSynth/README.md:
--------------------------------------------------------------------------------
1 | # FmSynth
2 |
3 | Experiment creating a FM Synth for Midi keyboard using Funbox. This synth uses just two operators, a modulator and a carrier. The modulator oscillator
4 | uses phase modulation to change the timbre of the carrier oscillator. An ADSR envelope is applied to both the modulator and carrier.
5 | The controls have been simplified to fit within the 6 knobs on Funbox.
6 |
7 | ## Controls
8 |
9 | | Control | Description | Comment |
10 | | --- | --- | --- |
11 | | Ctrl 1 | Level | The carrier level, or overall output of the synth |
12 | | Ctrl 2 | Mod level | The modulator level, which changes the timbre of the sound |
13 | | Ctrl 3 | Mod Ratio | Frequency multiplier of the modulator, from 0.5 to 16 by increments of 0.5, multiplied by the base frequncy of the note |
14 | | Ctrl 4 | Attack | Controls the Attack/Decay time of both the modulator and carrier |
15 | | Ctrl 5 | Sustain | Controls the sustain level (volume while note is held) |
16 | | Ctrl 6 | Release | Controls the release time of the note |
17 | | 3-Way Switch 1 | | |
18 | | 3-Way Switch 2 | | |
19 | | 3-Way Switch 3 | | |
20 | | Dip Switch 1 | | |
21 | | Dip Switch 2 | | |
22 | | FS 1 | Bypass | |
23 | | FS 2 | | |
24 | | LED 1 | Bypass Indicator | |
25 | | LED 2 | Lights up for MIDI Notes Received | |
26 | | Audio In 1 | N/A | Ignores Right channel input |
27 | | Audio Out 1 | Stereo | |
28 |
29 | Expression controls Knob 2 only, Mod Level. Plug in expression pedal to use, move knob 2 to deactivate expression control.
30 |
31 | ### MIDI Reference
32 |
33 | | Control | MIDI CC | Value |
34 | | --- | --- | --- |
35 | | Knob 1 | 14 | 0- 127 |
36 | | Knob 2 | 15 | 0- 127 |
37 | | Knob 3 | 16 | 0- 127 |
38 | | Knob 4 | 17 | 0- 127 |
39 | | Knob 5 | 18 | 0- 127 |
40 | | Knob 6 | 19 | 0- 127 |
41 |
42 | Takes Keyboard Midi input to play a sound.
43 |
44 | ## Build
45 |
46 | MidiKeys runs in Flash memory on the Daisy Seed.
47 |
48 |
--------------------------------------------------------------------------------
/software/Experiments/FmSynth/operator.cpp:
--------------------------------------------------------------------------------
1 | #include "operator.h"
2 |
3 | using namespace daisysp;
4 |
5 |
6 |
7 | void Operator::Init(float samplerate, bool isCarrier)
8 | {
9 | //init oscillators
10 | osc_.Init(samplerate);
11 |
12 | //set some reasonable values
13 | lfreq_ = freq_ = 440.f;
14 | lratio_ = ratio_ = 2.f;
15 | SetFrequency(lfreq_);
16 | SetRatio(lratio_);
17 |
18 | llevel_ = level_ = 1.0;
19 | osc_.SetAmp(llevel_);
20 |
21 | osc_.SetWaveform(Oscillator::WAVE_SIN);
22 |
23 | iscarrier_ = isCarrier;
24 |
25 | modval_ = 0.0;
26 |
27 | }
28 |
29 | float Operator::Process()
30 | {
31 | if(lratio_ != ratio_ || lfreq_ != freq_)
32 | {
33 | lratio_ = ratio_;
34 | lfreq_ = freq_;
35 | osc_.SetFreq(lfreq_ * lratio_);
36 | }
37 |
38 | if (llevel_ != level_) {
39 | llevel_ = level_;
40 | osc_.SetAmp(llevel_);
41 | }
42 |
43 | if (iscarrier_)
44 | osc_.PhaseAdd(modval_);
45 |
46 | // Return the processed oscillator, scaled by the velocity of the keystroke
47 | return osc_.Process() * velocity_amp_;
48 | }
49 |
50 | void Operator::SetFrequency(float freq) ///Currently unused
51 | {
52 | freq_ = fabsf(freq);
53 | }
54 |
55 | void Operator::SetRatio(float ratio)
56 | {
57 | ratio_ = fabsf(ratio);
58 | }
59 |
60 | void Operator::SetLevel(float level)
61 | {
62 | level_ = fabsf(level);
63 | }
64 |
65 | void Operator::setPhaseInput(float modval) // TODO should I use this function to just do the osc phase add instead?
66 | {
67 | modval_ = modval;
68 | }
69 |
70 |
71 | void Operator::Reset()
72 | {
73 | osc_.Reset();
74 | }
75 |
76 | void Operator::OnNoteOn(float note, float velocity)
77 | {
78 | velocity_ = velocity;
79 | velocity_amp_ = velocity_ / 127.f;
80 | freq_ = mtof(note); /// The base frequency of the note is set here, modified by the ratio in the Process function
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/software/Experiments/FmSynth/operator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef OPERATOR_H
3 | #define OPERATOR_H
4 |
5 | #include
6 | #include "daisysp.h"
7 | #ifdef __cplusplus
8 |
9 | using namespace daisysp;
10 |
11 |
12 | /**
13 | Single FM Operator that can be either a modulator or a carrier
14 | */
15 |
16 | class Operator
17 | {
18 | public:
19 | Operator() {}
20 | ~Operator() {}
21 |
22 | /** Initializes the Operator module.
23 | \param samplerate - The sample rate of the audio engine being run.
24 | */
25 | void Init(float samplerate, bool isCarrier);
26 |
27 |
28 | /** Returns the next sample
29 | */
30 | float Process();
31 |
32 | /** Carrier freq. setter
33 | \param freq Carrier frequency in Hz
34 | */
35 | void SetFrequency(float freq);
36 |
37 | /** Set modulator freq. relative to carrier
38 | \param ratio New modulator freq = carrier freq. * ratio
39 | */
40 | void SetRatio(float ratio);
41 |
42 | /** Sets the amplitude of the oscillator
43 | */
44 | void SetLevel(float level);
45 |
46 | /** Sets the phase input if this is a carrier driven by a modulator
47 | Intended to be called by an outside function at samplerate
48 | */
49 | void setPhaseInput(float modval);
50 |
51 | /** Resets oscillators */
52 | void Reset();
53 |
54 | ///////////////////////////// NEW STUFF
55 |
56 | /** Starts note */
57 | void OnNoteOn(float note, float velocity);
58 |
59 |
60 |
61 | private:
62 |
63 | Oscillator osc_;
64 | float level_, llevel_;
65 | float freq_, lfreq_, ratio_, lratio_;
66 | bool iscarrier_;
67 | float modval_;
68 |
69 | // Notes
70 | float velocity_;
71 | float velocity_amp_;
72 |
73 | };
74 | #endif
75 | #endif
76 |
--------------------------------------------------------------------------------
/software/Experiments/Granular/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = granular
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Ofast
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = granular.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../../libDaisy
18 | DAISYSP_DIR = ../../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/Granular/README.md:
--------------------------------------------------------------------------------
1 | # Granular
2 |
3 | Experiment testing out the GranularPlayer class in DaisySP. Uses a triggered 2 second sample recorder.
4 |
5 | ## Controls
6 |
7 | | Control | Description | Comment |
8 | | --- | --- | --- |
9 | | Ctrl 1 | Size | Grain size 1ms to 200ms |
10 | | Ctrl 2 | Speed | Speed of grain playback -2x to +2x |
11 | | Ctrl 3 | Pitch | Pitch (transposition) of the grains, -1 to +1 octave |
12 | | Ctrl 4 | Mix | Controls the Attack/Decay time of both the modulator and carrier |
13 | | Ctrl 5 | Level | Controls the sustain level (volume while note is held) |
14 | | Ctrl 6 | | |
15 | | 3-Way Switch 1 | | |
16 | | 3-Way Switch 2 | | |
17 | | 3-Way Switch 3 | | |
18 | | Dip Switch 1 | | |
19 | | Dip Switch 2 | | |
20 | | FS 1 | Bypass | |
21 | | FS 2 | Trigger | Trigger recording a sample (will repeat until another sample is recorded) |
22 | | LED 1 | Bypass Indicator | |
23 | | LED 2 | Recording Indicator | |
24 | | Audio In 1 | N/A | Ignores Right channel input |
25 | | Audio Out 1 | Stereo | |
26 |
27 | Expression controls Knob 2 only, Speed. Plug in expression pedal to use, move knob 2 to deactivate expression control.
28 |
29 |
30 |
31 | ## Build
32 |
33 | Granular runs in Flash memory on the Daisy Seed.
34 |
35 |
--------------------------------------------------------------------------------
/software/Experiments/MidiKeys/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = midikeys
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | #OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = midikeys.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../../libDaisy
18 | DAISYSP_DIR = ../../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/MidiKeys/README.md:
--------------------------------------------------------------------------------
1 | # MidiKeys
2 |
3 | Experiment using the DaisySP ModalVoice, StringVoice, and a synth voice. Use a midi keyboard to strike the resonator, and shape the sound with the controls.
4 | Reverb and Delay included as well.
5 | Monophonic (one note at a time) for modal and string, and 8 polyphony for synth.
6 | An expression pedal can be used to control knob 1. The expression takes control when the pedal is moved.
7 |
8 | ## Controls
9 |
10 | | Control | Description | Comment |
11 | | --- | --- | --- |
12 | | Ctrl 1 | Structure or Synth Filter | Can be Expression controlled |
13 | | Ctrl 2 | Brightness | |
14 | | Ctrl 3 | Level | |
15 | | Ctrl 4 | Damping | |
16 | | Ctrl 5 | Reverb Time or Delay Time | |
17 | | Ctrl 6 | Reverb Damping or Delay Feedback| |
18 | | 3-Way Switch 1 | Voice Mode | left=Modal, center=String spreadFreq, right=Synth |
19 | | 3-Way Switch 2 | Effect Mode | left=Reverb, center=Dotted 8th Delay, right=Normal Delay |
20 | | 3-Way Switch 3 | | |
21 | | Dip Switch 1 | | |
22 | | Dip Switch 2 | | |
23 | | FS 1 | Bypass | |
24 | | FS 2 | | |
25 | | LED 1 | Bypass Indicator | |
26 | | LED 2 | Lights up for MIDI Notes Received | |
27 | | Audio In 1 | N/A | Ignores Right channel input |
28 | | Audio Out 1 | Stereo | |
29 |
30 | ### MIDI Reference
31 |
32 | | Control | MIDI CC | Value |
33 | | --- | --- | --- |
34 | | Knob 1 | 14 | 0- 127 |
35 | | Knob 2 | 15 | 0- 127 |
36 | | Knob 3 | 16 | 0- 127 |
37 | | Knob 4 | 17 | 0- 127 |
38 | | Knob 5 | 18 | 0- 127 |
39 | | Knob 6 | 19 | 0- 127 |
40 |
41 | Takes Keyboard Midi input to play a sound.
42 |
43 | ## Build
44 |
45 | MidiKeys runs in Flash memory on the Daisy Seed.
46 |
47 |
--------------------------------------------------------------------------------
/software/Experiments/NoiseFilterFFT/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = noisefilter
3 |
4 | # Sources
5 | CPP_SOURCES = noisefilter.cpp
6 |
7 | OPT = -O1
8 | #OPT ?= -O3
9 |
10 | # Library Locations
11 | LIBDAISY_DIR = ../../../libDaisy
12 | DAISYSP_DIR = ../../../DaisySP
13 |
14 |
15 | # Core location, and generic Makefile.
16 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
17 | include $(SYSTEM_FILES_DIR)/Makefile
18 |
19 |
20 | # Include funbox.h
21 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/NoiseFilterFFT/README.md:
--------------------------------------------------------------------------------
1 | # NoiseFilterFFT
2 |
3 | A test using a Short Time Fourier Transform to filter out noise using a subractive method. Hold the
4 | right footswitch for the pedal to "learn" the current background noise. Don't play the guitar while
5 | in learning mode. Let go of the right footswitch to stop learning, and perform the noise reduction on
6 | your guitar signal. The learned noise in each FFT bin is subtracted from your signal. Hold the right
7 | footswitch again to clear the previous learned noise and start learning mode again.
8 |
9 | Note: The NoiseFilter won't eliminate noise created by the Funbox pedal itself, as it can only learn the noise from the signal going into it.
10 |
11 |
12 | This code adapts the code found here to run on Funbox hardware:
13 | https://github.com/amcerbu/DaisySTFT
14 |
15 | The noise reduction logic was obtained from the noise-reduction STFT example in this blog post:
16 | https://forum.cockos.com/showthread.php?t=225955
17 |
18 |
19 | ## Controls
20 |
21 | | Control | Description | Comment |
22 | | --- | --- | --- |
23 | | Ctrl 1 | Reduction Factor | Amount of noise reduction |
24 | | Ctrl 2 | Level | Output level, 0 to 2x |
25 | | Ctrl 3 | | |
26 | | Ctrl 4 | | |
27 | | Ctrl 5 | | |
28 | | Ctrl 6 | | |
29 | | 3-Way Switch 1 | | |
30 | | 3-Way Switch 2 | | |
31 | | 3-Way Switch 3 | | |
32 | | Dip Switch 1 | | |
33 | | Dip Switch 2 | | |
34 | | FS 1 | Bypass/Engage | |
35 | | FS 2 | Learning mode | While held, will learn the current noise level. Let go to stop learning. |
36 | | LED 1 | Bypass indicator | |
37 | | LED 2 | Learning indicator | Illuminated while in learning mode |
38 | | Audio In 1 | Mono In | |
39 | | Audio Out 1 | Mono out (left copied to right channel) | |
40 |
41 |
42 | ## Build
43 |
44 | Denoise runs in Flash memory on the Daisy Seed.
45 |
--------------------------------------------------------------------------------
/software/Experiments/NoiseFilterFFT/wave.h:
--------------------------------------------------------------------------------
1 | // wave.h // interpolated lookup table
2 | #ifndef WAVE
3 |
4 | #include
5 |
6 | namespace soundmath
7 | {
8 | const int TABSIZE = 2048;
9 |
10 | template class Wave
11 | {
12 | public:
13 | Wave() { }
14 | ~Wave() { }
15 |
16 | Wave(std::function shape, T left = 0, T right = 1, bool periodic = true)
17 | {
18 | this->shape = shape;
19 | this->left = left;
20 | this->right = right;
21 | this->periodic = periodic;
22 |
23 | for (int i = 0; i < TABSIZE; i++)
24 | {
25 | T phase = (T) i / TABSIZE;
26 | table[i] = shape((1 - phase) * left + phase * right);
27 | }
28 |
29 | this->endpoint = shape(right);
30 | }
31 |
32 | #ifdef FUNCTIONAL
33 | T lookup(T input)
34 | {
35 | return shape(input);
36 | }
37 | #else
38 | T lookup(T input)
39 | {
40 | T phase = (input - left) / (right - left);
41 |
42 | // get value at endpoint if input is out of bounds
43 | if (!periodic && (phase < 0 || phase >= 1))
44 | {
45 | if (phase < 0)
46 | return none(0);
47 | else
48 | return endpoint;
49 | }
50 | else
51 | {
52 | phase += 1;
53 | phase -= int(phase);
54 |
55 | int center = (int)(phase * TABSIZE) % TABSIZE;
56 | int after = (center + 1) % TABSIZE;
57 |
58 | T disp = (phase * TABSIZE - center);
59 | disp -= int(disp);
60 |
61 | return linear(center, after, disp);
62 | }
63 | }
64 | #endif
65 |
66 | T operator()(T phase)
67 | {
68 | return lookup(phase);
69 | }
70 |
71 | protected:
72 | T table[TABSIZE];
73 |
74 | private:
75 | T left; // input phases are interpreted as lying in [left, right)
76 | T right;
77 | bool periodic;
78 |
79 | T endpoint; // if (this->periodic == false), provides a value for (*this)(right)
80 |
81 | std::function shape;
82 |
83 | T none(int center)
84 | {
85 | return table[center];
86 | }
87 |
88 | T linear(int center, int after, T disp)
89 | {
90 | return table[center] * (1 - disp) + table[after] * disp;
91 | }
92 |
93 | };
94 | }
95 |
96 | #define WAVE
97 | #endif
--------------------------------------------------------------------------------
/software/Experiments/README.md:
--------------------------------------------------------------------------------
1 | # Pedal Experiments
--------------------------------------------------------------------------------
/software/Experiments/SpectralReverb/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = spectralreverb
3 |
4 | # Sources
5 | CPP_SOURCES = spectralreverb.cpp
6 |
7 | OPT = -O1
8 | #OPT ?= -O3
9 |
10 | # Library Locations
11 | LIBDAISY_DIR = ../../../libDaisy
12 | DAISYSP_DIR = ../../../DaisySP
13 |
14 |
15 | # Core location, and generic Makefile.
16 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
17 | include $(SYSTEM_FILES_DIR)/Makefile
18 |
19 |
20 | # Include funbox.h
21 | C_INCLUDES += -I../../../include
--------------------------------------------------------------------------------
/software/Experiments/SpectralReverb/README.md:
--------------------------------------------------------------------------------
1 | # Spectral Reverb
2 |
3 | Spectral Reverb using an stft
4 | This code adapts the code found here to run on Funbox hardware:
5 | https://github.com/amcerbu/DaisySTFT
6 |
7 | This reverb is based on the example reverb found on this forum:
8 | https://forum.cockos.com/showthread.php?t=225955
9 |
10 |
11 | ## Controls
12 |
13 | | Control | Description | Comment |
14 | | --- | --- | --- |
15 | | Ctrl 1 | Decay | Decay time of reverb |
16 | | Ctrl 2 | Mix | Dry/Wet mix |
17 | | Ctrl 3 | Damp | Reverb dampening |
18 | | Ctrl 4 | Shimmer Amount | Adds octave shimmer |
19 | | Ctrl 5 | Shimmer Tone | Adds in octave + 5ths to shimmer |
20 | | Ctrl 6 | | |
21 | | 3-Way Switch 1 | Shimmer Mode | left=octave up, center= octave down, right=octave up and octave down |
22 | | 3-Way Switch 2 | | |
23 | | 3-Way Switch 3 | | |
24 | | Dip Switch 1 | | |
25 | | Dip Switch 2 | | |
26 | | FS 1 | Bypass/Engage | |
27 | | FS 2 | Freeze | |
28 | | LED 1 | Bypass indicator | |
29 | | LED 2 | Freeze indicator | |
30 | | Audio In 1 | Mono in | |
31 | | Audio Out 1 | Mono out (left copied to right) | |
32 |
33 |
34 | ## Build
35 |
36 | Spectral Reverb runs in Flash memory on the Daisy Seed.
37 |
38 |
--------------------------------------------------------------------------------
/software/Experiments/SpectralReverb/wave.h:
--------------------------------------------------------------------------------
1 | // wave.h // interpolated lookup table
2 | #ifndef WAVE
3 |
4 | #include
5 |
6 | namespace soundmath
7 | {
8 | const int TABSIZE = 2048;
9 |
10 | template class Wave
11 | {
12 | public:
13 | Wave() { }
14 | ~Wave() { }
15 |
16 | Wave(std::function shape, T left = 0, T right = 1, bool periodic = true)
17 | {
18 | this->shape = shape;
19 | this->left = left;
20 | this->right = right;
21 | this->periodic = periodic;
22 |
23 | for (int i = 0; i < TABSIZE; i++)
24 | {
25 | T phase = (T) i / TABSIZE;
26 | table[i] = shape((1 - phase) * left + phase * right);
27 | }
28 |
29 | this->endpoint = shape(right);
30 | }
31 |
32 | #ifdef FUNCTIONAL
33 | T lookup(T input)
34 | {
35 | return shape(input);
36 | }
37 | #else
38 | T lookup(T input)
39 | {
40 | T phase = (input - left) / (right - left);
41 |
42 | // get value at endpoint if input is out of bounds
43 | if (!periodic && (phase < 0 || phase >= 1))
44 | {
45 | if (phase < 0)
46 | return none(0);
47 | else
48 | return endpoint;
49 | }
50 | else
51 | {
52 | phase += 1;
53 | phase -= int(phase);
54 |
55 | int center = (int)(phase * TABSIZE) % TABSIZE;
56 | int after = (center + 1) % TABSIZE;
57 |
58 | T disp = (phase * TABSIZE - center);
59 | disp -= int(disp);
60 |
61 | return linear(center, after, disp);
62 | }
63 | }
64 | #endif
65 |
66 | T operator()(T phase)
67 | {
68 | return lookup(phase);
69 | }
70 |
71 | protected:
72 | T table[TABSIZE];
73 |
74 | private:
75 | T left; // input phases are interpreted as lying in [left, right)
76 | T right;
77 | bool periodic;
78 |
79 | T endpoint; // if (this->periodic == false), provides a value for (*this)(right)
80 |
81 | std::function shape;
82 |
83 | T none(int center)
84 | {
85 | return table[center];
86 | }
87 |
88 | T linear(int center, int after, T disp)
89 | {
90 | return table[center] * (1 - disp) + table[after] * disp;
91 | }
92 |
93 | };
94 | }
95 |
96 | #define WAVE
97 | #endif
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AllpassDiffuser.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include
5 | #include "ModulatedAllpass.h"
6 | #include "AudioLib/ShaRandom.h"
7 |
8 | using namespace std;
9 |
10 | namespace CloudSeed
11 | {
12 | class AllpassDiffuser
13 | {
14 | public:
15 | static const int MaxStageCount = 2;
16 |
17 | private:
18 | int samplerate;
19 |
20 | vector filters;
21 | int delay;
22 | float modRate;
23 | vector seedValues;
24 | int seed;
25 | float crossSeed;
26 |
27 | public:
28 | int Stages;
29 |
30 | AllpassDiffuser(int samplerate, int delayBufferLengthMillis)
31 | {
32 | auto delayBufferSize = samplerate * ((float)delayBufferLengthMillis / 1000.0);
33 | for (int i = 0; i < MaxStageCount; i++)
34 | {
35 | filters.push_back(new ModulatedAllpass((int)delayBufferSize, 100));
36 | }
37 |
38 | crossSeed = 0.0;
39 | seed = 23456;
40 | UpdateSeeds();
41 | Stages = 1;
42 |
43 | SetSamplerate(samplerate);
44 | }
45 |
46 | ~AllpassDiffuser()
47 | {
48 | for (auto filter : filters)
49 | delete filter;
50 | }
51 |
52 | int GetSamplerate()
53 | {
54 | return samplerate;
55 | }
56 |
57 | void SetSamplerate(int samplerate)
58 | {
59 | this->samplerate = samplerate;
60 | SetModRate(modRate);
61 | }
62 |
63 | void SetSeed(int seed)
64 | {
65 | this->seed = seed;
66 | UpdateSeeds();
67 | }
68 |
69 | void SetCrossSeed(float crossSeed)
70 | {
71 | this->crossSeed = crossSeed;
72 | UpdateSeeds();
73 | }
74 |
75 |
76 | bool GetModulationEnabled()
77 | {
78 | return filters[0]->ModulationEnabled;
79 | }
80 |
81 | void SetModulationEnabled(bool value)
82 | {
83 | for (auto filter : filters)
84 | filter->ModulationEnabled = value;
85 | }
86 |
87 | void SetInterpolationEnabled(bool enabled)
88 | {
89 | for (auto filter : filters)
90 | filter->InterpolationEnabled = enabled;
91 | }
92 |
93 | float* GetOutput()
94 | {
95 | return filters[Stages - 1]->GetOutput();
96 | }
97 |
98 |
99 | void SetDelay(int delaySamples)
100 | {
101 | delay = delaySamples;
102 | Update();
103 | }
104 |
105 | void SetFeedback(float feedback)
106 | {
107 | for (auto filter : filters)
108 | filter->Feedback = feedback;
109 | }
110 |
111 | void SetModAmount(float amount)
112 | {
113 | for (int i = 0; i < filters.size(); i++)
114 | {
115 | filters[i]->ModAmount = amount * (0.85 + 0.3 * seedValues[MaxStageCount + i]);
116 | }
117 | }
118 |
119 | void SetModRate(float rate)
120 | {
121 | modRate = rate;
122 |
123 | for (size_t i = 0; i < filters.size(); i++)
124 | filters[i]->ModRate = rate * (0.85 + 0.3 * seedValues[MaxStageCount * 2 + i]) / samplerate;
125 | }
126 |
127 | void Process(float* input, int sampleCount)
128 | {
129 | ModulatedAllpass** filterPtr = &filters[0];
130 |
131 | filterPtr[0]->Process(input, sampleCount);
132 |
133 | for (int i = 1; i < Stages; i++)
134 | {
135 | filterPtr[i]->Process(filterPtr[i - 1]->GetOutput(), sampleCount);
136 | }
137 | }
138 |
139 | void ClearBuffers()
140 | {
141 | for (size_t i = 0; i < filters.size(); i++)
142 | filters[i]->ClearBuffers();
143 | }
144 |
145 | private:
146 | void Update()
147 | {
148 | for (size_t i = 0; i < filters.size(); i++)
149 | {
150 | auto r = seedValues[i];
151 | auto d = std::pow(10, r) * 0.1; // 0.1 ... 1.0
152 | filters[i]->SampleDelay = (int)(delay * d);
153 | }
154 | }
155 |
156 | void UpdateSeeds()
157 | {
158 | this->seedValues = AudioLib::ShaRandom::Generate(seed, MaxStageCount * 3, crossSeed);
159 | Update();
160 | }
161 |
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/Biquad2.cpp:
--------------------------------------------------------------------------------
1 | #define _USE_MATH_DEFINES
2 | #include
3 | #include "Biquad2.h"
4 |
5 | namespace AudioLib
6 | {
7 | Biquad2::Biquad2()
8 | {
9 | ClearBuffers();
10 | }
11 |
12 | Biquad2::Biquad2(FilterType filterType, float samplerate)
13 | {
14 | Type = filterType;
15 | SetSamplerate(samplerate);
16 |
17 | SetGainDb(0.0);
18 | Frequency = samplerate / 4;
19 | SetQ(0.5);
20 | ClearBuffers();
21 | }
22 |
23 | Biquad2::~Biquad2()
24 | {
25 |
26 | }
27 |
28 |
29 | float Biquad2::GetSamplerate()
30 | {
31 | return samplerate;
32 | }
33 |
34 | void Biquad2::SetSamplerate(float value)
35 | {
36 | samplerate = value;
37 | Update();
38 | }
39 |
40 | float Biquad2::GetGainDb()
41 | {
42 | return std::log10(gain) * 20;
43 | }
44 |
45 | void Biquad2::SetGainDb(float value)
46 | {
47 | SetGain(std::pow(10, value / 20));
48 | }
49 |
50 | float Biquad2::GetGain()
51 | {
52 | return gain;
53 | }
54 |
55 | void Biquad2::SetGain(float value)
56 | {
57 | if (value == 0)
58 | value = 0.001; // -60dB
59 |
60 | gain = value;
61 | }
62 |
63 | float Biquad2::GetQ()
64 | {
65 | return _q;
66 | }
67 |
68 | void Biquad2::SetQ(float value)
69 | {
70 | if (value == 0)
71 | value = 1e-12;
72 | _q = value;
73 | }
74 |
75 | vector Biquad2::GetA()
76 | {
77 | return vector({ 1, a1, a2 });
78 | }
79 |
80 | vector Biquad2::GetB()
81 | {
82 | return vector({ b0, b1, b2 });
83 | }
84 |
85 |
86 | void Biquad2::Update()
87 | {
88 | float omega = 2 * M_PI * Frequency / samplerate;
89 | float sinOmega = std::sin(omega);
90 | float cosOmega = std::cos(omega);
91 |
92 | float sqrtGain = 0.0;
93 | float alpha = 0.0;
94 |
95 | if (Type == FilterType::LowShelf || Type == FilterType::HighShelf)
96 | {
97 | alpha = sinOmega / 2 * std::sqrt((gain + 1 / gain) * (1 / Slope - 1) + 2);
98 | sqrtGain = std::sqrt(gain);
99 | }
100 | else
101 | {
102 | alpha = sinOmega / (2 * _q);
103 | }
104 |
105 | switch (Type)
106 | {
107 | case FilterType::LowPass:
108 | b0 = (1 - cosOmega) / 2;
109 | b1 = 1 - cosOmega;
110 | b2 = (1 - cosOmega) / 2;
111 | a0 = 1 + alpha;
112 | a1 = -2 * cosOmega;
113 | a2 = 1 - alpha;
114 | break;
115 | case FilterType::HighPass:
116 | b0 = (1 + cosOmega) / 2;
117 | b1 = -(1 + cosOmega);
118 | b2 = (1 + cosOmega) / 2;
119 | a0 = 1 + alpha;
120 | a1 = -2 * cosOmega;
121 | a2 = 1 - alpha;
122 | break;
123 | case FilterType::BandPass:
124 | b0 = alpha;
125 | b1 = 0;
126 | b2 = -alpha;
127 | a0 = 1 + alpha;
128 | a1 = -2 * cosOmega;
129 | a2 = 1 - alpha;
130 | break;
131 | case FilterType::Notch:
132 | b0 = 1;
133 | b1 = -2 * cosOmega;
134 | b2 = 1;
135 | a0 = 1 + alpha;
136 | a1 = -2 * cosOmega;
137 | a2 = 1 - alpha;
138 | break;
139 | case FilterType::Peak:
140 | b0 = 1 + (alpha * gain);
141 | b1 = -2 * cosOmega;
142 | b2 = 1 - (alpha * gain);
143 | a0 = 1 + (alpha / gain);
144 | a1 = -2 * cosOmega;
145 | a2 = 1 - (alpha / gain);
146 | break;
147 | case FilterType::LowShelf:
148 | b0 = gain * ((gain + 1) - (gain - 1) * cosOmega + 2 * sqrtGain * alpha);
149 | b1 = 2 * gain * ((gain - 1) - (gain + 1) * cosOmega);
150 | b2 = gain * ((gain + 1) - (gain - 1) * cosOmega - 2 * sqrtGain * alpha);
151 | a0 = (gain + 1) + (gain - 1) * cosOmega + 2 * sqrtGain * alpha;
152 | a1 = -2 * ((gain - 1) + (gain + 1) * cosOmega);
153 | a2 = (gain + 1) + (gain - 1) * cosOmega - 2 * sqrtGain * alpha;
154 | break;
155 | case FilterType::HighShelf:
156 | b0 = gain * ((gain + 1) + (gain - 1) * cosOmega + 2 * sqrtGain * alpha);
157 | b1 = -2 * gain * ((gain - 1) + (gain + 1) * cosOmega);
158 | b2 = gain * ((gain + 1) + (gain - 1) * cosOmega - 2 * sqrtGain * alpha);
159 | a0 = (gain + 1) - (gain - 1) * cosOmega + 2 * sqrtGain * alpha;
160 | a1 = 2 * ((gain - 1) - (gain + 1) * cosOmega);
161 | a2 = (gain + 1) - (gain - 1) * cosOmega - 2 * sqrtGain * alpha;
162 | break;
163 | }
164 |
165 | float g = 1 / a0;
166 |
167 | b0 = b0 * g;
168 | b1 = b1 * g;
169 | b2 = b2 * g;
170 | a1 = a1 * g;
171 | a2 = a2 * g;
172 | }
173 |
174 | float Biquad2::GetResponse(float freq)
175 | {
176 | float phi = std::pow((std::sin(2 * M_PI * freq / (2.0 * samplerate))), 2);
177 | return (std::pow(b0 + b1 + b2, 2.0) - 4.0 * (b0 * b1 + 4.0 * b0 * b2 + b1 * b2) * phi + 16.0 * b0 * b2 * phi * phi) / (std::pow(1.0 + a1 + a2, 2.0) - 4.0 * (a1 + 4.0 * a2 + a1 * a2) * phi + 16.0 * a2 * phi * phi);
178 | }
179 |
180 | void Biquad2::ClearBuffers()
181 | {
182 | y = 0;
183 | x2 = 0;
184 | y2 = 0;
185 | x1 = 0;
186 | y1 = 0;
187 | }
188 |
189 | }
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/Biquad2.h:
--------------------------------------------------------------------------------
1 | #ifndef BIQUAD2
2 | #define BIQUAD2
3 |
4 | #include
5 | using namespace std;
6 |
7 | namespace AudioLib
8 | {
9 | class Biquad2
10 | {
11 | public:
12 | enum class FilterType
13 | {
14 | LowPass = 0,
15 | HighPass,
16 | BandPass,
17 | Notch,
18 | Peak,
19 | LowShelf,
20 | HighShelf
21 | };
22 |
23 | private:
24 | float samplerate;
25 | float _gainDb;
26 | float _q;
27 | float a0, a1, a2, b0, b1, b2;
28 | float x1, x2, y, y1, y2;
29 | float gain;
30 |
31 | public:
32 | FilterType Type;
33 | float Output;
34 | float Frequency;
35 | float Slope;
36 |
37 | Biquad2();
38 | Biquad2(FilterType filterType, float samplerate);
39 | ~Biquad2();
40 |
41 | float GetSamplerate();
42 | void SetSamplerate(float samplerate);
43 | float GetGainDb();
44 | void SetGainDb(float value);
45 | float GetGain();
46 | void SetGain(float value);
47 | float GetQ();
48 | void SetQ(float value);
49 | vector GetA();
50 | vector GetB();
51 |
52 | void Update();
53 | float GetResponse(float freq);
54 |
55 | float inline Process(float x)
56 | {
57 | y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
58 | x2 = x1;
59 | y2 = y1;
60 | x1 = x;
61 | y1 = y;
62 |
63 | Output = y;
64 | return Output;
65 | }
66 |
67 | void inline Process(float* input, float* output, int len)
68 | {
69 | for (int i = 0; i < len; i++)
70 | output[i] = Process(input[i]);
71 | }
72 |
73 | void ClearBuffers();
74 | };
75 | }
76 |
77 | #endif
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/Hp1.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #define PI 3.141592653589793238462643383
5 |
6 | namespace AudioLib
7 | {
8 | class Hp1
9 | {
10 | private:
11 | float fs;
12 | float b0, a1;
13 | float lpOut;
14 | float cutoffHz;
15 |
16 | public:
17 | float Output;
18 |
19 | public:
20 | Hp1(float fs)
21 | {
22 | this->lpOut = 0;
23 | this->fs = fs;
24 | }
25 |
26 | float GetSamplerate()
27 | {
28 | return fs;
29 | }
30 |
31 | void SetSamplerate(float samplerate)
32 | {
33 | fs = samplerate;
34 | }
35 |
36 | float GetCutoffHz()
37 | {
38 | return cutoffHz;
39 | }
40 |
41 | void SetCutoffHz(float hz)
42 | {
43 | cutoffHz = hz;
44 | Update();
45 | }
46 |
47 | void Update()
48 | {
49 | // Prevent going over the Nyquist frequency
50 | if (cutoffHz >= fs * 0.5)
51 | cutoffHz = fs * 0.499;
52 |
53 | auto x = 2 * PI * cutoffHz / fs;
54 | auto nn = (2 - cos(x));
55 | auto alpha = nn - sqrt(nn * nn - 1);
56 |
57 | a1 = alpha;
58 | b0 = 1 - alpha;
59 | }
60 |
61 | float Process(float input)
62 | {
63 | if (input == 0 && lpOut < 0.000000000001)
64 | {
65 | Output = 0;
66 | }
67 | else
68 | {
69 | lpOut = b0 * input + a1 * lpOut;
70 | Output = input - lpOut;
71 | }
72 |
73 | return Output;
74 | }
75 |
76 | void Process(float* input, float* output, int len)
77 | {
78 | for (int i = 0; i < len; i++)
79 | output[i] = Process(input[i]);
80 | }
81 | };
82 | }
83 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/Lp1.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #define PI 3.141592653589793238462643383
6 |
7 | namespace AudioLib
8 | {
9 | using namespace std;
10 |
11 | class Lp1
12 | {
13 | public:
14 | float Output;
15 |
16 | public:
17 | Lp1(float fs)
18 | {
19 | this->fs = fs;
20 | }
21 |
22 | float GetSamplerate()
23 | {
24 | return fs;
25 | }
26 |
27 | void SetSamplerate(float samplerate)
28 | {
29 | fs = samplerate;
30 | }
31 |
32 | float GetCutoffHz()
33 | {
34 | return cutoffHz;
35 | }
36 |
37 | void SetCutoffHz(float hz)
38 | {
39 | cutoffHz = hz;
40 | Update();
41 | }
42 |
43 | void Update()
44 | {
45 | // Prevent going over the Nyquist frequency
46 | if (cutoffHz >= fs * 0.5)
47 | cutoffHz = fs * 0.499;
48 |
49 | auto x = 2 * PI * cutoffHz / fs;
50 | auto nn = (2 - cos(x));
51 | auto alpha = nn - sqrt(nn * nn - 1);
52 |
53 | a1 = alpha;
54 | b0 = 1 - alpha;
55 | }
56 |
57 | float Process(float input)
58 | {
59 | if (input == 0 && Output < 0.000000000001)
60 | {
61 | Output = 0;
62 | }
63 | else
64 | {
65 | Output = b0 * input + a1 * Output;
66 | }
67 | return Output;
68 | }
69 |
70 | void Process(float* input, float* output, int len)
71 | {
72 | for (int i = 0; i < len; i++)
73 | output[i] = Process(input[i]);
74 | }
75 |
76 |
77 | private:
78 | float fs;
79 | float b0, a1;
80 | float cutoffHz;
81 | };
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/MathDefs.h:
--------------------------------------------------------------------------------
1 | #ifndef MATH_DEFS
2 | #define MATH_DEFS
3 |
4 | #ifndef DSY_SDRAM_BSS
5 | #define DSY_SDRAM_BSS __attribute__((section(".sdram_bss")))
6 | #endif
7 |
8 |
9 |
10 |
11 | //#define M_E 2.71828182845904523536 // e
12 | //#define M_LOG2E 1.44269504088896340736 // log2(e)
13 | //#define M_LOG10E 0.434294481903251827651 // log10(e)
14 | //#define M_LN2 0.693147180559945309417 // ln(2)
15 | //#define M_LN10 2.30258509299404568402 // ln(10)
16 | #define M_PI 3.14159265358979323846 // pi
17 | #define M_PI_2 1.57079632679489661923 // pi/2
18 | //#define M_PI_4 0.785398163397448309616 // pi/4
19 | //#define M_1_PI 0.318309886183790671538 // 1/pi
20 | //#define M_2_PI 0.636619772367581343076 // 2/pi
21 | #define M_2_SQRTPI 1.12837916709551257390 // 2/sqrt(pi)
22 | #define M_SQRT2 1.41421356237309504880 // sqrt(2)
23 | //#define M_SQRT1_2 0.707106781186547524401 // 1/sqrt(2)
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/ShaRandom.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include "ShaRandom.h"
4 | #include "../Utils/Sha256.h"
5 |
6 | namespace AudioLib
7 | {
8 | using namespace std;
9 |
10 | vector ShaRandom::Generate(long long seed, int count)
11 | {
12 | vector byteList;
13 | auto iterations = count * sizeof(unsigned int) / (256 / 8) + 1;
14 | auto byteArr = (unsigned char*)&seed;
15 | vector bytes(byteArr, byteArr + 8);
16 |
17 | for (size_t i = 0; i < iterations; i++)
18 | {
19 | bytes = sha256(&bytes[0], 8);
20 | for (auto b : bytes)
21 | byteList.push_back(b);
22 | }
23 |
24 | auto intArray = (unsigned int*)(&byteList[0]);
25 | vector output;
26 |
27 | for (int i = 0; i < count; i++)
28 | {
29 | unsigned int val = intArray[i];
30 | float doubleVal = val / (float)UINT_MAX;
31 | output.push_back(doubleVal);
32 | }
33 |
34 | return output;
35 | }
36 |
37 | vector ShaRandom::Generate(long long seed, int count, float crossSeed)
38 | {
39 | auto seedA = seed;
40 | auto seedB = ~seed;
41 | auto seriesA = Generate(seedA, count);
42 | auto seriesB = Generate(seedB, count);
43 |
44 | vector output;
45 | for (int i = 0; i < count; i++)
46 | output.push_back(seriesA[i] * (1 - crossSeed) + seriesB[i] * crossSeed);
47 |
48 | return output;
49 | }
50 | }
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/ShaRandom.h:
--------------------------------------------------------------------------------
1 | #ifndef SHARANDOM
2 | #define SHARANDOM
3 |
4 | #include
5 |
6 | namespace AudioLib
7 | {
8 | class ShaRandom
9 | {
10 | public:
11 | static std::vector Generate(long long seed, int count);
12 | static std::vector Generate(long long seed, int count, float crossSeed);
13 | };
14 | }
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/ValueTables.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include "ValueTables.h"
4 | #include
5 |
6 | namespace AudioLib
7 | {
8 | float DSY_SDRAM_BSS ValueTables::Sqrt[TableSize];
9 | float DSY_SDRAM_BSS ValueTables::Sqrt3[TableSize];
10 | float DSY_SDRAM_BSS ValueTables::Pow1_5[TableSize];
11 | float DSY_SDRAM_BSS ValueTables::Pow2[TableSize];
12 | float DSY_SDRAM_BSS ValueTables::Pow3[TableSize];
13 | float DSY_SDRAM_BSS ValueTables::Pow4[TableSize];
14 | float DSY_SDRAM_BSS ValueTables::x2Pow3[TableSize];
15 |
16 | // octave response. value float every step (2,3,4,5 or 6 steps)
17 | float DSY_SDRAM_BSS ValueTables::Response2Oct[TableSize];
18 | float DSY_SDRAM_BSS ValueTables::Response3Oct[TableSize];
19 | float DSY_SDRAM_BSS ValueTables::Response4Oct[TableSize];
20 | float DSY_SDRAM_BSS ValueTables::Response5Oct[TableSize];
21 | float DSY_SDRAM_BSS ValueTables::Response6Oct[TableSize];
22 |
23 | // decade response, value multiplies by 10 every step
24 | float DSY_SDRAM_BSS ValueTables::Response2Dec[TableSize];
25 | float DSY_SDRAM_BSS ValueTables::Response3Dec[TableSize];
26 | float DSY_SDRAM_BSS ValueTables::Response4Dec[TableSize];
27 |
28 | void ValueTables::Init()
29 | {
30 | // Initialize tables
31 |
32 | for (int i = 0; i <= 4000; i++)
33 | {
34 | float x = i / 4000.0;
35 |
36 | Sqrt[i] = std::sqrt(x);
37 | Sqrt3[i] = std::pow(x, 1.0 / 3.0);
38 | Pow1_5[i] = std::pow(x, 1.5);
39 | Pow2[i] = std::pow(x, 2.0);
40 | Pow3[i] = std::pow(x, 3.0);
41 | Pow4[i] = std::pow(x, 4.0);
42 |
43 | x2Pow3[i] = std::pow(2 * x, 3.0);
44 | Response2Oct[i] = (std::pow(4, x) - 1.0) / 4.0 + 0.25;
45 | Response3Oct[i] = (std::pow(8, x) - 1.0) / 8.0 + 0.125;
46 | Response4Oct[i] = (std::pow(16, x) - 1.0) / 16.0 + 0.125 / 2.0;
47 | Response5Oct[i] = (std::pow(32, x) - 1.0) / 32.0 + 0.125 / 4.0;
48 | Response6Oct[i] = (std::pow(64, x) - 1.0) / 64.0 + 0.125 / 8.0;
49 |
50 | Response2Dec[i] = std::pow(100, x) / 100.0;
51 | Response3Dec[i] = std::pow(1000, x) / 1000.0;
52 | Response4Dec[i] = std::pow(10000, x) / 10000.0;
53 | }
54 |
55 | for (int i = 1; i <= 4000; i++)
56 | {
57 | Response2Oct[i] = (Response2Oct[i] - Response2Oct[0]) / (1 - Response2Oct[0]);
58 | Response3Oct[i] = (Response3Oct[i] - Response3Oct[0]) / (1 - Response3Oct[0]);
59 | Response4Oct[i] = (Response4Oct[i] - Response4Oct[0]) / (1 - Response4Oct[0]);
60 | Response5Oct[i] = (Response5Oct[i] - Response5Oct[0]) / (1 - Response5Oct[0]);
61 | Response6Oct[i] = (Response6Oct[i] - Response6Oct[0]) / (1 - Response6Oct[0]);
62 | Response2Dec[i] = (Response2Dec[i] - Response2Dec[0]) / (1 - Response2Dec[0]);
63 | Response3Dec[i] = (Response3Dec[i] - Response3Dec[0]) / (1 - Response3Dec[0]);
64 | Response4Dec[i] = (Response4Dec[i] - Response4Dec[0]) / (1 - Response4Dec[0]);
65 | }
66 |
67 | Response2Oct[0] = 0;
68 | Response3Oct[0] = 0;
69 | Response4Oct[0] = 0;
70 | Response5Oct[0] = 0;
71 | Response6Oct[0] = 0;
72 | Response2Dec[0] = 0;
73 | Response3Dec[0] = 0;
74 | Response4Dec[0] = 0;
75 | }
76 |
77 | float ValueTables::Get(float index, float* table)
78 | {
79 | if (table == nullptr)
80 | return index;
81 |
82 | int idx = (int)(index * 4000.999);
83 |
84 | assert(idx >= 0);
85 | assert(idx < AudioLib::ValueTables::TableSize);
86 |
87 |
88 | return table[idx];
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/AudioLib/ValueTables.h:
--------------------------------------------------------------------------------
1 | #ifndef AUDIOLIB_VALUETABLES
2 | #define AUDIOLIB_VALUETABLES
3 |
4 | #include "MathDefs.h"
5 |
6 |
7 | namespace AudioLib
8 | {
9 | class ValueTables
10 | {
11 | public:
12 | static const int TableSize = 40001;
13 |
14 | static DSY_SDRAM_BSS float Sqrt[TableSize];
15 | static DSY_SDRAM_BSS float Sqrt3[TableSize];
16 | static DSY_SDRAM_BSS float Pow1_5[TableSize];
17 | static DSY_SDRAM_BSS float Pow2[TableSize];
18 | static DSY_SDRAM_BSS float Pow3[TableSize];
19 | static DSY_SDRAM_BSS float Pow4[TableSize];
20 | static DSY_SDRAM_BSS float x2Pow3[TableSize];
21 |
22 | // octave response. value float every step (2,3,4,5 or 6 steps)
23 | static DSY_SDRAM_BSS float Response2Oct[TableSize];
24 | static DSY_SDRAM_BSS float Response3Oct[TableSize];
25 | static DSY_SDRAM_BSS float Response4Oct[TableSize];
26 | static DSY_SDRAM_BSS float Response5Oct[TableSize];
27 | static DSY_SDRAM_BSS float Response6Oct[TableSize];
28 |
29 | // decade response, value multiplies by 10 every step
30 | static DSY_SDRAM_BSS float Response2Dec[TableSize];
31 | static DSY_SDRAM_BSS float Response3Dec[TableSize];
32 | static DSY_SDRAM_BSS float Response4Dec[TableSize];
33 |
34 | static void Init();
35 | static float Get(float index, float* table);
36 | };
37 | }
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Default.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef DEFAULT_INCLUDE
3 | #define DEFAULT_INCLUDE
4 |
5 | typedef unsigned char byte;
6 | typedef unsigned int uint;
7 | #ifdef _WIN32
8 | typedef unsigned long long ulong;
9 | #endif
10 |
11 |
12 | #ifdef DEBUG
13 | #define __inline_always inline
14 | #else
15 | #define __inline_always __forceinline
16 | #endif
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Exports.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Default.h"
3 | #include "ReverbController.h"
4 | #include "FastSin.h"
5 | #include "AudioLib/ValueTables.h"
6 |
7 | using namespace CloudSeed;
8 | bool isInitialized = false;
9 |
10 | extern "C"
11 | {
12 | ReverbController* Create(int samplerate)
13 | {
14 | if (!isInitialized)
15 | {
16 | AudioLib::ValueTables::Init();
17 | FastSin::Init();
18 | isInitialized = true;
19 | }
20 |
21 | return new ReverbController(samplerate);
22 | }
23 |
24 | void Delete(ReverbController* item)
25 | {
26 | delete item;
27 | }
28 |
29 | int GetSamplerate(ReverbController* item)
30 | {
31 | return item->GetSamplerate();
32 | }
33 |
34 | void SetSamplerate(ReverbController* item, int samplerate)
35 | {
36 | return item->SetSamplerate(samplerate);
37 | }
38 |
39 | int GetParameterCount(ReverbController* item)
40 | {
41 | return item->GetParameterCount();
42 | }
43 |
44 | float* GetAllParameters(ReverbController* item)
45 | {
46 | return item->GetAllParameters();
47 | }
48 |
49 | float GetScaledParameter(ReverbController* item, Parameter2 param)
50 | {
51 | return item->GetScaledParameter(param);
52 | }
53 |
54 | void SetParameter(ReverbController* item, Parameter2 param, float value)
55 | {
56 | item->SetParameter(param, value);
57 | }
58 |
59 | void ClearBuffers(ReverbController* item)
60 | {
61 | item->ClearBuffers();
62 | }
63 |
64 | void Process(ReverbController* item, float* input, float* output, int bufferSize)
65 | {
66 | item->Process(input, output, bufferSize);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/FastSin.cpp:
--------------------------------------------------------------------------------
1 |
2 | #define _USE_MATH_DEFINES
3 | #include
4 | #include "Default.h"
5 | #include "FastSin.h"
6 |
7 | namespace CloudSeed
8 | {
9 | DSY_SDRAM_BSS float FastSin::data[FastSin::DataSize];
10 | }
11 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/FastSin.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "AudioLib/MathDefs.h"
5 | #include "FastSin.h"
6 |
7 | namespace CloudSeed
8 | {
9 | class FastSin
10 | {
11 | private:
12 | static const int DataSize = 32768;
13 | static DSY_SDRAM_BSS float data[DataSize];
14 |
15 | public:
16 | static void ZeroBuffer(float* buffer, int len);
17 | static void Init()
18 | {
19 | for (int i = 0; i < DataSize; i++)
20 | {
21 | data[i] = std::sin(2 * M_PI * i / (float)DataSize);
22 | }
23 | }
24 |
25 | static float Get(float index)
26 | {
27 | return data[(int)(index * 32767.99999)];
28 | }
29 | };
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Makefile:
--------------------------------------------------------------------------------
1 | TARGET = libcloudseed
2 |
3 | MODULE_DIR = .
4 | MODULES = \
5 | FastSin \
6 | AudioLib/Biquad2 \
7 | AudioLib/ShaRandom \
8 | AudioLib/ValueTables \
9 | Utils/Sha256 \
10 |
11 |
12 | # TODO: Consider making this work for PCs as well?
13 |
14 | CHIPSET = stm32f7x
15 |
16 | ######################################
17 | # building variables
18 | ######################################
19 | # debug build?
20 | #DEBUG = 0
21 | # optimization
22 | #OPT = -Og
23 | OPT = -O3
24 |
25 | #######################################
26 | # paths
27 | #######################################
28 | # source path
29 | SOURCES_DIR = \
30 |
31 | # Build path
32 | BUILD_DIR = build
33 |
34 | ######################################
35 | # source
36 | ######################################
37 |
38 | # C sources
39 | C_SOURCES += $(addsuffix .c, $(MODULE_DIR)/$(MODULES))
40 | # CPP sources
41 | CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(MODULES))
42 |
43 | #######################################
44 | # binaries
45 | #######################################
46 | PREFIX = arm-none-eabi-
47 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
48 | # either it can be added to the PATH environment variable.
49 | ifdef GCC_PATH
50 | CC = $(GCC_PATH)/$(PREFIX)gcc
51 | CXX = $(GCC_PATH)/$(PREFIX)g++
52 | AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
53 | CP = $(GCC_PATH)/$(PREFIX)objcopy
54 | SZ = $(GCC_PATH)/$(PREFIX)size
55 | AR = $(GCC_PATH)/$(PREFIX)ar
56 | GDB = $(GCC_PATH)/$(PREFIX)gdb
57 | else
58 | CC = $(PREFIX)gcc
59 | CXX = $(PREFIX)g++
60 | AS = $(PREFIX)gcc -x assembler-with-cpp
61 | CP = $(PREFIX)objcopy
62 | SZ = $(PREFIX)size
63 | AR = $(PREFIX)ar
64 | GDB = $(PREFIX)gdb
65 | endif
66 | HEX = $(CP) -O ihex
67 | BIN = $(CP) -O binary -S
68 |
69 | #######################################
70 | # CFLAGS
71 | #######################################
72 |
73 | # language standards
74 | C_STD = -std=gnu11
75 | CPP_STD = -std=gnu++14
76 |
77 | # cpu
78 | CPU = -mcpu=cortex-m7
79 |
80 | # fpu
81 | FPU = -mfpu=fpv5-d16
82 |
83 | # float-abi
84 | FLOAT-ABI = -mfloat-abi=hard
85 |
86 | # mcu
87 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
88 |
89 | # macros for gcc
90 | # AS defines
91 | AS_DEFS =
92 |
93 | # C defines
94 | C_DEFS = \
95 | -DUSE_HAL_DRIVER \
96 | -DSTM32H750xx \
97 | -DUSE_HAL_DRIVER \
98 | -DSTM32H750xx
99 |
100 | C_INCLUDES = \
101 | -I. \
102 |
103 | # compile gcc flags
104 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
105 |
106 | CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -Werror -fdata-sections -ffunction-sections
107 |
108 | ifeq ($(DEBUG), 1)
109 | CFLAGS += -g -gdwarf-2
110 | endif
111 |
112 | # Generate dependency information
113 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"
114 |
115 | CPPFLAGS = $(CFLAGS)
116 | CPPFLAGS += \
117 | -fno-exceptions \
118 | -finline-functions \
119 | -fno-aggressive-loop-optimizations
120 |
121 | #######################################
122 | # LDFLAGS # Not Used
123 | # TODO: Clean this up.
124 | #######################################
125 | # link script
126 | #LDSCRIPT = STM32H750IB_FLASH.lds
127 |
128 | # libraries
129 | #LIBS = lc -lm -lnosys
130 | #LIBDIR =
131 | #LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
132 |
133 | # default action: build all
134 | all: $(BUILD_DIR)/$(TARGET).a
135 |
136 | #######################################
137 | # build the library
138 | #######################################
139 |
140 | # list of objects
141 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
142 | vpath %.c $(sort $(dir $(C_SOURCES)))
143 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
144 | vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
145 | # list of ASM program objects
146 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
147 | vpath %.s $(sort $(dir $(ASM_SOURCES)))
148 |
149 | $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
150 | $(CC) -c $(CFLAGS) $(C_STD) -static -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
151 |
152 | $(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
153 | $(CXX) -c $(CPPFLAGS) $(CPP_STD) -static -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@
154 |
155 | $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
156 | $(AS) -c $(CFLAGS) $< -o $@
157 |
158 | $(BUILD_DIR)/$(TARGET).a: $(OBJECTS) Makefile
159 | $(AR) rcs $@ $(OBJECTS)
160 |
161 | $(BUILD_DIR):
162 | mkdir $@
163 |
164 | #######################################
165 | # clean up
166 | #######################################
167 | clean:
168 | -rm -fR $(BUILD_DIR)
169 | #######################################
170 |
171 | # dependencies
172 | #######################################
173 | -include $(wildcard $(BUILD_DIR)/*.d)
174 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/ModulatedAllpass.h:
--------------------------------------------------------------------------------
1 | #ifndef MODULATEDALLPASS
2 | #define MODULATEDALLPASS
3 |
4 | #include "ModulatedAllpass.h"
5 | #include "FastSin.h"
6 | #include "Utils.h"
7 | extern void* custom_pool_allocate(size_t size);
8 |
9 | namespace CloudSeed
10 | {
11 | class ModulatedAllpass
12 | {
13 | public:
14 | const int DelayBufferSamples = 19200; // 100ms at 192Khz
15 | static const int ModulationUpdateRate = 8;
16 |
17 | private:
18 | float* delayBuffer;
19 | float* output;
20 | int bufferSize;
21 | int index;
22 | unsigned int samplesProcessed;
23 |
24 | float modPhase;
25 | int delayA;
26 | int delayB;
27 | float gainA;
28 | float gainB;
29 |
30 | public:
31 |
32 | int SampleDelay;
33 | float Feedback;
34 | float ModAmount;
35 | float ModRate;
36 |
37 | bool InterpolationEnabled;
38 | bool ModulationEnabled;
39 |
40 | ModulatedAllpass(int bufferSize, int sampleDelay)
41 | {
42 | this->InterpolationEnabled = true;
43 | this->bufferSize = bufferSize;
44 | delayBuffer = new (custom_pool_allocate(sizeof(float) * DelayBufferSamples)) float[DelayBufferSamples];
45 | output = new (custom_pool_allocate(sizeof(float) * bufferSize)) float[bufferSize];
46 | SampleDelay = sampleDelay;
47 | index = DelayBufferSamples - 1;
48 | modPhase = 0.01 + 0.98 * std::rand() / (float)RAND_MAX;
49 | ModRate = 0.0;
50 | ModAmount = 0.0;
51 | Update();
52 | }
53 |
54 | ~ModulatedAllpass()
55 | {
56 | delete delayBuffer;
57 | delete output;
58 | }
59 |
60 |
61 | inline float* GetOutput()
62 | {
63 | return output;
64 | }
65 |
66 | void ClearBuffers()
67 | {
68 | Utils::ZeroBuffer(delayBuffer, DelayBufferSamples);
69 | Utils::ZeroBuffer(output, bufferSize);
70 | }
71 |
72 | void Process(float* input, int sampleCount)
73 | {
74 | if (ModulationEnabled)
75 | ProcessWithMod(input, sampleCount);
76 | else
77 | ProcessNoMod(input, sampleCount);
78 | }
79 |
80 |
81 | private:
82 | void ProcessNoMod(float* input, int sampleCount)
83 | {
84 | auto delayedIndex = index - SampleDelay;
85 | if (delayedIndex < 0) delayedIndex += DelayBufferSamples;
86 |
87 | for (int i = 0; i < sampleCount; i++)
88 | {
89 | auto bufOut = delayBuffer[delayedIndex];
90 | auto inVal = input[i] + bufOut * Feedback;
91 |
92 | delayBuffer[index] = inVal;
93 | output[i] = bufOut - inVal * Feedback;
94 |
95 | index++;
96 | delayedIndex++;
97 | if (index >= DelayBufferSamples) index -= DelayBufferSamples;
98 | if (delayedIndex >= DelayBufferSamples) delayedIndex -= DelayBufferSamples;
99 | samplesProcessed++;
100 | }
101 | }
102 |
103 | void ProcessWithMod(float* input, int sampleCount)
104 | {
105 | for (int i = 0; i < sampleCount; i++)
106 | {
107 | if (samplesProcessed >= ModulationUpdateRate)
108 | Update();
109 |
110 | float bufOut;
111 |
112 | if (InterpolationEnabled)
113 | {
114 | int idxA = index - delayA;
115 | int idxB = index - delayB;
116 | idxA += DelayBufferSamples * (idxA < 0); // modulo
117 | idxB += DelayBufferSamples * (idxB < 0); // modulo
118 |
119 | bufOut = delayBuffer[idxA] * gainA + delayBuffer[idxB] * gainB;
120 | }
121 | else
122 | {
123 | int idxA = index - delayA;
124 | idxA += DelayBufferSamples * (idxA < 0); // modulo
125 | bufOut = delayBuffer[idxA];
126 | }
127 |
128 | auto inVal = input[i] + bufOut * Feedback;
129 | delayBuffer[index] = inVal;
130 | output[i] = bufOut - inVal * Feedback;
131 |
132 | index++;
133 | if (index >= DelayBufferSamples) index -= DelayBufferSamples;
134 | samplesProcessed++;
135 | }
136 | }
137 |
138 | inline float Get(int delay)
139 | {
140 | int idx = index - delay;
141 | if (idx < 0)
142 | idx += DelayBufferSamples;
143 |
144 | return delayBuffer[idx];
145 | }
146 |
147 | void Update()
148 | {
149 | modPhase += ModRate * ModulationUpdateRate;
150 | if (modPhase > 1)
151 | modPhase = std::fmod(modPhase, 1.0);
152 |
153 | auto mod = FastSin::Get(modPhase);
154 |
155 | if (ModAmount >= SampleDelay) // don't modulate to negative value
156 | ModAmount = SampleDelay - 1;
157 |
158 |
159 | auto totalDelay = SampleDelay + ModAmount * mod;
160 |
161 | if (totalDelay <= 0) // should no longer be required
162 | totalDelay = 1;
163 |
164 | delayA = (int)totalDelay;
165 | delayB = (int)totalDelay + 1;
166 |
167 | auto partial = totalDelay - delayA;
168 |
169 | gainA = 1 - partial;
170 | gainB = partial;
171 |
172 | samplesProcessed = 0;
173 | }
174 |
175 | };
176 | }
177 |
178 | #endif
179 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/ModulatedDelay.h:
--------------------------------------------------------------------------------
1 | #ifndef MODULATEDDELAY
2 | #define MODULATEDDELAY
3 |
4 | #include "ModulatedDelay.h"
5 | #include "Utils.h"
6 | #include "FastSin.h"
7 |
8 | extern void* custom_pool_allocate(size_t size);
9 |
10 | namespace CloudSeed
11 | {
12 | class ModulatedDelay
13 | {
14 | private:
15 |
16 | const int ModulationUpdateRate = 8;
17 |
18 | float* delayBuffer;
19 | float* output;
20 | int bufferSize;
21 | int writeIndex;
22 | int readIndexA;
23 | int readIndexB;
24 | int samplesProcessed;
25 | int delayBufferSizeSamples;
26 |
27 | float modPhase;
28 | float gainA;
29 | float gainB;
30 |
31 | public:
32 | int SampleDelay;
33 |
34 | float ModAmount;
35 | float ModRate;
36 |
37 | ModulatedDelay(int bufferSize, int delayBufferSizeSamples, int sampleDelay)
38 | {
39 | this->delayBufferSizeSamples = delayBufferSizeSamples;
40 | this->bufferSize = bufferSize;
41 | this->delayBuffer = new (custom_pool_allocate(sizeof(float) * delayBufferSizeSamples)) float[delayBufferSizeSamples];
42 | this->output = new (custom_pool_allocate(sizeof(float) * bufferSize)) float[bufferSize];
43 | this->SampleDelay = sampleDelay;
44 | writeIndex = 0;
45 | modPhase = 0.01 + 0.98 * (std::rand() / (float)RAND_MAX);
46 | ModRate = 0.0;
47 | ModAmount = 0.0;
48 | Update();
49 | }
50 |
51 | ~ModulatedDelay()
52 | {
53 | delete delayBuffer;
54 | delete output;
55 | }
56 |
57 | float* GetOutput()
58 | {
59 | return output;
60 | }
61 |
62 | void Process(float* input, int sampleCount)
63 | {
64 | for (int i = 0; i < sampleCount; i++)
65 | {
66 | if (samplesProcessed == ModulationUpdateRate)
67 | Update();
68 |
69 | delayBuffer[writeIndex] = input[i];
70 | output[i] = delayBuffer[readIndexA] * gainA + delayBuffer[readIndexB] * gainB;
71 |
72 | writeIndex++;
73 | readIndexA++;
74 | readIndexB++;
75 | if (writeIndex >= delayBufferSizeSamples) writeIndex -= delayBufferSizeSamples;
76 | if (readIndexA >= delayBufferSizeSamples) readIndexA -= delayBufferSizeSamples;
77 | if (readIndexB >= delayBufferSizeSamples) readIndexB -= delayBufferSizeSamples;
78 | samplesProcessed++;
79 | }
80 | }
81 |
82 | void ClearBuffers()
83 | {
84 | Utils::ZeroBuffer(delayBuffer, delayBufferSizeSamples);
85 | Utils::ZeroBuffer(output, bufferSize);
86 | }
87 |
88 |
89 | private:
90 | void Update()
91 | {
92 | modPhase += ModRate * ModulationUpdateRate;
93 | if (modPhase > 1)
94 | modPhase = std::fmod(modPhase, 1.0);
95 |
96 | auto mod = FastSin::Get(modPhase);
97 | auto totalDelay = SampleDelay + ModAmount * mod;
98 |
99 | auto delayA = (int)totalDelay;
100 | auto delayB = (int)totalDelay + 1;
101 |
102 | auto partial = totalDelay - delayA;
103 |
104 | gainA = 1 - partial;
105 | gainB = partial;
106 |
107 | readIndexA = writeIndex - delayA;
108 | readIndexB = writeIndex - delayB;
109 | if (readIndexA < 0) readIndexA += delayBufferSizeSamples;
110 | if (readIndexB < 0) readIndexB += delayBufferSizeSamples;
111 |
112 | samplesProcessed = 0;
113 | }
114 | };
115 | }
116 |
117 | #endif
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/MultitapDiffuser.h:
--------------------------------------------------------------------------------
1 | #ifndef MULTITAPDIFFUSER
2 | #define MULTITAPDIFFUSER
3 |
4 | #include
5 | #include
6 | #include
7 | #include "MultitapDiffuser.h"
8 | #include "Utils.h"
9 | #include "AudioLib/ShaRandom.h"
10 | extern void* custom_pool_allocate(size_t size);
11 |
12 | namespace CloudSeed
13 | {
14 | using namespace std;
15 |
16 | class MultitapDiffuser
17 | {
18 | public:
19 | static const int MaxTaps = 50;
20 |
21 | private:
22 | float* buffer;
23 | float* output;
24 | int len;
25 |
26 | int index;
27 | vector tapGains;
28 | vector tapPosition;
29 | vector seedValues;
30 | int seed;
31 | float crossSeed;
32 | int count;
33 | float length;
34 | float gain;
35 | float decay;
36 |
37 | bool isDirty;
38 | vector tapGainsTemp;
39 | vector tapPositionTemp;
40 | int countTemp;
41 |
42 | public:
43 | MultitapDiffuser(int delayBufferSize)
44 | {
45 | len = delayBufferSize;
46 | buffer = new (custom_pool_allocate(sizeof(float) * delayBufferSize)) float[delayBufferSize];
47 | output = new (custom_pool_allocate(sizeof(float) * delayBufferSize)) float[delayBufferSize];
48 | index = 0;
49 | count = 1;
50 | length = 1;
51 | gain = 1.0;
52 | decay = 0.0;
53 | crossSeed = 0.0;
54 | UpdateSeeds();
55 | }
56 |
57 | ~MultitapDiffuser()
58 | {
59 | delete buffer;
60 | delete output;
61 | }
62 |
63 |
64 | void SetSeed(int seed)
65 | {
66 | this->seed = seed;
67 | UpdateSeeds();
68 | }
69 |
70 | void SetCrossSeed(float crossSeed)
71 | {
72 | this->crossSeed = crossSeed;
73 | UpdateSeeds();
74 | }
75 |
76 | float* GetOutput()
77 | {
78 | return output;
79 | }
80 |
81 | void SetTapCount(int tapCount)
82 | {
83 | count = tapCount;
84 | Update();
85 | }
86 |
87 | void SetTapLength(int tapLength)
88 | {
89 | length = tapLength;
90 | Update();
91 | }
92 |
93 | void SetTapDecay(float tapDecay)
94 | {
95 | decay = tapDecay;
96 | Update();
97 | }
98 |
99 | void SetTapGain(float tapGain)
100 | {
101 | gain = tapGain;
102 | Update();
103 | }
104 |
105 | void Process(float* input, int sampleCount)
106 | {
107 | // prevents race condition when parameters are updated from Gui
108 | if (isDirty)
109 | {
110 | tapGainsTemp = tapGains;
111 | tapPositionTemp = tapPosition;
112 | countTemp = count;
113 | isDirty = false;
114 | }
115 |
116 | int* const tapPos = &tapPositionTemp[0];
117 | float* const tapGain = &tapGainsTemp[0];
118 | const int cnt = countTemp;
119 |
120 | for (int i = 0; i < sampleCount; i++)
121 | {
122 | if (index < 0) index += len;
123 | buffer[index] = input[i];
124 | output[i] = 0.0;
125 |
126 | for (int j = 0; j < cnt; j++)
127 | {
128 | auto idx = (index + tapPos[j]) % len;
129 | output[i] += buffer[idx] * tapGain[j];
130 | }
131 |
132 | index--;
133 | }
134 | }
135 |
136 | void ClearBuffers()
137 | {
138 | Utils::ZeroBuffer(buffer, len);
139 | Utils::ZeroBuffer(output, len);
140 | }
141 |
142 |
143 | private:
144 | void Update()
145 | {
146 | vector newTapGains;
147 | vector newTapPosition;
148 |
149 | int s = 0;
150 | auto rand = [&]() {return seedValues[s++]; };
151 |
152 | if (count < 1)
153 | count = 1;
154 |
155 | if (length < count)
156 | length = count;
157 |
158 | // used to adjust the volume of the overall output as it grows when we add more taps
159 | float tapCountFactor = 1.0 / (1 + std::sqrt(count / MaxTaps));
160 |
161 | newTapGains.resize(count);
162 | newTapPosition.resize(count);
163 |
164 | vector tapData(count, 0.0);
165 |
166 | auto sumLengths = 0.0;
167 | for (size_t i = 0; i < count; i++)
168 | {
169 | auto val = 0.1 + rand();
170 | tapData[i] = val;
171 | sumLengths += val;
172 | }
173 |
174 | auto scaleLength = length / sumLengths;
175 | newTapPosition[0] = 0;
176 |
177 | for (int i = 1; i < count; i++)
178 | {
179 | newTapPosition[i] = newTapPosition[i - 1] + (int)(tapData[i] * scaleLength);
180 | }
181 |
182 | float sumGains = 0.0;
183 | float lastTapPos = newTapPosition[count - 1];
184 | for (int i = 0; i < count; i++)
185 | {
186 | // when decay set to 0, there is no decay, when set to 1, the gain at the last sample is 0.01 = -40dB
187 | auto g = std::pow(10, -decay * 2 * newTapPosition[i] / (float)(lastTapPos + 1));
188 |
189 | auto tap = (2 * rand() - 1) * tapCountFactor;
190 | newTapGains[i] = tap * g * gain;
191 | }
192 |
193 | // Set the tap vs. clean mix
194 | newTapGains[0] = (1 - gain);
195 |
196 | this->tapGains = newTapGains;
197 | this->tapPosition = newTapPosition;
198 | isDirty = true;
199 | }
200 |
201 | void UpdateSeeds()
202 | {
203 | this->seedValues = AudioLib::ShaRandom::Generate(seed, 100, crossSeed);
204 | Update();
205 | }
206 | };
207 | }
208 |
209 | #endif
210 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Parameter.h:
--------------------------------------------------------------------------------
1 | #ifndef PARAMETER2
2 | #define PARAMETER2
3 |
4 | enum class Parameter2
5 | {
6 | // Input
7 |
8 | InputMix = 0,
9 | PreDelay,
10 |
11 | HighPass,
12 | LowPass,
13 |
14 | // Early
15 |
16 | TapCount,
17 | TapLength,
18 | TapGain,
19 | TapDecay,
20 |
21 | DiffusionEnabled,
22 | DiffusionStages,
23 | DiffusionDelay,
24 | DiffusionFeedback,
25 |
26 | // Late
27 |
28 | LineCount,
29 | LineDelay,
30 | LineDecay,
31 |
32 |
33 | LateDiffusionEnabled,
34 | LateDiffusionStages,
35 | LateDiffusionDelay,
36 | LateDiffusionFeedback,
37 |
38 | // Frequency Response
39 |
40 | PostLowShelfGain,
41 | PostLowShelfFrequency,
42 | PostHighShelfGain,
43 | PostHighShelfFrequency,
44 | PostCutoffFrequency,
45 |
46 | // Modulation
47 |
48 | EarlyDiffusionModAmount,
49 | EarlyDiffusionModRate,
50 |
51 | LineModAmount,
52 | LineModRate,
53 |
54 | LateDiffusionModAmount,
55 | LateDiffusionModRate,
56 |
57 | // Seeds
58 |
59 | TapSeed,
60 | DiffusionSeed,
61 | DelaySeed,
62 | PostDiffusionSeed,
63 |
64 | // Seed Mix
65 |
66 | CrossSeed,
67 |
68 | DryOut,
69 | PredelayOut,
70 | EarlyOut,
71 | MainOut,
72 |
73 | // Switches
74 | HiPassEnabled,
75 | LowPassEnabled,
76 | LowShelfEnabled,
77 | HighShelfEnabled,
78 | CutoffEnabled,
79 | LateStageTap,
80 |
81 | // Effects
82 | Interpolation,
83 |
84 | Count,
85 |
86 | Unused = 999
87 | };
88 |
89 | #endif
90 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Utils.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS
2 | #define UTILS
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace CloudSeed
9 | {
10 | class Utils
11 | {
12 | public:
13 |
14 | static inline void ZeroBuffer(float* buffer, int len)
15 | {
16 | for (int i = 0; i < len; i++)
17 | buffer[i] = 0.0;
18 | }
19 |
20 | static inline void Copy(float* source, float* dest, int len)
21 | {
22 | std::memcpy(dest, source, len * sizeof(float));
23 | }
24 |
25 | static inline void Gain(float* buffer, float gain, int len)
26 | {
27 | for (int i = 0; i < len; i++)
28 | {
29 | buffer[i] *= gain;
30 | }
31 | }
32 |
33 | // perform bit crushing and undersampling
34 | // undersampling: if set to 1, perfroms no effect, if set to 2, will undersample to 1/2 samplerate, etc...
35 | // sampleResolution: if set to 32, will use 2^32 steps, if set to 8, will resude to 2^8 = 256 steps
36 | // Currently Unused
37 | static inline void BitcrushAndReduce(float* bufferIn, float* bufferOut, int len, int undersampling, int sampleResolution)
38 | {
39 | float sampleSteps = std::pow(2, sampleResolution);
40 | float inverseSteps = 1.0 / sampleSteps;
41 |
42 | float sample = 0.0;
43 |
44 | for (int i = 0; i < len; i++)
45 | {
46 | if (i % undersampling == 0)
47 | sample = ((long)(bufferIn[i] * sampleSteps)) * inverseSteps;
48 |
49 | bufferOut[i] = sample;
50 | }
51 | }
52 |
53 | template
54 | static float DB2gain(T input)
55 | {
56 | return std::pow(10, input / 20.0);
57 | }
58 |
59 | template
60 | static float Gain2DB(T input)
61 | {
62 | if (input < 0.0000001)
63 | return -100000;
64 |
65 | return 20.0f * std::log10(input);
66 | }
67 | };
68 | }
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/Utils/Sha256.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Updated to C++, zedwood.com 2012
3 | * Based on Olivier Gay's version
4 | * See Modified BSD License below:
5 | *
6 | * FIPS 180-2 SHA-224/256/384/512 implementation
7 | * Issue date: 04/30/2005
8 | * http://www.ouah.org/ogay/sha2/
9 | *
10 | * Copyright (C) 2005, 2007 Olivier Gay
11 | * All rights reserved.
12 | *
13 | * Redistribution and use in source and binary forms, with or without
14 | * modification, are permitted provided that the following conditions
15 | * are met:
16 | * 1. Redistributions of source code must retain the above copyright
17 | * notice, this list of conditions and the following disclaimer.
18 | * 2. Redistributions in binary form must reproduce the above copyright
19 | * notice, this list of conditions and the following disclaimer in the
20 | * documentation and/or other materials provided with the distribution.
21 | * 3. Neither the name of the project nor the names of its contributors
22 | * may be used to endorse or promote products derived from this software
23 | * without specific prior written permission.
24 | *
25 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 | * SUCH DAMAGE.
36 | */
37 |
38 | #ifndef SHA256_H
39 | #define SHA256_H
40 | #include
41 |
42 | class SHA256
43 | {
44 | protected:
45 | typedef unsigned char uint8;
46 | typedef unsigned int uint32;
47 | typedef unsigned long long uint64;
48 |
49 | const static uint32 sha256_k[];
50 | static const unsigned int SHA224_256_BLOCK_SIZE = (512 / 8);
51 | public:
52 | void init();
53 | void update(const unsigned char *message, unsigned int len);
54 | void final(unsigned char *digest);
55 | static const unsigned int DIGEST_SIZE = (256 / 8);
56 |
57 | protected:
58 | void transform(const unsigned char *message, unsigned int block_nb);
59 | unsigned int m_tot_len;
60 | unsigned int m_len;
61 | unsigned char m_block[2 * SHA224_256_BLOCK_SIZE];
62 | uint32 m_h[8];
63 | };
64 |
65 | std::vector sha256(unsigned char* input, int len);
66 |
67 | #define SHA2_SHFR(x, n) (x >> n)
68 | #define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
69 | #define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
70 | #define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
71 | #define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
72 | #define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))
73 | #define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))
74 | #define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))
75 | #define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))
76 | #define SHA2_UNPACK32(x, str) \
77 | { \
78 | *((str) + 3) = (uint8) ((x) ); \
79 | *((str) + 2) = (uint8) ((x) >> 8); \
80 | *((str) + 1) = (uint8) ((x) >> 16); \
81 | *((str) + 0) = (uint8) ((x) >> 24); \
82 | }
83 | #define SHA2_PACK32(str, x) \
84 | { \
85 | *(x) = ((uint32) *((str) + 3) ) \
86 | | ((uint32) *((str) + 2) << 8) \
87 | | ((uint32) *((str) + 1) << 16) \
88 | | ((uint32) *((str) + 0) << 24); \
89 | }
90 | #endif
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Valdemar Erlingsson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/software/Jupiter/CloudSeed/premake4.lua:
--------------------------------------------------------------------------------
1 | project "CloudSeed"
2 |
3 | language "C++"
4 |
5 | kind "StaticLib"
6 |
7 | includedirs {"."}
8 |
9 | files {
10 | "*.cpp",
11 | "*.h",
12 | "AudioLib/*.cpp",
13 | "AudioLib/*.h",
14 | "Utils/*.cpp",
15 | "Utils/*.h",
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/software/Jupiter/README.md:
--------------------------------------------------------------------------------
1 | # Jupiter (Planet Series)
2 |
3 | Jupiter is a Stereo Reverb pedal. The reverb used here is from the [CloudSeed plugin](https://github.com/ValdemarOrn/CloudSeed) (MIT License). It is the same reverb from the Neptune pedal,
4 | but more EQ controls are exposed to the user, specifically the post reverb low and high shelf filters, both the frequency cutoff and gain.
5 |
6 |
7 | 
8 |
9 | ## Controls
10 |
11 | | Control | Description | Comment |
12 | | --- | --- | --- |
13 | | Ctrl 1 | Reverb Decay | Increases the decay time of the reverb, about 300ms to 60 seconds, exponential taper (noon is 2 seconds decay) |
14 | | Ctrl 2 | Low Shelf Frequency | Log Taper 20Hz to 1000Hz, noon is about 200Hz |
15 | | Ctrl 3 | High Shelf Frequency | Log Taper 400 Hz to 20000Hz, noon is about 4300Hz |
16 | | Ctrl 4 | Mix | Dry to Wet mix |
17 | | Ctrl 5 | Low Shelf Gain | Low shelf cut, from 100% cut to 0.0 gain at max knob |
18 | | Ctrl 6 | High Shelf Gain | High shelf cut, from 100% cut to 0.0 gain at max knob |
19 | | 3-Way Switch 1 | Lush Level | Amount of "Lushness", low, medium, high |
20 | | 3-Way Switch 2 | Modulation Level | Sets the modulation amount and rate, low, medium, high |
21 | | 3-Way Switch 3 | PreDelay | Sets predelay, 0, 100ms, 200ms |
22 | | Dip Switch 1 | MISO/Stereo | MISO (Mono in stereo out), or True Stereo |
23 | | Dip Switch 2 | | |
24 | | Dip Switch 3 | | |
25 | | Dip Switch 4 | | |
26 | | FS 1 | Bypass/Engage | |
27 | | FS 2 | Preset | Hold to save preset, press to engage/disengage preset. Saves between power cycles. |
28 | | LED 1 | Bypass Indicator | |
29 | | LED 2 | Preset Indicator | |
30 | | Audio In 1 | Stereo In | Right channel ignored if MISO Mode turned on |
31 | | Audio Out 1 | Stereo Out | |
32 |
33 | ### Expression
34 | 1. Plug in passive expression pedal into the 1/8" jack on the top left side of pedal. (will need a 1/4" female to 1/8" male TRS adapter)
35 | 2. Hold both footswitches until they both light up (more than 0.5 seconds, but less than 2 seconds), you are now in Set Expression mode.
36 | 3. Move the expression pedal into the heel position (up) and move any number of knobs to where you want to heel limit to be (for example you could turn Volume down). The right LED should be brighter up to indicate the heel position is ready to set.*
37 | 3. Move the expression pedal into the toe position (down) and move any number of knobs to where you want to toe limit to be (for example you could turn Volume up). The Left LED should be brighter to indicate the toe position is ready to set.*
38 | 4. Hold both footswitches to exit Set Expression mode. This will activate expression for the moved knobs. The moved knobs will be inactive until Expression Mode is deactivated.
39 | 5. Repeat step 2 to reset Expression knobs.
40 | 6. Hold both footswitches for 2 seconds or more to clear any Expression action and give control back to the Funbox knobs.
41 |
42 | * Currently, the expression input requires the full range of the expression pedal, in order to detect Up/Down positions. You can sometimes trim the expression pedal to not use the full range, so adjust the trim as necessary.
43 | Also, some expression pedals have a "Standard" or "Alternate/Other" mode. Funbox should work on the "Standard" mode.
44 |
45 | ### MIDI Reference
46 |
47 | | Control | MIDI CC | Value |
48 | | --- | --- | --- |
49 | | Knob 1 | 14 | 0- 127 |
50 | | Knob 2 | 15 | 0- 127 |
51 | | Knob 3 | 16 | 0- 127 |
52 | | Knob 4 | 17 | 0- 127 |
53 | | Knob 5 | 18 | 0- 127 |
54 | | Knob 6 | 19 | 0- 127 |
55 |
56 | ## Build
57 |
58 | Before building Jupiter, you must build Cloudseed with ```make``` in the CloudSeed folder.
--------------------------------------------------------------------------------
/software/Jupiter/jupiter/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = jupiter
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | #APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = jupiter.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../../libDaisy
18 | DAISYSP_DIR = ../../../DaisySP
19 | CLOUDSEED_DIR = ../CloudSeed
20 |
21 | # Core location, and generic Makefile.
22 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
23 | include $(SYSTEM_FILES_DIR)/Makefile
24 |
25 |
26 | # Include funbox.h
27 | C_INCLUDES += -I../../../include -I../CloudSeed \
28 |
29 | LIBS += -lcloudseed
30 | LIBDIR += -L../CloudSeed/build
--------------------------------------------------------------------------------
/software/Mars/ImpulseResponse/ImpulseResponse.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // ImpulseResponse.cpp
3 | // NeuralAmpModeler-macOS
4 | //
5 | // Created by Steven Atkinson on 12/30/22.
6 | //
7 | // Modified by Keith Bloemer on 12/28/23
8 | // Greatly simplified by assuming 1 channel, 1 input per Process call, and constant samplerate.
9 | // For initial investigation into running IR's on the Daisy Seed
10 |
11 | #include "ImpulseResponse.h"
12 |
13 |
14 | ImpulseResponse::ImpulseResponse()
15 | {
16 | }
17 |
18 | // Destructor
19 | ImpulseResponse::~ImpulseResponse()
20 | {
21 | // No Code Needed
22 | }
23 |
24 |
25 | void ImpulseResponse::Init(std::vector irData)
26 | {
27 | mRawAudio = irData;
28 | _SetWeights();
29 | }
30 |
31 | float ImpulseResponse::Process(float inputs)
32 | {
33 |
34 | _UpdateHistory(inputs);
35 |
36 | int j = mHistoryIndex - mHistoryRequired;
37 | auto input = Eigen::Map(&mHistory[j], mHistoryRequired + 1);
38 |
39 | _AdvanceHistoryIndex(1); // KAB MOD - for Daisy implementation numFrames is always 1
40 |
41 | return (float)mWeight.dot(input);
42 |
43 | }
44 |
45 | void ImpulseResponse::_SetWeights()
46 | {
47 |
48 | const size_t irLength = std::min(mRawAudio.size(), mMaxLength);
49 | mWeight.resize(irLength);
50 | // Gain reduction.
51 | // https://github.com/sdatkinson/NeuralAmpModelerPlugin/issues/100#issuecomment-1455273839
52 | // Add sample rate-dependence
53 | //const float gain = pow(10, -18 * 0.05) * 48000 / mSampleRate; //KAB NOTE: This made a very bad/loud sound on Daisy Seed
54 | for (size_t i = 0, j = irLength - 1; i < irLength; i++, j--)
55 | //mWeight[j] = gain * mRawAudio[i];
56 | mWeight[j] = mRawAudio[i];
57 | mHistoryRequired = irLength - 1;
58 |
59 | // Moved from HISTORY::EnsureHistorySize since only doing once for this module (assuming same size IR's)
60 | // TODO: Maybe find a more efficient method of indexing mHistory,
61 | // rather than copying the end of the vector (length of IR) back to the beginning all at once.
62 | const size_t requiredHistoryArraySize = 5 * mHistoryRequired; // Just so we don't spend too much time copying back. // KAB NOTE: was 10 *
63 | mHistory.resize(requiredHistoryArraySize);
64 | std::fill(mHistory.begin(), mHistory.end(), 0.0f);
65 | mHistoryIndex = mHistoryRequired;
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/software/Mars/ImpulseResponse/ImpulseResponse.h:
--------------------------------------------------------------------------------
1 | //
2 | // ImpulseResponse.h
3 | // NeuralAmpModeler-macOS
4 | //
5 | // Created by Steven Atkinson on 12/30/22.
6 | //
7 | // Impulse response processing
8 | //
9 | // Modified by Keith Bloemer on 12/28/23
10 | // Greatly simplified by assuming 1 channel, 1 input per Process call, and constant samplerate.
11 | // For initial investigation into running IR's on the Daisy Seed
12 |
13 | #pragma once
14 |
15 | #include
16 | #include "dsp.h"
17 |
18 |
19 | class ImpulseResponse : public History
20 | {
21 | public:
22 | ImpulseResponse();
23 | ~ImpulseResponse();
24 |
25 | void Init(std::vector irData);
26 | float Process(float inputs);
27 |
28 |
29 | private:
30 | // Set the weights, given that the plugin is running at the provided sample
31 | // rate.
32 | void _SetWeights();
33 |
34 | // State of audio
35 | // Keep a copy of the raw audio that was loaded so that it can be resampled
36 | std::vector mRawAudio;
37 | float mRawAudioSampleRate;
38 | float mSampleRate;
39 |
40 | const size_t mMaxLength = 8192;
41 | // The weights
42 | Eigen::VectorXf mWeight;
43 | };
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/software/Mars/ImpulseResponse/dsp.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * File: dsp.cpp
3 | * Created Date: March 17, 2023
4 | * Author: Steven Atkinson (steven@atkinson.mn)
5 | */
6 | // Modified by Keith Bloemer on 12/28/23
7 | // Greatly simplified by assuming 1 channel, 1 input per Process call, and constant samplerate.
8 | // For initial investigation into running IR's on the Daisy Seed
9 |
10 | #include "dsp.h"
11 |
12 |
13 | History::History()
14 | {
15 | }
16 |
17 | // Destructor
18 | History::~History()
19 | {
20 | // No Code Needed
21 | }
22 |
23 |
24 | void History::_AdvanceHistoryIndex(const size_t bufferSize)
25 | {
26 | mHistoryIndex += bufferSize;
27 | }
28 |
29 |
30 | void History::_RewindHistory()
31 | {
32 | // TODO memcpy? Should be fine w/ history array being >2x the history length.
33 | for (size_t i = 0, j = mHistoryIndex - mHistoryRequired; i < mHistoryRequired; i++, j++)
34 | mHistory[i] = mHistory[j];
35 | mHistoryIndex = mHistoryRequired;
36 | }
37 |
38 | void History::_UpdateHistory(float inputs)
39 | {
40 | if (mHistoryIndex + 1 >= mHistory.size())
41 | _RewindHistory();
42 |
43 | mHistory[mHistoryIndex] = inputs;
44 | }
45 |
--------------------------------------------------------------------------------
/software/Mars/ImpulseResponse/dsp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | // A class where a longer buffer of history is needed to correctly calculate
6 | // the DSP algorithm (e.g. algorithms involving convolution).
7 | //
8 | // Hacky stuff:
9 | // * Mono
10 | // * Single-precision floats.
11 | class History
12 | {
13 | public:
14 | History();
15 | ~History();
16 | protected:
17 | // Called at the end of the DSP, advance the hsitory index to the next open
18 | // spot. Does not ensure that it's at a valid address.
19 | void _AdvanceHistoryIndex(const size_t bufferSize);
20 | // Drop the new samples into the history array.
21 | // Manages history array size
22 | void _UpdateHistory(float inputs);
23 |
24 | // The history array that's used for DSP calculations.
25 | std::vector mHistory;
26 | // How many samples previous are required.
27 | // Zero means that no history is required--only the current sample.
28 | size_t mHistoryRequired = 0;
29 | // Location of the first sample in the current buffer.
30 | // Shall always be in the range [mHistoryRequired, mHistory.size()).
31 | size_t mHistoryIndex = 0;
32 |
33 | private:
34 |
35 | // Copy the end of the history back to the front and reset mHistoryIndex
36 | void _RewindHistory();
37 | };
38 |
--------------------------------------------------------------------------------
/software/Mars/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = mars
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = mars.cpp ImpulseResponse/ImpulseResponse.cpp ImpulseResponse/dsp.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../libDaisy
18 | DAISYSP_DIR = ../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../include -I../../RTNeural -I../../RTNeural/modules/Eigen
27 | CPPFLAGS += -DRTNEURAL_DEFAULT_ALIGNMENT=8 -DRTNEURAL_NO_DEBUG=1
--------------------------------------------------------------------------------
/software/Mars/README.md:
--------------------------------------------------------------------------------
1 | # Mars (Planet Series)
2 |
3 | Mars is an amp sim / delay pedal. It includes 3 neural models, 3 Impulse Responses (Cab Sim), and a delay effect with dotted 8th and triplett modes.
4 |
5 | Neural Network inference for the amp/pedal models uses [RTNeural](https://github.com/jatinchowdhury18/RTNeural)
6 | The Impluse Response code is a modified version of the IR processing in the [NAM plugin](https://github.com/sdatkinson/NeuralAmpModelerPlugin) (MIT License)
7 |
8 | Note: Due to the processing power required for the neural models and IRs, Mars is a mono effect, which on the Funbox pedal is copied left to right channel for output.
9 | If a stereo signal is going into the input, Mars will only take the left channel for processing.
10 |
11 | 
12 |
13 | ## Controls
14 |
15 | | Control | Description | Comment |
16 | | --- | --- | --- |
17 | | Ctrl 1 | Gain | Increases the input gain to the neural model |
18 | | Ctrl 2 | Mix | Mix control between the amp and delay |
19 | | Ctrl 3 | Level | Overall volume output |
20 | | Ctrl 4 | Filter | Lowpass filter left of center, highpass right of center |
21 | | Ctrl 5 | Delay Time | Delay time 0 to 2 seconds. |
22 | | Ctrl 6 | Delay Feedback | Delay Feedback (how long delay takes to fade out) |
23 | | 3-Way Switch 1 | Amp/Model Select | 3 available models, default: left: Matchless SC30, center: Klon pedal, right: Mesa iib |
24 | | 3-Way Switch 2 | IR Select | 3 available IRs, default: left: Proteus (from GuitarML Proteus plugin), center: American, right: Rectifier |
25 | | 3-Way Switch 3 | Delay Mode | left: normal, center: dotted 8th, right: triplett |
26 | | Dip Switch 1 | Amp On/Off | Engage/Disengage Neural model |
27 | | Dip Switch 2 | IR On/Off| Engage/Disengage IR |
28 | | FS 1 | Bypass | |
29 | | FS 2 | Preset | Hold to save preset, press to engage/disengage preset. Saves between power cycles. |
30 | | LED 1 | Bypass Indicator | |
31 | | LED 2 | Preset Indicator | ||
32 | | Audio In 1 | Mono In (Left Channel) | Right channel ignored if using TRS |
33 | | Audio Out 1 | Mono Out | Left channel copied to Right Channel if using TRS |
34 |
35 |
36 | ## Build
37 |
38 | Mars runs in SRAM memory on the Daisy Seed. You must use the Bootloader to load the executable.
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AllpassDiffuser.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include
5 | #include "ModulatedAllpass.h"
6 | #include "AudioLib/ShaRandom.h"
7 |
8 | using namespace std;
9 |
10 | namespace CloudSeed
11 | {
12 | class AllpassDiffuser
13 | {
14 | public:
15 | static const int MaxStageCount = 2;
16 |
17 | private:
18 | int samplerate;
19 |
20 | vector filters;
21 | int delay;
22 | float modRate;
23 | vector seedValues;
24 | int seed;
25 | float crossSeed;
26 |
27 | public:
28 | int Stages;
29 |
30 | AllpassDiffuser(int samplerate, int delayBufferLengthMillis)
31 | {
32 | auto delayBufferSize = samplerate * ((float)delayBufferLengthMillis / 1000.0);
33 | for (int i = 0; i < MaxStageCount; i++)
34 | {
35 | filters.push_back(new ModulatedAllpass((int)delayBufferSize, 100));
36 | }
37 |
38 | crossSeed = 0.0;
39 | seed = 23456;
40 | UpdateSeeds();
41 | Stages = 1;
42 |
43 | SetSamplerate(samplerate);
44 | }
45 |
46 | ~AllpassDiffuser()
47 | {
48 | for (auto filter : filters)
49 | delete filter;
50 | }
51 |
52 | int GetSamplerate()
53 | {
54 | return samplerate;
55 | }
56 |
57 | void SetSamplerate(int samplerate)
58 | {
59 | this->samplerate = samplerate;
60 | SetModRate(modRate);
61 | }
62 |
63 | void SetSeed(int seed)
64 | {
65 | this->seed = seed;
66 | UpdateSeeds();
67 | }
68 |
69 | void SetCrossSeed(float crossSeed)
70 | {
71 | this->crossSeed = crossSeed;
72 | UpdateSeeds();
73 | }
74 |
75 |
76 | bool GetModulationEnabled()
77 | {
78 | return filters[0]->ModulationEnabled;
79 | }
80 |
81 | void SetModulationEnabled(bool value)
82 | {
83 | for (auto filter : filters)
84 | filter->ModulationEnabled = value;
85 | }
86 |
87 | void SetInterpolationEnabled(bool enabled)
88 | {
89 | for (auto filter : filters)
90 | filter->InterpolationEnabled = enabled;
91 | }
92 |
93 | float* GetOutput()
94 | {
95 | return filters[Stages - 1]->GetOutput();
96 | }
97 |
98 |
99 | void SetDelay(int delaySamples)
100 | {
101 | delay = delaySamples;
102 | Update();
103 | }
104 |
105 | void SetFeedback(float feedback)
106 | {
107 | for (auto filter : filters)
108 | filter->Feedback = feedback;
109 | }
110 |
111 | void SetModAmount(float amount)
112 | {
113 | for (int i = 0; i < filters.size(); i++)
114 | {
115 | filters[i]->ModAmount = amount * (0.85 + 0.3 * seedValues[MaxStageCount + i]);
116 | }
117 | }
118 |
119 | void SetModRate(float rate)
120 | {
121 | modRate = rate;
122 |
123 | for (size_t i = 0; i < filters.size(); i++)
124 | filters[i]->ModRate = rate * (0.85 + 0.3 * seedValues[MaxStageCount * 2 + i]) / samplerate;
125 | }
126 |
127 | void Process(float* input, int sampleCount)
128 | {
129 | ModulatedAllpass** filterPtr = &filters[0];
130 |
131 | filterPtr[0]->Process(input, sampleCount);
132 |
133 | for (int i = 1; i < Stages; i++)
134 | {
135 | filterPtr[i]->Process(filterPtr[i - 1]->GetOutput(), sampleCount);
136 | }
137 | }
138 |
139 | void ClearBuffers()
140 | {
141 | for (size_t i = 0; i < filters.size(); i++)
142 | filters[i]->ClearBuffers();
143 | }
144 |
145 | private:
146 | void Update()
147 | {
148 | for (size_t i = 0; i < filters.size(); i++)
149 | {
150 | auto r = seedValues[i];
151 | auto d = std::pow(10, r) * 0.1; // 0.1 ... 1.0
152 | filters[i]->SampleDelay = (int)(delay * d);
153 | }
154 | }
155 |
156 | void UpdateSeeds()
157 | {
158 | this->seedValues = AudioLib::ShaRandom::Generate(seed, MaxStageCount * 3, crossSeed);
159 | Update();
160 | }
161 |
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/Biquad2.cpp:
--------------------------------------------------------------------------------
1 | #define _USE_MATH_DEFINES
2 | #include
3 | #include "Biquad2.h"
4 |
5 | namespace AudioLib
6 | {
7 | Biquad2::Biquad2()
8 | {
9 | ClearBuffers();
10 | }
11 |
12 | Biquad2::Biquad2(FilterType filterType, float samplerate)
13 | {
14 | Type = filterType;
15 | SetSamplerate(samplerate);
16 |
17 | SetGainDb(0.0);
18 | Frequency = samplerate / 4;
19 | SetQ(0.5);
20 | ClearBuffers();
21 | }
22 |
23 | Biquad2::~Biquad2()
24 | {
25 |
26 | }
27 |
28 |
29 | float Biquad2::GetSamplerate()
30 | {
31 | return samplerate;
32 | }
33 |
34 | void Biquad2::SetSamplerate(float value)
35 | {
36 | samplerate = value;
37 | Update();
38 | }
39 |
40 | float Biquad2::GetGainDb()
41 | {
42 | return std::log10(gain) * 20;
43 | }
44 |
45 | void Biquad2::SetGainDb(float value)
46 | {
47 | SetGain(std::pow(10, value / 20));
48 | }
49 |
50 | float Biquad2::GetGain()
51 | {
52 | return gain;
53 | }
54 |
55 | void Biquad2::SetGain(float value)
56 | {
57 | if (value == 0)
58 | value = 0.001; // -60dB
59 |
60 | gain = value;
61 | }
62 |
63 | float Biquad2::GetQ()
64 | {
65 | return _q;
66 | }
67 |
68 | void Biquad2::SetQ(float value)
69 | {
70 | if (value == 0)
71 | value = 1e-12;
72 | _q = value;
73 | }
74 |
75 | vector Biquad2::GetA()
76 | {
77 | return vector({ 1, a1, a2 });
78 | }
79 |
80 | vector Biquad2::GetB()
81 | {
82 | return vector({ b0, b1, b2 });
83 | }
84 |
85 |
86 | void Biquad2::Update()
87 | {
88 | float omega = 2 * M_PI * Frequency / samplerate;
89 | float sinOmega = std::sin(omega);
90 | float cosOmega = std::cos(omega);
91 |
92 | float sqrtGain = 0.0;
93 | float alpha = 0.0;
94 |
95 | if (Type == FilterType::LowShelf || Type == FilterType::HighShelf)
96 | {
97 | alpha = sinOmega / 2 * std::sqrt((gain + 1 / gain) * (1 / Slope - 1) + 2);
98 | sqrtGain = std::sqrt(gain);
99 | }
100 | else
101 | {
102 | alpha = sinOmega / (2 * _q);
103 | }
104 |
105 | switch (Type)
106 | {
107 | case FilterType::LowPass:
108 | b0 = (1 - cosOmega) / 2;
109 | b1 = 1 - cosOmega;
110 | b2 = (1 - cosOmega) / 2;
111 | a0 = 1 + alpha;
112 | a1 = -2 * cosOmega;
113 | a2 = 1 - alpha;
114 | break;
115 | case FilterType::HighPass:
116 | b0 = (1 + cosOmega) / 2;
117 | b1 = -(1 + cosOmega);
118 | b2 = (1 + cosOmega) / 2;
119 | a0 = 1 + alpha;
120 | a1 = -2 * cosOmega;
121 | a2 = 1 - alpha;
122 | break;
123 | case FilterType::BandPass:
124 | b0 = alpha;
125 | b1 = 0;
126 | b2 = -alpha;
127 | a0 = 1 + alpha;
128 | a1 = -2 * cosOmega;
129 | a2 = 1 - alpha;
130 | break;
131 | case FilterType::Notch:
132 | b0 = 1;
133 | b1 = -2 * cosOmega;
134 | b2 = 1;
135 | a0 = 1 + alpha;
136 | a1 = -2 * cosOmega;
137 | a2 = 1 - alpha;
138 | break;
139 | case FilterType::Peak:
140 | b0 = 1 + (alpha * gain);
141 | b1 = -2 * cosOmega;
142 | b2 = 1 - (alpha * gain);
143 | a0 = 1 + (alpha / gain);
144 | a1 = -2 * cosOmega;
145 | a2 = 1 - (alpha / gain);
146 | break;
147 | case FilterType::LowShelf:
148 | b0 = gain * ((gain + 1) - (gain - 1) * cosOmega + 2 * sqrtGain * alpha);
149 | b1 = 2 * gain * ((gain - 1) - (gain + 1) * cosOmega);
150 | b2 = gain * ((gain + 1) - (gain - 1) * cosOmega - 2 * sqrtGain * alpha);
151 | a0 = (gain + 1) + (gain - 1) * cosOmega + 2 * sqrtGain * alpha;
152 | a1 = -2 * ((gain - 1) + (gain + 1) * cosOmega);
153 | a2 = (gain + 1) + (gain - 1) * cosOmega - 2 * sqrtGain * alpha;
154 | break;
155 | case FilterType::HighShelf:
156 | b0 = gain * ((gain + 1) + (gain - 1) * cosOmega + 2 * sqrtGain * alpha);
157 | b1 = -2 * gain * ((gain - 1) + (gain + 1) * cosOmega);
158 | b2 = gain * ((gain + 1) + (gain - 1) * cosOmega - 2 * sqrtGain * alpha);
159 | a0 = (gain + 1) - (gain - 1) * cosOmega + 2 * sqrtGain * alpha;
160 | a1 = 2 * ((gain - 1) - (gain + 1) * cosOmega);
161 | a2 = (gain + 1) - (gain - 1) * cosOmega - 2 * sqrtGain * alpha;
162 | break;
163 | }
164 |
165 | float g = 1 / a0;
166 |
167 | b0 = b0 * g;
168 | b1 = b1 * g;
169 | b2 = b2 * g;
170 | a1 = a1 * g;
171 | a2 = a2 * g;
172 | }
173 |
174 | float Biquad2::GetResponse(float freq)
175 | {
176 | float phi = std::pow((std::sin(2 * M_PI * freq / (2.0 * samplerate))), 2);
177 | return (std::pow(b0 + b1 + b2, 2.0) - 4.0 * (b0 * b1 + 4.0 * b0 * b2 + b1 * b2) * phi + 16.0 * b0 * b2 * phi * phi) / (std::pow(1.0 + a1 + a2, 2.0) - 4.0 * (a1 + 4.0 * a2 + a1 * a2) * phi + 16.0 * a2 * phi * phi);
178 | }
179 |
180 | void Biquad2::ClearBuffers()
181 | {
182 | y = 0;
183 | x2 = 0;
184 | y2 = 0;
185 | x1 = 0;
186 | y1 = 0;
187 | }
188 |
189 | }
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/Biquad2.h:
--------------------------------------------------------------------------------
1 | #ifndef BIQUAD2
2 | #define BIQUAD2
3 |
4 | #include
5 | using namespace std;
6 |
7 | namespace AudioLib
8 | {
9 | class Biquad2
10 | {
11 | public:
12 | enum class FilterType
13 | {
14 | LowPass = 0,
15 | HighPass,
16 | BandPass,
17 | Notch,
18 | Peak,
19 | LowShelf,
20 | HighShelf
21 | };
22 |
23 | private:
24 | float samplerate;
25 | float _gainDb;
26 | float _q;
27 | float a0, a1, a2, b0, b1, b2;
28 | float x1, x2, y, y1, y2;
29 | float gain;
30 |
31 | public:
32 | FilterType Type;
33 | float Output;
34 | float Frequency;
35 | float Slope;
36 |
37 | Biquad2();
38 | Biquad2(FilterType filterType, float samplerate);
39 | ~Biquad2();
40 |
41 | float GetSamplerate();
42 | void SetSamplerate(float samplerate);
43 | float GetGainDb();
44 | void SetGainDb(float value);
45 | float GetGain();
46 | void SetGain(float value);
47 | float GetQ();
48 | void SetQ(float value);
49 | vector GetA();
50 | vector GetB();
51 |
52 | void Update();
53 | float GetResponse(float freq);
54 |
55 | float inline Process(float x)
56 | {
57 | y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
58 | x2 = x1;
59 | y2 = y1;
60 | x1 = x;
61 | y1 = y;
62 |
63 | Output = y;
64 | return Output;
65 | }
66 |
67 | void inline Process(float* input, float* output, int len)
68 | {
69 | for (int i = 0; i < len; i++)
70 | output[i] = Process(input[i]);
71 | }
72 |
73 | void ClearBuffers();
74 | };
75 | }
76 |
77 | #endif
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/Hp1.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #define PI 3.141592653589793238462643383
5 |
6 | namespace AudioLib
7 | {
8 | class Hp1
9 | {
10 | private:
11 | float fs;
12 | float b0, a1;
13 | float lpOut;
14 | float cutoffHz;
15 |
16 | public:
17 | float Output;
18 |
19 | public:
20 | Hp1(float fs)
21 | {
22 | this->lpOut = 0;
23 | this->fs = fs;
24 | }
25 |
26 | float GetSamplerate()
27 | {
28 | return fs;
29 | }
30 |
31 | void SetSamplerate(float samplerate)
32 | {
33 | fs = samplerate;
34 | }
35 |
36 | float GetCutoffHz()
37 | {
38 | return cutoffHz;
39 | }
40 |
41 | void SetCutoffHz(float hz)
42 | {
43 | cutoffHz = hz;
44 | Update();
45 | }
46 |
47 | void Update()
48 | {
49 | // Prevent going over the Nyquist frequency
50 | if (cutoffHz >= fs * 0.5)
51 | cutoffHz = fs * 0.499;
52 |
53 | auto x = 2 * PI * cutoffHz / fs;
54 | auto nn = (2 - cos(x));
55 | auto alpha = nn - sqrt(nn * nn - 1);
56 |
57 | a1 = alpha;
58 | b0 = 1 - alpha;
59 | }
60 |
61 | float Process(float input)
62 | {
63 | if (input == 0 && lpOut < 0.000000000001)
64 | {
65 | Output = 0;
66 | }
67 | else
68 | {
69 | lpOut = b0 * input + a1 * lpOut;
70 | Output = input - lpOut;
71 | }
72 |
73 | return Output;
74 | }
75 |
76 | void Process(float* input, float* output, int len)
77 | {
78 | for (int i = 0; i < len; i++)
79 | output[i] = Process(input[i]);
80 | }
81 | };
82 | }
83 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/Lp1.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #define PI 3.141592653589793238462643383
6 |
7 | namespace AudioLib
8 | {
9 | using namespace std;
10 |
11 | class Lp1
12 | {
13 | public:
14 | float Output;
15 |
16 | public:
17 | Lp1(float fs)
18 | {
19 | this->fs = fs;
20 | }
21 |
22 | float GetSamplerate()
23 | {
24 | return fs;
25 | }
26 |
27 | void SetSamplerate(float samplerate)
28 | {
29 | fs = samplerate;
30 | }
31 |
32 | float GetCutoffHz()
33 | {
34 | return cutoffHz;
35 | }
36 |
37 | void SetCutoffHz(float hz)
38 | {
39 | cutoffHz = hz;
40 | Update();
41 | }
42 |
43 | void Update()
44 | {
45 | // Prevent going over the Nyquist frequency
46 | if (cutoffHz >= fs * 0.5)
47 | cutoffHz = fs * 0.499;
48 |
49 | auto x = 2 * PI * cutoffHz / fs;
50 | auto nn = (2 - cos(x));
51 | auto alpha = nn - sqrt(nn * nn - 1);
52 |
53 | a1 = alpha;
54 | b0 = 1 - alpha;
55 | }
56 |
57 | float Process(float input)
58 | {
59 | if (input == 0 && Output < 0.000000000001)
60 | {
61 | Output = 0;
62 | }
63 | else
64 | {
65 | Output = b0 * input + a1 * Output;
66 | }
67 | return Output;
68 | }
69 |
70 | void Process(float* input, float* output, int len)
71 | {
72 | for (int i = 0; i < len; i++)
73 | output[i] = Process(input[i]);
74 | }
75 |
76 |
77 | private:
78 | float fs;
79 | float b0, a1;
80 | float cutoffHz;
81 | };
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/MathDefs.h:
--------------------------------------------------------------------------------
1 | #ifndef MATH_DEFS
2 | #define MATH_DEFS
3 |
4 | #ifndef DSY_SDRAM_BSS
5 | #define DSY_SDRAM_BSS __attribute__((section(".sdram_bss")))
6 | #endif
7 |
8 |
9 |
10 |
11 | //#define M_E 2.71828182845904523536 // e
12 | //#define M_LOG2E 1.44269504088896340736 // log2(e)
13 | //#define M_LOG10E 0.434294481903251827651 // log10(e)
14 | //#define M_LN2 0.693147180559945309417 // ln(2)
15 | //#define M_LN10 2.30258509299404568402 // ln(10)
16 | #define M_PI 3.14159265358979323846 // pi
17 | #define M_PI_2 1.57079632679489661923 // pi/2
18 | //#define M_PI_4 0.785398163397448309616 // pi/4
19 | //#define M_1_PI 0.318309886183790671538 // 1/pi
20 | //#define M_2_PI 0.636619772367581343076 // 2/pi
21 | #define M_2_SQRTPI 1.12837916709551257390 // 2/sqrt(pi)
22 | #define M_SQRT2 1.41421356237309504880 // sqrt(2)
23 | //#define M_SQRT1_2 0.707106781186547524401 // 1/sqrt(2)
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/ShaRandom.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include "ShaRandom.h"
4 | #include "../Utils/Sha256.h"
5 |
6 | namespace AudioLib
7 | {
8 | using namespace std;
9 |
10 | vector ShaRandom::Generate(long long seed, int count)
11 | {
12 | vector byteList;
13 | auto iterations = count * sizeof(unsigned int) / (256 / 8) + 1;
14 | auto byteArr = (unsigned char*)&seed;
15 | vector bytes(byteArr, byteArr + 8);
16 |
17 | for (size_t i = 0; i < iterations; i++)
18 | {
19 | bytes = sha256(&bytes[0], 8);
20 | for (auto b : bytes)
21 | byteList.push_back(b);
22 | }
23 |
24 | auto intArray = (unsigned int*)(&byteList[0]);
25 | vector output;
26 |
27 | for (int i = 0; i < count; i++)
28 | {
29 | unsigned int val = intArray[i];
30 | float doubleVal = val / (float)UINT_MAX;
31 | output.push_back(doubleVal);
32 | }
33 |
34 | return output;
35 | }
36 |
37 | vector ShaRandom::Generate(long long seed, int count, float crossSeed)
38 | {
39 | auto seedA = seed;
40 | auto seedB = ~seed;
41 | auto seriesA = Generate(seedA, count);
42 | auto seriesB = Generate(seedB, count);
43 |
44 | vector output;
45 | for (int i = 0; i < count; i++)
46 | output.push_back(seriesA[i] * (1 - crossSeed) + seriesB[i] * crossSeed);
47 |
48 | return output;
49 | }
50 | }
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/ShaRandom.h:
--------------------------------------------------------------------------------
1 | #ifndef SHARANDOM
2 | #define SHARANDOM
3 |
4 | #include
5 |
6 | namespace AudioLib
7 | {
8 | class ShaRandom
9 | {
10 | public:
11 | static std::vector Generate(long long seed, int count);
12 | static std::vector Generate(long long seed, int count, float crossSeed);
13 | };
14 | }
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/ValueTables.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include "ValueTables.h"
4 | #include
5 |
6 | namespace AudioLib
7 | {
8 | float DSY_SDRAM_BSS ValueTables::Sqrt[TableSize];
9 | float DSY_SDRAM_BSS ValueTables::Sqrt3[TableSize];
10 | float DSY_SDRAM_BSS ValueTables::Pow1_5[TableSize];
11 | float DSY_SDRAM_BSS ValueTables::Pow2[TableSize];
12 | float DSY_SDRAM_BSS ValueTables::Pow3[TableSize];
13 | float DSY_SDRAM_BSS ValueTables::Pow4[TableSize];
14 | float DSY_SDRAM_BSS ValueTables::x2Pow3[TableSize];
15 |
16 | // octave response. value float every step (2,3,4,5 or 6 steps)
17 | float DSY_SDRAM_BSS ValueTables::Response2Oct[TableSize];
18 | float DSY_SDRAM_BSS ValueTables::Response3Oct[TableSize];
19 | float DSY_SDRAM_BSS ValueTables::Response4Oct[TableSize];
20 | float DSY_SDRAM_BSS ValueTables::Response5Oct[TableSize];
21 | float DSY_SDRAM_BSS ValueTables::Response6Oct[TableSize];
22 |
23 | // decade response, value multiplies by 10 every step
24 | float DSY_SDRAM_BSS ValueTables::Response2Dec[TableSize];
25 | float DSY_SDRAM_BSS ValueTables::Response3Dec[TableSize];
26 | float DSY_SDRAM_BSS ValueTables::Response4Dec[TableSize];
27 |
28 | void ValueTables::Init()
29 | {
30 | // Initialize tables
31 |
32 | for (int i = 0; i <= 4000; i++)
33 | {
34 | float x = i / 4000.0;
35 |
36 | Sqrt[i] = std::sqrt(x);
37 | Sqrt3[i] = std::pow(x, 1.0 / 3.0);
38 | Pow1_5[i] = std::pow(x, 1.5);
39 | Pow2[i] = std::pow(x, 2.0);
40 | Pow3[i] = std::pow(x, 3.0);
41 | Pow4[i] = std::pow(x, 4.0);
42 |
43 | x2Pow3[i] = std::pow(2 * x, 3.0);
44 | Response2Oct[i] = (std::pow(4, x) - 1.0) / 4.0 + 0.25;
45 | Response3Oct[i] = (std::pow(8, x) - 1.0) / 8.0 + 0.125;
46 | Response4Oct[i] = (std::pow(16, x) - 1.0) / 16.0 + 0.125 / 2.0;
47 | Response5Oct[i] = (std::pow(32, x) - 1.0) / 32.0 + 0.125 / 4.0;
48 | Response6Oct[i] = (std::pow(64, x) - 1.0) / 64.0 + 0.125 / 8.0;
49 |
50 | Response2Dec[i] = std::pow(100, x) / 100.0;
51 | Response3Dec[i] = std::pow(1000, x) / 1000.0;
52 | Response4Dec[i] = std::pow(10000, x) / 10000.0;
53 | }
54 |
55 | for (int i = 1; i <= 4000; i++)
56 | {
57 | Response2Oct[i] = (Response2Oct[i] - Response2Oct[0]) / (1 - Response2Oct[0]);
58 | Response3Oct[i] = (Response3Oct[i] - Response3Oct[0]) / (1 - Response3Oct[0]);
59 | Response4Oct[i] = (Response4Oct[i] - Response4Oct[0]) / (1 - Response4Oct[0]);
60 | Response5Oct[i] = (Response5Oct[i] - Response5Oct[0]) / (1 - Response5Oct[0]);
61 | Response6Oct[i] = (Response6Oct[i] - Response6Oct[0]) / (1 - Response6Oct[0]);
62 | Response2Dec[i] = (Response2Dec[i] - Response2Dec[0]) / (1 - Response2Dec[0]);
63 | Response3Dec[i] = (Response3Dec[i] - Response3Dec[0]) / (1 - Response3Dec[0]);
64 | Response4Dec[i] = (Response4Dec[i] - Response4Dec[0]) / (1 - Response4Dec[0]);
65 | }
66 |
67 | Response2Oct[0] = 0;
68 | Response3Oct[0] = 0;
69 | Response4Oct[0] = 0;
70 | Response5Oct[0] = 0;
71 | Response6Oct[0] = 0;
72 | Response2Dec[0] = 0;
73 | Response3Dec[0] = 0;
74 | Response4Dec[0] = 0;
75 | }
76 |
77 | float ValueTables::Get(float index, float* table)
78 | {
79 | if (table == nullptr)
80 | return index;
81 |
82 | int idx = (int)(index * 4000.999);
83 |
84 | assert(idx >= 0);
85 | assert(idx < AudioLib::ValueTables::TableSize);
86 |
87 |
88 | return table[idx];
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/AudioLib/ValueTables.h:
--------------------------------------------------------------------------------
1 | #ifndef AUDIOLIB_VALUETABLES
2 | #define AUDIOLIB_VALUETABLES
3 |
4 | #include "MathDefs.h"
5 |
6 |
7 | namespace AudioLib
8 | {
9 | class ValueTables
10 | {
11 | public:
12 | static const int TableSize = 40001;
13 |
14 | static DSY_SDRAM_BSS float Sqrt[TableSize];
15 | static DSY_SDRAM_BSS float Sqrt3[TableSize];
16 | static DSY_SDRAM_BSS float Pow1_5[TableSize];
17 | static DSY_SDRAM_BSS float Pow2[TableSize];
18 | static DSY_SDRAM_BSS float Pow3[TableSize];
19 | static DSY_SDRAM_BSS float Pow4[TableSize];
20 | static DSY_SDRAM_BSS float x2Pow3[TableSize];
21 |
22 | // octave response. value float every step (2,3,4,5 or 6 steps)
23 | static DSY_SDRAM_BSS float Response2Oct[TableSize];
24 | static DSY_SDRAM_BSS float Response3Oct[TableSize];
25 | static DSY_SDRAM_BSS float Response4Oct[TableSize];
26 | static DSY_SDRAM_BSS float Response5Oct[TableSize];
27 | static DSY_SDRAM_BSS float Response6Oct[TableSize];
28 |
29 | // decade response, value multiplies by 10 every step
30 | static DSY_SDRAM_BSS float Response2Dec[TableSize];
31 | static DSY_SDRAM_BSS float Response3Dec[TableSize];
32 | static DSY_SDRAM_BSS float Response4Dec[TableSize];
33 |
34 | static void Init();
35 | static float Get(float index, float* table);
36 | };
37 | }
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Default.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef DEFAULT_INCLUDE
3 | #define DEFAULT_INCLUDE
4 |
5 | typedef unsigned char byte;
6 | typedef unsigned int uint;
7 | #ifdef _WIN32
8 | typedef unsigned long long ulong;
9 | #endif
10 |
11 |
12 | #ifdef DEBUG
13 | #define __inline_always inline
14 | #else
15 | #define __inline_always __forceinline
16 | #endif
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Exports.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Default.h"
3 | #include "ReverbController.h"
4 | #include "FastSin.h"
5 | #include "AudioLib/ValueTables.h"
6 |
7 | using namespace CloudSeed;
8 | bool isInitialized = false;
9 |
10 | extern "C"
11 | {
12 | ReverbController* Create(int samplerate)
13 | {
14 | if (!isInitialized)
15 | {
16 | AudioLib::ValueTables::Init();
17 | FastSin::Init();
18 | isInitialized = true;
19 | }
20 |
21 | return new ReverbController(samplerate);
22 | }
23 |
24 | void Delete(ReverbController* item)
25 | {
26 | delete item;
27 | }
28 |
29 | int GetSamplerate(ReverbController* item)
30 | {
31 | return item->GetSamplerate();
32 | }
33 |
34 | void SetSamplerate(ReverbController* item, int samplerate)
35 | {
36 | return item->SetSamplerate(samplerate);
37 | }
38 |
39 | int GetParameterCount(ReverbController* item)
40 | {
41 | return item->GetParameterCount();
42 | }
43 |
44 | float* GetAllParameters(ReverbController* item)
45 | {
46 | return item->GetAllParameters();
47 | }
48 |
49 | float GetScaledParameter(ReverbController* item, Parameter2 param)
50 | {
51 | return item->GetScaledParameter(param);
52 | }
53 |
54 | void SetParameter(ReverbController* item, Parameter2 param, float value)
55 | {
56 | item->SetParameter(param, value);
57 | }
58 |
59 | void ClearBuffers(ReverbController* item)
60 | {
61 | item->ClearBuffers();
62 | }
63 |
64 | void Process(ReverbController* item, float* input, float* output, int bufferSize)
65 | {
66 | item->Process(input, output, bufferSize);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/FastSin.cpp:
--------------------------------------------------------------------------------
1 |
2 | #define _USE_MATH_DEFINES
3 | #include
4 | #include "Default.h"
5 | #include "FastSin.h"
6 |
7 | namespace CloudSeed
8 | {
9 | DSY_SDRAM_BSS float FastSin::data[FastSin::DataSize];
10 | }
11 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/FastSin.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "AudioLib/MathDefs.h"
5 | #include "FastSin.h"
6 |
7 | namespace CloudSeed
8 | {
9 | class FastSin
10 | {
11 | private:
12 | static const int DataSize = 32768;
13 | static DSY_SDRAM_BSS float data[DataSize];
14 |
15 | public:
16 | static void ZeroBuffer(float* buffer, int len);
17 | static void Init()
18 | {
19 | for (int i = 0; i < DataSize; i++)
20 | {
21 | data[i] = std::sin(2 * M_PI * i / (float)DataSize);
22 | }
23 | }
24 |
25 | static float Get(float index)
26 | {
27 | return data[(int)(index * 32767.99999)];
28 | }
29 | };
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Makefile:
--------------------------------------------------------------------------------
1 | TARGET = libcloudseed
2 |
3 | MODULE_DIR = .
4 | MODULES = \
5 | FastSin \
6 | AudioLib/Biquad2 \
7 | AudioLib/ShaRandom \
8 | AudioLib/ValueTables \
9 | Utils/Sha256 \
10 |
11 |
12 | # TODO: Consider making this work for PCs as well?
13 |
14 | CHIPSET = stm32f7x
15 |
16 | ######################################
17 | # building variables
18 | ######################################
19 | # debug build?
20 | #DEBUG = 0
21 | # optimization
22 | #OPT = -Og
23 | OPT = -O3
24 |
25 | #######################################
26 | # paths
27 | #######################################
28 | # source path
29 | SOURCES_DIR = \
30 |
31 | # Build path
32 | BUILD_DIR = build
33 |
34 | ######################################
35 | # source
36 | ######################################
37 |
38 | # C sources
39 | C_SOURCES += $(addsuffix .c, $(MODULE_DIR)/$(MODULES))
40 | # CPP sources
41 | CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(MODULES))
42 |
43 | #######################################
44 | # binaries
45 | #######################################
46 | PREFIX = arm-none-eabi-
47 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
48 | # either it can be added to the PATH environment variable.
49 | ifdef GCC_PATH
50 | CC = $(GCC_PATH)/$(PREFIX)gcc
51 | CXX = $(GCC_PATH)/$(PREFIX)g++
52 | AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
53 | CP = $(GCC_PATH)/$(PREFIX)objcopy
54 | SZ = $(GCC_PATH)/$(PREFIX)size
55 | AR = $(GCC_PATH)/$(PREFIX)ar
56 | GDB = $(GCC_PATH)/$(PREFIX)gdb
57 | else
58 | CC = $(PREFIX)gcc
59 | CXX = $(PREFIX)g++
60 | AS = $(PREFIX)gcc -x assembler-with-cpp
61 | CP = $(PREFIX)objcopy
62 | SZ = $(PREFIX)size
63 | AR = $(PREFIX)ar
64 | GDB = $(PREFIX)gdb
65 | endif
66 | HEX = $(CP) -O ihex
67 | BIN = $(CP) -O binary -S
68 |
69 | #######################################
70 | # CFLAGS
71 | #######################################
72 |
73 | # language standards
74 | C_STD = -std=gnu11
75 | CPP_STD = -std=gnu++14
76 |
77 | # cpu
78 | CPU = -mcpu=cortex-m7
79 |
80 | # fpu
81 | FPU = -mfpu=fpv5-d16
82 |
83 | # float-abi
84 | FLOAT-ABI = -mfloat-abi=hard
85 |
86 | # mcu
87 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
88 |
89 | # macros for gcc
90 | # AS defines
91 | AS_DEFS =
92 |
93 | # C defines
94 | C_DEFS = \
95 | -DUSE_HAL_DRIVER \
96 | -DSTM32H750xx \
97 | -DUSE_HAL_DRIVER \
98 | -DSTM32H750xx
99 |
100 | C_INCLUDES = \
101 | -I. \
102 |
103 | # compile gcc flags
104 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
105 |
106 | CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -Werror -fdata-sections -ffunction-sections
107 |
108 | ifeq ($(DEBUG), 1)
109 | CFLAGS += -g -gdwarf-2
110 | endif
111 |
112 | # Generate dependency information
113 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"
114 |
115 | CPPFLAGS = $(CFLAGS)
116 | CPPFLAGS += \
117 | -fno-exceptions \
118 | -finline-functions \
119 | -fno-aggressive-loop-optimizations
120 |
121 | #######################################
122 | # LDFLAGS # Not Used
123 | # TODO: Clean this up.
124 | #######################################
125 | # link script
126 | #LDSCRIPT = STM32H750IB_FLASH.lds
127 |
128 | # libraries
129 | #LIBS = lc -lm -lnosys
130 | #LIBDIR =
131 | #LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
132 |
133 | # default action: build all
134 | all: $(BUILD_DIR)/$(TARGET).a
135 |
136 | #######################################
137 | # build the library
138 | #######################################
139 |
140 | # list of objects
141 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
142 | vpath %.c $(sort $(dir $(C_SOURCES)))
143 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
144 | vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
145 | # list of ASM program objects
146 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
147 | vpath %.s $(sort $(dir $(ASM_SOURCES)))
148 |
149 | $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
150 | $(CC) -c $(CFLAGS) $(C_STD) -static -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
151 |
152 | $(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
153 | $(CXX) -c $(CPPFLAGS) $(CPP_STD) -static -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@
154 |
155 | $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
156 | $(AS) -c $(CFLAGS) $< -o $@
157 |
158 | $(BUILD_DIR)/$(TARGET).a: $(OBJECTS) Makefile
159 | $(AR) rcs $@ $(OBJECTS)
160 |
161 | $(BUILD_DIR):
162 | mkdir $@
163 |
164 | #######################################
165 | # clean up
166 | #######################################
167 | clean:
168 | -rm -fR $(BUILD_DIR)
169 | #######################################
170 |
171 | # dependencies
172 | #######################################
173 | -include $(wildcard $(BUILD_DIR)/*.d)
174 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/ModulatedAllpass.h:
--------------------------------------------------------------------------------
1 | #ifndef MODULATEDALLPASS
2 | #define MODULATEDALLPASS
3 |
4 | #include "ModulatedAllpass.h"
5 | #include "FastSin.h"
6 | #include "Utils.h"
7 | extern void* custom_pool_allocate(size_t size);
8 |
9 | namespace CloudSeed
10 | {
11 | class ModulatedAllpass
12 | {
13 | public:
14 | const int DelayBufferSamples = 19200; // 100ms at 192Khz
15 | static const int ModulationUpdateRate = 8;
16 |
17 | private:
18 | float* delayBuffer;
19 | float* output;
20 | int bufferSize;
21 | int index;
22 | unsigned int samplesProcessed;
23 |
24 | float modPhase;
25 | int delayA;
26 | int delayB;
27 | float gainA;
28 | float gainB;
29 |
30 | public:
31 |
32 | int SampleDelay;
33 | float Feedback;
34 | float ModAmount;
35 | float ModRate;
36 |
37 | bool InterpolationEnabled;
38 | bool ModulationEnabled;
39 |
40 | ModulatedAllpass(int bufferSize, int sampleDelay)
41 | {
42 | this->InterpolationEnabled = true;
43 | this->bufferSize = bufferSize;
44 | delayBuffer = new (custom_pool_allocate(sizeof(float) * DelayBufferSamples)) float[DelayBufferSamples];
45 | output = new (custom_pool_allocate(sizeof(float) * bufferSize)) float[bufferSize];
46 | SampleDelay = sampleDelay;
47 | index = DelayBufferSamples - 1;
48 | modPhase = 0.01 + 0.98 * std::rand() / (float)RAND_MAX;
49 | ModRate = 0.0;
50 | ModAmount = 0.0;
51 | Update();
52 | }
53 |
54 | ~ModulatedAllpass()
55 | {
56 | delete delayBuffer;
57 | delete output;
58 | }
59 |
60 |
61 | inline float* GetOutput()
62 | {
63 | return output;
64 | }
65 |
66 | void ClearBuffers()
67 | {
68 | Utils::ZeroBuffer(delayBuffer, DelayBufferSamples);
69 | Utils::ZeroBuffer(output, bufferSize);
70 | }
71 |
72 | void Process(float* input, int sampleCount)
73 | {
74 | if (ModulationEnabled)
75 | ProcessWithMod(input, sampleCount);
76 | else
77 | ProcessNoMod(input, sampleCount);
78 | }
79 |
80 |
81 | private:
82 | void ProcessNoMod(float* input, int sampleCount)
83 | {
84 | auto delayedIndex = index - SampleDelay;
85 | if (delayedIndex < 0) delayedIndex += DelayBufferSamples;
86 |
87 | for (int i = 0; i < sampleCount; i++)
88 | {
89 | auto bufOut = delayBuffer[delayedIndex];
90 | auto inVal = input[i] + bufOut * Feedback;
91 |
92 | delayBuffer[index] = inVal;
93 | output[i] = bufOut - inVal * Feedback;
94 |
95 | index++;
96 | delayedIndex++;
97 | if (index >= DelayBufferSamples) index -= DelayBufferSamples;
98 | if (delayedIndex >= DelayBufferSamples) delayedIndex -= DelayBufferSamples;
99 | samplesProcessed++;
100 | }
101 | }
102 |
103 | void ProcessWithMod(float* input, int sampleCount)
104 | {
105 | for (int i = 0; i < sampleCount; i++)
106 | {
107 | if (samplesProcessed >= ModulationUpdateRate)
108 | Update();
109 |
110 | float bufOut;
111 |
112 | if (InterpolationEnabled)
113 | {
114 | int idxA = index - delayA;
115 | int idxB = index - delayB;
116 | idxA += DelayBufferSamples * (idxA < 0); // modulo
117 | idxB += DelayBufferSamples * (idxB < 0); // modulo
118 |
119 | bufOut = delayBuffer[idxA] * gainA + delayBuffer[idxB] * gainB;
120 | }
121 | else
122 | {
123 | int idxA = index - delayA;
124 | idxA += DelayBufferSamples * (idxA < 0); // modulo
125 | bufOut = delayBuffer[idxA];
126 | }
127 |
128 | auto inVal = input[i] + bufOut * Feedback;
129 | delayBuffer[index] = inVal;
130 | output[i] = bufOut - inVal * Feedback;
131 |
132 | index++;
133 | if (index >= DelayBufferSamples) index -= DelayBufferSamples;
134 | samplesProcessed++;
135 | }
136 | }
137 |
138 | inline float Get(int delay)
139 | {
140 | int idx = index - delay;
141 | if (idx < 0)
142 | idx += DelayBufferSamples;
143 |
144 | return delayBuffer[idx];
145 | }
146 |
147 | void Update()
148 | {
149 | modPhase += ModRate * ModulationUpdateRate;
150 | if (modPhase > 1)
151 | modPhase = std::fmod(modPhase, 1.0);
152 |
153 | auto mod = FastSin::Get(modPhase);
154 |
155 | if (ModAmount >= SampleDelay) // don't modulate to negative value
156 | ModAmount = SampleDelay - 1;
157 |
158 |
159 | auto totalDelay = SampleDelay + ModAmount * mod;
160 |
161 | if (totalDelay <= 0) // should no longer be required
162 | totalDelay = 1;
163 |
164 | delayA = (int)totalDelay;
165 | delayB = (int)totalDelay + 1;
166 |
167 | auto partial = totalDelay - delayA;
168 |
169 | gainA = 1 - partial;
170 | gainB = partial;
171 |
172 | samplesProcessed = 0;
173 | }
174 |
175 | };
176 | }
177 |
178 | #endif
179 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/ModulatedDelay.h:
--------------------------------------------------------------------------------
1 | #ifndef MODULATEDDELAY
2 | #define MODULATEDDELAY
3 |
4 | #include "ModulatedDelay.h"
5 | #include "Utils.h"
6 | #include "FastSin.h"
7 |
8 | extern void* custom_pool_allocate(size_t size);
9 |
10 | namespace CloudSeed
11 | {
12 | class ModulatedDelay
13 | {
14 | private:
15 |
16 | const int ModulationUpdateRate = 8;
17 |
18 | float* delayBuffer;
19 | float* output;
20 | int bufferSize;
21 | int writeIndex;
22 | int readIndexA;
23 | int readIndexB;
24 | int samplesProcessed;
25 | int delayBufferSizeSamples;
26 |
27 | float modPhase;
28 | float gainA;
29 | float gainB;
30 |
31 | public:
32 | int SampleDelay;
33 |
34 | float ModAmount;
35 | float ModRate;
36 |
37 | ModulatedDelay(int bufferSize, int delayBufferSizeSamples, int sampleDelay)
38 | {
39 | this->delayBufferSizeSamples = delayBufferSizeSamples;
40 | this->bufferSize = bufferSize;
41 | this->delayBuffer = new (custom_pool_allocate(sizeof(float) * delayBufferSizeSamples)) float[delayBufferSizeSamples];
42 | this->output = new (custom_pool_allocate(sizeof(float) * bufferSize)) float[bufferSize];
43 | this->SampleDelay = sampleDelay;
44 | writeIndex = 0;
45 | modPhase = 0.01 + 0.98 * (std::rand() / (float)RAND_MAX);
46 | ModRate = 0.0;
47 | ModAmount = 0.0;
48 | Update();
49 | }
50 |
51 | ~ModulatedDelay()
52 | {
53 | delete delayBuffer;
54 | delete output;
55 | }
56 |
57 | float* GetOutput()
58 | {
59 | return output;
60 | }
61 |
62 | void Process(float* input, int sampleCount)
63 | {
64 | for (int i = 0; i < sampleCount; i++)
65 | {
66 | if (samplesProcessed == ModulationUpdateRate)
67 | Update();
68 |
69 | delayBuffer[writeIndex] = input[i];
70 | output[i] = delayBuffer[readIndexA] * gainA + delayBuffer[readIndexB] * gainB;
71 |
72 | writeIndex++;
73 | readIndexA++;
74 | readIndexB++;
75 | if (writeIndex >= delayBufferSizeSamples) writeIndex -= delayBufferSizeSamples;
76 | if (readIndexA >= delayBufferSizeSamples) readIndexA -= delayBufferSizeSamples;
77 | if (readIndexB >= delayBufferSizeSamples) readIndexB -= delayBufferSizeSamples;
78 | samplesProcessed++;
79 | }
80 | }
81 |
82 | void ClearBuffers()
83 | {
84 | Utils::ZeroBuffer(delayBuffer, delayBufferSizeSamples);
85 | Utils::ZeroBuffer(output, bufferSize);
86 | }
87 |
88 |
89 | private:
90 | void Update()
91 | {
92 | modPhase += ModRate * ModulationUpdateRate;
93 | if (modPhase > 1)
94 | modPhase = std::fmod(modPhase, 1.0);
95 |
96 | auto mod = FastSin::Get(modPhase);
97 | auto totalDelay = SampleDelay + ModAmount * mod;
98 |
99 | auto delayA = (int)totalDelay;
100 | auto delayB = (int)totalDelay + 1;
101 |
102 | auto partial = totalDelay - delayA;
103 |
104 | gainA = 1 - partial;
105 | gainB = partial;
106 |
107 | readIndexA = writeIndex - delayA;
108 | readIndexB = writeIndex - delayB;
109 | if (readIndexA < 0) readIndexA += delayBufferSizeSamples;
110 | if (readIndexB < 0) readIndexB += delayBufferSizeSamples;
111 |
112 | samplesProcessed = 0;
113 | }
114 | };
115 | }
116 |
117 | #endif
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/MultitapDiffuser.h:
--------------------------------------------------------------------------------
1 | #ifndef MULTITAPDIFFUSER
2 | #define MULTITAPDIFFUSER
3 |
4 | #include
5 | #include
6 | #include
7 | #include "MultitapDiffuser.h"
8 | #include "Utils.h"
9 | #include "AudioLib/ShaRandom.h"
10 | extern void* custom_pool_allocate(size_t size);
11 |
12 | namespace CloudSeed
13 | {
14 | using namespace std;
15 |
16 | class MultitapDiffuser
17 | {
18 | public:
19 | static const int MaxTaps = 50;
20 |
21 | private:
22 | float* buffer;
23 | float* output;
24 | int len;
25 |
26 | int index;
27 | vector tapGains;
28 | vector tapPosition;
29 | vector seedValues;
30 | int seed;
31 | float crossSeed;
32 | int count;
33 | float length;
34 | float gain;
35 | float decay;
36 |
37 | bool isDirty;
38 | vector tapGainsTemp;
39 | vector tapPositionTemp;
40 | int countTemp;
41 |
42 | public:
43 | MultitapDiffuser(int delayBufferSize)
44 | {
45 | len = delayBufferSize;
46 | buffer = new (custom_pool_allocate(sizeof(float) * delayBufferSize)) float[delayBufferSize];
47 | output = new (custom_pool_allocate(sizeof(float) * delayBufferSize)) float[delayBufferSize];
48 | index = 0;
49 | count = 1;
50 | length = 1;
51 | gain = 1.0;
52 | decay = 0.0;
53 | crossSeed = 0.0;
54 | UpdateSeeds();
55 | }
56 |
57 | ~MultitapDiffuser()
58 | {
59 | delete buffer;
60 | delete output;
61 | }
62 |
63 |
64 | void SetSeed(int seed)
65 | {
66 | this->seed = seed;
67 | UpdateSeeds();
68 | }
69 |
70 | void SetCrossSeed(float crossSeed)
71 | {
72 | this->crossSeed = crossSeed;
73 | UpdateSeeds();
74 | }
75 |
76 | float* GetOutput()
77 | {
78 | return output;
79 | }
80 |
81 | void SetTapCount(int tapCount)
82 | {
83 | count = tapCount;
84 | Update();
85 | }
86 |
87 | void SetTapLength(int tapLength)
88 | {
89 | length = tapLength;
90 | Update();
91 | }
92 |
93 | void SetTapDecay(float tapDecay)
94 | {
95 | decay = tapDecay;
96 | Update();
97 | }
98 |
99 | void SetTapGain(float tapGain)
100 | {
101 | gain = tapGain;
102 | Update();
103 | }
104 |
105 | void Process(float* input, int sampleCount)
106 | {
107 | // prevents race condition when parameters are updated from Gui
108 | if (isDirty)
109 | {
110 | tapGainsTemp = tapGains;
111 | tapPositionTemp = tapPosition;
112 | countTemp = count;
113 | isDirty = false;
114 | }
115 |
116 | int* const tapPos = &tapPositionTemp[0];
117 | float* const tapGain = &tapGainsTemp[0];
118 | const int cnt = countTemp;
119 |
120 | for (int i = 0; i < sampleCount; i++)
121 | {
122 | if (index < 0) index += len;
123 | buffer[index] = input[i];
124 | output[i] = 0.0;
125 |
126 | for (int j = 0; j < cnt; j++)
127 | {
128 | auto idx = (index + tapPos[j]) % len;
129 | output[i] += buffer[idx] * tapGain[j];
130 | }
131 |
132 | index--;
133 | }
134 | }
135 |
136 | void ClearBuffers()
137 | {
138 | Utils::ZeroBuffer(buffer, len);
139 | Utils::ZeroBuffer(output, len);
140 | }
141 |
142 |
143 | private:
144 | void Update()
145 | {
146 | vector newTapGains;
147 | vector newTapPosition;
148 |
149 | int s = 0;
150 | auto rand = [&]() {return seedValues[s++]; };
151 |
152 | if (count < 1)
153 | count = 1;
154 |
155 | if (length < count)
156 | length = count;
157 |
158 | // used to adjust the volume of the overall output as it grows when we add more taps
159 | float tapCountFactor = 1.0 / (1 + std::sqrt(count / MaxTaps));
160 |
161 | newTapGains.resize(count);
162 | newTapPosition.resize(count);
163 |
164 | vector tapData(count, 0.0);
165 |
166 | auto sumLengths = 0.0;
167 | for (size_t i = 0; i < count; i++)
168 | {
169 | auto val = 0.1 + rand();
170 | tapData[i] = val;
171 | sumLengths += val;
172 | }
173 |
174 | auto scaleLength = length / sumLengths;
175 | newTapPosition[0] = 0;
176 |
177 | for (int i = 1; i < count; i++)
178 | {
179 | newTapPosition[i] = newTapPosition[i - 1] + (int)(tapData[i] * scaleLength);
180 | }
181 |
182 | float sumGains = 0.0;
183 | float lastTapPos = newTapPosition[count - 1];
184 | for (int i = 0; i < count; i++)
185 | {
186 | // when decay set to 0, there is no decay, when set to 1, the gain at the last sample is 0.01 = -40dB
187 | auto g = std::pow(10, -decay * 2 * newTapPosition[i] / (float)(lastTapPos + 1));
188 |
189 | auto tap = (2 * rand() - 1) * tapCountFactor;
190 | newTapGains[i] = tap * g * gain;
191 | }
192 |
193 | // Set the tap vs. clean mix
194 | newTapGains[0] = (1 - gain);
195 |
196 | this->tapGains = newTapGains;
197 | this->tapPosition = newTapPosition;
198 | isDirty = true;
199 | }
200 |
201 | void UpdateSeeds()
202 | {
203 | this->seedValues = AudioLib::ShaRandom::Generate(seed, 100, crossSeed);
204 | Update();
205 | }
206 | };
207 | }
208 |
209 | #endif
210 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Parameter.h:
--------------------------------------------------------------------------------
1 | #ifndef PARAMETER2
2 | #define PARAMETER2
3 |
4 | enum class Parameter2
5 | {
6 | // Input
7 |
8 | InputMix = 0,
9 | PreDelay,
10 |
11 | HighPass,
12 | LowPass,
13 |
14 | // Early
15 |
16 | TapCount,
17 | TapLength,
18 | TapGain,
19 | TapDecay,
20 |
21 | DiffusionEnabled,
22 | DiffusionStages,
23 | DiffusionDelay,
24 | DiffusionFeedback,
25 |
26 | // Late
27 |
28 | LineCount,
29 | LineDelay,
30 | LineDecay,
31 |
32 |
33 | LateDiffusionEnabled,
34 | LateDiffusionStages,
35 | LateDiffusionDelay,
36 | LateDiffusionFeedback,
37 |
38 | // Frequency Response
39 |
40 | PostLowShelfGain,
41 | PostLowShelfFrequency,
42 | PostHighShelfGain,
43 | PostHighShelfFrequency,
44 | PostCutoffFrequency,
45 |
46 | // Modulation
47 |
48 | EarlyDiffusionModAmount,
49 | EarlyDiffusionModRate,
50 |
51 | LineModAmount,
52 | LineModRate,
53 |
54 | LateDiffusionModAmount,
55 | LateDiffusionModRate,
56 |
57 | // Seeds
58 |
59 | TapSeed,
60 | DiffusionSeed,
61 | DelaySeed,
62 | PostDiffusionSeed,
63 |
64 | // Seed Mix
65 |
66 | CrossSeed,
67 |
68 | DryOut,
69 | PredelayOut,
70 | EarlyOut,
71 | MainOut,
72 |
73 | // Switches
74 | HiPassEnabled,
75 | LowPassEnabled,
76 | LowShelfEnabled,
77 | HighShelfEnabled,
78 | CutoffEnabled,
79 | LateStageTap,
80 |
81 | // Effects
82 | Interpolation,
83 |
84 | Count,
85 |
86 | Unused = 999
87 | };
88 |
89 | #endif
90 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Utils.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS
2 | #define UTILS
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace CloudSeed
9 | {
10 | class Utils
11 | {
12 | public:
13 |
14 | static inline void ZeroBuffer(float* buffer, int len)
15 | {
16 | for (int i = 0; i < len; i++)
17 | buffer[i] = 0.0;
18 | }
19 |
20 | static inline void Copy(float* source, float* dest, int len)
21 | {
22 | std::memcpy(dest, source, len * sizeof(float));
23 | }
24 |
25 | static inline void Gain(float* buffer, float gain, int len)
26 | {
27 | for (int i = 0; i < len; i++)
28 | {
29 | buffer[i] *= gain;
30 | }
31 | }
32 |
33 | // perform bit crushing and undersampling
34 | // undersampling: if set to 1, perfroms no effect, if set to 2, will undersample to 1/2 samplerate, etc...
35 | // sampleResolution: if set to 32, will use 2^32 steps, if set to 8, will resude to 2^8 = 256 steps
36 | // Currently Unused
37 | static inline void BitcrushAndReduce(float* bufferIn, float* bufferOut, int len, int undersampling, int sampleResolution)
38 | {
39 | float sampleSteps = std::pow(2, sampleResolution);
40 | float inverseSteps = 1.0 / sampleSteps;
41 |
42 | float sample = 0.0;
43 |
44 | for (int i = 0; i < len; i++)
45 | {
46 | if (i % undersampling == 0)
47 | sample = ((long)(bufferIn[i] * sampleSteps)) * inverseSteps;
48 |
49 | bufferOut[i] = sample;
50 | }
51 | }
52 |
53 | template
54 | static float DB2gain(T input)
55 | {
56 | return std::pow(10, input / 20.0);
57 | }
58 |
59 | template
60 | static float Gain2DB(T input)
61 | {
62 | if (input < 0.0000001)
63 | return -100000;
64 |
65 | return 20.0f * std::log10(input);
66 | }
67 | };
68 | }
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/Utils/Sha256.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Updated to C++, zedwood.com 2012
3 | * Based on Olivier Gay's version
4 | * See Modified BSD License below:
5 | *
6 | * FIPS 180-2 SHA-224/256/384/512 implementation
7 | * Issue date: 04/30/2005
8 | * http://www.ouah.org/ogay/sha2/
9 | *
10 | * Copyright (C) 2005, 2007 Olivier Gay
11 | * All rights reserved.
12 | *
13 | * Redistribution and use in source and binary forms, with or without
14 | * modification, are permitted provided that the following conditions
15 | * are met:
16 | * 1. Redistributions of source code must retain the above copyright
17 | * notice, this list of conditions and the following disclaimer.
18 | * 2. Redistributions in binary form must reproduce the above copyright
19 | * notice, this list of conditions and the following disclaimer in the
20 | * documentation and/or other materials provided with the distribution.
21 | * 3. Neither the name of the project nor the names of its contributors
22 | * may be used to endorse or promote products derived from this software
23 | * without specific prior written permission.
24 | *
25 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 | * SUCH DAMAGE.
36 | */
37 |
38 | #ifndef SHA256_H
39 | #define SHA256_H
40 | #include
41 |
42 | class SHA256
43 | {
44 | protected:
45 | typedef unsigned char uint8;
46 | typedef unsigned int uint32;
47 | typedef unsigned long long uint64;
48 |
49 | const static uint32 sha256_k[];
50 | static const unsigned int SHA224_256_BLOCK_SIZE = (512 / 8);
51 | public:
52 | void init();
53 | void update(const unsigned char *message, unsigned int len);
54 | void final(unsigned char *digest);
55 | static const unsigned int DIGEST_SIZE = (256 / 8);
56 |
57 | protected:
58 | void transform(const unsigned char *message, unsigned int block_nb);
59 | unsigned int m_tot_len;
60 | unsigned int m_len;
61 | unsigned char m_block[2 * SHA224_256_BLOCK_SIZE];
62 | uint32 m_h[8];
63 | };
64 |
65 | std::vector sha256(unsigned char* input, int len);
66 |
67 | #define SHA2_SHFR(x, n) (x >> n)
68 | #define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
69 | #define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
70 | #define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
71 | #define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
72 | #define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))
73 | #define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))
74 | #define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))
75 | #define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))
76 | #define SHA2_UNPACK32(x, str) \
77 | { \
78 | *((str) + 3) = (uint8) ((x) ); \
79 | *((str) + 2) = (uint8) ((x) >> 8); \
80 | *((str) + 1) = (uint8) ((x) >> 16); \
81 | *((str) + 0) = (uint8) ((x) >> 24); \
82 | }
83 | #define SHA2_PACK32(str, x) \
84 | { \
85 | *(x) = ((uint32) *((str) + 3) ) \
86 | | ((uint32) *((str) + 2) << 8) \
87 | | ((uint32) *((str) + 1) << 16) \
88 | | ((uint32) *((str) + 0) << 24); \
89 | }
90 | #endif
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Valdemar Erlingsson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/software/Neptune/CloudSeed/premake4.lua:
--------------------------------------------------------------------------------
1 | project "CloudSeed"
2 |
3 | language "C++"
4 |
5 | kind "StaticLib"
6 |
7 | includedirs {"."}
8 |
9 | files {
10 | "*.cpp",
11 | "*.h",
12 | "AudioLib/*.cpp",
13 | "AudioLib/*.h",
14 | "Utils/*.cpp",
15 | "Utils/*.h",
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/software/Neptune/README.md:
--------------------------------------------------------------------------------
1 | # Neptune (Planet Series)
2 |
3 | Neptune is a Stereo Reverb/Delay pedal. The reverb used here is from the [CloudSeed plugin](https://github.com/ValdemarOrn/CloudSeed) (MIT License), and the Delay includes normal, octave, and reverse modes.
4 | Neptune is very similar to the GuitarML Atlas pedal. The reverse delay is a modified version of the reverse delay from [Veno-Echo](https://github.com/AdamFulford/Veno-Echo) (MIT License)
5 |
6 | 
7 |
8 | ## Controls
9 |
10 | | Control | Description | Comment |
11 | | --- | --- | --- |
12 | | Ctrl 1 | Reverb Decay | Increases the decay time of the reverb |
13 | | Ctrl 2 | Mix (rev/delay mix) | Mix control between the Dry input and effect, alternate is Reverb/Delay volume ratio |
14 | | Ctrl 3 | Delay Time | Delay time from 0 to 4 seconds |
15 | | Ctrl 4 | Mod (Mod Rate) | Amount of modulation of the reverb, Alternate mode sets is mod rate |
16 | | Ctrl 5 | Reverb LowPass | Delay time 0 to 2 seconds. |
17 | | Ctrl 6 | Delay Feedback | Delay Feedback (how long delay takes to fade out) |
18 | | 3-Way Switch 1 | Reverb Mode | left: Factory Chorus, center: Medium Space, right: RubiKai (These mostly match the CloudSeed presets) |
19 | | 3-Way Switch 2 | Routing | left: Some delay fed to reverb, center: Parallel reverb/delay right: delay into reverb in series |
20 | | 3-Way Switch 3 | Delay Mode | left: normal, center: octave, right: reverse |
21 | | Dip Switch 1 | MISO/Stereo | MISO (Mono in stereo out), or True Stereo |
22 | | Dip Switch 2 | | |
23 | | FS 1 | Bypass, hold to put into Alternate mode | Alternate mode indicated by dimmed LED, switches back when let go |
24 | | FS 2 | Preset | Hold to save preset, press to engage/disengage preset. Saves between power cycles. |
25 | | LED 1 | Bypass/Alternate Indicator | |
26 | | LED 2 | Preset Indicator | ||
27 | | Audio In 1 | Stereo In | Right channel ignored if MISO Mode turned on |
28 | | Audio Out 1 | Stereo Out | |
29 |
30 | ### Expression
31 | 1. Plug in passive expression pedal into the 1/8" jack on the top left side of pedal. (will need a 1/4" female to 1/8" male TRS adapter)
32 | 2. Hold both footswitches until they both light up (more than 0.5 seconds, but less than 2 seconds), you are now in Set Expression mode.
33 | 3. Move the expression pedal into the heel position (up) and move any number of knobs to where you want to heel limit to be (for example you could turn Volume down). The right LED should be brighter up to indicate the heel position is ready to set.*
34 | 3. Move the expression pedal into the toe position (down) and move any number of knobs to where you want to toe limit to be (for example you could turn Volume up). The Left LED should be brighter to indicate the toe position is ready to set.*
35 | 4. Hold both footswitches to exit Set Expression mode. This will activate expression for the moved knobs. The moved knobs will be inactive until Expression Mode is deactivated.
36 | 5. Repeat step 2 to reset Expression knobs.
37 | 6. Hold both footswitches for 2 seconds or more to clear any Expression action and give control back to the Funbox knobs.
38 |
39 | * Currently, the expression input requires the full range of the expression pedal, in order to detect Up/Down positions. You can sometimes trim the expression pedal to not use the full range, so adjust the trim as necessary.
40 | Also, some expression pedals have a "Standard" or "Alternate/Other" mode. Funbox should work on the "Standard" mode.
41 |
42 |
43 | ### MIDI Reference
44 |
45 | | Control | MIDI CC | Value |
46 | | --- | --- | --- |
47 | | Knob 1 | 14 | 0- 127 |
48 | | Knob 2 | 15 | 0- 127 |
49 | | Knob 3 | 16 | 0- 127 |
50 | | Knob 4 | 17 | 0- 127 |
51 | | Knob 5 | 18 | 0- 127 |
52 | | Knob 6 | 19 | 0- 127 |
53 |
54 | ## Build
55 |
56 | Neptune runs in SRAM memory on the Daisy Seed. You must use the Bootloader to load the executable.
57 | Note: MIDI will not work if you use the Bootloader from the Daisy Web Programmer (it's an old version).
58 |
59 | Before building Neptune, you must build Cloudseed with ```make```
--------------------------------------------------------------------------------
/software/Neptune/neptune/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = neptune
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = neptune.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../../libDaisy
18 | DAISYSP_DIR = ../../../DaisySP
19 | CLOUDSEED_DIR = ../CloudSeed
20 |
21 | # Core location, and generic Makefile.
22 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
23 | include $(SYSTEM_FILES_DIR)/Makefile
24 |
25 |
26 | # Include funbox.h
27 | C_INCLUDES += -I../../../include -I../CloudSeed \
28 |
29 | LIBS += -lcloudseed
30 | LIBDIR += -L../CloudSeed/build
--------------------------------------------------------------------------------
/software/Pluto/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = pluto
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | #APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | OPT = -O1
10 | #OPT=-Os
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = pluto.cpp reverbsc96.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../libDaisy
18 | DAISYSP_DIR = ../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../include
--------------------------------------------------------------------------------
/software/Pluto/README.md:
--------------------------------------------------------------------------------
1 | # Pluto
2 |
3 | Pluto is a wacky dual/stereo looper for endless experimentation. Each looper features a variable speed control, smooth or stepped,
4 | and several effects and loop modes. Pluto runs at 96kHz instead of 48kHz, in order to have the best quality when slowing down loops,
5 | but don't worry, lots of aliasing/artifacts are present when strethching audio!
6 |
7 | Loops are recorded at the current speed setting. For example, if the speed of Loop A is at 2x and you record a loop, it will sound normal, but turning the speed
8 | knob down to 1x will play your loop at half speed (and half the samplerate).
9 |
10 | Pluto is in active development, more features coming
11 |
12 |
13 | 
14 |
15 | ## Controls
16 |
17 | | Control | Description | Comment |
18 | | --- | --- | --- |
19 | | Ctrl 1 | Looper A Volume | |
20 | | Ctrl 2 | Looper A Modify | Modifies the current effect applied to loop A (or for Reverb, controls decay time) |
21 | | Ctrl 3 | Looper B Volume | |
22 | | Ctrl 4 | Looper A Speed/Direction | Speed and direction of Loop A, -2x (reverse) to +2x speed, noon is 1x speed |
23 | | Ctrl 5 | Looper A Modify | Modifies the current effect applied to loop A (or for Reverb, controls decay time) |
24 | | Ctrl 6 | Looper B Speed/Direction | Speed and direction of Loop B, -2x (reverse) to +2x speed, noon is 1x speed | |
25 | | 3-Way Switch 1 | Looper A/B Speed mode | Left = smooth, Center=Stepped, Right= TBD |
26 | | 3-Way Switch 2 | Live effect select (controls what modify knobs do) | Left=Stability(random variations in playback speed), Center=Filter (LP to the left, HP to the right), Right=Reverb (stereo, ModA is decay, ModB is damping) |
27 | | 3-Way Switch 3 | Loop Record Mode | Left = normal, Center = One Time loop record, Right= Frippertronics (when recording, acts like a delay, applying a decay time to the loop) |
28 | | Dip Switch 1 | MISO/Stereo | Miso only takes the left channel input, and treats each looper as independant. Stereo takes L/R input and treats loopers as connected when recording (Looper B footswitch is inactive in Stereo Mode) |
29 | | Dip Switch 2 | TBD | Want to add a Sync mode here, where the loop time for both A/B are equal |
30 | | FS 1 | Loop A control | Tap once to start recording loop, tap again to stop record and start playback. Double tap to pause loop. Hold to clear loop. Tap again to overdub. Currently no undo function. |
31 | | FS 2 | Loop B control | Same as Loop A |
32 | | LED 1 | Loop A Indicator | Pulses while recording, Solid while playback, blinking while paused. |
33 | | LED 2 | Loop B indicator | Same as Loop A|
34 | | Audio In 1 | Stereo (or MISO) | MISO will use 2 speparate loopers, and copy left channel output to right, Stereo will use 1 looper, and loop A is left channel, loop B is right channel |
35 | | Audio Out 1 | Stereo | |
36 |
37 |
38 | ### Expression
39 | Expression Operation: NOTE THAT THIS IS DIFFERENT FROM OTHER PLANET PEDALS**
40 | 1. Plug in passive expression pedal into the 1/8" jack on the top left side of pedal. (will need a 1/4" female to 1/8" male TRS adapter)
41 | 2. Turn on Dipswitch 3 to enter Set Expression mode, both LEDs should light up, you are now in Set Expression mode.
42 | 3. Move the expression pedal into the heel position (up) and move any number of knobs to where you want to heel limit to be (for example you could turn Volume down). The right LED should be brighter up to indicate the heel position is ready to set.*
43 | 3. Move the expression pedal into the toe position (down) and move any number of knobs to where you want to toe limit to be (for example you could turn Volume up). The Left LED should be brighter to indicate the toe position is ready to set.*
44 | 4. Turn off Dipswitch 3 to exit Set Expression mode and enter Expression Active Mode.
45 | 5. Flip Dipswitch 3 on and move expression pedal into both up and down positions without turning any knobs. Flip Dipswitch 3 off to clear expression and give control back to knobs.
46 |
47 |
48 | * Currently, the expression input requires the full range of the expression pedal, in order to detect Up/Down positions. You can sometimes trim the expression pedal to not use the full range, so adjust the trim as necessary.
49 | Also, some expression pedals have a "Standard" or "Alternate/Other" mode. Funbox should work on the "Standard" mode.
50 |
51 | ** Since Pluto uses the footswitches for looper funtions, the third dip switch is used to enter/exit Set Expression mode. Flip dipswitch 3 without adjusting any knobs to clear expression settings.
52 |
53 | ### MIDI Reference
54 |
55 | | Control | MIDI CC | Value |
56 | | --- | --- | --- |
57 | | Knob 1 | 14 | 0- 127 |
58 | | Knob 2 | 15 | 0- 127 |
59 | | Knob 3 | 16 | 0- 127 |
60 | | Knob 4 | 17 | 0- 127 |
61 | | Knob 5 | 18 | 0- 127 |
62 | | Knob 6 | 19 | 0- 127 |
63 | | Toggle Left | 21 | 0,1:left ; 2, center; 3 or > right |
64 | | Toggle Center | 22 | 0,1:left ; 2, center; 3 or > right |
65 | | Toggle Right| 23 | 0,1:left ; 2, center; 3 or > right |
66 |
67 | ## Build
68 |
--------------------------------------------------------------------------------
/software/Pluto/reverbsc96.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2023 Electrosmith, Corp, Sean Costello, Istvan Varga, Paul Batchelor
3 |
4 | Use of this source code is governed by the LGPL V2.1
5 | license that can be found in the LICENSE file or at
6 | https://opensource.org/license/lgpl-2-1/
7 | */
8 |
9 | #pragma once
10 | #ifndef REVERBSC96_H
11 | #define REVERBSC96_H
12 |
13 | #define DSY_REVERBSC_MAX_SIZE 98936
14 |
15 |
16 | /**Delay line for internal reverb use
17 | */
18 | typedef struct
19 | {
20 | int write_pos; /**< write position */
21 | int buffer_size; /**< buffer size */
22 | int read_pos; /**< read position */
23 | int read_pos_frac; /**< fractional component of read pos */
24 | int read_pos_frac_inc; /**< increment for fractional */
25 | int dummy; /**< dummy var */
26 | int seed_val; /**< randseed */
27 | int rand_line_cnt; /**< number of random lines */
28 | float filter_state; /**< state of filter */
29 | float *buf; /**< buffer ptr */
30 | } ReverbSc96Dl;
31 |
32 | /** Stereo Reverb */
33 | class ReverbSc96
34 | {
35 | public:
36 | ReverbSc96() {}
37 | ~ReverbSc96() {}
38 | /** Initializes the reverb module, and sets the sample_rate at which the Process function will be called.
39 | Returns 0 if all good, or 1 if it runs out of delay times exceed maximum allowed.
40 | */
41 | int Init(float sample_rate);
42 |
43 | /** Process the input through the reverb, and updates values of out1, and out2 with the new processed signal.
44 | */
45 | int Process(const float &in1, const float &in2, float *out1, float *out2);
46 |
47 | /** controls the reverb time. reverb tail becomes infinite when set to 1.0
48 | \param fb - sets reverb time. range: 0.0 to 1.0
49 | */
50 | inline void SetFeedback(const float &fb) { feedback_ = fb; }
51 | /** controls the internal dampening filter's cutoff frequency.
52 | \param freq - low pass frequency. range: 0.0 to sample_rate / 2
53 | */
54 | inline void SetLpFreq(const float &freq) { lpfreq_ = freq; }
55 |
56 | private:
57 | void NextRandomLineseg(ReverbSc96Dl *lp, int n);
58 | int InitDelayLine(ReverbSc96Dl *lp, int n);
59 | float feedback_, lpfreq_;
60 | float i_sample_rate_, i_pitch_mod_, i_skip_init_;
61 | float sample_rate_;
62 | float damp_fact_;
63 | float prv_lpfreq_;
64 | int init_done_;
65 | ReverbSc96Dl delay_lines_[8];
66 | float aux_[DSY_REVERBSC_MAX_SIZE];
67 | };
68 |
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/software/README.md:
--------------------------------------------------------------------------------
1 | # Software
2 |
3 | Software for the Funbox platform.
4 |
5 | The Planet Series are what I would consider to be ready-to-go guitar pedals.
6 | - Mercury : An amp emulator running NAM neural amp modeler and 4 band EQ.
7 | - Venus : A spectral reverb with string-like harmonies, detune, and freeze.
8 | - Earth : A plate reverb with octave and overdrive effects.
9 | - Mars : An amp sim including neural models and IRs, with a 3-mode delay.
10 | - Jupiter : A stereo reverb with tons of customization.
11 | - Saturn : A stereo spectral delay that diffracts your signal into particles.
12 | - Neptune : A stereo reverb/delay capable of ethereal sounds.
13 | - Uranus : A granular delay and FM synth.
14 | - Pluto : A wacky Dual/Stereo Looper with speed/direction controls.
15 |
16 | "Experiments" includes tests that might be interesting, but are not necessarily a polished product.
17 |
18 | The files in the "Template" directory serve as a starting place for developing your own effects.
19 |
20 |
--------------------------------------------------------------------------------
/software/Saturn/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = saturn
3 |
4 | # Sources
5 | CPP_SOURCES = saturn.cpp
6 |
7 | #OPT = -O1
8 | OPT = -Ofast
9 | #OPT ?= -O3
10 | #OPT = -Os
11 |
12 | # Library Locations
13 | LIBDAISY_DIR = ../../libDaisy
14 | DAISYSP_DIR = ../../DaisySP
15 |
16 |
17 | # Core location, and generic Makefile.
18 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
19 | include $(SYSTEM_FILES_DIR)/Makefile
20 |
21 |
22 | # Include funbox.h
23 | C_INCLUDES += -I../../include
--------------------------------------------------------------------------------
/software/Saturn/fourier.h:
--------------------------------------------------------------------------------
1 | // fourier.h
2 | #ifndef FOURIER
3 |
4 | #include "wave.h"
5 |
6 | namespace soundmath
7 | {
8 | template class Fourier
9 | {
10 | public:
11 | void (*processor)(const T* in, T* out);
12 |
13 | // in, middle, out need to be arrays of size (N * laps * 2)
14 | Fourier(void (*processor)(const T*, T*), ShyFFT* fft, Wave* window, size_t laps, T* in, T* middle, T* out)
15 | : processor(processor), in(in), middle(middle), out(out), fft(fft), window(window), laps(laps), stride(N / laps)
16 | {
17 | writepoints = new int[laps * 2];
18 | readpoints = new int[laps * 2];
19 |
20 | memset(writepoints, 0, sizeof(int) * laps * 2);
21 | memset(readpoints, 0, sizeof(int) * laps * 2);
22 |
23 | for (int i = 0; i < 2 * (int)laps; i++) // initialize half of writepoints
24 | writepoints[i] = -i * (int)stride;
25 |
26 | reading = new bool[laps * 2];
27 | writing = new bool[laps * 2];
28 |
29 | memset(reading, false, sizeof(bool) * laps * 2);
30 | memset(writing, true, sizeof(bool) * laps * 2);
31 | }
32 |
33 | ~Fourier()
34 | {
35 | delete [] writepoints;
36 | delete [] readpoints;
37 | delete [] reading;
38 | delete [] writing;
39 | }
40 |
41 | // writes a single sample (with windowing) into the in array
42 | void write(T x)
43 | {
44 | for (size_t i = 0; i < laps * 2; i++)
45 | {
46 | if (writing[i])
47 | {
48 | if (writepoints[i] >= 0)
49 | {
50 | T amp = (*window)((T)writepoints[i] / N);
51 | in[writepoints[i] + N * i] = amp * x;
52 | }
53 | writepoints[i]++;
54 |
55 | if (writepoints[i] == N)
56 | {
57 | writing[i] = false;
58 | reading[i] = true;
59 | readpoints[i] = 0;
60 |
61 | forward(i); // FTs ith in to ith middle buffer
62 | process(i); // user-defined; ought to move info from ith middle to out buffer
63 | backward(i); // IFTs ith out to ith in buffer
64 |
65 | current = i;
66 | }
67 | }
68 | }
69 | }
70 |
71 | inline void forward(const size_t i)
72 | {
73 | fft->Direct((in + i * N), (middle + i * N)); // analysis
74 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
75 | }
76 |
77 | inline void backward(const size_t i)
78 | {
79 | fft->Inverse((out + i * N), (in + i * N)); // synthesis
80 | // arm_rfft_fast_f32(fft, out + i * N, in + i * N, 1);
81 | }
82 |
83 | // executes user-defined callback
84 | inline void process(const size_t i)
85 | {
86 | processor((middle + i * N), (out + i * N));
87 | }
88 |
89 | // read a single reconstructed sample
90 | T read()
91 | {
92 | T accum = 0;
93 |
94 | for (size_t i = 0; i < laps * 2; i++)
95 | {
96 | if (reading[i])
97 | {
98 | T amp = (*window)((T)readpoints[i] / N);
99 | accum += amp * in[readpoints[i] + N * i];
100 |
101 | readpoints[i]++;
102 |
103 | if (readpoints[i] == N)
104 | {
105 | writing[i] = true;
106 | reading[i] = false;
107 | writepoints[i] = 0;
108 | }
109 | }
110 | }
111 |
112 | accum /= N * laps / 2.0;
113 | return accum;
114 | }
115 |
116 |
117 |
118 | private:
119 | T *in, *middle, *out;
120 |
121 | public:
122 | ShyFFT* fft;
123 | Wave* window;
124 |
125 | size_t laps;
126 | size_t stride;
127 |
128 | int* writepoints;
129 | int* readpoints;
130 | bool* reading;
131 | bool* writing;
132 |
133 | int current = 0;
134 | };
135 |
136 |
137 | template class Analyzer
138 | {
139 | public:
140 | int (*processor)(const T* in);
141 |
142 | // in, middle, out need to be arrays of size (N * laps * 2)
143 | Analyzer(int (*processor)(const T*), ShyFFT* fft, size_t laps, T* in, T* middle)
144 | : processor(processor), in(in), middle(middle), fft(fft), laps(laps), stride(N / laps)
145 | {
146 | writepoints = new int[laps];
147 |
148 | memset(writepoints, 0, sizeof(int) * laps);
149 |
150 | for (int i = 0; i < (int)laps; i++) // initialize half of writepoints
151 | writepoints[i] = -i * (int)stride;
152 |
153 | writing = new bool[laps];
154 | memset(writing, true, sizeof(bool) * laps);
155 | }
156 |
157 | ~Analyzer()
158 | {
159 | delete [] writepoints;
160 | delete [] writing;
161 | }
162 |
163 | // writes a single sample (with windowing) into the in array
164 | void write(T x)
165 | {
166 | for (size_t i = 0; i < laps; i++)
167 | {
168 | if (writing[i])
169 | {
170 | if (writepoints[i] >= 0)
171 | {
172 | // T window = halfhann((T)writepoints[i] / N);
173 | T window = hann((T)writepoints[i] / N);
174 | in[writepoints[i] + N * i] = window * x;
175 | }
176 | writepoints[i]++;
177 |
178 | if (writepoints[i] == N)
179 | {
180 | writing[i] = false;
181 |
182 | forward(i); // FTs ith in to ith middle buffer
183 | process(i); // user-defined; ought to move info from ith middle to out buffer
184 | current = i;
185 |
186 | size_t next = (i + 1) % (laps);
187 | writing[next] = true;
188 | writepoints[next] = 0;
189 | }
190 | }
191 | }
192 | }
193 |
194 | inline void forward(const size_t i)
195 | {
196 | fft->Direct((in + i * N), (middle + i * N)); // analysis
197 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
198 | }
199 |
200 | // executes user-defined callback
201 | inline void process(const size_t i)
202 | {
203 | processor((middle + i * N));
204 | }
205 |
206 | private:
207 | T *in, *middle;
208 |
209 | public:
210 | ShyFFT* fft;
211 |
212 | size_t laps;
213 | size_t stride;
214 |
215 | int* writepoints;
216 | bool* writing;
217 |
218 | int current = 0;
219 | };
220 | }
221 |
222 | #define FOURIER
223 | #endif
--------------------------------------------------------------------------------
/software/Saturn/wave.h:
--------------------------------------------------------------------------------
1 | // wave.h // interpolated lookup table
2 | #ifndef WAVE
3 |
4 | #include
5 |
6 | namespace soundmath
7 | {
8 | const int TABSIZE = 2048;
9 |
10 | template class Wave
11 | {
12 | public:
13 | Wave() { }
14 | ~Wave() { }
15 |
16 | Wave(std::function shape, T left = 0, T right = 1, bool periodic = true)
17 | {
18 | this->shape = shape;
19 | this->left = left;
20 | this->right = right;
21 | this->periodic = periodic;
22 |
23 | for (int i = 0; i < TABSIZE; i++)
24 | {
25 | T phase = (T) i / TABSIZE;
26 | table[i] = shape((1 - phase) * left + phase * right);
27 | }
28 |
29 | this->endpoint = shape(right);
30 | }
31 |
32 | #ifdef FUNCTIONAL
33 | T lookup(T input)
34 | {
35 | return shape(input);
36 | }
37 | #else
38 | T lookup(T input)
39 | {
40 | T phase = (input - left) / (right - left);
41 |
42 | // get value at endpoint if input is out of bounds
43 | if (!periodic && (phase < 0 || phase >= 1))
44 | {
45 | if (phase < 0)
46 | return none(0);
47 | else
48 | return endpoint;
49 | }
50 | else
51 | {
52 | phase += 1;
53 | phase -= int(phase);
54 |
55 | int center = (int)(phase * TABSIZE) % TABSIZE;
56 | int after = (center + 1) % TABSIZE;
57 |
58 | T disp = (phase * TABSIZE - center);
59 | disp -= int(disp);
60 |
61 | return linear(center, after, disp);
62 | }
63 | }
64 | #endif
65 |
66 | T operator()(T phase)
67 | {
68 | return lookup(phase);
69 | }
70 |
71 | protected:
72 | T table[TABSIZE];
73 |
74 | private:
75 | T left; // input phases are interpreted as lying in [left, right)
76 | T right;
77 | bool periodic;
78 |
79 | T endpoint; // if (this->periodic == false), provides a value for (*this)(right)
80 |
81 | std::function shape;
82 |
83 | T none(int center)
84 | {
85 | return table[center];
86 | }
87 |
88 | T linear(int center, int after, T disp)
89 | {
90 | return table[center] * (1 - disp) + table[after] * disp;
91 | }
92 |
93 | };
94 | }
95 |
96 | #define WAVE
97 | #endif
--------------------------------------------------------------------------------
/software/Template/README.md:
--------------------------------------------------------------------------------
1 | # Pedal
2 |
3 | ## Controls
4 |
5 | | Control | Description | Comment |
6 | | --- | --- | --- |
7 | | Ctrl 1 | | |
8 | | Ctrl 2 | | |
9 | | Ctrl 3 | | |
10 | | Ctrl 4 | | |
11 | | Ctrl 5 | | |
12 | | Ctrl 6 | | |
13 | | 3-Way Switch 1 | | |
14 | | 3-Way Switch 2 | | |
15 | | 3-Way Switch 3 | | |
16 | | Dip Switch 1 | | |
17 | | Dip Switch 2 | | |
18 | | FS 1 | | |
19 | | FS 2 | | |
20 | | LED 1 | | |
21 | | LED 2 | | |
22 | | Audio In 1 | | |
23 | | Audio Out 1 | | |
24 |
25 |
26 | ## Build
27 |
--------------------------------------------------------------------------------
/software/Uranus/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = uranus
3 | CPP_STANDARD = -std=gnu++20
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # APP_TYPE = BOOT_SRAM
7 |
8 | # Compiler options
9 | #OPT = -O1
10 | OPT=-Ofast
11 |
12 |
13 | # Sources
14 | CPP_SOURCES = uranus.cpp granularplayermod.cpp operator.cpp
15 |
16 | # Library Locations
17 | LIBDAISY_DIR = ../../libDaisy
18 | DAISYSP_DIR = ../../DaisySP
19 |
20 | # Core location, and generic Makefile.
21 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
22 | include $(SYSTEM_FILES_DIR)/Makefile
23 |
24 |
25 | # Include funbox.h
26 | C_INCLUDES += -I../../infra/include
27 | C_INCLUDES += -I../../q/q_lib/include
28 | C_INCLUDES += -I../../include
--------------------------------------------------------------------------------
/software/Uranus/README.md:
--------------------------------------------------------------------------------
1 | # Uranus
2 |
3 | Uranus is a Granular delay and synth. It splits your guitar signal (or anything else) into
4 | small grains of audio that can be manipulated to create atmospheric soundscapes. It features a monophonic
5 | granular synth mode and a polyphonic FM synthesizer with controllable parameters over Midi.
6 |
7 | Uranus uses a modified version of the GranularPlayer class in DaisySP.
8 |
9 | ## Controls
10 |
11 | | Control | Description | Comment |
12 | | --- | --- | --- |
13 | | Ctrl 1 | Size | Grain size 1ms to 300ms |
14 | | Ctrl 2 | Mix (Alt Stereo Spread) | Dry/Wet Mix, or alternate mode Stereo spread of each individual grain |
15 | | Ctrl 3 | Pitch (Alt pitch LFO Depth) | Pitch (transposition) of the grains, -1 to +1 octave in semitones |
16 | | Ctrl 4 | Feedback | Feedback of the delayline |
17 | | Ctrl 5 | Width | The width of time that grains can be randomly sampled from (0 to 50ms). Turn down for more a concise sound, turn up to sample a wider range of the audio |
18 | | Ctrl 6 | Speed (Alt pitch LFO Rate) | Speed of grain playback -2x to +2x |
19 | | 3-Way Switch 1 | Grain Mode | left=Oct up mid=oct down right=oct up and oct down |
20 | | 3-Way Switch 2 | Grain Envelope | left= smooth cosine envelope for each grain mid= slow attack linear envelope right=fast attack linear envelope |
21 | | 3-Way Switch 3 | Synth Mode | left=none (only taking audio input) mid=granular synth mode (puts an ADSR envelope over the current granular effect, triggered by a midi keyboard and transposed from middle C) right=FM Synth (blocks audio in, use midi for polyphonic, 2 operator FM synthesizer) |
22 | | Dip Switch 1 | N/A | |
23 | | Dip Switch 2 | N/A | |
24 | | Dip Switch 3 | N/A | |
25 | | Dip Switch 4 | N/A | |
26 | | FS 1 | Bypass | Effect bypass or hold for Alternate mode |
27 | | FS 2 | Hold Sample | Holds the current delay buffer (latching), blocks overwriting |
28 | | LED 1 | Bypass/Alt Indicator | Dims LED while footswitch held in alt mode |
29 | | LED 2 | Hold Indicator | On when in Hold mode|
30 | | Audio In 1 | Mono In | Ignores Right channel input |
31 | | Audio Out 1 | Stereo | Stereo Out |
32 |
33 | ### Expression
34 | 1. Plug in passive expression pedal into the 1/8" jack on the top left side of pedal. (will need a 1/4" female to 1/8" male TRS adapter)
35 | 2. Hold both footswitches until they both light up (more than 0.5 seconds, but less than 2 seconds), you are now in Set Expression mode.
36 | 3. Move the expression pedal into the heel position (up) and move any number of knobs to where you want to heel limit to be (for example you could turn Volume down). The right LED should be brighter up to indicate the heel position is ready to set.*
37 | 3. Move the expression pedal into the toe position (down) and move any number of knobs to where you want to toe limit to be (for example you could turn Volume up). The Left LED should be brighter to indicate the toe position is ready to set.*
38 | 4. Hold both footswitches to exit Set Expression mode. This will activate expression for the moved knobs. The moved knobs will be inactive until Expression Mode is deactivated.
39 | 5. Repeat step 2 to reset Expression knobs.
40 | 6. Hold both footswitches for 2 seconds or more to clear any Expression action and give control back to the Funbox knobs.
41 |
42 | * Currently, the expression input requires the full range of the expression pedal, in order to detect Up/Down positions. You can sometimes trim the expression pedal to not use the full range, so adjust the trim as necessary.
43 | Also, some expression pedals have a "Standard" or "Alternate/Other" mode. Funbox should work on the "Standard" mode.
44 |
45 |
46 | ### MIDI Reference
47 |
48 | | Control | MIDI CC | Value |
49 | | --- | --- | --- |
50 | | Knob 1 | 14 | 0- 127 |
51 | | Knob 2 | 15 | 0- 127 |
52 | | Knob 3 | 16 | 0- 127 |
53 | | Knob 4 | 17 | 0- 127 |
54 | | Knob 5 | 18 | 0- 127 |
55 | | Knob 6 | 19 | 0- 127 |
56 |
57 |
58 | FM Synth Parameters over MIDI
59 |
60 | | Control | MIDI CC | Value |
61 | | --- | --- | --- |
62 | | Carrier Level (overall volume) | 20 | 0- 127 |
63 | | Carrier Ratio (0.5 to 16.5 in 0.5 increments) | 21 | 0- 127 |
64 | | Modulator Level | 22 | 0- 127 |
65 | | Modulator Ratio (0.5 to 16.5 in 0.5 increments) | 23 | 0- 127 |
66 | | Modulator Envelope Attack | 24 | 0- 127 |
67 | | Modulator Envelope Decay | 25 | 0- 127 |
68 | | Modulator Envelope Sustain| 26 | 0- 127 |
69 | | Modulator Envelope Release| 27 | 0- 127 |
70 | | Carrier Envelope Attack | 28 | 0- 127 |
71 | | Carrier Envelope Decay | 29 | 0- 127 |
72 | | Carrier Envelope Sustain | 30 | 0- 127 |
73 | | Carrier Envelope Release | 31 | 0- 127 |
74 |
75 |
76 | Granular Synth Parameters over MIDI (uses the same MIDI CC as FM Carrier Envelope, based on Synth Mode Toggle)
77 |
78 | | Control | MIDI CC | Value |
79 | | --- | --- | --- |
80 | | Envelope Attack | 28 | 0- 127 |
81 | | Envelope Decay | 29 | 0- 127 |
82 | | Envelope Sustain | 30 | 0- 127 |
83 | | Envelope Release | 31 | 0- 127 |
84 |
85 | ## Build
86 |
87 | Uranus runs in Flash memory on the Daisy Seed.
88 |
89 |
--------------------------------------------------------------------------------
/software/Uranus/operator.cpp:
--------------------------------------------------------------------------------
1 | #include "operator.h"
2 |
3 | using namespace daisysp;
4 |
5 |
6 |
7 | void Operator::Init(float samplerate, bool isCarrier)
8 | {
9 | //init oscillators
10 | osc_.Init(samplerate);
11 |
12 | lfreq_ = freq_ = 440.f;
13 | lratio_ = ratio_ = 2.f;
14 | SetFrequency(lfreq_);
15 | SetRatio(lratio_);
16 |
17 | llevel_ = level_ = 1.0;
18 | osc_.SetAmp(llevel_);
19 |
20 | osc_.SetWaveform(Oscillator::WAVE_SIN);
21 |
22 | iscarrier_ = isCarrier;
23 |
24 | modval_ = 0.0;
25 |
26 | }
27 |
28 | float Operator::Process()
29 | {
30 | if(lratio_ != ratio_ || lfreq_ != freq_)
31 | {
32 | lratio_ = ratio_;
33 | lfreq_ = freq_;
34 | osc_.SetFreq(lfreq_ * lratio_);
35 | }
36 |
37 | if (llevel_ != level_) {
38 | llevel_ = level_;
39 | osc_.SetAmp(llevel_);
40 | }
41 |
42 | if (iscarrier_)
43 | osc_.PhaseAdd(modval_);
44 |
45 | // Return the processed oscillator, scaled by the velocity of the keystroke
46 | return osc_.Process() * velocity_amp_;
47 | }
48 |
49 | void Operator::SetFrequency(float freq) ///Currently unused
50 | {
51 | freq_ = fabsf(freq);
52 | }
53 |
54 | void Operator::SetRatio(float ratio)
55 | {
56 | ratio_ = fabsf(ratio);
57 | }
58 |
59 | void Operator::SetLevel(float level)
60 | {
61 | level_ = fabsf(level);
62 | }
63 |
64 | void Operator::setPhaseInput(float modval)
65 | {
66 | modval_ = modval;
67 | }
68 |
69 |
70 | void Operator::Reset()
71 | {
72 | osc_.Reset();
73 | }
74 |
75 | void Operator::OnNoteOn(float note, float velocity)
76 | {
77 | velocity_ = velocity;
78 | velocity_amp_ = velocity_ / 127.f;
79 | freq_ = mtof(note); /// The base frequency of the note is set here, modified by the ratio in the Process function
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/software/Uranus/operator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef OPERATOR_H
3 | #define OPERATOR_H
4 |
5 | #include
6 | #include "daisysp.h"
7 | #ifdef __cplusplus
8 |
9 | using namespace daisysp;
10 |
11 |
12 | /**
13 | Single FM Operator that can be either a modulator or a carrier
14 | */
15 |
16 | class Operator
17 | {
18 | public:
19 | Operator() {}
20 | ~Operator() {}
21 |
22 | /** Initializes the Operator module.
23 | \param samplerate - The sample rate of the audio engine being run.
24 | */
25 | void Init(float samplerate, bool isCarrier);
26 |
27 |
28 | /** Returns the next sample
29 | */
30 | float Process();
31 |
32 | /** Carrier freq. setter
33 | \param freq Carrier frequency in Hz
34 | */
35 | void SetFrequency(float freq);
36 |
37 | /** Set modulator freq. relative to carrier
38 | \param ratio New modulator freq = carrier freq. * ratio
39 | */
40 | void SetRatio(float ratio);
41 |
42 | /** Sets the amplitude of the oscillator
43 | */
44 | void SetLevel(float level);
45 |
46 | /** Sets the phase input if this is a carrier driven by a modulator
47 | Intended to be called by an outside function at samplerate
48 | */
49 | void setPhaseInput(float modval);
50 |
51 | /** Resets oscillators */
52 | void Reset();
53 |
54 | ///////////////////////////// NEW STUFF
55 |
56 | /** Starts note */
57 | void OnNoteOn(float note, float velocity);
58 |
59 |
60 |
61 | private:
62 |
63 | Oscillator osc_;
64 | float level_, llevel_;
65 | float freq_, lfreq_, ratio_, lratio_;
66 | bool iscarrier_;
67 | float modval_;
68 |
69 | // Notes
70 | float velocity_;
71 | float velocity_amp_;
72 |
73 | };
74 | #endif
75 | #endif
76 |
--------------------------------------------------------------------------------
/software/Venus/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = venus
3 |
4 | USE_DAISYSP_LGPL = 1
5 |
6 | # Sources
7 | CPP_SOURCES = venus.cpp
8 |
9 | OPT = -O1
10 | #OPT ?= -O3
11 |
12 | # Library Locations
13 | LIBDAISY_DIR = ../../libDaisy
14 | DAISYSP_DIR = ../../DaisySP
15 |
16 |
17 | # Core location, and generic Makefile.
18 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
19 | include $(SYSTEM_FILES_DIR)/Makefile
20 |
21 |
22 | # Include funbox.h
23 | C_INCLUDES += -I../../include
--------------------------------------------------------------------------------
/software/Venus/README.md:
--------------------------------------------------------------------------------
1 | # Venus
2 |
3 | Venus is a Spectral Reverb that uses a STFT (Short time Fourier Transform) to operate on your signal in the frequency
4 | domain. It can create lush soundscapes with string-like overtones, detuning, and spectral freeze. It features
5 | two LoFi modes that reduce the samplerate and two "drift" modes that modulate knob values slowly over time.
6 |
7 | Notes: The Venus pedal runs at 32kHz samplerate and buffersize of 256 in order to run smoothly with the current STFT implementation.
8 | Improving the efficiency of the STFT to run at higher samplerates and lower buffersize is of interest.
9 |
10 | 
11 |
12 | ## Controls
13 |
14 | | Control | Description | Comment |
15 | | --- | --- | --- |
16 | | Ctrl 1 | Decay | Decay time of reverb |
17 | | Ctrl 2 | Mix | Dry/Wet mix |
18 | | Ctrl 3 | Damp | Reverb dampening |
19 | | Ctrl 4 | Shimmer Amount | Adds octave shimmer |
20 | | Ctrl 5 | Shimmer Tone | Adds in octave + 5ths to shimmer |
21 | | Ctrl 6 | Detune | Left of noon detunes down, right of noon detunes up |
22 | | 3-Way Switch 1 | Shimmer Mode | left=octave down, center= octave up, right=octave up and octave down |
23 | | 3-Way Switch 2 | LoFi Mode (lofi applied to wet mix only, not dry mix) | left= samplerate of 9600 with lowpass filter, center=None, right= samplerate of 6400, no lowpass filter |
24 | | 3-Way Switch 3 | Drift Mode | left=same as right except at a rate of ~50 seconds, center=none, right=more, oscillates the Damp, Shimmer, ShimmerTone, and Detune controls from the current setting to 0 at a rate of 1 cycle per ~25 seconds |
25 | | Dip Switch 1 | N/A | |
26 | | Dip Switch 2 | N/A | |
27 | | Dip Switch 3 | N/A | |
28 | | Dip Switch 4 | N/A | |
29 | | FS 1 | Bypass/Engage | |
30 | | FS 2 | Freeze | |
31 | | LED 1 | Bypass indicator | |
32 | | LED 2 | Freeze indicator | |
33 | | Audio In 1 | Mono in | |
34 | | Audio Out 1 | Mono out (left copied to right) | |
35 |
36 | ### Expression
37 | 1. Plug in passive expression pedal into the 1/8" jack on the top left side of pedal. (will need a 1/4" female to 1/8" male TRS adapter)
38 | 2. Hold left footswitche until they both LEDS blink (more than 0.6 seconds, but less than 2 seconds), you are now in Set Expression mode.
39 | 3. Move the expression pedal into the heel position (up) and move any number of knobs to where you want to heel limit to be (for example you could turn Volume down). The right LED should be brighter up to indicate the heel position is ready to set.*
40 | 3. Move the expression pedal into the toe position (down) and move any number of knobs to where you want to toe limit to be (for example you could turn Volume up). The Left LED should be brighter to indicate the toe position is ready to set.*
41 | 4. Hold left footswitch to exit Set Expression mode. This will activate expression for the moved knobs. The moved knobs will be inactive until Expression Mode is deactivated.
42 | 5. Repeat step 2 to reset Expression knobs.
43 | 6. Hold left footswitch for 2 seconds or more to clear any Expression action and give control back to the Funbox knobs.
44 |
45 | * Currently, the expression input requires the full range of the expression pedal, in order to detect Up/Down positions. You can sometimes trim the expression pedal to not use the full range, so adjust the trim as necessary.
46 | Also, some expression pedals have a "Standard" or "Alternate/Other" mode. Funbox should work on the "Standard" mode.
47 |
48 |
49 | ### MIDI Reference
50 |
51 | | Control | MIDI CC | Value |
52 | | --- | --- | --- |
53 | | Knob 1 | 14 | 0- 127 |
54 | | Knob 2 | 15 | 0- 127 |
55 | | Knob 3 | 16 | 0- 127 |
56 | | Knob 4 | 17 | 0- 127 |
57 | | Knob 5 | 18 | 0- 127 |
58 | | Knob 6 | 19 | 0- 127 |
59 |
60 | ## Build
61 |
62 | Venus runs in Flash memory on the Daisy Seed.
63 |
64 | ## Acknowledgements
65 |
66 | This code adapts the code found here to run a STFT on the Daisy Seed:
67 | https://github.com/amcerbu/DaisySTFT
68 |
69 | Which uses the "shyfft" authored by Émilie Gillet of Mutable Instruments:
70 | https://github.com/pichenettes/eurorack
71 |
72 | The math used in this reverb is heavily inspired by the Atlantis Reverb by Geraint Luff:
73 | https://geraintluff.github.io/jsfx/#Atlantis%20Reverb
74 |
75 | And directly from the examples in this forum post by Geraint Luff:
76 | https://forum.cockos.com/showthread.php?t=225955
77 |
78 | The Venus pedal would not be possible without the generosity of smart people sharing their work in the open source community. Thank you!
79 |
80 |
--------------------------------------------------------------------------------
/software/Venus/fourier.h:
--------------------------------------------------------------------------------
1 | // fourier.h
2 | #ifndef FOURIER
3 |
4 | #include "wave.h"
5 |
6 | namespace soundmath
7 | {
8 | template class Fourier
9 | {
10 | public:
11 | void (*processor)(const T* in, T* out);
12 |
13 | // in, middle, out need to be arrays of size (N * laps * 2)
14 | Fourier(void (*processor)(const T*, T*), ShyFFT* fft, Wave* window, size_t laps, T* in, T* middle, T* out)
15 | : processor(processor), in(in), middle(middle), out(out), fft(fft), window(window), laps(laps), stride(N / laps)
16 | {
17 | writepoints = new int[laps * 2];
18 | readpoints = new int[laps * 2];
19 |
20 | memset(writepoints, 0, sizeof(int) * laps * 2);
21 | memset(readpoints, 0, sizeof(int) * laps * 2);
22 |
23 | for (int i = 0; i < 2 * (int)laps; i++) // initialize half of writepoints
24 | writepoints[i] = -i * (int)stride;
25 |
26 | reading = new bool[laps * 2];
27 | writing = new bool[laps * 2];
28 |
29 | memset(reading, false, sizeof(bool) * laps * 2);
30 | memset(writing, true, sizeof(bool) * laps * 2);
31 | }
32 |
33 | ~Fourier()
34 | {
35 | delete [] writepoints;
36 | delete [] readpoints;
37 | delete [] reading;
38 | delete [] writing;
39 | }
40 |
41 | // writes a single sample (with windowing) into the in array
42 | void write(T x)
43 | {
44 | for (size_t i = 0; i < laps * 2; i++)
45 | {
46 | if (writing[i])
47 | {
48 | if (writepoints[i] >= 0)
49 | {
50 | T amp = (*window)((T)writepoints[i] / N);
51 | in[writepoints[i] + N * i] = amp * x;
52 | }
53 | writepoints[i]++;
54 |
55 | if (writepoints[i] == N)
56 | {
57 | writing[i] = false;
58 | reading[i] = true;
59 | readpoints[i] = 0;
60 |
61 | forward(i); // FTs ith in to ith middle buffer
62 | process(i); // user-defined; ought to move info from ith middle to out buffer
63 | backward(i); // IFTs ith out to ith in buffer
64 |
65 | current = i;
66 | }
67 | }
68 | }
69 | }
70 |
71 | inline void forward(const size_t i)
72 | {
73 | fft->Direct((in + i * N), (middle + i * N)); // analysis
74 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
75 | }
76 |
77 | inline void backward(const size_t i)
78 | {
79 | fft->Inverse((out + i * N), (in + i * N)); // synthesis
80 | // arm_rfft_fast_f32(fft, out + i * N, in + i * N, 1);
81 | }
82 |
83 | // executes user-defined callback
84 | inline void process(const size_t i)
85 | {
86 | processor((middle + i * N), (out + i * N));
87 | }
88 |
89 | // read a single reconstructed sample
90 | T read()
91 | {
92 | T accum = 0;
93 |
94 | for (size_t i = 0; i < laps * 2; i++)
95 | {
96 | if (reading[i])
97 | {
98 | T amp = (*window)((T)readpoints[i] / N);
99 | accum += amp * in[readpoints[i] + N * i];
100 |
101 | readpoints[i]++;
102 |
103 | if (readpoints[i] == N)
104 | {
105 | writing[i] = true;
106 | reading[i] = false;
107 | writepoints[i] = 0;
108 | }
109 | }
110 | }
111 |
112 | accum /= N * laps / 2.0;
113 | return accum;
114 | }
115 |
116 |
117 |
118 | private:
119 | T *in, *middle, *out;
120 |
121 | public:
122 | ShyFFT* fft;
123 | Wave* window;
124 |
125 | size_t laps;
126 | size_t stride;
127 |
128 | int* writepoints;
129 | int* readpoints;
130 | bool* reading;
131 | bool* writing;
132 |
133 | int current = 0;
134 | };
135 |
136 |
137 | template class Analyzer
138 | {
139 | public:
140 | int (*processor)(const T* in);
141 |
142 | // in, middle, out need to be arrays of size (N * laps * 2)
143 | Analyzer(int (*processor)(const T*), ShyFFT* fft, size_t laps, T* in, T* middle)
144 | : processor(processor), in(in), middle(middle), fft(fft), laps(laps), stride(N / laps)
145 | {
146 | writepoints = new int[laps];
147 |
148 | memset(writepoints, 0, sizeof(int) * laps);
149 |
150 | for (int i = 0; i < (int)laps; i++) // initialize half of writepoints
151 | writepoints[i] = -i * (int)stride;
152 |
153 | writing = new bool[laps];
154 | memset(writing, true, sizeof(bool) * laps);
155 | }
156 |
157 | ~Analyzer()
158 | {
159 | delete [] writepoints;
160 | delete [] writing;
161 | }
162 |
163 | // writes a single sample (with windowing) into the in array
164 | void write(T x)
165 | {
166 | for (size_t i = 0; i < laps; i++)
167 | {
168 | if (writing[i])
169 | {
170 | if (writepoints[i] >= 0)
171 | {
172 | // T window = halfhann((T)writepoints[i] / N);
173 | T window = hann((T)writepoints[i] / N);
174 | in[writepoints[i] + N * i] = window * x;
175 | }
176 | writepoints[i]++;
177 |
178 | if (writepoints[i] == N)
179 | {
180 | writing[i] = false;
181 |
182 | forward(i); // FTs ith in to ith middle buffer
183 | process(i); // user-defined; ought to move info from ith middle to out buffer
184 | current = i;
185 |
186 | size_t next = (i + 1) % (laps);
187 | writing[next] = true;
188 | writepoints[next] = 0;
189 | }
190 | }
191 | }
192 | }
193 |
194 | inline void forward(const size_t i)
195 | {
196 | fft->Direct((in + i * N), (middle + i * N)); // analysis
197 | // arm_rfft_fast_f32(fft, in + i * N, middle + i * N, 0);
198 | }
199 |
200 | // executes user-defined callback
201 | inline void process(const size_t i)
202 | {
203 | processor((middle + i * N));
204 | }
205 |
206 | private:
207 | T *in, *middle;
208 |
209 | public:
210 | ShyFFT* fft;
211 |
212 | size_t laps;
213 | size_t stride;
214 |
215 | int* writepoints;
216 | bool* writing;
217 |
218 | int current = 0;
219 | };
220 | }
221 |
222 | #define FOURIER
223 | #endif
--------------------------------------------------------------------------------
/software/Venus/wave.h:
--------------------------------------------------------------------------------
1 | // wave.h // interpolated lookup table
2 | #ifndef WAVE
3 |
4 | #include
5 |
6 | namespace soundmath
7 | {
8 | const int TABSIZE = 2048;
9 |
10 | template class Wave
11 | {
12 | public:
13 | Wave() { }
14 | ~Wave() { }
15 |
16 | Wave(std::function shape, T left = 0, T right = 1, bool periodic = true)
17 | {
18 | this->shape = shape;
19 | this->left = left;
20 | this->right = right;
21 | this->periodic = periodic;
22 |
23 | for (int i = 0; i < TABSIZE; i++)
24 | {
25 | T phase = (T) i / TABSIZE;
26 | table[i] = shape((1 - phase) * left + phase * right);
27 | }
28 |
29 | this->endpoint = shape(right);
30 | }
31 |
32 | #ifdef FUNCTIONAL
33 | T lookup(T input)
34 | {
35 | return shape(input);
36 | }
37 | #else
38 | T lookup(T input)
39 | {
40 | T phase = (input - left) / (right - left);
41 |
42 | // get value at endpoint if input is out of bounds
43 | if (!periodic && (phase < 0 || phase >= 1))
44 | {
45 | if (phase < 0)
46 | return none(0);
47 | else
48 | return endpoint;
49 | }
50 | else
51 | {
52 | phase += 1;
53 | phase -= int(phase);
54 |
55 | int center = (int)(phase * TABSIZE) % TABSIZE;
56 | int after = (center + 1) % TABSIZE;
57 |
58 | T disp = (phase * TABSIZE - center);
59 | disp -= int(disp);
60 |
61 | return linear(center, after, disp);
62 | }
63 | }
64 | #endif
65 |
66 | T operator()(T phase)
67 | {
68 | return lookup(phase);
69 | }
70 |
71 | protected:
72 | T table[TABSIZE];
73 |
74 | private:
75 | T left; // input phases are interpreted as lying in [left, right)
76 | T right;
77 | bool periodic;
78 |
79 | T endpoint; // if (this->periodic == false), provides a value for (*this)(right)
80 |
81 | std::function shape;
82 |
83 | T none(int center)
84 | {
85 | return table[center];
86 | }
87 |
88 | T linear(int center, int after, T disp)
89 | {
90 | return table[center] * (1 - disp) + table[after] * disp;
91 | }
92 |
93 | };
94 | }
95 |
96 | #define WAVE
97 | #endif
--------------------------------------------------------------------------------
/software/images/Infographics.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/Infographics.pptx
--------------------------------------------------------------------------------
/software/images/earth_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/earth_infographic.jpg
--------------------------------------------------------------------------------
/software/images/funbox_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/funbox_infographic.jpg
--------------------------------------------------------------------------------
/software/images/jupiter_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/jupiter_infographic.jpg
--------------------------------------------------------------------------------
/software/images/mars_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/mars_infographic.jpg
--------------------------------------------------------------------------------
/software/images/mercury_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/mercury_infographic.jpg
--------------------------------------------------------------------------------
/software/images/neptune_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/neptune_infographic.jpg
--------------------------------------------------------------------------------
/software/images/pluto_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/pluto_infographic.jpg
--------------------------------------------------------------------------------
/software/images/saturn_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/saturn_infographic.jpg
--------------------------------------------------------------------------------
/software/images/uranus_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/uranus_infographic.jpg
--------------------------------------------------------------------------------
/software/images/venus_infographic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuitarML/FunBox/194d7052cfb1bf9fbb21a7cfa7d0bd383156b151/software/images/venus_infographic.jpg
--------------------------------------------------------------------------------