ref: a11130bb24ab844778fc770841e263f5d3aba0c7
parent: 5d657f0156b1e5048ab1887b3e86e4333f463a9d
author: Matthew Wang <mjw7@princeton.edu>
date: Thu May 28 06:44:47 EDT 2020
rename LEAF_JUCEPlugin to TestPlugin
--- a/LEAF_JUCEPlugin/LEAF.jucer
+++ /dev/null
@@ -1,154 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<JUCERPROJECT id="ArQetv" name="LEAF" projectType="audioplug" version="1.0.0"
- bundleIdentifier="com.pumusic.LEAF" includeBinaryInAppConfig="1"
- buildVST="0" buildVST3="0" buildAU="1" buildAUv3="0" buildRTAS="0"
- buildAAX="0" pluginName="LEAF" pluginDesc="LEAF" pluginManufacturer="pumusic"
- pluginManufacturerCode="Manu" pluginCode="Arqe" pluginChannelConfigs="{2,2}"
- pluginIsSynth="0" pluginWantsMidiIn="1" pluginProducesMidiOut="0"
- pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="LEAFAU"
- pluginRTASCategory="" aaxIdentifier="com.pumusic.LEAF" pluginAAXCategory="2"
- jucerVersion="5.4.7" companyName="Princeton University" companyEmail="mrmulshine@gmail.com"
- displaySplashScreen="1" reportAppUsage="1" splashScreenColour="Dark"
- buildStandalone="1" enableIAA="0" cppLanguageStandard="11" companyCopyright="Princeton University"
- pluginFormats="buildAU,buildStandalone" pluginCharacteristicsValue="pluginWantsMidiIn">
- <MAINGROUP id="F7Bywq" name="LEAF">
- <GROUP id="{F7096CF4-1A84-4CC8-A236-06FAE894451E}" name="Examples">
- <FILE id="hMMOsl" name="basic-oscillators.c" compile="0" resource="0"
- file="../Examples/basic-oscillators.c"/>
- <FILE id="mVSe2h" name="basic-oscillators.h" compile="0" resource="0"
- file="../Examples/basic-oscillators.h"/>
- </GROUP>
- <GROUP id="{14C5E2CD-5D51-3FD3-5677-28BECA29E95E}" name="Source">
- <GROUP id="{FFA9F0EC-F45A-74FC-5A10-9B3CAA731E7C}" name="External">
- <FILE id="ixwZea" name="Yin.h" compile="0" resource="0" file="Source/Yin.h"/>
- <FILE id="wbnjmF" name="Yin.cpp" compile="1" resource="0" file="Source/Yin.cpp"/>
- </GROUP>
- <GROUP id="{5EAA8994-9CCF-AFE1-27F3-6B2132200B97}" name="Test">
- <FILE id="XkflAI" name="LEAFLink.h" compile="0" resource="0" file="Source/LEAFLink.h"/>
- <FILE id="O9woHe" name="LEAFLink.cpp" compile="1" resource="0" file="Source/LEAFLink.cpp"/>
- <FILE id="xGEfAX" name="LEAFTest.h" compile="0" resource="0" file="Source/LEAFTest.h"/>
- <FILE id="xRGWtb" name="MyTest.h" compile="0" resource="0" file="Source/MyTest.h"/>
- <FILE id="PGmAOc" name="MyTest.cpp" compile="1" resource="0" file="Source/MyTest.cpp"/>
- </GROUP>
- <GROUP id="{A89F40A7-55BD-BADE-F6FC-0813ECB90B8B}" name="Wrapper">
- <FILE id="R9R9N2" name="Globals.h" compile="0" resource="0" file="Source/Globals.h"/>
- <FILE id="oQ7Hdj" name="UIComponent.h" compile="0" resource="0" file="Source/UIComponent.h"/>
- <FILE id="ONd1SP" name="UIComponent.cpp" compile="1" resource="0" file="Source/UIComponent.cpp"/>
- <FILE id="EnmsIi" name="PluginProcessor.h" compile="0" resource="0"
- file="Source/PluginProcessor.h"/>
- <FILE id="xwxe1U" name="PluginProcessor.cpp" compile="1" resource="0"
- file="Source/PluginProcessor.cpp"/>
- <FILE id="L2MQTe" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
- <FILE id="euDngN" name="PluginEditor.cpp" compile="1" resource="0"
- file="Source/PluginEditor.cpp"/>
- </GROUP>
- </GROUP>
- </MAINGROUP>
- <EXPORTFORMATS>
- <XCODE_MAC targetFolder="Builds/MacOSX">
- <CONFIGURATIONS>
- <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>
- <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"
- enablePluginBinaryCopyStep="1"/>
- </CONFIGURATIONS>
- <MODULEPATHS>
- <MODULEPATH id="juce_core" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_events" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_graphics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_data_structures" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_gui_basics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_gui_extra" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_cryptography" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_video" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_opengl" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_basics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_devices" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_formats" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_processors" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_plugin_client" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_utils" path="../../../../JUCE/modules"/>
- <MODULEPATH id="leaf" path="../../LEAF"/>
- </MODULEPATHS>
- </XCODE_MAC>
- <XCODE_IPHONE targetFolder="Builds/iOS" iosScreenOrientation="portraitlandscape"
- iosDevelopmentTeamID="QY96HSP2FJ" microphonePermissionNeeded="1"
- iosBackgroundAudio="1" iPadScreenOrientation="portraitlandscape"
- iosDeviceFamily="1,2">
- <CONFIGURATIONS>
- <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>
- <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"
- enablePluginBinaryCopyStep="1"/>
- </CONFIGURATIONS>
- <MODULEPATHS>
- <MODULEPATH id="juce_core" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_events" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_graphics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_data_structures" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_gui_basics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_gui_extra" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_cryptography" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_video" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_opengl" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_basics" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_devices" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_formats" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_processors" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_plugin_client" path="../../../../JUCE/modules"/>
- <MODULEPATH id="juce_audio_utils" path="../../../../JUCE/modules"/>
- <MODULEPATH id="leaf" path="../../LEAF"/>
- </MODULEPATHS>
- </XCODE_IPHONE>
- <VS2017 targetFolder="Builds/VisualStudio2017">
- <CONFIGURATIONS>
- <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
- isDebug="1" optimisation="1" targetName="OOPS" debugInformationFormat="ProgramDatabase"
- enablePluginBinaryCopyStep="0"/>
- <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
- isDebug="0" optimisation="3" targetName="OOPS" debugInformationFormat="ProgramDatabase"
- enablePluginBinaryCopyStep="0" linkTimeOptimisation="1"/>
- </CONFIGURATIONS>
- <MODULEPATHS>
- <MODULEPATH id="juce_video" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_opengl" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_gui_extra" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_gui_basics" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_graphics" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_events" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_data_structures" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_cryptography" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_core" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_utils" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_processors" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_plugin_client" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_formats" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_devices" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="juce_audio_basics" path="..\..\..\JUCE\modules"/>
- <MODULEPATH id="leaf" path="../../LEAF"/>
- </MODULEPATHS>
- </VS2017>
- </EXPORTFORMATS>
- <MODULES>
- <MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"
- useGlobalPath="1"/>
- <MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="juce_video" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
- <MODULE id="leaf" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/>
- </MODULES>
- <JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
- <LIVE_SETTINGS>
- <OSX/>
- </LIVE_SETTINGS>
-</JUCERPROJECT>
--- a/LEAF_JUCEPlugin/Source/Globals.h
+++ /dev/null
@@ -1,44 +1,0 @@
-/*
- ==============================================================================
-
- Globals.h
- Created: 17 Jan 2017 12:16:12pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef GLOBALS_H_INCLUDED
-#define GLOBALS_H_INCLUDED
-
-#include "../JuceLibraryCode/JuceHeader.h"
-
-#define TEST 1
-
-
-String floatArrayToString(Array<float> arr)
-{
- String s = "";
- for (auto key : arr)
- {
- s.append(String(key), 6);
- s.append(" ", 1);
- }
- return s;
-}
-
-String intArrayToString(Array<int> arr)
-{
- String s = "";
- for (auto key : arr)
- {
- s.append(String(key), 6);
- s.append(" ", 1);
- }
- return s;
-}
-
-
-
-
-#endif // GLOBALS_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/LEAFLink.cpp
+++ /dev/null
@@ -1,144 +1,0 @@
-/*
- ==============================================================================
-
- LEAFLink.c
- Created: 18 Jan 2017 11:25:00am
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#include "LEAFLink.h"
-
-#define MYTEST 0
-#define FM 1
-
-std::vector<juce::String> cButtonNames = std::vector<juce::String>
-{
-
-};
-
-std::vector<juce::String> cSliderNames = std::vector<juce::String>
-{
- "on/off",
- "mod freq",
- "mod depth"
-};
-
-std::vector<juce::String> cComboBoxNames = std::vector<juce::String>
-{
-
-};
-
-std::vector<juce::String> cWaveformTypes = std::vector<juce::String>
-{
-
-};
-
-std::vector<float> cSliderModelValues(cSliderNames.size());
-std::vector<float> cSliderValues(cSliderNames.size());
-std::vector<bool> cButtonStates(cButtonNames.size());
-std::vector<int> cComboBoxStates(cComboBoxNames.size());
-
-void setSliderModelValue(String name, float val)
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- {
- if (name == cSliderNames[i])
- {
- cSliderModelValues[i] = val;
- break;
- }
- }
-}
-
-void printSliderValues(void)
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- {
- DBG(String(cSliderNames[i]) + ": " + String(cSliderValues[i]));
- }
-}
-
-bool getButtonState(String name)
-{
- for (int i = 0; i < cButtonNames.size(); i++)
- {
- if (name == cButtonNames[i])
- {
- return cButtonStates[i];
- }
- }
-
- return false;
-}
-
-void setButtonState(String name, bool on)
-{
- for (int i = 0; i < cButtonNames.size(); i++)
- {
- if (name == cButtonNames[i])
- {
- cButtonStates[i] = on;
- break;
- }
- }
-}
-
-int getComboBoxState(String name)
-{
- for (int i = 0; i < cComboBoxNames.size(); i++)
- {
- if (name == cComboBoxNames[i])
- {
- return cComboBoxStates[i];
- }
- }
- return -1;
-}
-
-void setComboBoxState(String name, int idx)
-{
- DBG("set state: " + name + " " + String(idx));
- for (int i = 0; i < cComboBoxNames.size(); i++)
- {
- if (name == cComboBoxNames[i])
- {
- cComboBoxStates[i] = idx;
- break;
- }
- }
-}
-
-void setSliderValue(String name, float val)
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- {
- if (name == cSliderNames[i])
- {
- cSliderValues[i] = val;
- break;
- }
- }
-}
-
-float getSliderValue(String name)
-{
- float value = 0.0f;
-
- for (int i = 0; i < cSliderNames.size(); i++)
- {
- if (name == cSliderNames[i])
- {
- value = cSliderValues[i];
- break;
- }
- }
-
- return value;
-}
-
-float getRandomFloat(void)
-{
- return ((float)rand()/RAND_MAX);
-}
--- a/LEAF_JUCEPlugin/Source/LEAFLink.h
+++ /dev/null
@@ -1,52 +1,0 @@
-/*
- ==============================================================================
-
- Utilities.h
- Created: 5 Dec 2016 2:37:03pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef UTILITIES_H_INCLUDED
-#define UTILITIES_H_INCLUDED
-
-#include "../JuceLibraryCode/JuceHeader.h"
-
-#include "stdlib.h"
-
-typedef enum WaveformType {
- Sine=0,
- Triangle,
- Sawtooth,
- Square,
- WaveformTypeNil
-}WaveformType;
-
-extern std::vector<juce::String> cSliderNames;
-
-extern std::vector<juce::String> cButtonNames;
-
-extern std::vector<juce::String> cComboBoxNames;
-
-extern std::vector<juce::String> cWaveformTypes;
-
-extern std::vector<float> cSliderValues;
-
-extern std::vector<float> cSliderModelValues;
-
-extern std::vector<bool> cButtonStates;
-
-extern std::vector<int> cComboBoxStates;
-
-void printSliderValues(void);
-bool getButtonState(String name);
-void setButtonState(String name, bool on);
-int getComboBoxState(String name);
-void setComboBoxState(String name, int idx);
-void setSliderModelValue(String name, float val);
-void setSliderValue(String name, float val);
-float getSliderValue(String name);
-float getRandomFloat(void);
-
-#endif // UTILITIES_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/LEAFTest.h
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- ==============================================================================
-
- OOPSTest.h
- Created: 4 Dec 2016 9:14:16pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef LEAFTEST1_H_INCLUDED
-#define LEAFTEST1_H_INCLUDED
-
-#include "LEAFLink.h"
-
-#include "../../leaf/leaf.h"
-
-#include "Yin.h"
-
-// LEAFTest API
-float LEAFTest_tick (float input);
-void LEAFTest_init (float sampleRate, int blocksize);
-void LEAFTest_end (void);
-void LEAFTest_block (void);
-
-void LEAFTest_noteOn (int midiNoteNumber, float velocity);
-void LEAFTest_noteOff (int midiNoteNumber);
-
-#endif // LEAFTEST1_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ /dev/null
@@ -1,222 +1,0 @@
-/*
- ==============================================================================
- FM.c
- Created: 23 Jan 2017 9:39:38am
- Author: Michael R Mulshine
- ==============================================================================
- */
-
-#include "LEAFTest.h"
-#include "MyTest.h"
-
-
-static void leaf_pool_report(void);
-static void leaf_pool_dump(void);
-static void run_pool_test(void);
-
-tNoise noise;
-tSVF bp1;
-tSVF bp2;
-tFormantShifter fs;
-
-tSampler samp;
-tBuffer buff;
-tEnvelope env;
-
-tAutotune at;
-
-
-tMinBLEP minblep;
-
-tPhasor phasor;
-
-tHighpass hipass;
-
-tMBSaw saw;
-tMBPulse pulse;
-tMBTriangle tri;
-
-float gain;
-float freq;
-float dtime;
-bool buttonState;
-int ratio = 2;
-float x = 0.0f;
-float y = 0.0f;
-float a, b, c, d;
-
-#define MSIZE 500000
-char memory[MSIZE];
-
-void LEAFTest_init (float sampleRate, int blockSize)
-{
- LEAF_init(sampleRate, blockSize, memory, MSIZE, &getRandomFloat);
-
- tMBSaw_init(&saw);
-
- tMBPulse_init(&pulse);
-
- tMBTriangle_init(&tri);
-
- tPhasor_init(&phasor);
-
- tPhasor_setFreq(&phasor, 200);
-}
-
-inline double getSawFall(double angle) {
-
- angle = fmod(angle + double_Pi, 2*double_Pi); // shift x
- double sample = angle/double_Pi - double(1); // computer as remainder
-
- return sample;
-
-}
-
-float LEAFTest_tick (float input)
-{
-
- tMBSaw_setFreq(&saw, y);
- tMBPulse_setWidth(&pulse, x);
- tMBPulse_setFreq(&pulse, y);
- tMBTriangle_setSkew(&tri, 0.0);//x*2.0f - 1.0f);
- tMBTriangle_setFreq(&tri, y);
-
- tPhasor_tick(&phasor);
-
-// if (phasor->phaseDidReset) tMBSaw_sync(&saw, 0.0f);
-// if (phasor->phaseDidReset) tMBPulse_sync(&pulse, 0.0f);
- if (phasor->phaseDidReset) tMBTriangle_sync(&tri, 0.0f);
-
-// return tMBSaw_tick(&saw);
-// return tMBPulse_tick(&pulse);
- return tMBTriangle_tick(&tri);
-}
-
-int firstFrame = 1;
-bool lastState = false, lastPlayState = false;
-void LEAFTest_block (void)
-{
- // if (firstFrame == 1)
- // {
- // tBuffer_record(&buff); // starts recording
- // tSampler_play(&samp); // start spitting samples out
- // firstFrame = 0;
- // }
-
- float val = getSliderValue("mod freq");
-
- x = val ;
-
- // a = val * tBuffer_getBufferLength(&buff);
-
- DBG("start: " + String(a));
-
- val = getSliderValue("mod depth");
-
- y = val * 5000.0f + 20.0f;
-
- DBG(String(y));
- // b = val * tBuffer_getBufferLength(&buff);
-
- DBG("rate: " + String(b));
- //
- // tSampler_setStart(&samp, a);
- // tSampler_setEnd(&samp, b);
- // tSampler_setRate(&samp, b);
-
- // tFormantShifter_setShiftFactor(&fs, x);
- // tFormantShifter_setIntensity(&fs, y);
-
-}
-
-void LEAFTest_controllerInput (int cnum, float cval)
-{
-
-}
-
-void LEAFTest_pitchBendInput (int pitchBend)
-{
-
-}
-
-int lastNote;
-void LEAFTest_noteOn (int note, float velocity)
-{
-}
-
-
-void LEAFTest_noteOff (int note)
-{
-}
-
-
-
-void LEAFTest_end (void)
-{
-
-}
-
-// LEAF POOL UTILITIES
-
-void leaf_pool_report(void)
-{
- DBG(String(leaf_pool_get_used()) + " of " + String(leaf_pool_get_size()));
-}
-
-void leaf_pool_dump(void)
-{
- float* buff = (float*)leaf_pool_get_pool();
- unsigned long siz = leaf_pool_get_size();
- siz /= sizeof(float);
- for (int i = 0; i < siz; i++)
- {
- DBG(String(buff[i]));
- }
-}
-
-static void run_pool_test(void)
-{
- leaf_pool_report();
-
- DBG("ALLOC BUFFER 1");
- int size = 50;
- float* buffer;
- buffer = (float*) leaf_alloc(sizeof(float) * size);
-
- for (int i = 0; i < size; i++)
- {
- buffer[i] = (float)i;
-
- }
-
- leaf_pool_report();
-
- DBG("ALLOC BUFFER 2");
- size = 25;
-
- buffer = (float*) leaf_alloc(sizeof(float) * size);
-
- leaf_pool_report();
-
- for (int i = 0; i < size; i++)
- {
- buffer[i] = (float)(i*2);
- }
- leaf_free((char*)buffer);
-
- leaf_pool_report();
-
- DBG("ALLOC BUFFER 3");
- size = 15;
-
- buffer = (float*) leaf_alloc(sizeof(float) * size);
-
- for (int i = 0; i < size; i++)
- {
- buffer[i] = (float)(i*3);
- }
-
- leaf_pool_report();
-
- leaf_pool_dump();
-}
--- a/LEAF_JUCEPlugin/Source/MyTest.h
+++ /dev/null
@@ -1,16 +1,0 @@
-/*
- ==============================================================================
-
- MyTest.h
- Created: 23 Jan 2017 9:39:38am
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef FM_H_INCLUDED
-#define FM_H_INCLUDED
-
-
-
-#endif // FM_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/PluginEditor.cpp
+++ /dev/null
@@ -1,13 +1,0 @@
-/*
- ==============================================================================
-
- This file was auto-generated!
-
- It contains the basic framework code for a JUCE plugin editor.
-
- ==============================================================================
-*/
-
-//#include "PluginEditor.h"
-
-
--- a/LEAF_JUCEPlugin/Source/PluginEditor.h
+++ /dev/null
@@ -1,42 +1,0 @@
-/*
- ==============================================================================
-
- This file was auto-generated!
-
- It contains the basic framework code for a JUCE plugin editor.
-
- ==============================================================================
-*/
-
-#ifndef PLUGINEDITOR_H_INCLUDED
-#define PLUGINEDITOR_H_INCLUDED
-
-#include "PluginProcessor.h"
-
-#include "UIComponent.h"
-
-//==============================================================================
-/**
-*/
-class OopsAudioProcessorEditor : public AudioProcessorEditor
-{
-public:
- OopsAudioProcessorEditor (OopsAudioProcessor&);
- ~OopsAudioProcessorEditor();
-
- //==============================================================================
- void paint (Graphics&) override;
- void resized() override;
-
-private:
- // This reference is provided as a quick way for your editor to
- // access the processor object that created it.
-
- UIComponent uicomponent;
- OopsAudioProcessor& processor;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OopsAudioProcessorEditor)
-};
-
-
-#endif // PLUGINEDITOR_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/PluginProcessor.cpp
+++ /dev/null
@@ -1,237 +1,0 @@
-/*
- ==============================================================================
-
- This file was auto-generated!
-
- It contains the basic framework code for a JUCE plugin processor.
-
- ==============================================================================
-*/
-
-#include "PluginProcessor.h"
-#include "PluginEditor.h"
-
-#include "UIComponent.h"
-
-#include "LEAFTest.h"
-
-//==============================================================================
-OopsAudioProcessorEditor::OopsAudioProcessorEditor (OopsAudioProcessor& p)
-: AudioProcessorEditor (&p), processor (p)
-{
- // Make sure that before the constructor has finished, you've set the
- // editor's size to whatever you need it to be.
- setSize (600, 400);
-
- addAndMakeVisible(uicomponent);
-}
-
-OopsAudioProcessorEditor::~OopsAudioProcessorEditor()
-{
-}
-
-//==============================================================================
-void OopsAudioProcessorEditor::paint (Graphics& g)
-{
- g.fillAll (Colours::white);
-}
-
-void OopsAudioProcessorEditor::resized()
-{
- uicomponent.setBounds(getBounds());
-}
-//==============================================================================
-void OopsAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
-{
- gain = 0.0f;
- timer = 0;
- start = false;
- ramp = false;
-
- LEAFTest_init(sampleRate, samplesPerBlock);
-}
-
-
-
-//====================================BLOCK=======================================
-
-void OopsAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
-{
- const int totalNumInputChannels = getTotalNumInputChannels();
- const int totalNumOutputChannels = getTotalNumOutputChannels();
-
- for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
- buffer.clear (i, 0, buffer.getNumSamples());
-
- LEAFTest_block();
-
- MidiMessage m;
- int time;
-
- for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
- {
- int noteNumber = m.getNoteNumber();
- float velocity = m.getFloatVelocity();
-
- if (m.isNoteOn())
- {
- LEAFTest_noteOn(noteNumber, velocity);
- }
- else if (m.isNoteOff())
- {
- LEAFTest_noteOff(noteNumber);
- }
- else
- {
-
- }
- }
-
-
- const float* inPointerL = buffer.getReadPointer (0);
- const float* inPointerR = buffer.getReadPointer (1);
-
- float* outPointerL = buffer.getWritePointer( 0);
- float* outPointerR = buffer.getWritePointer( 1);
-
- for (int samp = 0; samp < buffer.getNumSamples(); ++samp)
- {
- outPointerL[samp] = LEAFTest_tick( (inPointerL[samp] +inPointerR[samp]) * 0.5f);
- outPointerR[samp] = outPointerL[samp];
- }
-}
-
-//==============================================================================
-
-OopsAudioProcessor::OopsAudioProcessor()
-#ifndef JucePlugin_PreferredChannelConfigurations
-: AudioProcessor (BusesProperties()
- #if ! JucePlugin_IsMidiEffect
- #if ! JucePlugin_IsSynth
- .withInput ("Input", AudioChannelSet::stereo(), true)
- #endif
- .withOutput ("Output", AudioChannelSet::stereo(), true)
- #endif
- )
-#endif
-{
-
-}
-
-OopsAudioProcessor::~OopsAudioProcessor()
-{
-
-}
-
-//==============================================================================
-const String OopsAudioProcessor::getName() const
-{
- return JucePlugin_Name;
-}
-
-bool OopsAudioProcessor::acceptsMidi() const
-{
- return true;
-}
-
-bool OopsAudioProcessor::producesMidi() const
-{
- #if JucePlugin_ProducesMidiOutput
- return true;
- #else
- return false;
- #endif
-}
-
-double OopsAudioProcessor::getTailLengthSeconds() const
-{
- return 0.0;
-}
-
-int OopsAudioProcessor::getNumPrograms()
-{
- return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
- // so this should be at least 1, even if you're not really implementing programs.
-}
-
-int OopsAudioProcessor::getCurrentProgram()
-{
- return 0;
-}
-
-void OopsAudioProcessor::setCurrentProgram (int index)
-{
-}
-
-const String OopsAudioProcessor::getProgramName (int index)
-{
- return String();
-}
-
-void OopsAudioProcessor::changeProgramName (int index, const String& newName)
-{
-}
-
-void OopsAudioProcessor::releaseResources()
-{
- // When playback stops, you can use this as an opportunity to free up any
- // spare memory, etc.
- LEAFTest_end();
-}
-
-#ifndef JucePlugin_PreferredChannelConfigurations
-bool OopsAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
-{
- #if JucePlugin_IsMidiEffect
- ignoreUnused (layouts);
- return true;
- #else
- // This is the place where you check if the layout is supported.
- // In this template code we only support mono or stereo.
- if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
- && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
- return false;
-
- // This checks if the input layout matches the output layout
- #if ! JucePlugin_IsSynth
- if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
- return false;
- #endif
-
- return true;
- #endif
-}
-#endif
-
-
-//==============================================================================
-bool OopsAudioProcessor::hasEditor() const
-{
- return true; // (change this to false if you choose to not supply an editor)
-}
-
-AudioProcessorEditor* OopsAudioProcessor::createEditor()
-{
- return new OopsAudioProcessorEditor (*this);
-}
-
-//==============================================================================
-void OopsAudioProcessor::getStateInformation (MemoryBlock& destData)
-{
- // You should use this method to store your parameters in the memory block.
- // You could do that either as raw data, or use the XML or ValueTree classes
- // as intermediaries to make it easy to save and load complex data.
-}
-
-void OopsAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
-{
- // You should use this method to restore your parameters from this memory block,
- // whose contents will have been created by the getStateInformation() call.
-}
-
-//==============================================================================
-// This creates new instances of the plugin..
-AudioProcessor* JUCE_CALLTYPE createPluginFilter()
-{
- return new OopsAudioProcessor();
-}
--- a/LEAF_JUCEPlugin/Source/PluginProcessor.h
+++ /dev/null
@@ -1,68 +1,0 @@
-/*
- ==============================================================================
-
- This file was auto-generated!
-
- It contains the basic framework code for a JUCE plugin processor.
-
- ==============================================================================
-*/
-
-#ifndef PLUGINPROCESSOR_H_INCLUDED
-#define PLUGINPROCESSOR_H_INCLUDED
-
-#include "../JuceLibraryCode/JuceHeader.h"
-
-
-//==============================================================================
-/**
-*/
-class OopsAudioProcessor : public AudioProcessor
-{
-public:
- //==============================================================================
- OopsAudioProcessor();
- ~OopsAudioProcessor();
-
- //==============================================================================
- void prepareToPlay (double sampleRate, int samplesPerBlock) override;
- void releaseResources() override;
-
- #ifndef JucePlugin_PreferredChannelConfigurations
- bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
- #endif
-
- void processBlock (AudioSampleBuffer&, MidiBuffer&) override;
-
- //==============================================================================
- AudioProcessorEditor* createEditor() override;
- bool hasEditor() const override;
-
- //==============================================================================
- const String getName() const override;
-
- bool acceptsMidi() const override;
- bool producesMidi() const override;
- double getTailLengthSeconds() const override;
-
- //==============================================================================
- int getNumPrograms() override;
- int getCurrentProgram() override;
- void setCurrentProgram (int index) override;
- const String getProgramName (int index) override;
- void changeProgramName (int index, const String& newName) override;
-
- //==============================================================================
- void getStateInformation (MemoryBlock& destData) override;
- void setStateInformation (const void* data, int sizeInBytes) override;
-
-private:
- uint64 timer;
- float gain;
- bool start,ramp;
- //==============================================================================
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OopsAudioProcessor)
-};
-
-
-#endif // PLUGINPROCESSOR_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/UIComponent.cpp
+++ /dev/null
@@ -1,155 +1,0 @@
-/*
- ==============================================================================
-
- UIComponent.c
- Created: 18 Jan 2017 11:19:15am
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#include "UIComponent.h"
-
-#include "LEAFLink.h"
-
-UIComponent::UIComponent()
-
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- {
-
- sliders.set(i, new Slider());
- sliders[i]->setSliderStyle(Slider::SliderStyle::LinearVertical);
- sliders[i]->setRange(0.0, 1.0, 1.0/50000.0);
- sliders[i]->setName(cSliderNames[i]);
- sliders[i]->setComponentID(String(i));
- sliders[i]->addListener(this);
- addAndMakeVisible(sliders[i]);
-
- sliderLabels.set(i, new Label());
- sliderLabels[i]->setName(cSliderNames[i]);
- sliderLabels[i]->setColour(Label::textColourId, Colours::aliceblue);
- sliderLabels[i]->setText(cSliderNames[i], NotificationType::dontSendNotification);
- addAndMakeVisible(sliderLabels[i]);
-
- textFields.set(i, new TextEditor());
- textFields[i]->addListener(this);
- textFields[i]->setName(cSliderNames[i]);
- textFields[i]->setEnabled(false);
- addAndMakeVisible(textFields[i]);
- }
-
- for (int i = 0; i < cButtonNames.size(); i++)
- {
- buttons.set(i, new TextButton(cButtonNames[i]));
- buttons[i]->changeWidthToFitText();
- buttons[i]->setButtonText(cButtonNames[i]);
- buttons[i]->addListener(this);
- addAndMakeVisible(buttons[i]);
- }
-
- for (int i = 0; i < cComboBoxNames.size(); i++)
- {
- comboBoxes.set(i, new ComboBox());
- comboBoxes[i]->setName(cComboBoxNames[i]);
- comboBoxes[i]->addSeparator();
- comboBoxes[i]->addListener(this);
- addAndMakeVisible(comboBoxes[i]);
-
- }
-
- for (int i = 0; i < cComboBoxNames.size(); i++)
- {
- for (int j = 0; j < cWaveformTypes.size(); j++)
- {
- comboBoxes[i]->addItem(cWaveformTypes[j], j+1);
- }
- comboBoxes[i]->setSelectedItemIndex(0);
- }
-
-
- startTimerHz(20);
-}
-
-void UIComponent::timerCallback(void)
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- textFields[i]->setText(String(cSliderModelValues[i]), false);
-}
-
-void UIComponent::textEditorTextChanged (TextEditor& tf)
-{
-
-}
-
-UIComponent::~UIComponent()
-{
-}
-
-void UIComponent::paint (Graphics& g)
-{
- /* This demo code just fills the component's background and
- draws some placeholder text to get you started.
-
- You should replace everything in this method with your own
- drawing code..
- */
-
- g.fillAll (Colours::slategrey); // clear the background
-
- g.setColour (Colours::aliceblue);
- g.drawRect (getLocalBounds(), 1); // draw an outline around the component
-}
-
-void UIComponent::resized()
-{
- for (int i = 0; i < cSliderNames.size(); i++)
- {
- sliders[i] ->setBounds(cLeftOffset + ((cSliderWidth + cXSpacing) * i),
- cTopOffset,
- cSliderWidth,
- cSliderHeight);
-
- textFields[i] ->setBounds(sliders[i]->getX() - (cSliderNames[i].length() * 2.0f),
- sliders[i]->getBottom() + cYSpacing,
- 75,
- 20);
-
- sliderLabels[i] ->setBounds(sliders[i]->getX() - (cSliderNames[i].length() * 2.0f),
- textFields[i]->getBottom() + cYSpacing,
- cLabelWidth,
- cLabelHeight);
- }
-
- for (int i = 0; i < cButtonNames.size(); i++)
- {
- buttons[i] ->setBounds(cLeftOffset + ((cButtonWidth + cXSpacing) * i),
- 500,
- cButtonWidth,
- cButtonHeight);
- }
-
- for (int i = 0; i < cComboBoxNames.size(); i++)
- {
- comboBoxes[i] ->setBounds(
- cLeftOffset + ((cButtonWidth + cXSpacing) * i),
- cTopOffset + cSliderHeight + cLabelHeight + cButtonHeight + 3 * cYSpacing,
- cBoxWidth,
- cBoxHeight );
- }
-}
-
-void UIComponent::sliderValueChanged(Slider* s)
-{
- setSliderValue(s->getName(), s->getValue());
-}
-
-void UIComponent::buttonStateChanged (Button* b)
-{
- setButtonState(b->getName(), b->getState());
-}
-
-void UIComponent::comboBoxChanged (ComboBox* cb)
-{
- setComboBoxState(cb->getName(), cb->getSelectedId() - 1);
-}
--- a/LEAF_JUCEPlugin/Source/UIComponent.h
+++ /dev/null
@@ -1,77 +1,0 @@
-/*
- ==============================================================================
-
- UIComponent.h
- Created: 5 Dec 2016 2:23:38pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef UICOMPONENT_H_INCLUDED
-#define UICOMPONENT_H_INCLUDED
-
-#include "../JuceLibraryCode/JuceHeader.h"
-
-//==============================================================================
-/*
-*/
-class UIComponent:
-public Component,
-public Slider::Listener,
-public TextButton::Listener,
-public ComboBox::Listener,
-public TextEditor::Listener,
-private Timer
-{
-public:
- UIComponent();
-
- ~UIComponent();
-
- void paint (Graphics& g) override;
-
- void resized() override;
-
- void sliderValueChanged(Slider* s) override;
-
- void buttonClicked(Button*b) override {};
- void buttonStateChanged(Button* b) override;
-
- void textEditorTextChanged (TextEditor&) override;
-
- void comboBoxChanged (ComboBox* cb) override;
-
- void timerCallback() override;
-
-private:
-
- static const int cLeftOffset = 30;
- static const int cTopOffset = 30;
-
- static const int cXSpacing = 60;
- static const int cYSpacing = 5;
-
- static const int cSliderHeight = 200;
- static const int cSliderWidth = 20;
-
- static const int cLabelHeight = 20;
- static const int cLabelWidth = cSliderWidth + cXSpacing;
-
- static const int cButtonHeight = 30;
- static const int cButtonWidth = 60;
-
- static const int cBoxHeight = 20;
- static const int cBoxWidth = 100;
-
- OwnedArray<Slider> sliders;
- OwnedArray<Label> sliderLabels;
- OwnedArray<TextButton> buttons;
- OwnedArray<TextEditor> textFields;
- OwnedArray<ComboBox> comboBoxes;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIComponent)
-};
-
-
-#endif // UICOMPONENT_H_INCLUDED
--- a/LEAF_JUCEPlugin/Source/Yin.cpp
+++ /dev/null
@@ -1,233 +1,0 @@
-/*
- ==============================================================================
-
- Yin.c
- Created: 17 Jan 2017 1:20:23pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#include "Yin.h"
-
-#include <stdint.h> /* For standard interger types (int16_t) */
-#include <stdlib.h> /* For call to malloc */
-
-/* ------------------------------------------------------------------------------------------
---------------------------------------------------------------------------- PRIVATE FUNCTIONS
--------------------------------------------------------------------------------------------*/
-
-/**
- * Step 1: Calculates the squared difference of the signal with a shifted version of itself.
- * @param buffer Buffer of samples to process.
- *
- * This is the Yin algorithms tweak on autocorellation. Read http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf
- * for more details on what is in here and why it's done this way.
- */
-void Yin_difference(Yin *yin, int16_t* buffer){
- int16_t i;
- int16_t tau;
- float delta;
-
- /* Calculate the difference for difference shift values (tau) for the half of the samples */
- for(tau = 0 ; tau < yin->halfBufferSize; tau++){
-
- /* Take the difference of the signal with a shifted version of itself, then square it.
- * (This is the Yin algorithm's tweak on autocorellation) */
- for(i = 0; i < yin->halfBufferSize; i++){
- delta = buffer[i] - buffer[i + tau];
- yin->yinBuffer[tau] += delta * delta;
- }
- }
-}
-
-
-/**
- * Step 2: Calculate the cumulative mean on the normalised difference calculated in step 1
- * @param yin #Yin structure with information about the signal
- *
- * This goes through the Yin autocorellation values and finds out roughly where shift is which
- * produced the smallest difference
- */
-void Yin_cumulativeMeanNormalizedDifference(Yin *yin){
- int16_t tau;
- float runningSum = 0;
- yin->yinBuffer[0] = 1;
-
- /* Sum all the values in the autocorellation buffer and nomalise the result, replacing
- * the value in the autocorellation buffer with a cumulative mean of the normalised difference */
- for (tau = 1; tau < yin->halfBufferSize; tau++) {
- runningSum += yin->yinBuffer[tau];
- yin->yinBuffer[tau] *= tau / runningSum;
- }
-}
-
-/**
- * Step 3: Search through the normalised cumulative mean array and find values that are over the threshold
- * @return Shift (tau) which caused the best approximate autocorellation. -1 if no suitable value is found over the threshold.
- */
-int16_t Yin_absoluteThreshold(Yin *yin){
- int16_t tau;
-
- /* Search through the array of cumulative mean values, and look for ones that are over the threshold
- * The first two positions in yinBuffer are always so start at the third (index 2) */
- for (tau = 2; tau < yin->halfBufferSize ; tau++) {
- if (yin->yinBuffer[tau] < yin->threshold) {
- while (tau + 1 < yin->halfBufferSize && yin->yinBuffer[tau + 1] < yin->yinBuffer[tau]) {
- tau++;
- }
- /* found tau, exit loop and return
- * store the probability
- * From the YIN paper: The yin->threshold determines the list of
- * candidates admitted to the set, and can be interpreted as the
- * proportion of aperiodic power tolerated
- * within a periodic signal.
- *
- * Since we want the periodicity and and not aperiodicity:
- * periodicity = 1 - aperiodicity */
- yin->probability = 1 - yin->yinBuffer[tau];
- break;
- }
- }
-
- /* if no pitch found, tau => -1 */
- if (tau == yin->halfBufferSize || yin->yinBuffer[tau] >= yin->threshold) {
- tau = -1;
- yin->probability = 0;
- }
-
- return tau;
-}
-
-/**
- * Step 5: Interpolate the shift value (tau) to improve the pitch estimate.
- * @param yin [description]
- * @param tauEstimate [description]
- * @return [description]
- *
- * The 'best' shift value for autocorellation is most likely not an interger shift of the signal.
- * As we only autocorellated using integer shifts we should check that there isn't a better fractional
- * shift value.
- */
-float Yin_parabolicInterpolation(Yin *yin, int16_t tauEstimate) {
- float betterTau;
- int16_t x0;
- int16_t x2;
-
- /* Calculate the first polynomial coeffcient based on the current estimate of tau */
- if (tauEstimate < 1) {
- x0 = tauEstimate;
- }
- else {
- x0 = tauEstimate - 1;
- }
-
- /* Calculate the second polynomial coeffcient based on the current estimate of tau */
- if (tauEstimate + 1 < yin->halfBufferSize) {
- x2 = tauEstimate + 1;
- }
- else {
- x2 = tauEstimate;
- }
-
- /* Algorithm to parabolically interpolate the shift value tau to find a better estimate */
- if (x0 == tauEstimate) {
- if (yin->yinBuffer[tauEstimate] <= yin->yinBuffer[x2]) {
- betterTau = tauEstimate;
- }
- else {
- betterTau = x2;
- }
- }
- else if (x2 == tauEstimate) {
- if (yin->yinBuffer[tauEstimate] <= yin->yinBuffer[x0]) {
- betterTau = tauEstimate;
- }
- else {
- betterTau = x0;
- }
- }
- else {
- float s0, s1, s2;
- s0 = yin->yinBuffer[x0];
- s1 = yin->yinBuffer[tauEstimate];
- s2 = yin->yinBuffer[x2];
- // fixed AUBIO implementation, thanks to Karl Helgason:
- // (2.0f * s1 - s2 - s0) was incorrectly multiplied with -1
- betterTau = tauEstimate + (s2 - s0) / (2 * (2 * s1 - s2 - s0));
- }
-
-
- return betterTau;
-}
-
-
-
-
-
-/* ------------------------------------------------------------------------------------------
----------------------------------------------------------------------------- PUBLIC FUNCTIONS
--------------------------------------------------------------------------------------------*/
-
-
-
-/**
- * Initialise the Yin pitch detection object
- * @param yin Yin pitch detection object to initialise
- * @param bufferSize Length of the audio buffer to analyse
- * @param threshold Allowed uncertainty (e.g 0.05 will return a pitch with ~95% probability)
- */
-void Yin_init(Yin *yin, int16_t bufferSize, float threshold){
- /* Initialise the fields of the Yin structure passed in */
- yin->bufferSize = bufferSize;
- yin->halfBufferSize = bufferSize / 2;
- yin->probability = 0.0;
- yin->threshold = threshold;
-
- /* Allocate the autocorellation buffer and initialise it to zero */
- yin->yinBuffer = (float *) malloc(sizeof(float)* yin->halfBufferSize);
-
- int16_t i;
- for(i = 0; i < yin->halfBufferSize; i++){
- yin->yinBuffer[i] = 0;
- }
-}
-
-/**
- * Runs the Yin pitch detection algortihm
- * @param yin Initialised Yin object
- * @param buffer Buffer of samples to analyse
- * @return Fundamental frequency of the signal in Hz. Returns -1 if pitch can't be found
- */
-float Yin_getPitch(Yin *yin, int16_t* buffer){
- int16_t tauEstimate = -1;
- float pitchInHertz = -1;
-
- /* Step 1: Calculates the squared difference of the signal with a shifted version of itself. */
- Yin_difference(yin, buffer);
-
- /* Step 2: Calculate the cumulative mean on the normalised difference calculated in step 1 */
- Yin_cumulativeMeanNormalizedDifference(yin);
-
- /* Step 3: Search through the normalised cumulative mean array and find values that are over the threshold */
- tauEstimate = Yin_absoluteThreshold(yin);
-
- /* Step 5: Interpolate the shift value (tau) to improve the pitch estimate. */
- if(tauEstimate != -1){
- pitchInHertz = YIN_SAMPLING_RATE / Yin_parabolicInterpolation(yin, tauEstimate);
- }
-
- return pitchInHertz;
-}
-
-/**
- * Certainty of the pitch found
- * @param yin Yin object that has been run over a buffer
- * @return Returns the certainty of the note found as a decimal (i.e 0.3 is 30%)
- */
-float Yin_getProbability(Yin *yin){
- return yin->probability;
-}
-
-
-
--- a/LEAF_JUCEPlugin/Source/Yin.h
+++ /dev/null
@@ -1,56 +1,0 @@
-/*
- ==============================================================================
-
- Yin.h
- Created: 17 Jan 2017 1:20:23pm
- Author: Michael R Mulshine
-
- ==============================================================================
-*/
-
-#ifndef YIN_H_INCLUDED
-#define YIN_H_INCLUDED
-
-#include <stdint.h>
-
-#define YIN_SAMPLING_RATE 44100
-#define YIN_DEFAULT_THRESHOLD 0.15
-
-/**
- * @struct Yin
- * @breif Object to encapsulate the parameters for the Yin pitch detection algorithm
- */
-typedef struct _Yin {
- int16_t bufferSize; /**< Size of the audio buffer to be analysed */
- int16_t halfBufferSize; /**< Half the buffer length */
- float* yinBuffer; /**< Buffer that stores the results of the intermediate processing steps of the algorithm */
- float probability; /**< Probability that the pitch found is correct as a decimal (i.e 0.85 is 85%) */
- float threshold; /**< Allowed uncertainty in the result as a decimal (i.e 0.15 is 15%) */
-} Yin;
-
-/**
- * Initialise the Yin pitch detection object
- * @param yin Yin pitch detection object to initialise
- * @param bufferSize Length of the audio buffer to analyse
- * @param threshold Allowed uncertainty (e.g 0.05 will return a pitch with ~95% probability)
- */
-void Yin_init(Yin *yin, int16_t bufferSize, float threshold);
-
-/**
- * Runs the Yin pitch detection algortihm
- * @param yin Initialised Yin object
- * @param buffer Buffer of samples to analyse
- * @return Fundamental frequency of the signal in Hz. Returns -1 if pitch can't be found
- */
-float Yin_getPitch(Yin *yin, int16_t* buffer);
-
-/**
- * Certainty of the pitch found
- * @param yin Yin object that has been run over a buffer
- * @return Returns the certainty of the note found as a decimal (i.e 0.3 is 30%)
- */
-float Yin_getProbability(Yin *yin);
-
-
-
-#endif // YIN_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/LEAF.jucer
@@ -1,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<JUCERPROJECT id="ArQetv" name="LEAF" projectType="audioplug" version="1.0.0"
+ bundleIdentifier="com.pumusic.LEAF" includeBinaryInAppConfig="1"
+ buildVST="0" buildVST3="0" buildAU="1" buildAUv3="0" buildRTAS="0"
+ buildAAX="0" pluginName="LEAF" pluginDesc="LEAF" pluginManufacturer="pumusic"
+ pluginManufacturerCode="Manu" pluginCode="Arqe" pluginChannelConfigs="{2,2}"
+ pluginIsSynth="0" pluginWantsMidiIn="1" pluginProducesMidiOut="0"
+ pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="LEAFAU"
+ pluginRTASCategory="" aaxIdentifier="com.pumusic.LEAF" pluginAAXCategory="2"
+ jucerVersion="5.4.7" companyName="Princeton University" companyEmail="mrmulshine@gmail.com"
+ displaySplashScreen="1" reportAppUsage="1" splashScreenColour="Dark"
+ buildStandalone="1" enableIAA="0" cppLanguageStandard="11" companyCopyright="Princeton University"
+ pluginFormats="buildAU,buildStandalone" pluginCharacteristicsValue="pluginWantsMidiIn">
+ <MAINGROUP id="F7Bywq" name="LEAF">
+ <GROUP id="{F7096CF4-1A84-4CC8-A236-06FAE894451E}" name="Examples">
+ <FILE id="hMMOsl" name="basic-oscillators.c" compile="0" resource="0"
+ file="../Examples/basic-oscillators.c"/>
+ <FILE id="mVSe2h" name="basic-oscillators.h" compile="0" resource="0"
+ file="../Examples/basic-oscillators.h"/>
+ </GROUP>
+ <GROUP id="{14C5E2CD-5D51-3FD3-5677-28BECA29E95E}" name="Source">
+ <GROUP id="{FFA9F0EC-F45A-74FC-5A10-9B3CAA731E7C}" name="External">
+ <FILE id="ixwZea" name="Yin.h" compile="0" resource="0" file="Source/Yin.h"/>
+ <FILE id="wbnjmF" name="Yin.cpp" compile="1" resource="0" file="Source/Yin.cpp"/>
+ </GROUP>
+ <GROUP id="{5EAA8994-9CCF-AFE1-27F3-6B2132200B97}" name="Test">
+ <FILE id="XkflAI" name="LEAFLink.h" compile="0" resource="0" file="Source/LEAFLink.h"/>
+ <FILE id="O9woHe" name="LEAFLink.cpp" compile="1" resource="0" file="Source/LEAFLink.cpp"/>
+ <FILE id="xGEfAX" name="LEAFTest.h" compile="0" resource="0" file="Source/LEAFTest.h"/>
+ <FILE id="xRGWtb" name="MyTest.h" compile="0" resource="0" file="Source/MyTest.h"/>
+ <FILE id="PGmAOc" name="MyTest.cpp" compile="1" resource="0" file="Source/MyTest.cpp"/>
+ </GROUP>
+ <GROUP id="{A89F40A7-55BD-BADE-F6FC-0813ECB90B8B}" name="Wrapper">
+ <FILE id="R9R9N2" name="Globals.h" compile="0" resource="0" file="Source/Globals.h"/>
+ <FILE id="oQ7Hdj" name="UIComponent.h" compile="0" resource="0" file="Source/UIComponent.h"/>
+ <FILE id="ONd1SP" name="UIComponent.cpp" compile="1" resource="0" file="Source/UIComponent.cpp"/>
+ <FILE id="EnmsIi" name="PluginProcessor.h" compile="0" resource="0"
+ file="Source/PluginProcessor.h"/>
+ <FILE id="xwxe1U" name="PluginProcessor.cpp" compile="1" resource="0"
+ file="Source/PluginProcessor.cpp"/>
+ <FILE id="L2MQTe" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
+ <FILE id="euDngN" name="PluginEditor.cpp" compile="1" resource="0"
+ file="Source/PluginEditor.cpp"/>
+ </GROUP>
+ </GROUP>
+ </MAINGROUP>
+ <EXPORTFORMATS>
+ <XCODE_MAC targetFolder="Builds/MacOSX">
+ <CONFIGURATIONS>
+ <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>
+ <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"
+ enablePluginBinaryCopyStep="1"/>
+ </CONFIGURATIONS>
+ <MODULEPATHS>
+ <MODULEPATH id="juce_core" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_events" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_graphics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_data_structures" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_gui_basics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_gui_extra" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_cryptography" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_video" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_opengl" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_basics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_devices" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_formats" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_processors" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_plugin_client" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_utils" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="leaf" path="../../LEAF"/>
+ </MODULEPATHS>
+ </XCODE_MAC>
+ <XCODE_IPHONE targetFolder="Builds/iOS" iosScreenOrientation="portraitlandscape"
+ iosDevelopmentTeamID="QY96HSP2FJ" microphonePermissionNeeded="1"
+ iosBackgroundAudio="1" iPadScreenOrientation="portraitlandscape"
+ iosDeviceFamily="1,2">
+ <CONFIGURATIONS>
+ <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>
+ <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"
+ enablePluginBinaryCopyStep="1"/>
+ </CONFIGURATIONS>
+ <MODULEPATHS>
+ <MODULEPATH id="juce_core" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_events" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_graphics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_data_structures" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_gui_basics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_gui_extra" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_cryptography" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_video" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_opengl" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_basics" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_devices" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_formats" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_processors" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_plugin_client" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="juce_audio_utils" path="../../../../JUCE/modules"/>
+ <MODULEPATH id="leaf" path="../../LEAF"/>
+ </MODULEPATHS>
+ </XCODE_IPHONE>
+ <VS2017 targetFolder="Builds/VisualStudio2017">
+ <CONFIGURATIONS>
+ <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
+ isDebug="1" optimisation="1" targetName="OOPS" debugInformationFormat="ProgramDatabase"
+ enablePluginBinaryCopyStep="0"/>
+ <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
+ isDebug="0" optimisation="3" targetName="OOPS" debugInformationFormat="ProgramDatabase"
+ enablePluginBinaryCopyStep="0" linkTimeOptimisation="1"/>
+ </CONFIGURATIONS>
+ <MODULEPATHS>
+ <MODULEPATH id="juce_video" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_opengl" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_gui_extra" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_gui_basics" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_graphics" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_events" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_data_structures" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_cryptography" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_core" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_utils" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_processors" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_plugin_client" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_formats" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_devices" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="juce_audio_basics" path="..\..\..\JUCE\modules"/>
+ <MODULEPATH id="leaf" path="../../LEAF"/>
+ </MODULEPATHS>
+ </VS2017>
+ </EXPORTFORMATS>
+ <MODULES>
+ <MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"
+ useGlobalPath="1"/>
+ <MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="juce_video" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
+ <MODULE id="leaf" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/>
+ </MODULES>
+ <JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
+ <LIVE_SETTINGS>
+ <OSX/>
+ </LIVE_SETTINGS>
+</JUCERPROJECT>
--- /dev/null
+++ b/TestPlugin/Source/Globals.h
@@ -1,0 +1,44 @@
+/*
+ ==============================================================================
+
+ Globals.h
+ Created: 17 Jan 2017 12:16:12pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef GLOBALS_H_INCLUDED
+#define GLOBALS_H_INCLUDED
+
+#include "../JuceLibraryCode/JuceHeader.h"
+
+#define TEST 1
+
+
+String floatArrayToString(Array<float> arr)
+{
+ String s = "";
+ for (auto key : arr)
+ {
+ s.append(String(key), 6);
+ s.append(" ", 1);
+ }
+ return s;
+}
+
+String intArrayToString(Array<int> arr)
+{
+ String s = "";
+ for (auto key : arr)
+ {
+ s.append(String(key), 6);
+ s.append(" ", 1);
+ }
+ return s;
+}
+
+
+
+
+#endif // GLOBALS_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/LEAFLink.cpp
@@ -1,0 +1,144 @@
+/*
+ ==============================================================================
+
+ LEAFLink.c
+ Created: 18 Jan 2017 11:25:00am
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#include "LEAFLink.h"
+
+#define MYTEST 0
+#define FM 1
+
+std::vector<juce::String> cButtonNames = std::vector<juce::String>
+{
+
+};
+
+std::vector<juce::String> cSliderNames = std::vector<juce::String>
+{
+ "on/off",
+ "mod freq",
+ "mod depth"
+};
+
+std::vector<juce::String> cComboBoxNames = std::vector<juce::String>
+{
+
+};
+
+std::vector<juce::String> cWaveformTypes = std::vector<juce::String>
+{
+
+};
+
+std::vector<float> cSliderModelValues(cSliderNames.size());
+std::vector<float> cSliderValues(cSliderNames.size());
+std::vector<bool> cButtonStates(cButtonNames.size());
+std::vector<int> cComboBoxStates(cComboBoxNames.size());
+
+void setSliderModelValue(String name, float val)
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+ if (name == cSliderNames[i])
+ {
+ cSliderModelValues[i] = val;
+ break;
+ }
+ }
+}
+
+void printSliderValues(void)
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+ DBG(String(cSliderNames[i]) + ": " + String(cSliderValues[i]));
+ }
+}
+
+bool getButtonState(String name)
+{
+ for (int i = 0; i < cButtonNames.size(); i++)
+ {
+ if (name == cButtonNames[i])
+ {
+ return cButtonStates[i];
+ }
+ }
+
+ return false;
+}
+
+void setButtonState(String name, bool on)
+{
+ for (int i = 0; i < cButtonNames.size(); i++)
+ {
+ if (name == cButtonNames[i])
+ {
+ cButtonStates[i] = on;
+ break;
+ }
+ }
+}
+
+int getComboBoxState(String name)
+{
+ for (int i = 0; i < cComboBoxNames.size(); i++)
+ {
+ if (name == cComboBoxNames[i])
+ {
+ return cComboBoxStates[i];
+ }
+ }
+ return -1;
+}
+
+void setComboBoxState(String name, int idx)
+{
+ DBG("set state: " + name + " " + String(idx));
+ for (int i = 0; i < cComboBoxNames.size(); i++)
+ {
+ if (name == cComboBoxNames[i])
+ {
+ cComboBoxStates[i] = idx;
+ break;
+ }
+ }
+}
+
+void setSliderValue(String name, float val)
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+ if (name == cSliderNames[i])
+ {
+ cSliderValues[i] = val;
+ break;
+ }
+ }
+}
+
+float getSliderValue(String name)
+{
+ float value = 0.0f;
+
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+ if (name == cSliderNames[i])
+ {
+ value = cSliderValues[i];
+ break;
+ }
+ }
+
+ return value;
+}
+
+float getRandomFloat(void)
+{
+ return ((float)rand()/RAND_MAX);
+}
--- /dev/null
+++ b/TestPlugin/Source/LEAFLink.h
@@ -1,0 +1,52 @@
+/*
+ ==============================================================================
+
+ Utilities.h
+ Created: 5 Dec 2016 2:37:03pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef UTILITIES_H_INCLUDED
+#define UTILITIES_H_INCLUDED
+
+#include "../JuceLibraryCode/JuceHeader.h"
+
+#include "stdlib.h"
+
+typedef enum WaveformType {
+ Sine=0,
+ Triangle,
+ Sawtooth,
+ Square,
+ WaveformTypeNil
+}WaveformType;
+
+extern std::vector<juce::String> cSliderNames;
+
+extern std::vector<juce::String> cButtonNames;
+
+extern std::vector<juce::String> cComboBoxNames;
+
+extern std::vector<juce::String> cWaveformTypes;
+
+extern std::vector<float> cSliderValues;
+
+extern std::vector<float> cSliderModelValues;
+
+extern std::vector<bool> cButtonStates;
+
+extern std::vector<int> cComboBoxStates;
+
+void printSliderValues(void);
+bool getButtonState(String name);
+void setButtonState(String name, bool on);
+int getComboBoxState(String name);
+void setComboBoxState(String name, int idx);
+void setSliderModelValue(String name, float val);
+void setSliderValue(String name, float val);
+float getSliderValue(String name);
+float getRandomFloat(void);
+
+#endif // UTILITIES_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/LEAFTest.h
@@ -1,0 +1,29 @@
+/*
+ ==============================================================================
+
+ OOPSTest.h
+ Created: 4 Dec 2016 9:14:16pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef LEAFTEST1_H_INCLUDED
+#define LEAFTEST1_H_INCLUDED
+
+#include "LEAFLink.h"
+
+#include "../../leaf/leaf.h"
+
+#include "Yin.h"
+
+// LEAFTest API
+float LEAFTest_tick (float input);
+void LEAFTest_init (float sampleRate, int blocksize);
+void LEAFTest_end (void);
+void LEAFTest_block (void);
+
+void LEAFTest_noteOn (int midiNoteNumber, float velocity);
+void LEAFTest_noteOff (int midiNoteNumber);
+
+#endif // LEAFTEST1_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/MyTest.cpp
@@ -1,0 +1,222 @@
+/*
+ ==============================================================================
+ FM.c
+ Created: 23 Jan 2017 9:39:38am
+ Author: Michael R Mulshine
+ ==============================================================================
+ */
+
+#include "LEAFTest.h"
+#include "MyTest.h"
+
+
+static void leaf_pool_report(void);
+static void leaf_pool_dump(void);
+static void run_pool_test(void);
+
+tNoise noise;
+tSVF bp1;
+tSVF bp2;
+tFormantShifter fs;
+
+tSampler samp;
+tBuffer buff;
+tEnvelope env;
+
+tAutotune at;
+
+
+tMinBLEP minblep;
+
+tPhasor phasor;
+
+tHighpass hipass;
+
+tMBSaw saw;
+tMBPulse pulse;
+tMBTriangle tri;
+
+float gain;
+float freq;
+float dtime;
+bool buttonState;
+int ratio = 2;
+float x = 0.0f;
+float y = 0.0f;
+float a, b, c, d;
+
+#define MSIZE 500000
+char memory[MSIZE];
+
+void LEAFTest_init (float sampleRate, int blockSize)
+{
+ LEAF_init(sampleRate, blockSize, memory, MSIZE, &getRandomFloat);
+
+ tMBSaw_init(&saw);
+
+ tMBPulse_init(&pulse);
+
+ tMBTriangle_init(&tri);
+
+ tPhasor_init(&phasor);
+
+ tPhasor_setFreq(&phasor, 200);
+}
+
+inline double getSawFall(double angle) {
+
+ angle = fmod(angle + double_Pi, 2*double_Pi); // shift x
+ double sample = angle/double_Pi - double(1); // computer as remainder
+
+ return sample;
+
+}
+
+float LEAFTest_tick (float input)
+{
+
+ tMBSaw_setFreq(&saw, y);
+ tMBPulse_setWidth(&pulse, x);
+ tMBPulse_setFreq(&pulse, y);
+ tMBTriangle_setSkew(&tri, 0.0);//x*2.0f - 1.0f);
+ tMBTriangle_setFreq(&tri, y);
+
+ tPhasor_tick(&phasor);
+
+// if (phasor->phaseDidReset) tMBSaw_sync(&saw, 0.0f);
+// if (phasor->phaseDidReset) tMBPulse_sync(&pulse, 0.0f);
+ if (phasor->phaseDidReset) tMBTriangle_sync(&tri, 0.0f);
+
+// return tMBSaw_tick(&saw);
+// return tMBPulse_tick(&pulse);
+ return tMBTriangle_tick(&tri);
+}
+
+int firstFrame = 1;
+bool lastState = false, lastPlayState = false;
+void LEAFTest_block (void)
+{
+ // if (firstFrame == 1)
+ // {
+ // tBuffer_record(&buff); // starts recording
+ // tSampler_play(&samp); // start spitting samples out
+ // firstFrame = 0;
+ // }
+
+ float val = getSliderValue("mod freq");
+
+ x = val ;
+
+ // a = val * tBuffer_getBufferLength(&buff);
+
+ DBG("start: " + String(a));
+
+ val = getSliderValue("mod depth");
+
+ y = val * 5000.0f + 20.0f;
+
+ DBG(String(y));
+ // b = val * tBuffer_getBufferLength(&buff);
+
+ DBG("rate: " + String(b));
+ //
+ // tSampler_setStart(&samp, a);
+ // tSampler_setEnd(&samp, b);
+ // tSampler_setRate(&samp, b);
+
+ // tFormantShifter_setShiftFactor(&fs, x);
+ // tFormantShifter_setIntensity(&fs, y);
+
+}
+
+void LEAFTest_controllerInput (int cnum, float cval)
+{
+
+}
+
+void LEAFTest_pitchBendInput (int pitchBend)
+{
+
+}
+
+int lastNote;
+void LEAFTest_noteOn (int note, float velocity)
+{
+}
+
+
+void LEAFTest_noteOff (int note)
+{
+}
+
+
+
+void LEAFTest_end (void)
+{
+
+}
+
+// LEAF POOL UTILITIES
+
+void leaf_pool_report(void)
+{
+ DBG(String(leaf_pool_get_used()) + " of " + String(leaf_pool_get_size()));
+}
+
+void leaf_pool_dump(void)
+{
+ float* buff = (float*)leaf_pool_get_pool();
+ unsigned long siz = leaf_pool_get_size();
+ siz /= sizeof(float);
+ for (int i = 0; i < siz; i++)
+ {
+ DBG(String(buff[i]));
+ }
+}
+
+static void run_pool_test(void)
+{
+ leaf_pool_report();
+
+ DBG("ALLOC BUFFER 1");
+ int size = 50;
+ float* buffer;
+ buffer = (float*) leaf_alloc(sizeof(float) * size);
+
+ for (int i = 0; i < size; i++)
+ {
+ buffer[i] = (float)i;
+
+ }
+
+ leaf_pool_report();
+
+ DBG("ALLOC BUFFER 2");
+ size = 25;
+
+ buffer = (float*) leaf_alloc(sizeof(float) * size);
+
+ leaf_pool_report();
+
+ for (int i = 0; i < size; i++)
+ {
+ buffer[i] = (float)(i*2);
+ }
+ leaf_free((char*)buffer);
+
+ leaf_pool_report();
+
+ DBG("ALLOC BUFFER 3");
+ size = 15;
+
+ buffer = (float*) leaf_alloc(sizeof(float) * size);
+
+ for (int i = 0; i < size; i++)
+ {
+ buffer[i] = (float)(i*3);
+ }
+
+ leaf_pool_report();
+
+ leaf_pool_dump();
+}
--- /dev/null
+++ b/TestPlugin/Source/MyTest.h
@@ -1,0 +1,16 @@
+/*
+ ==============================================================================
+
+ MyTest.h
+ Created: 23 Jan 2017 9:39:38am
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef FM_H_INCLUDED
+#define FM_H_INCLUDED
+
+
+
+#endif // FM_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/PluginEditor.cpp
@@ -1,0 +1,13 @@
+/*
+ ==============================================================================
+
+ This file was auto-generated!
+
+ It contains the basic framework code for a JUCE plugin editor.
+
+ ==============================================================================
+*/
+
+//#include "PluginEditor.h"
+
+
--- /dev/null
+++ b/TestPlugin/Source/PluginEditor.h
@@ -1,0 +1,42 @@
+/*
+ ==============================================================================
+
+ This file was auto-generated!
+
+ It contains the basic framework code for a JUCE plugin editor.
+
+ ==============================================================================
+*/
+
+#ifndef PLUGINEDITOR_H_INCLUDED
+#define PLUGINEDITOR_H_INCLUDED
+
+#include "PluginProcessor.h"
+
+#include "UIComponent.h"
+
+//==============================================================================
+/**
+*/
+class OopsAudioProcessorEditor : public AudioProcessorEditor
+{
+public:
+ OopsAudioProcessorEditor (OopsAudioProcessor&);
+ ~OopsAudioProcessorEditor();
+
+ //==============================================================================
+ void paint (Graphics&) override;
+ void resized() override;
+
+private:
+ // This reference is provided as a quick way for your editor to
+ // access the processor object that created it.
+
+ UIComponent uicomponent;
+ OopsAudioProcessor& processor;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OopsAudioProcessorEditor)
+};
+
+
+#endif // PLUGINEDITOR_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/PluginProcessor.cpp
@@ -1,0 +1,237 @@
+/*
+ ==============================================================================
+
+ This file was auto-generated!
+
+ It contains the basic framework code for a JUCE plugin processor.
+
+ ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+#include "UIComponent.h"
+
+#include "LEAFTest.h"
+
+//==============================================================================
+OopsAudioProcessorEditor::OopsAudioProcessorEditor (OopsAudioProcessor& p)
+: AudioProcessorEditor (&p), processor (p)
+{
+ // Make sure that before the constructor has finished, you've set the
+ // editor's size to whatever you need it to be.
+ setSize (600, 400);
+
+ addAndMakeVisible(uicomponent);
+}
+
+OopsAudioProcessorEditor::~OopsAudioProcessorEditor()
+{
+}
+
+//==============================================================================
+void OopsAudioProcessorEditor::paint (Graphics& g)
+{
+ g.fillAll (Colours::white);
+}
+
+void OopsAudioProcessorEditor::resized()
+{
+ uicomponent.setBounds(getBounds());
+}
+//==============================================================================
+void OopsAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
+{
+ gain = 0.0f;
+ timer = 0;
+ start = false;
+ ramp = false;
+
+ LEAFTest_init(sampleRate, samplesPerBlock);
+}
+
+
+
+//====================================BLOCK=======================================
+
+void OopsAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
+{
+ const int totalNumInputChannels = getTotalNumInputChannels();
+ const int totalNumOutputChannels = getTotalNumOutputChannels();
+
+ for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
+ buffer.clear (i, 0, buffer.getNumSamples());
+
+ LEAFTest_block();
+
+ MidiMessage m;
+ int time;
+
+ for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
+ {
+ int noteNumber = m.getNoteNumber();
+ float velocity = m.getFloatVelocity();
+
+ if (m.isNoteOn())
+ {
+ LEAFTest_noteOn(noteNumber, velocity);
+ }
+ else if (m.isNoteOff())
+ {
+ LEAFTest_noteOff(noteNumber);
+ }
+ else
+ {
+
+ }
+ }
+
+
+ const float* inPointerL = buffer.getReadPointer (0);
+ const float* inPointerR = buffer.getReadPointer (1);
+
+ float* outPointerL = buffer.getWritePointer( 0);
+ float* outPointerR = buffer.getWritePointer( 1);
+
+ for (int samp = 0; samp < buffer.getNumSamples(); ++samp)
+ {
+ outPointerL[samp] = LEAFTest_tick( (inPointerL[samp] +inPointerR[samp]) * 0.5f);
+ outPointerR[samp] = outPointerL[samp];
+ }
+}
+
+//==============================================================================
+
+OopsAudioProcessor::OopsAudioProcessor()
+#ifndef JucePlugin_PreferredChannelConfigurations
+: AudioProcessor (BusesProperties()
+ #if ! JucePlugin_IsMidiEffect
+ #if ! JucePlugin_IsSynth
+ .withInput ("Input", AudioChannelSet::stereo(), true)
+ #endif
+ .withOutput ("Output", AudioChannelSet::stereo(), true)
+ #endif
+ )
+#endif
+{
+
+}
+
+OopsAudioProcessor::~OopsAudioProcessor()
+{
+
+}
+
+//==============================================================================
+const String OopsAudioProcessor::getName() const
+{
+ return JucePlugin_Name;
+}
+
+bool OopsAudioProcessor::acceptsMidi() const
+{
+ return true;
+}
+
+bool OopsAudioProcessor::producesMidi() const
+{
+ #if JucePlugin_ProducesMidiOutput
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+double OopsAudioProcessor::getTailLengthSeconds() const
+{
+ return 0.0;
+}
+
+int OopsAudioProcessor::getNumPrograms()
+{
+ return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
+ // so this should be at least 1, even if you're not really implementing programs.
+}
+
+int OopsAudioProcessor::getCurrentProgram()
+{
+ return 0;
+}
+
+void OopsAudioProcessor::setCurrentProgram (int index)
+{
+}
+
+const String OopsAudioProcessor::getProgramName (int index)
+{
+ return String();
+}
+
+void OopsAudioProcessor::changeProgramName (int index, const String& newName)
+{
+}
+
+void OopsAudioProcessor::releaseResources()
+{
+ // When playback stops, you can use this as an opportunity to free up any
+ // spare memory, etc.
+ LEAFTest_end();
+}
+
+#ifndef JucePlugin_PreferredChannelConfigurations
+bool OopsAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
+{
+ #if JucePlugin_IsMidiEffect
+ ignoreUnused (layouts);
+ return true;
+ #else
+ // This is the place where you check if the layout is supported.
+ // In this template code we only support mono or stereo.
+ if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
+ && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
+ return false;
+
+ // This checks if the input layout matches the output layout
+ #if ! JucePlugin_IsSynth
+ if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
+ return false;
+ #endif
+
+ return true;
+ #endif
+}
+#endif
+
+
+//==============================================================================
+bool OopsAudioProcessor::hasEditor() const
+{
+ return true; // (change this to false if you choose to not supply an editor)
+}
+
+AudioProcessorEditor* OopsAudioProcessor::createEditor()
+{
+ return new OopsAudioProcessorEditor (*this);
+}
+
+//==============================================================================
+void OopsAudioProcessor::getStateInformation (MemoryBlock& destData)
+{
+ // You should use this method to store your parameters in the memory block.
+ // You could do that either as raw data, or use the XML or ValueTree classes
+ // as intermediaries to make it easy to save and load complex data.
+}
+
+void OopsAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
+{
+ // You should use this method to restore your parameters from this memory block,
+ // whose contents will have been created by the getStateInformation() call.
+}
+
+//==============================================================================
+// This creates new instances of the plugin..
+AudioProcessor* JUCE_CALLTYPE createPluginFilter()
+{
+ return new OopsAudioProcessor();
+}
--- /dev/null
+++ b/TestPlugin/Source/PluginProcessor.h
@@ -1,0 +1,68 @@
+/*
+ ==============================================================================
+
+ This file was auto-generated!
+
+ It contains the basic framework code for a JUCE plugin processor.
+
+ ==============================================================================
+*/
+
+#ifndef PLUGINPROCESSOR_H_INCLUDED
+#define PLUGINPROCESSOR_H_INCLUDED
+
+#include "../JuceLibraryCode/JuceHeader.h"
+
+
+//==============================================================================
+/**
+*/
+class OopsAudioProcessor : public AudioProcessor
+{
+public:
+ //==============================================================================
+ OopsAudioProcessor();
+ ~OopsAudioProcessor();
+
+ //==============================================================================
+ void prepareToPlay (double sampleRate, int samplesPerBlock) override;
+ void releaseResources() override;
+
+ #ifndef JucePlugin_PreferredChannelConfigurations
+ bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
+ #endif
+
+ void processBlock (AudioSampleBuffer&, MidiBuffer&) override;
+
+ //==============================================================================
+ AudioProcessorEditor* createEditor() override;
+ bool hasEditor() const override;
+
+ //==============================================================================
+ const String getName() const override;
+
+ bool acceptsMidi() const override;
+ bool producesMidi() const override;
+ double getTailLengthSeconds() const override;
+
+ //==============================================================================
+ int getNumPrograms() override;
+ int getCurrentProgram() override;
+ void setCurrentProgram (int index) override;
+ const String getProgramName (int index) override;
+ void changeProgramName (int index, const String& newName) override;
+
+ //==============================================================================
+ void getStateInformation (MemoryBlock& destData) override;
+ void setStateInformation (const void* data, int sizeInBytes) override;
+
+private:
+ uint64 timer;
+ float gain;
+ bool start,ramp;
+ //==============================================================================
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OopsAudioProcessor)
+};
+
+
+#endif // PLUGINPROCESSOR_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/UIComponent.cpp
@@ -1,0 +1,155 @@
+/*
+ ==============================================================================
+
+ UIComponent.c
+ Created: 18 Jan 2017 11:19:15am
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#include "UIComponent.h"
+
+#include "LEAFLink.h"
+
+UIComponent::UIComponent()
+
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+
+ sliders.set(i, new Slider());
+ sliders[i]->setSliderStyle(Slider::SliderStyle::LinearVertical);
+ sliders[i]->setRange(0.0, 1.0, 1.0/50000.0);
+ sliders[i]->setName(cSliderNames[i]);
+ sliders[i]->setComponentID(String(i));
+ sliders[i]->addListener(this);
+ addAndMakeVisible(sliders[i]);
+
+ sliderLabels.set(i, new Label());
+ sliderLabels[i]->setName(cSliderNames[i]);
+ sliderLabels[i]->setColour(Label::textColourId, Colours::aliceblue);
+ sliderLabels[i]->setText(cSliderNames[i], NotificationType::dontSendNotification);
+ addAndMakeVisible(sliderLabels[i]);
+
+ textFields.set(i, new TextEditor());
+ textFields[i]->addListener(this);
+ textFields[i]->setName(cSliderNames[i]);
+ textFields[i]->setEnabled(false);
+ addAndMakeVisible(textFields[i]);
+ }
+
+ for (int i = 0; i < cButtonNames.size(); i++)
+ {
+ buttons.set(i, new TextButton(cButtonNames[i]));
+ buttons[i]->changeWidthToFitText();
+ buttons[i]->setButtonText(cButtonNames[i]);
+ buttons[i]->addListener(this);
+ addAndMakeVisible(buttons[i]);
+ }
+
+ for (int i = 0; i < cComboBoxNames.size(); i++)
+ {
+ comboBoxes.set(i, new ComboBox());
+ comboBoxes[i]->setName(cComboBoxNames[i]);
+ comboBoxes[i]->addSeparator();
+ comboBoxes[i]->addListener(this);
+ addAndMakeVisible(comboBoxes[i]);
+
+ }
+
+ for (int i = 0; i < cComboBoxNames.size(); i++)
+ {
+ for (int j = 0; j < cWaveformTypes.size(); j++)
+ {
+ comboBoxes[i]->addItem(cWaveformTypes[j], j+1);
+ }
+ comboBoxes[i]->setSelectedItemIndex(0);
+ }
+
+
+ startTimerHz(20);
+}
+
+void UIComponent::timerCallback(void)
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ textFields[i]->setText(String(cSliderModelValues[i]), false);
+}
+
+void UIComponent::textEditorTextChanged (TextEditor& tf)
+{
+
+}
+
+UIComponent::~UIComponent()
+{
+}
+
+void UIComponent::paint (Graphics& g)
+{
+ /* This demo code just fills the component's background and
+ draws some placeholder text to get you started.
+
+ You should replace everything in this method with your own
+ drawing code..
+ */
+
+ g.fillAll (Colours::slategrey); // clear the background
+
+ g.setColour (Colours::aliceblue);
+ g.drawRect (getLocalBounds(), 1); // draw an outline around the component
+}
+
+void UIComponent::resized()
+{
+ for (int i = 0; i < cSliderNames.size(); i++)
+ {
+ sliders[i] ->setBounds(cLeftOffset + ((cSliderWidth + cXSpacing) * i),
+ cTopOffset,
+ cSliderWidth,
+ cSliderHeight);
+
+ textFields[i] ->setBounds(sliders[i]->getX() - (cSliderNames[i].length() * 2.0f),
+ sliders[i]->getBottom() + cYSpacing,
+ 75,
+ 20);
+
+ sliderLabels[i] ->setBounds(sliders[i]->getX() - (cSliderNames[i].length() * 2.0f),
+ textFields[i]->getBottom() + cYSpacing,
+ cLabelWidth,
+ cLabelHeight);
+ }
+
+ for (int i = 0; i < cButtonNames.size(); i++)
+ {
+ buttons[i] ->setBounds(cLeftOffset + ((cButtonWidth + cXSpacing) * i),
+ 500,
+ cButtonWidth,
+ cButtonHeight);
+ }
+
+ for (int i = 0; i < cComboBoxNames.size(); i++)
+ {
+ comboBoxes[i] ->setBounds(
+ cLeftOffset + ((cButtonWidth + cXSpacing) * i),
+ cTopOffset + cSliderHeight + cLabelHeight + cButtonHeight + 3 * cYSpacing,
+ cBoxWidth,
+ cBoxHeight );
+ }
+}
+
+void UIComponent::sliderValueChanged(Slider* s)
+{
+ setSliderValue(s->getName(), s->getValue());
+}
+
+void UIComponent::buttonStateChanged (Button* b)
+{
+ setButtonState(b->getName(), b->getState());
+}
+
+void UIComponent::comboBoxChanged (ComboBox* cb)
+{
+ setComboBoxState(cb->getName(), cb->getSelectedId() - 1);
+}
--- /dev/null
+++ b/TestPlugin/Source/UIComponent.h
@@ -1,0 +1,77 @@
+/*
+ ==============================================================================
+
+ UIComponent.h
+ Created: 5 Dec 2016 2:23:38pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef UICOMPONENT_H_INCLUDED
+#define UICOMPONENT_H_INCLUDED
+
+#include "../JuceLibraryCode/JuceHeader.h"
+
+//==============================================================================
+/*
+*/
+class UIComponent:
+public Component,
+public Slider::Listener,
+public TextButton::Listener,
+public ComboBox::Listener,
+public TextEditor::Listener,
+private Timer
+{
+public:
+ UIComponent();
+
+ ~UIComponent();
+
+ void paint (Graphics& g) override;
+
+ void resized() override;
+
+ void sliderValueChanged(Slider* s) override;
+
+ void buttonClicked(Button*b) override {};
+ void buttonStateChanged(Button* b) override;
+
+ void textEditorTextChanged (TextEditor&) override;
+
+ void comboBoxChanged (ComboBox* cb) override;
+
+ void timerCallback() override;
+
+private:
+
+ static const int cLeftOffset = 30;
+ static const int cTopOffset = 30;
+
+ static const int cXSpacing = 60;
+ static const int cYSpacing = 5;
+
+ static const int cSliderHeight = 200;
+ static const int cSliderWidth = 20;
+
+ static const int cLabelHeight = 20;
+ static const int cLabelWidth = cSliderWidth + cXSpacing;
+
+ static const int cButtonHeight = 30;
+ static const int cButtonWidth = 60;
+
+ static const int cBoxHeight = 20;
+ static const int cBoxWidth = 100;
+
+ OwnedArray<Slider> sliders;
+ OwnedArray<Label> sliderLabels;
+ OwnedArray<TextButton> buttons;
+ OwnedArray<TextEditor> textFields;
+ OwnedArray<ComboBox> comboBoxes;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIComponent)
+};
+
+
+#endif // UICOMPONENT_H_INCLUDED
--- /dev/null
+++ b/TestPlugin/Source/Yin.cpp
@@ -1,0 +1,233 @@
+/*
+ ==============================================================================
+
+ Yin.c
+ Created: 17 Jan 2017 1:20:23pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#include "Yin.h"
+
+#include <stdint.h> /* For standard interger types (int16_t) */
+#include <stdlib.h> /* For call to malloc */
+
+/* ------------------------------------------------------------------------------------------
+--------------------------------------------------------------------------- PRIVATE FUNCTIONS
+-------------------------------------------------------------------------------------------*/
+
+/**
+ * Step 1: Calculates the squared difference of the signal with a shifted version of itself.
+ * @param buffer Buffer of samples to process.
+ *
+ * This is the Yin algorithms tweak on autocorellation. Read http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf
+ * for more details on what is in here and why it's done this way.
+ */
+void Yin_difference(Yin *yin, int16_t* buffer){
+ int16_t i;
+ int16_t tau;
+ float delta;
+
+ /* Calculate the difference for difference shift values (tau) for the half of the samples */
+ for(tau = 0 ; tau < yin->halfBufferSize; tau++){
+
+ /* Take the difference of the signal with a shifted version of itself, then square it.
+ * (This is the Yin algorithm's tweak on autocorellation) */
+ for(i = 0; i < yin->halfBufferSize; i++){
+ delta = buffer[i] - buffer[i + tau];
+ yin->yinBuffer[tau] += delta * delta;
+ }
+ }
+}
+
+
+/**
+ * Step 2: Calculate the cumulative mean on the normalised difference calculated in step 1
+ * @param yin #Yin structure with information about the signal
+ *
+ * This goes through the Yin autocorellation values and finds out roughly where shift is which
+ * produced the smallest difference
+ */
+void Yin_cumulativeMeanNormalizedDifference(Yin *yin){
+ int16_t tau;
+ float runningSum = 0;
+ yin->yinBuffer[0] = 1;
+
+ /* Sum all the values in the autocorellation buffer and nomalise the result, replacing
+ * the value in the autocorellation buffer with a cumulative mean of the normalised difference */
+ for (tau = 1; tau < yin->halfBufferSize; tau++) {
+ runningSum += yin->yinBuffer[tau];
+ yin->yinBuffer[tau] *= tau / runningSum;
+ }
+}
+
+/**
+ * Step 3: Search through the normalised cumulative mean array and find values that are over the threshold
+ * @return Shift (tau) which caused the best approximate autocorellation. -1 if no suitable value is found over the threshold.
+ */
+int16_t Yin_absoluteThreshold(Yin *yin){
+ int16_t tau;
+
+ /* Search through the array of cumulative mean values, and look for ones that are over the threshold
+ * The first two positions in yinBuffer are always so start at the third (index 2) */
+ for (tau = 2; tau < yin->halfBufferSize ; tau++) {
+ if (yin->yinBuffer[tau] < yin->threshold) {
+ while (tau + 1 < yin->halfBufferSize && yin->yinBuffer[tau + 1] < yin->yinBuffer[tau]) {
+ tau++;
+ }
+ /* found tau, exit loop and return
+ * store the probability
+ * From the YIN paper: The yin->threshold determines the list of
+ * candidates admitted to the set, and can be interpreted as the
+ * proportion of aperiodic power tolerated
+ * within a periodic signal.
+ *
+ * Since we want the periodicity and and not aperiodicity:
+ * periodicity = 1 - aperiodicity */
+ yin->probability = 1 - yin->yinBuffer[tau];
+ break;
+ }
+ }
+
+ /* if no pitch found, tau => -1 */
+ if (tau == yin->halfBufferSize || yin->yinBuffer[tau] >= yin->threshold) {
+ tau = -1;
+ yin->probability = 0;
+ }
+
+ return tau;
+}
+
+/**
+ * Step 5: Interpolate the shift value (tau) to improve the pitch estimate.
+ * @param yin [description]
+ * @param tauEstimate [description]
+ * @return [description]
+ *
+ * The 'best' shift value for autocorellation is most likely not an interger shift of the signal.
+ * As we only autocorellated using integer shifts we should check that there isn't a better fractional
+ * shift value.
+ */
+float Yin_parabolicInterpolation(Yin *yin, int16_t tauEstimate) {
+ float betterTau;
+ int16_t x0;
+ int16_t x2;
+
+ /* Calculate the first polynomial coeffcient based on the current estimate of tau */
+ if (tauEstimate < 1) {
+ x0 = tauEstimate;
+ }
+ else {
+ x0 = tauEstimate - 1;
+ }
+
+ /* Calculate the second polynomial coeffcient based on the current estimate of tau */
+ if (tauEstimate + 1 < yin->halfBufferSize) {
+ x2 = tauEstimate + 1;
+ }
+ else {
+ x2 = tauEstimate;
+ }
+
+ /* Algorithm to parabolically interpolate the shift value tau to find a better estimate */
+ if (x0 == tauEstimate) {
+ if (yin->yinBuffer[tauEstimate] <= yin->yinBuffer[x2]) {
+ betterTau = tauEstimate;
+ }
+ else {
+ betterTau = x2;
+ }
+ }
+ else if (x2 == tauEstimate) {
+ if (yin->yinBuffer[tauEstimate] <= yin->yinBuffer[x0]) {
+ betterTau = tauEstimate;
+ }
+ else {
+ betterTau = x0;
+ }
+ }
+ else {
+ float s0, s1, s2;
+ s0 = yin->yinBuffer[x0];
+ s1 = yin->yinBuffer[tauEstimate];
+ s2 = yin->yinBuffer[x2];
+ // fixed AUBIO implementation, thanks to Karl Helgason:
+ // (2.0f * s1 - s2 - s0) was incorrectly multiplied with -1
+ betterTau = tauEstimate + (s2 - s0) / (2 * (2 * s1 - s2 - s0));
+ }
+
+
+ return betterTau;
+}
+
+
+
+
+
+/* ------------------------------------------------------------------------------------------
+---------------------------------------------------------------------------- PUBLIC FUNCTIONS
+-------------------------------------------------------------------------------------------*/
+
+
+
+/**
+ * Initialise the Yin pitch detection object
+ * @param yin Yin pitch detection object to initialise
+ * @param bufferSize Length of the audio buffer to analyse
+ * @param threshold Allowed uncertainty (e.g 0.05 will return a pitch with ~95% probability)
+ */
+void Yin_init(Yin *yin, int16_t bufferSize, float threshold){
+ /* Initialise the fields of the Yin structure passed in */
+ yin->bufferSize = bufferSize;
+ yin->halfBufferSize = bufferSize / 2;
+ yin->probability = 0.0;
+ yin->threshold = threshold;
+
+ /* Allocate the autocorellation buffer and initialise it to zero */
+ yin->yinBuffer = (float *) malloc(sizeof(float)* yin->halfBufferSize);
+
+ int16_t i;
+ for(i = 0; i < yin->halfBufferSize; i++){
+ yin->yinBuffer[i] = 0;
+ }
+}
+
+/**
+ * Runs the Yin pitch detection algortihm
+ * @param yin Initialised Yin object
+ * @param buffer Buffer of samples to analyse
+ * @return Fundamental frequency of the signal in Hz. Returns -1 if pitch can't be found
+ */
+float Yin_getPitch(Yin *yin, int16_t* buffer){
+ int16_t tauEstimate = -1;
+ float pitchInHertz = -1;
+
+ /* Step 1: Calculates the squared difference of the signal with a shifted version of itself. */
+ Yin_difference(yin, buffer);
+
+ /* Step 2: Calculate the cumulative mean on the normalised difference calculated in step 1 */
+ Yin_cumulativeMeanNormalizedDifference(yin);
+
+ /* Step 3: Search through the normalised cumulative mean array and find values that are over the threshold */
+ tauEstimate = Yin_absoluteThreshold(yin);
+
+ /* Step 5: Interpolate the shift value (tau) to improve the pitch estimate. */
+ if(tauEstimate != -1){
+ pitchInHertz = YIN_SAMPLING_RATE / Yin_parabolicInterpolation(yin, tauEstimate);
+ }
+
+ return pitchInHertz;
+}
+
+/**
+ * Certainty of the pitch found
+ * @param yin Yin object that has been run over a buffer
+ * @return Returns the certainty of the note found as a decimal (i.e 0.3 is 30%)
+ */
+float Yin_getProbability(Yin *yin){
+ return yin->probability;
+}
+
+
+
--- /dev/null
+++ b/TestPlugin/Source/Yin.h
@@ -1,0 +1,56 @@
+/*
+ ==============================================================================
+
+ Yin.h
+ Created: 17 Jan 2017 1:20:23pm
+ Author: Michael R Mulshine
+
+ ==============================================================================
+*/
+
+#ifndef YIN_H_INCLUDED
+#define YIN_H_INCLUDED
+
+#include <stdint.h>
+
+#define YIN_SAMPLING_RATE 44100
+#define YIN_DEFAULT_THRESHOLD 0.15
+
+/**
+ * @struct Yin
+ * @breif Object to encapsulate the parameters for the Yin pitch detection algorithm
+ */
+typedef struct _Yin {
+ int16_t bufferSize; /**< Size of the audio buffer to be analysed */
+ int16_t halfBufferSize; /**< Half the buffer length */
+ float* yinBuffer; /**< Buffer that stores the results of the intermediate processing steps of the algorithm */
+ float probability; /**< Probability that the pitch found is correct as a decimal (i.e 0.85 is 85%) */
+ float threshold; /**< Allowed uncertainty in the result as a decimal (i.e 0.15 is 15%) */
+} Yin;
+
+/**
+ * Initialise the Yin pitch detection object
+ * @param yin Yin pitch detection object to initialise
+ * @param bufferSize Length of the audio buffer to analyse
+ * @param threshold Allowed uncertainty (e.g 0.05 will return a pitch with ~95% probability)
+ */
+void Yin_init(Yin *yin, int16_t bufferSize, float threshold);
+
+/**
+ * Runs the Yin pitch detection algortihm
+ * @param yin Initialised Yin object
+ * @param buffer Buffer of samples to analyse
+ * @return Fundamental frequency of the signal in Hz. Returns -1 if pitch can't be found
+ */
+float Yin_getPitch(Yin *yin, int16_t* buffer);
+
+/**
+ * Certainty of the pitch found
+ * @param yin Yin object that has been run over a buffer
+ * @return Returns the certainty of the note found as a decimal (i.e 0.3 is 30%)
+ */
+float Yin_getProbability(Yin *yin);
+
+
+
+#endif // YIN_H_INCLUDED