<phyphox version="1.7" locale="en">
  <title>Spectral Amplitude</title>
  <category>Acoustics</category>
  <description>Plots the amplitude auf sine waves against their frequencies.</description>
  <data-containers>
    <container size="32768">recording</container>
    <container>rate</container>
    <container>rate/2</container>
    <container size="32768">recording_subrange</container>
    <container>recording_length</container>
    <container init="2048">samples</container>
    <container>actual_samples/2</container>
    <container>actual_samples/2+1</container>
    <container>actual_samples+1</container>
    <container>actual_samples</container>
    <container>subrange_start</container>
    <container>period</container>
    <container size="32768">time</container>
    <container size="32769">frequency</container>
    <container size="32768">fftX</container>
    <container size="32768">fftY</container>
    <container size="16384">halfFrequency</container>
    <container size="16384">halfFFTtempX</container>
    <container size="16384">halfFFTtempY</container>
    <container size="16384">fft</container>
    <container size="1">f0</container>
    <container size="1">t</container>


    <container size="32768">recordingSquared</container>
    <container>sum</container>
    <container>mean</container>
    <container>dbUncal</container>
    <container>lnMean</container>
    <container>userCalibration</container>
    <container static="true">ln10</container>
    <container size="1">dB</container>
    <container init="0">calibration</container>
    <container init="60">target dB</container>
    <container>newCal</container>

    <container size="0">tout</container>
    <container size="0">fout</container>
    <container size="0">dBout</container>
  </data-containers>
  <input>
    <audio>
      <output>recording</output>
      <output component="rate">rate</output>
    </audio>
  </input>
  <views>
    <view label="Results">
      <graph label="Result" labelX="Frequency" unitX="Hz" labelY="Amplitude" unitY="dB" style="dots">
        <input axis="x">fout</input>
        <input axis="y">dBout</input>
      </graph>
      <graph label="Amplitude" labelX="Time" unitX="s" labelY="Amplitude" unitY="dB">
        <input axis="x">tout</input>
        <input axis="y">dBout</input>
      </graph>
      <graph label="Frequency" labelX="Time" unitX="s" labelY="Frequency" unitY="Hz">
        <input axis="x">tout</input>
        <input axis="y">fout</input>
      </graph>
    </view>
    <view label="Spectrum">
      <value label="Peak-Frequency" unit="Hz">
        <input>f0</input>
      </value>
      <separator height="1"/>
      <graph label="Fourier Transform" logX="true" logY="true" labelX="Frequency" unitX="Hz" labelY="FFT Mag" unitY="a.u.">
        <input axis="x">halfFrequency</input>
        <input axis="y">fft</input>
      </graph>
      <separator height="1" precision="0"/>
      <value label="Samples used">
        <input>actual_samples</input>
      </value>
      <value label="Period used" unit="ms" precision="2" factor="1000">
        <input>period</input>
      </value>
    </view>
    <view label="Settings">
      <info label="Below you can set the number of samples used for the Fourier transform. More samples means slower updates, but higher spectral resolution."/>
      <value label="Samples" precision="0">
        <input>samples</input>
      </value>
      <separator height="0.5"/>
      <button label="2048">
        <input type="value">2048</input>
        <output>samples</output>
      </button>
      <button label="4096">
        <input type="value">4096</input>
        <output>samples</output>
      </button>
      <button label="8192">
        <input type="value">8192</input>
        <output>samples</output>
      </button>
      <button label="16384">
        <input type="value">16384</input>
        <output>samples</output>
      </button>
      <button label="32768">
        <input type="value">32768</input>
        <output>samples</output>
      </button>
    </view>
    <view label="Amplitude">
      <value label="Status">
        <input>calibration</input>
        <map min="0" max="0">NOT calibrated</map>
        <map>calibrated</map>
      </value>
      <value label="Sound pressure level" unit="dB" size="3" precision="1">
        <input>dB</input>
      </value>
      <separator height="1"/>
      <graph label="History" labelX="Time" unitX="s" labelY="SPL" unitY="dB">
        <input axis="x">tout</input>
        <input axis="y">dBout</input>
      </graph>
      <separator height="1"/>
      <info label="Please see the calibration tab to get proper results."/>
    </view>
    <view label="Calibration">
      <info label="This experiment uses a rather naive approach to determine the sound pressure level (SPL). You will need a reference sound with a known amplitude in dB. For example, you could setup a constant noise source and measure its sound pressure level with an external device. Enter the measured level as the reference SPL and push 'calibrate' while the experiment is running."/>
      <separator height="1"/>
      <edit label="Reference SPL" unit="dB">
        <output>target dB</output>
      </edit>
      <button label="Calibrate">
        <input>newCal</input>
        <output>calibration</output>
      </button>
      <value label="Calibration offset" unit="dB">
        <input>calibration</input>
      </value>
      <separator height="1"/>
      <info label="If you have done this before or on an identical device you may just enter the calibration offset from your previous calibration directly and press 'set offset'."/>
      <separator height="1"/>
      <edit label="Custom offset" unit="dB">
        <output>userCalibration</output>
      </edit>
      <button label="Set offset">
        <input>userCalibration</input>
        <output>calibration</output>
      </button>
    </view>
    <view label="Raw data">
      <graph label="Recording" labelX="t" unitX="s" labelY="Amplitude" unitY="a.u.">
        <input axis="x">time</input>
        <input axis="y">recording_subrange</input>
      </graph>
    </view>
  </views>
  <analysis sleep="0.05" dynamicSleep="period">
    <timer>
      <output clear="false">t</output>
    </timer>
    <count>
      <input clear="false">recording</input>
      <output>recording_length</output>
    </count>
    <subtract>
      <input>recording_length</input>
      <input clear="false">samples</input>
      <output>subrange_start</output>
    </subtract>
    <subrange>
      <input clear="false" as="from">subrange_start</input>
      <input as="in" clear="false">recording</input>
      <output>recording_subrange</output>
    </subrange>
    <count>
      <input clear="false">recording_subrange</input>
      <output>actual_samples</output>
    </count>
    <add>
      <input clear="false">actual_samples</input>
      <input type="value">1</input>
      <output>actual_samples+1</output>
    </add>
    <divide>
      <input clear="false">actual_samples</input>
      <input type="value">2</input>
      <output>actual_samples/2</output>
    </divide>
    <add>
      <input clear="false">actual_samples/2</input>
      <input type="value">1</input>
      <output>actual_samples/2+1</output>
    </add>
    <divide>
      <input clear="false">actual_samples</input>
      <input clear="false">rate</input>
      <output>period</output>
    </divide>
    <divide>
      <input clear="false">rate</input>
      <input type="value">2</input>
      <output>rate/2</output>
    </divide>
    <ramp>
      <input as="start" type="value">0</input>
      <input as="stop" clear="false">period</input>
      <input as="length" clear="false">actual_samples+1</input>
      <output>time</output>
    </ramp>
    <ramp>
      <input as="start" type="value">0</input>
      <input as="stop" clear="false">rate/2</input>
      <input as="length" clear="false">actual_samples/2+1</input>
      <output>frequency</output>
    </ramp>
    <fft>
      <input clear="false">recording_subrange</input>
      <output as="re">fftX</output>
      <output as="im">fftY</output>
    </fft>
    <subrange>
      <input type="value" as="from">1</input>
      <input clear="false" as="to">actual_samples/2</input>
      <input as="in">frequency</input>
      <input as="in">fftX</input>
      <input as="in">fftY</input>
      <output>halfFrequency</output>
      <output>halfFFTtempX</output>
      <output>halfFFTtempY</output>
    </subrange>
    <formula formula="sqrt([1_]*[1_]+[2_]*[2_])">
      <input>halfFFTtempX</input>
      <input>halfFFTtempY</input>
      <output>fft</output>
    </formula>
    <max>
      <input as="y" clear="false">fft</input>
      <input as="x" clear="false">halfFrequency</input>
      <output as="position" clear="false">f0</output>
    </max>

    <power>
      <input as="base" clear="false">recording_subrange</input>
      <input as="exponent" type="value">2</input>
      <output>recordingSquared</output>
    </power>
    <integrate>
      <input>recordingSquared</input>
      <output>sum</output>
    </integrate>
    <divide>
      <input>sum</input>
      <input clear="false">actual_samples</input>
      <output>mean</output>
    </divide>
    <log>
      <input clear="false">mean</input>
      <output>lnMean</output>
    </log>
    <log>
      <input type="value">10</input>
      <output>ln10</output>
    </log>
    <divide>
      <input clear="false">lnMean</input>
      <input clear="false">ln10</input>
      <input type="value">0.1</input>
      <output>dbUncal</output>
    </divide>
    <add>
      <input clear="false">dbUncal</input>
      <input clear="false">calibration</input>
      <output clear="false">dB</output>
    </add>
    <subtract>
      <input clear="false">target dB</input>
      <input clear="false">dbUncal</input>
      <output>newCal</output>
    </subtract>

    <if equal="true">
        <input clear="false">actual_samples</input>
        <input clear="false">samples</input>
        <input clear="false">t</input>
        <output clear="false">tout</output>
    </if>
    <if equal="true">
        <input clear="false">actual_samples</input>
        <input clear="false">samples</input>
        <input clear="false">f0</input>
        <output clear="false">fout</output>
    </if>
    <if equal="true">
        <input clear="false">actual_samples</input>
        <input clear="false">samples</input>
        <input clear="false">dB</input>
        <output clear="false">dBout</output>
    </if>

  </analysis>
  <export>
    <set name="Results">
      <data name="Time (s)">tout</data>
      <data name="Frequency (Hz)">fout</data>
      <data name="Absolute Amplitude (a.u.)">dBout</data>
    </set>
    <set name="Calibration">
      <data name="calibration offset (dB)">calibration</data>
    </set>
  </export>
</phyphox>
