{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ccc61334-38ac-4c86-a86a-bd2975d5a60d",
   "metadata": {},
   "source": [
    "# lib_audio_dsp pipeline designer\n",
    "\n",
    "In this file you can generate the DSP pipeline of your choice.\n",
    "\n",
    "Below you will find 3 cells which can be modified and executed to configure, tune and run the desired pipeline.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0acbc09d",
   "metadata": {},
   "source": [
    "1. This is the pipeline design cell. Here you must break the DSP pipeline down into threads and use the provided DSP stages to create a pipeline. Running this cell will produce a diagram showing your pipeline. Make sure to capture each stage in your pipeline as a variable, as it will be needed in the next step.\n",
    "Note that every time the pipeline cell is changed, the app must be regenerated before the tuning stage can work correctly as the stage indices used for communication may have changed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3806bd0-99e0-42b6-a084-e9a2f17ba7dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Pipeline design stage\n",
    "\n",
    "from audio_dsp.design.pipeline import Pipeline\n",
    "from audio_dsp.stages import *\n",
    "\n",
    "p, inputs = Pipeline.begin(2, fs=48000)\n",
    "\n",
    "# inputs is a list of pipeline inputs. \"input gain\" is a label for this instance of VolumeControl.\n",
    "# The new variable x is the output of the input gain VolumeContro and has two elements.\n",
    "x = p.stage(VolumeControl, inputs, \"input_gain\")\n",
    "\n",
    "# Pass the output of the input gain stage to a low-pass filter.\n",
    "# The variable x is reassigned as the outputs of this filter.\n",
    "x = p.stage(Biquad, x, \"low_pass\")\n",
    "\n",
    "# Pass the output of the low-pass filter to a high pass filter.\n",
    "# The variable x is reassigned as the outputs of this filter.\n",
    "x = p.stage(Biquad, x, \"high_pass\")\n",
    "\n",
    "# Pass the output of the high-pass filter to a notch filter.\n",
    "# The variable x is reassigned as the outputs of this filter.\n",
    "x = p.stage(Biquad, x, \"notch\")\n",
    "\n",
    "# Pass the output of the notch filter to a low-shelf filter.\n",
    "# The variable x is reassigned as the outputs of this filter.\n",
    "x = p.stage(Biquad, x, \"low_shelf\")\n",
    "\n",
    "# Fork the output of the low-shelf filter.\n",
    "# The variable x, which now contains four elements, is reassigned as the outputs of the fork stage.\n",
    "x = p.stage(Fork, x, \"fork\")\n",
    "\n",
    "# Pass one pair of the outputs from the fork to a mixer.\n",
    "# The new variable y holds the outputs from the new mixer.\n",
    "y = p.stage(Mixer, x[0,2], \"mixer_1\")\n",
    "\n",
    "# Pass the other pair of the outputs from the fork to another mixer.\n",
    "# The new variable z holds the outputs from the new mixer.\n",
    "z = p.stage(Mixer, x[1,3], \"mixer_2\")\n",
    "\n",
    "# Pass the output of mixer 1 and mixer 2 to an output gain stage.\n",
    "# The variable y is reassigned to the output of this gain stage.\n",
    "y = p.stage(VolumeControl, y+z, \"output_gain\")\n",
    "\n",
    "# Connect output gain to the clipper.\n",
    "y = p.stage(Clipper, y)\n",
    "\n",
    "# Finally connect to the output of the pipeline.\n",
    "p.set_outputs(y)\n",
    "\n",
    "p.draw()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27e9d385",
   "metadata": {},
   "source": [
    "2. This is the tuning cell. First time through this can be ignored, but once your pipeline is running on a connected device, this cell can be updated and executed to update each pipeline stage live."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89d245d6-b908-4815-ae22-fa10e40d65dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "from audio_dsp.tuning import send_config_to_device, profile_pipeline\n",
    "from audio_dsp.tuning.transport import XScopeTransport\n",
    "from time import sleep\n",
    "\n",
    "# Make a low pass filter with a cut-off frequency of 20000 Hz and q of 0.707\n",
    "p[\"low_pass\"].make_lowpass(20000, 0.707)\n",
    "p[\"low_pass\"].plot_frequency_response(16000)\n",
    "\n",
    "# Make a high pass filter with a cut-off frequency of 20 Hz and q of 0.177\n",
    "p[\"high_pass\"].make_highpass(20, 0.707)\n",
    "p[\"high_pass\"].plot_frequency_response(16000)\n",
    "\n",
    "# Make a notch filter with a center frequency of 50 Hz and q of 0.707\n",
    "p[\"notch\"].make_notch(50, 0.707)\n",
    "p[\"notch\"].plot_frequency_response(16000)\n",
    "\n",
    "# Make a low-shelf filter with a center frequency of 130 Hz, a q of 0.707, and a boost of 6 dB\n",
    "p[\"low_shelf\"].make_lowshelf(130, 0.707, 6.0)\n",
    "p[\"low_shelf\"].plot_frequency_response(16000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2113ddc3",
   "metadata": {},
   "source": [
    "3. This is the build and run cell. This stage generates an application which uses your pipeline. The tuning parameters set in the previous cell are baked in the application."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "32492495-d82a-45ba-87e3-80b01de38981",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Build and run\n",
    "from audio_dsp.design.pipeline import generate_dsp_main\n",
    "from audio_dsp.design.build_utils import XCommonCMakeHelper\n",
    "\n",
    "b = XCommonCMakeHelper()\n",
    "generate_dsp_main(p)\n",
    "\n",
    "b.configure_build_run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a31cc9af-d81d-4862-bcc0-5f692ae38c44",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
