<!-- Contactless acoustic stopwatch from standard of phyphox.
     Project: to create double stopwatch using arduino Nano 33 sense board BLE.
     mIv Dec 2020, also comments -->
<phyphox version="1.7" locale="en"> <!-- for BLE the version may be higher.. -->
    <title>Acoustic Contactless Stopwatch</title>
    <category>Timers</category>
    <description>
        Get the time between two acoustic events.

        This experiment allows to measure the time between two loud acoustic signals. These can be clicks, beeps, claps etc. as long as they are louder than the environment. You might want to adjust the threshold, giving the level at which the stop watch is triggered (ranging from 0 to 1).

        After starting the experiment, the clock will start on the first noise exceeding the threshold and will be stopped on the second noise. To repeat the experiment, clear the data and start again. Make sure that the first noise is short as a long sound might be immediately detected as a stop. New: Two more claps clear the data and let you restart again.
    </description>
    <icon>TIM</icon>
    <color>red</color>
  <data-containers>
    <container>threshold</container> <!-- sound threshold to START/STOP -->
    <container>mindelay</container> <!-- max sound duration -->
    <container size="16384">recording</container> <!-- 16384 ??? -->
    <container>rate</container>
    <container>i</container>
    <container>i2</container>
    <container>t</container>
    <container>limit</container>
    <container>max</container>
    <container>last</container>
    <container size="0">tlist</container>
    <container size="0">dtlist</container>
    <container size="0">tindex</container>
    <container size="1">tcount</container>
    <container size="1">tcount-1</container>

    <container>t0</container> <!-- size = 1 by default -->
    <container>t1</container>
    <container>t0effective</container>
    <container>t1effective</container>
    <container>tmax</container>
    <container>dt01</container>

    <container>count</container>
    <container init="0">index</container>
  </data-containers>

    <input> <!-- Continuous sound recording -->
        <audio>
            <output>recording</output>
            <output component="rate">rate</output>
        </audio>
    </input>

  <views>
    <view label="Simple">
      <edit label="Threshold" unit="a.u." default="0.1" signed="false" min="0" max="1">
        <output>threshold</output>
      </edit>
      <edit label="Minimum Delay" unit="s" default="0.1" signed="false">
        <output>mindelay</output>
      </edit>
      <value label="Time" size="3" precision="4" unit="s">
        <input>dt01</input>
      </value>

      <button label="Reset">
        <input type="empty"/>
        <output>tlist</output>
        <input type="value">0</input>
        <output>index</output>
      </button>

      <separator height="1"/>
      <info label="Change the threshold to be above the environmental noise level, but below the trigger noise (you can try the audio scope experiment to check these). Also set the minimum delay to avoid triggers shorter than that time (for example due to echo or reverberation)."/>
      <separator height="1"/>
      <info color="red" label="Unfortunately, this won't work on slow phones. Please compare to a regular clock first, to make sure, that the experiment is working as expected."/>
    </view>
  </views>

  <analysis>

    <count> <!-- length of the sound recording -->
      <input clear="false">recording</input>
      <output>count</output>
    </count>
    <max>   <!-- position and value of sound peak, recording is cleared -->
      <input as="y">recording</input>
      <output as="position">i</output>
      <output as="max">max</output>
    </max>
    <add>   <!-- index + i = absolute peak position, i is cleared -->
      <input>i</input>
      <input clear="false">index</input>
      <output>i2</output>
    </add>

    <divide> <!-- absolute time, i2 is cleared -->
      <input>i2</input>
      <input clear="false">rate</input>
      <output>t</output>
    </divide>
    <if greater="true"> <!-- if not high enough t to zero -->
      <input clear="false">max</input>
      <input clear="false">threshold</input>
      <input clear="false">t</input>
      <input type="value">0</input>
      <output>t</output>
    </if>

    <const>  <!-- last=0 -->
      <output>last</output>
    </const>
    <append>
      <input clear="false">tlist</input>
      <output clear="false">last</output>
    </append>

    <add> <!-- limit = mindelay for absolute time t -->
      <input clear="false">last</input>
      <input clear="false">mindelay</input>
      <output>limit</output>
    </add>
    <if less="true" equal="true">
      <input clear="false">limit</input>
      <input clear="false">t</input>
      <input clear="false">t</input>
      <input type="value">0</input>
      <output>t</output>
    </if>
    <if greater="true"> <!-- if t greater 0, t saved to tlist -->
      <input clear="false">t</input>
      <input type="value">0</input>
      <input clear="false">t</input>
      <output clear="false">tlist</output>
    </if>

    <differentiate> <!-- calculate time intervals in tlist -->
      <input clear="false">tlist</input>
      <output>dtlist</output>
    </differentiate>
    <append>
      <input type="value">0</input>
      <output clear="false">dtlist</output>
    </append>

    <count> <!-- number of measurements in tlist -->
      <input clear="false">tlist</input>
      <output>tcount</output>
    </count>
    <subtract>
      <input clear="false">tcount</input>
      <input type="value">1</input>
      <output>tcount-1</output>
    </subtract>

    <add> <!-- upgrade index for next run, count is cleared -->
      <input clear="false">index</input>
      <input>count</input>
      <output>index</output>
    </add>
    <divide> <!-- tmax ? -->
      <input clear="false">index</input>
      <input clear="false">rate</input>
      <output>tmax</output>
    </divide>

    <!-- NEW: restart by two more claps -->
    <if greater="true">
      <input as="a" clear="false">tcount</input>
      <input as="b" type="value">3</input>
      <input as="true" type="empty"/>
      <output>tlist</output>
    </if>
    <if greater="true">
      <input as="a" clear="false">tcount</input>
      <input as="b" type="value">3</input>
      <input as="true" type="value">0</input>
      <output>index</output>
    </if>

    <const>  <!-- ? if followed by subrange -->
      <output>t0</output>
    </const>
    <const>
      <output>t1</output>
    </const>

    <subrange> <!-- 1st element of tlist -->
      <input as="from" type="value">0</input>
      <input as="length" type="value">1</input>
      <input as="in" clear="false">tlist</input>
      <output clear="false">t0</output>
    </subrange>
    <subrange>  <!-- 2nd element of tlist -->
      <input as="from" type="value">1</input>
      <input as="length" type="value">1</input>
      <input as="in" clear="false">tlist</input>
      <output clear="false">t1</output>
    </subrange>
    <if less="true" equal="true">
      <input clear="false">t1</input>
      <input type="value">0</input>
      <input clear="false">tmax</input>
      <input clear="false">t1</input>
      <output>t1effective</output>
    </if>
    <if less="true" equal="true">
      <input clear="false">t0</input>
      <input type="value">0</input>
      <input clear="false">tmax</input>
      <input clear="false">t0</input>
      <output>t0effective</output>
    </if>
    <subtract>
      <input>t1effective</input>
      <input>t0effective</input>
      <output>dt01</output>
    </subtract>
  </analysis>

  <!-- ALL peak times: for some potential usage -->
  <export>
    <set name="ALL times">
      <data name="times (s)">tlist</data>
    </set>
  </export>

</phyphox>