<phyphox version="1.7" locale="en">
  <title>Audio Amplitude+Magnetometer</title>
  <category>Raw Sensors</category>
    <description>
        Audio Amplitude+Magnetometer (RAW)
    </description>

  <data-containers>
    <!-- audio -->
    <container size="4800">recording</container>
    <container size="4800">recordingSquared</container>
    <container>sum</container>
    <container>mean</container>
    <container>dbUncal</container>
    <container>lnMean</container>
    <container>userCalibration</container>
    <container static="true">ln10</container>
    <container size="0">time</container>
    <container>now</container>
    <container init="0">t0</container>
    <container init="0">resetTime</container>
    <container size="0">dB</container>
    <container init="0">calibration</container>
    <container init="60">target dB</container>
    <container>newCal</container>
    <!--  magneto -->
    <container size="0">mag_time</container>
    <container size="0">magX</container>
    <container size="0">magY</container>
    <container size="0">magZ</container>
    <container size="0">mag</container>
    <container size="0">magAccuracy</container>
  </data-containers>
  
  <input>
  <!-- audio -->
    <audio rate="48000">
      <output>recording</output>
    </audio>
    <!-- magneto -->
    <sensor type="magnetic_field">
      <output component="x">magX</output>
      <output component="y">magY</output>
      <output component="z">magZ</output>
      <output component="t">mag_time</output>
      <output component="abs">mag</output>
      <output component="accuracy">magAccuracy</output>
    </sensor>
  </input>
  
  <views>
    <!-- magneto -->
    <view label="Graph">
      <value label="Accuracy">
        <input>magAccuracy</input>
        <map max="-1">Uncalibrated</map>
        <map max="0">Raw data</map>
        <map max="1">Low</map>
        <map max="2">Medium</map>
        <map max="3">High</map>
      </value>
      <separator height="0.5"/>
      <graph label="Magnetometer x" labelX="t" unitX="s" labelY="B" unitY="µT" partialUpdate="true" color="green">
        <input axis="x">mag_time</input>
        <input axis="y">magX</input>
      </graph>
      <graph label="Magnetometer y" labelX="t" unitX="s" labelY="B" unitY="µT" partialUpdate="true" color="blue">
        <input axis="x">mag_time</input>
        <input axis="y">magY</input>
      </graph>
      <graph label="Magnetometer z" labelX="t" unitX="s" labelY="B" unitY="µT" partialUpdate="true" color="yellow">
        <input axis="x">mag_time</input>
        <input axis="y">magZ</input>
      </graph>
    </view>
    <view label="Absolute">
      <value label="Accuracy">
        <input>magAccuracy</input>
        <map max="-1">Uncalibrated</map>
        <map max="0">Raw data</map>
        <map max="1">Low</map>
        <map max="2">Medium</map>
        <map max="3">High</map>
      </value>
      <separator height="0.5"/>
      <graph label="Absolute" labelX="t" unitX="s" labelY="B" unitY="µT" partialUpdate="true" color="white">
        <input axis="x">mag_time</input>
        <input axis="y">mag</input>
      </graph>
      <value label="Absolute" size="2" precision="2" unit="µT">
        <input>mag</input>
      </value>
    </view>
    <view label="Multi">
      <value label="Accuracy">
        <input>magAccuracy</input>
        <map max="-1">Uncalibrated</map>
        <map max="0">Raw data</map>
        <map max="1">Low</map>
        <map max="2">Medium</map>
        <map max="3">High</map>
      </value>
      <graph label="Magnetometer" labelX="t" unitX="s" labelY="B" unitY="µT" partialUpdate="true">
        <input axis="x" color="green">mag_time</input>
        <input axis="y">magX</input>
        <input axis="x" color="blue">mag_time</input>
        <input axis="y">magY</input>
        <input axis="x" color="yellow">mag_time</input>
        <input axis="y">magZ</input>
        <input axis="x" color="white">mag_time</input>
        <input axis="y">mag</input>
      </graph>
      <value label="Magnetometer x" size="2" precision="2" unit="µT" color="green">
        <input>magX</input>
      </value>
      <value label="Magnetometer y" size="2" precision="2" unit="µT" color="blue">
        <input>magY</input>
      </value>
      <value label="Magnetometer z" size="2" precision="2" unit="µT" color="yellow">
        <input>magZ</input>
      </value>
      <value label="Absolute" size="2" precision="2" unit="µT" color="white">
        <input>mag</input>
      </value>
    </view>
    <view label="Simple">
      <value label="Accuracy">
        <input>magAccuracy</input>
        <map max="-1">Uncalibrated</map>
        <map max="0">Raw data</map>
        <map max="1">Low</map>
        <map max="2">Medium</map>
        <map max="3">High</map>
      </value>
      <separator height="0.5"/>
      <value label="Magnetometer x" size="2" precision="2" unit="µT" color="green">
        <input>magX</input>
      </value>
      <value label="Magnetometer y" size="2" precision="2" unit="µT" color="blue">
        <input>magY</input>
      </value>
      <value label="Magnetometer z" size="2" precision="2" unit="µT" color="yellow">
        <input>magZ</input>
      </value>
      <value label="Absolute" size="2" precision="2" unit="µT" color="white">
        <input>mag</input>
      </value>
    </view>
    <view label="Help">
      <info label="The magnetometer in your phone is always exposed to internal fields from the electronics in your phone, which lead to incorrect results. Therefore phyphox tries to get the calibrated magnetic field from the system. In some cases, you might not get any data, if it is not yet calibrated (for example after the phone has just started). In this case you should rotate your phone a few times while the experiment is running. This helps the system to calibrate the sensor. Also, on many devices (not all) you can switch to uncalibrated magnetometer data via the menu in the top right."/>
    </view>
    <!-- audio -->
    <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">time</input>
        <input axis="y">dB</input>
      </graph>
      <button label="Clear history">
        <input type="empty"/>
        <output>dB</output>
        <input type="empty"/>
        <output>time</output>
        <input type="value">1</input>
        <output>resetTime</output>
      </button>
      <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="FAQ">
      <info label="How accurate are these results?"/>
      <info label="For teaching and exploring? Probably good enough. For serious studies? Probably not, but other apps might perform better (see below). For scientific or health-related applications? Certainly not, get a dedicated device for this."/>
      <separator height="1"/>
      <info label="Why isn't this already calibrated?"/>
      <info label="phyphox is available on more than 10000 devices. Most of them have different microphones, different electronics and different software - all affecting their response to sound. We cannot calibrate them all, but in some cases there are apps which only target a limited number of devices (like apps specific to iPhones) which can calibrate these few devices. If you are interested in better results without calibration, you should check out specific apps for your device."/>
      <separator height="1"/>
      <info label="Why can't we get a better calibration?"/>
      <info label="We wanted a simple procedure to allow students to get comparable data across different devices. With decent equipment you could calibrate the frequency dependency of your microphone as well and maybe even compensate for non-linear responses. If you have such equipment and want to try it, please let us know - we already have phyphox-experiments that allow for more advanced calibration techniques."/>
    </view>
  </views>
  <analysis sleep="0.1">
    <timer>
      <output clear="false">now</output>
    </timer>
    <if equal="true">
      <input clear="false">resetTime</input>
      <input type="value">1</input>
      <input clear="false">now</input>
      <output>t0</output>
    </if>
    <append>
      <input type="value">0</input>
      <output>resetTime</output>
    </append>
    <subtract>
      <input clear="false">now</input>
      <input clear="false">t0</input>
      <output clear="false">time</output>
    </subtract>
    <power>
      <input as="base" clear="false">recording</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 type="value">2400</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>
  </analysis>
  <export>
    <set name="Amplitudes">
      <data name="Time (s)">time</data>
      <data name="Sound pressure level (dB)">dB</data>
    </set>
    <set name="Calibration">
      <data name="calibration offset (dB)">calibration</data>
    </set>
    <set name="Raw Data Magnetometer">
      <data name="Time (s)">mag_time</data>
      <data name="Magnetic Field x (µT)">magX</data>
      <data name="Magnetic Field y (µT)">magY</data>
      <data name="Magnetic Field z (µT)">magZ</data>
      <data name="Absolute field (µT)">mag</data>
    </set>
  </export>
</phyphox>
