[{"element_type":"alert","content":"Now including ADSR envelope widgets!","metadata":{"class":"element row-fluid alert-element build-alert alert-primary","markdown":"","alert_type":"primary"}},{"element_type":"text","content":"\n        \u003cp\u003e\u003cspan\u003e\u003cstrong\u003e\u003cem\u003eWaveViz\u003c/em\u003e\u003c/strong\u003e is a \u003cem\u003e\u003cstrong\u003eCircuitPython\u003c/strong\u003e\u003c/em\u003e class to create a positionable \u003c/span\u003e\u003ccode\u003edisplayio.TileGrid\u003c/code\u003e\u003cspan\u003e\u0026nbsp;graphics widget from a \u003c/span\u003e\u003ccode\u003esynthio.waveform\u003c/code\u003e\u003cspan\u003ewave table or \u003ccode\u003esynthio.Envelope \u003c/code\u003eobject (or any one-dimensional list for that matter). The class also makes the underlying bitmap and palette objects available for other uses such as saving the widget to an image file.\u003c/span\u003e\u003c/p\u003e\n      ","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eThe \u003cem\u003eWaveViz\u003c/em\u003e class currently resides in its \u003ca href=\"https://github.com/CedarGroveStudios/CircuitPython_WaveViz\" target=\"_blank\"\u003eGitHub repository\u003c/a\u003e\u0026nbsp; and is included in the \u003ca href=\"https://circuitpython.org/libraries\" target=\"_blank\"\u003eCircuitPython Community Bundle\u003c/a\u003e. The update utility \u003cem\u003ecircup\u003c/em\u003e can be used to install \u003cem\u003ecedargrove_waveviz\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/CedarGroveStudios/CircuitPython_WaveViz/blob/main/media/pseudo_rtd_cedargrove_waveviz.pdf\" target=\"_blank\"\u003eWaveViz API\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/603/original/IMG_1762.jpeg?1704837466","metadata":{"caption":"Multiple Synthetic Harmonica Waveform Images of Various Sizes Created by WaveViz"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eThe long-term objective is to be able to save and import sounds and ADSR envelopes from a library of \u003cem\u003esynthio\u003c/em\u003e wave table files and envelope objects. The first step in the process is to create a visualizer to help characterize the sounds graphically. We'll worry about saving and retrieving waveform and envelope objects sometime in the future (watch for a new class, WaveStore to appear soon). For now, let's work on getting images of wave tables and envelopes.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"alert","content":"Todbot investigated and deployed wave table file retrieval in a couple of projects and covers it nicely on his hints page: https://github.com/todbot/circuitpython-synthio-tricks","metadata":{"class":"element row-fluid alert-element build-alert alert-info","markdown":"","alert_type":"info"}},{"element_type":"alert","content":"The WaveStore class (in development) will create and manage a file-based collection of synthio object assets and graphic widgets. The goal is to create a managed library of synthio sounds and voices that can be included in CircuitPython code with simple import statements.","metadata":{"class":"element row-fluid alert-element build-alert alert-primary","markdown":"","alert_type":"primary"}},{"element_type":"text","content":"\n  \n  \n  \n        \u003ch3\u003eI See What You Did There\u003c/h3\u003e\n\u003cp\u003eWhen instantiated, \u003cem\u003eWaveViz\u003c/em\u003e is given a waveform or envelope object, the screen origin pixel coordinates (x, y), an image size (width, height) in pixels, as well as RGB 24-bit colors for the waveform, border, and background. Internally, the class creates a bitmap image where:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ea waveform wave table fills the image with positive and negative sample values above and below a baseline, or\u003c/li\u003e\n\u003cli\u003ean envelope object representing the four phases of attack, decay, sustain, and release with 0.0 to 1.0 amplitude values on the y-axis and relative phase timing on the x-axis.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAfter the image is created, the class instance becomes a \u003ccode\u003edisplayio.TileGrid\u003c/code\u003e object. The image is also available as a bitmap (\u003ccode\u003eWaveViz.bitmap\u003c/code\u003e, \u003ccode\u003eWaveViz.pixel_shader\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003eThe resultant image can be plotted anywhere on the display in any aspect ratio. If nested layering is required, the background color can also be specified as transparent (\u003ccode\u003eback_color=None\u003c/code\u003e).\u003c/p\u003e\n      \n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eSimple Test Example Code\u003c/h3\u003e\n\u003cp\u003eThe following is a simple test that used a FeatherS2 attached to a 2.4-inch TFT FeatherWing display. The code imports WaveBuilder to construct a synthetic harmonica wave table from five oscillators.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"# SPDX-FileCopyrightText: Copyright (c) 2024 JG for Cedar Grove Maker Studios\n# SPDX-License-Identifier: MIT\n\nimport board\nimport displayio\nimport synthio\nimport adafruit_ili9341\nfrom cedargrove_wavebuilder import WaveBuilder, WaveShape\nfrom cedargrove_waveviz import WaveViz\n\n# Define wave table parameters\nWAVE_TABLE_LENGTH = 512  # The wave table length in samples\nSAMPLE_MAXIMUM = 32700  # The maximum value of a sample\n\n# Instantiate a built-in display\n# display = board.DISPLAY\n\n# Instantiate the FeatherS2 with 2.4-inch TFT FeatherWing display\ndisplayio.release_displays()  # Release display resources\ndisplay_bus = displayio.FourWire(\n    board.SPI(), command=board.D6, chip_select=board.D5, reset=None\n)\ndisplay = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)\ndisplay.rotation = 0\n\nsplash = displayio.Group()\ndisplay.root_group = splash\n\n# Define the Harmonica wave shape, overtone ratio, and amplitude\ntone = [\n    (WaveShape.Sine, 1.00, 0.10),\n    (WaveShape.Sine, 2.00, 0.48),\n    (WaveShape.Sine, 3.00, 0.28),\n    (WaveShape.Sine, 4.00, 0.02),\n    (WaveShape.Sine, 5.00, 0.12),\n]\n\n# Create the wave table (wave.wave_table)\nwave = WaveBuilder(\n    oscillators=tone,\n    table_length=WAVE_TABLE_LENGTH,\n    sample_max=SAMPLE_MAXIMUM,\n    lambda_factor=1.0,\n    loop_smoothing=True,\n    debug=False,\n)\n\n# Create a synthio.Envelope object\nenv = synthio.Envelope(\n    attack_time=0.05,\n    attack_level=1.0,\n    decay_time=0.1,\n    release_time=0.1,\n    sustain_level=0.5,\n)\n\n# Display a small version on the bottom layer\nsplash.append(\n    WaveViz(wave.wave_table, x=20, y=80, width=25, height=25, back_color=0x0000A0)\n)\n\n# Display a full-sized version on the middle layer\nsplash.append(\n    WaveViz(wave.wave_table, x=0, y=0, width=300, height=240, back_color=None)\n)\n\n# Display the envelope object on the top layer\nsplash.append(\n    WaveViz(\n        env,\n        x=150,\n        y=170,\n        width=80,\n        height=40,\n        plot_color=0xFFFFFF,\n        back_color=0x800080,\n    )\n)\n\nwhile True:\n    pass","metadata":{"language":"python","linenums":false}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/712/original/waveviz_simpletest.jpeg?1708119976","metadata":{"caption":"WaveViz simpletest display showing two waveforms and one envelope widget"}}]