include Yin pitch tracking algo

This commit is contained in:
Trent
2017-06-26 22:30:05 -04:00
parent 025d7cd6aa
commit 7db2d6c00b
10 changed files with 324 additions and 172 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
JuceLibraryCode/ JuceLibraryCode/
Builds/ Builds/
*bak *bak
*jucer

View File

@@ -1,7 +1,6 @@
#include "PluginProcessor.h" #include "PluginProcessor.h"
#include "PluginEditor.h" #include "PluginEditor.h"
LampshadeAudioProcessor::LampshadeAudioProcessor() LampshadeAudioProcessor::LampshadeAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations #ifndef JucePlugin_PreferredChannelConfigurations
: AudioProcessor (BusesProperties() : AudioProcessor (BusesProperties()
@@ -69,6 +68,7 @@ void LampshadeAudioProcessor::changeProgramName (int index, const String& newNam
void LampshadeAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) void LampshadeAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{ {
myYin = Yin(sampleRate, samplesPerBlock);
} }
void LampshadeAudioProcessor::releaseResources() void LampshadeAudioProcessor::releaseResources()
@@ -105,8 +105,12 @@ void LampshadeAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffe
for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i) for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear(i, 0, buffer.getNumSamples()); buffer.clear(i, 0, buffer.getNumSamples());
float pitch = myYin.getPitch(buffer.getWritePointer (0)); // returns Pitch in Hertz
printf("pitch: %f", pitch);
for (int channel = 0; channel < totalNumInputChannels; ++channel) { for (int channel = 0; channel < totalNumInputChannels; ++channel) {
//float* channelData = buffer.getWritePointer (channel); //float* channelData = buffer.getWritePointer (channel);
} }
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../JuceLibraryCode/JuceHeader.h" #include "../JuceLibraryCode/JuceHeader.h"
#include "Yin.h"
class LampshadeAudioProcessor : public AudioProcessor class LampshadeAudioProcessor : public AudioProcessor
{ {
@@ -38,4 +38,5 @@ public:
private: private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LampshadeAudioProcessor) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LampshadeAudioProcessor)
Yin myYin;
}; };

146
Source/Yin.cpp Normal file
View File

@@ -0,0 +1,146 @@
#include "Yin.h"
#include <stdlib.h>
//#include "WProgram.h"
void Yin::initialize(float yinSampleRate,int yinBufferSize){
bufferSize = yinBufferSize;
sampleRate = yinSampleRate;
halfBufferSize = bufferSize / 2;
threshold = 0.15;
probability = 0.0;
//initialize array and set it to zero
yinBuffer = (float *) malloc(sizeof(float)* halfBufferSize);
for(int i = 0; i < halfBufferSize; i++){
yinBuffer[i] = 0;
}
}
Yin::Yin(){
}
Yin::Yin(float yinSampleRate,int yinBufferSize){
initialize(yinSampleRate,yinBufferSize);
}
float Yin::getProbability(){
return probability;
}
float Yin::getPitch(float* buffer){
int tauEstimate = -1;
float pitchInHertz = -1;
//step 2
difference(buffer);
// step 3
cumulativeMeanNormalizedDifference();
//step 4
tauEstimate = absoluteThreshold();
//step 5
if(tauEstimate != -1){
pitchInHertz = sampleRate / parabolicInterpolation(tauEstimate);
}
return pitchInHertz;
}
float Yin::parabolicInterpolation(int tauEstimate) {
float betterTau;
int x0;
int x2;
if (tauEstimate < 1) {
x0 = tauEstimate;
}
else {
x0 = tauEstimate - 1;
}
if (tauEstimate + 1 < halfBufferSize) {
x2 = tauEstimate + 1;
}
else {
x2 = tauEstimate;
}
if (x0 == tauEstimate) {
if (yinBuffer[tauEstimate] <= yinBuffer[x2]) {
betterTau = tauEstimate;
}
else {
betterTau = x2;
}
}
else if (x2 == tauEstimate) {
if (yinBuffer[tauEstimate] <= yinBuffer[x0]) {
betterTau = tauEstimate;
}
else {
betterTau = x0;
}
}
else {
float s0, s1, s2;
s0 = yinBuffer[x0];
s1 = yinBuffer[tauEstimate];
s2 = 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;
}
void Yin::cumulativeMeanNormalizedDifference(){
int tau;
yinBuffer[0] = 1;
float runningSum = 0;
for (tau = 1; tau < halfBufferSize; tau++) {
runningSum += yinBuffer[tau];
yinBuffer[tau] *= tau / runningSum;
}
}
void Yin::difference(float* buffer){
int index;
int tau;
float delta;
for(tau = 0 ; tau < halfBufferSize; tau++){
for(index = 0; index < halfBufferSize; index++){
delta= buffer[index] - buffer[index + tau];
yinBuffer[tau] += delta * delta;
}
}
}
int Yin::absoluteThreshold(){
int tau;
// first two positions in yinBuffer are always 1
// So start at the third (index 2)
for (tau = 2; tau < halfBufferSize ; tau++) {
if (yinBuffer[tau] < threshold) {
while (tau + 1 < halfBufferSize && yinBuffer[tau + 1] < yinBuffer[tau]) {
tau++;
}
// found tau, exit loop and return
// store the probability
// From the YIN paper: The 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
probability = 1 - yinBuffer[tau];
break;
}
}
// if no pitch found, tau => -1
if (tau == halfBufferSize || yinBuffer[tau] >= threshold) {
tau = -1;
probability = 0;
}
return tau;
}

26
Source/Yin.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
//#include "WProgram.h"
class Yin{
public:
Yin();
Yin(float sampleRate,int bufferSize);
void initialize(float sampleRate,int bufferSize);
float getPitch(float* buffer);
float getProbability();
private:
float parabolicInterpolation(int tauEstimate);
int absoluteThreshold();
void cumulativeMeanNormalizedDifference();
void difference(float* buffer);
double threshold;
int bufferSize;
int halfBufferSize;
float sampleRate;
float* yinBuffer;
float probability;
};

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="RELS1e" name="lampshade" displaySplashScreen="1" reportAppUsage="1"
splashScreenColour="Dark" projectType="audioplug" version="1.0.0"
bundleIdentifier="com.yourcompany.lampshade" includeBinaryInAppConfig="1"
buildVST="1" buildVST3="0" buildAU="1" buildAUv3="0" buildRTAS="0"
buildAAX="0" buildStandalone="0" enableIAA="0" pluginName="lampshade"
pluginDesc="lampshade" pluginManufacturer="yourcompany" pluginManufacturerCode="Manu"
pluginCode="Rels" pluginChannelConfigs="" pluginIsSynth="0" pluginWantsMidiIn="0"
pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0"
pluginAUExportPrefix="lampshadeAU" pluginRTASCategory="" aaxIdentifier="com.yourcompany.lampshade"
pluginAAXCategory="AAX_ePlugInCategory_Dynamics" jucerVersion="5.0.2">
<MAINGROUP id="GHLPwD" name="lampshade">
<GROUP id="{C42E5ACC-06AB-BF28-4550-5DDDE3A4BA5F}" name="Source">
<FILE id="YxKhY1" name="PluginProcessor.cpp" compile="1" resource="0"
file="Source/PluginProcessor.cpp"/>
<FILE id="n6D5RN" name="PluginProcessor.h" compile="0" resource="0"
file="Source/PluginProcessor.h"/>
<FILE id="LeuZUn" name="PluginEditor.cpp" compile="1" resource="0"
file="Source/PluginEditor.cpp"/>
<FILE id="ReytWw" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
</GROUP>
</MAINGROUP>
<EXPORTFORMATS>
<XCODE_MAC targetFolder="Builds/MacOSX">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="lampshade"/>
<CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="lampshade"/>
</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"/>
</MODULEPATHS>
</XCODE_MAC>
</EXPORTFORMATS>
<MODULES>
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0"/>
<MODULE id="juce_video" showAllCode="1" useLocalCopy="0"/>
</MODULES>
<JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
</JUCERPROJECT>

Binary file not shown.

0
test Project/Icon Normal file
View File

BIN
test Project/test.als Normal file

Binary file not shown.

249
test.RPP
View File

@@ -1,105 +1,144 @@
<REAPER_PROJECT 0.1 "5.40/OSX64" 1497899251 <REAPER_PROJECT 0.1 "5.40/OSX64" 1498529808
RIPPLE 0 RIPPLE 0
GROUPOVERRIDE 0 0 0 GROUPOVERRIDE 0 0 0
AUTOXFADE 1 AUTOXFADE 1
ENVATTACH 1 ENVATTACH 1
MIXERUIFLAGS 11 48 MIXERUIFLAGS 11 48
PEAKGAIN 1 PEAKGAIN 1
FEEDBACK 0 FEEDBACK 0
PANLAW 1 PANLAW 1
PROJOFFS 0 0 PROJOFFS 0 0
MAXPROJLEN 0 600 MAXPROJLEN 0 600
GRID 3199 8 1 8 1 0 0 0 GRID 3199 8 1 8 1 0 0 0
TIMEMODE 1 5 -1 30 0 TIMEMODE 1 5 -1 30 0
VIDEO_CONFIG 0 0 256 VIDEO_CONFIG 0 0 256
PANMODE 3 PANMODE 3
CURSOR 0 CURSOR 0
ZOOM 100 0 0 ZOOM 100 0 0
VZOOMEX 6 VZOOMEX 6
USE_REC_CFG 0 USE_REC_CFG 0
RECMODE 1 RECMODE 1
SMPTESYNC 0 30 100 40 1000 300 0 0 1 0 0 SMPTESYNC 0 30 100 40 1000 300 0 0 1 0 0
LOOP 0 LOOP 0
LOOPGRAN 0 4 LOOPGRAN 0 4
RECORD_PATH "" "" RECORD_PATH "" ""
<RECORD_CFG <RECORD_CFG
> >
<APPLYFX_CFG <APPLYFX_CFG
> >
RENDER_FILE "" RENDER_FILE ""
RENDER_PATTERN "" RENDER_PATTERN ""
RENDER_FMT 0 2 0 RENDER_FMT 0 2 0
RENDER_1X 0 RENDER_1X 0
RENDER_RANGE 1 0 0 18 1000 RENDER_RANGE 1 0 0 18 1000
RENDER_RESAMPLE 3 0 1 RENDER_RESAMPLE 3 0 1
RENDER_ADDTOPROJ 0 RENDER_ADDTOPROJ 0
RENDER_STEMS 0 RENDER_STEMS 0
RENDER_DITHER 0 RENDER_DITHER 0
TIMELOCKMODE 1 TIMELOCKMODE 1
TEMPOENVLOCKMODE 1 TEMPOENVLOCKMODE 1
ITEMMIX 0 ITEMMIX 0
DEFPITCHMODE 589824 DEFPITCHMODE 589824
TAKELANE 1 TAKELANE 1
SAMPLERATE 44100 0 0 SAMPLERATE 44100 0 0
<RENDER_CFG <RENDER_CFG
> >
LOCK 1 LOCK 1
<METRONOME 6 2 <METRONOME 6 2
VOL 0.25 0.125 VOL 0.25 0.125
FREQ 800 1600 1 FREQ 800 1600 1
BEATLEN 4 BEATLEN 4
SAMPLES "" "" SAMPLES "" ""
PATTERN 2863311530 2863311529 PATTERN 2863311530 2863311529
> >
GLOBAL_AUTO -1 GLOBAL_AUTO -1
TEMPO 120 4 4 TEMPO 120 4 4
PLAYRATE 1 0 0.25 4 PLAYRATE 1 0 0.25 4
SELECTION 0 0 SELECTION 0 0
SELECTION2 0 0 SELECTION2 0 0
MASTERAUTOMODE 0 MASTERAUTOMODE 0
MASTERTRACKHEIGHT 0 MASTERTRACKHEIGHT 0
MASTERPEAKCOL 16576 MASTERPEAKCOL 16576
MASTERMUTESOLO 0 MASTERMUTESOLO 0
MASTERTRACKVIEW 0 0.6667 0.5 0.5 0 0 0 MASTERTRACKVIEW 0 0.6667 0.5 0.5 0 0 0
MASTERHWOUT 0 0 1 0 0 0 0 -1 MASTERHWOUT 0 0 1 0 0 0 0 -1
MASTER_NCH 2 2 MASTER_NCH 2 2
MASTER_VOLUME 1 0 -1 -1 1 MASTER_VOLUME 1 0 -1 -1 1
MASTER_FX 1 MASTER_FX 1
MASTER_SEL 0 MASTER_SEL 0
<MASTERFXLIST <MASTERFXLIST
WNDRECT 34 368 639 377 WNDRECT 34 368 639 377
SHOW 0 SHOW 0
LASTSEL 0 LASTSEL 0
DOCKED 0 DOCKED 0
BYPASS 0 0 0 BYPASS 0 0 0
<AU "AU: yourcompany: lampshade" "yourcompany: lampshade" "" 1635083896 1382378611 1298230901 <AU "AU: yourcompany: lampshade" "yourcompany: lampshade" "" 1635083896 1382378611 1298230901
6QMAAAAAAAACAAAAAQAAAAAAAAACAAAAAAAAAAIAAAABAAAAAAAAAAIAAAAAAAAAkgIAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+CjwhRE9D 6QMAAAAAAAACAAAAAQAAAAAAAAACAAAAAAAAAAIAAAABAAAAAAAAAAIAAAAAAAAAkgIAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+CjwhRE9D
VFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQi VFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQi
Pgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+Cgk8a2V5PmRhdGE8L2tleT4KCTxkYXRhPgoJPC9kYXRhPgoJPGtleT5lbGVtZW50LW5hbWU8L2tleT4KCTxkaWN0 Pgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+Cgk8a2V5PmRhdGE8L2tleT4KCTxkYXRhPgoJPC9kYXRhPgoJPGtleT5lbGVtZW50LW5hbWU8L2tleT4KCTxkaWN0
PgoJCTxrZXk+MTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PjA8L2tleT4KCQkJPHN0cmluZz5JbnB1dDwvc3RyaW5nPgoJCTwvZGljdD4KCQk8a2V5PjI8L2tleT4KCQk8 PgoJCTxrZXk+MTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PjA8L2tleT4KCQkJPHN0cmluZz5JbnB1dDwvc3RyaW5nPgoJCTwvZGljdD4KCQk8a2V5PjI8L2tleT4KCQk8
ZGljdD4KCQkJPGtleT4wPC9rZXk+CgkJCTxzdHJpbmc+T3V0cHV0PC9zdHJpbmc+CgkJPC9kaWN0PgoJPC9kaWN0PgoJPGtleT5tYW51ZmFjdHVyZXI8L2tleT4KCTxp ZGljdD4KCQkJPGtleT4wPC9rZXk+CgkJCTxzdHJpbmc+T3V0cHV0PC9zdHJpbmc+CgkJPC9kaWN0PgoJPC9kaWN0PgoJPGtleT5tYW51ZmFjdHVyZXI8L2tleT4KCTxp
bnRlZ2VyPjEyOTgyMzA5MDE8L2ludGVnZXI+Cgk8a2V5Pm5hbWU8L2tleT4KCTxzdHJpbmc+VW50aXRsZWQ8L3N0cmluZz4KCTxrZXk+c3VidHlwZTwva2V5PgoJPGlu bnRlZ2VyPjEyOTgyMzA5MDE8L2ludGVnZXI+Cgk8a2V5Pm5hbWU8L2tleT4KCTxzdHJpbmc+VW50aXRsZWQ8L3N0cmluZz4KCTxrZXk+c3VidHlwZTwva2V5PgoJPGlu
dGVnZXI+MTM4MjM3ODYxMTwvaW50ZWdlcj4KCTxrZXk+dHlwZTwva2V5PgoJPGludGVnZXI+MTYzNTA4Mzg5NjwvaW50ZWdlcj4KCTxrZXk+dmVyc2lvbjwva2V5PgoJ dGVnZXI+MTM4MjM3ODYxMTwvaW50ZWdlcj4KCTxrZXk+dHlwZTwva2V5PgoJPGludGVnZXI+MTYzNTA4Mzg5NjwvaW50ZWdlcj4KCTxrZXk+dmVyc2lvbjwva2V5PgoJ
PGludGVnZXI+MDwvaW50ZWdlcj4KPC9kaWN0Pgo8L3BsaXN0PgoBAAAAAAAAAAAA PGludGVnZXI+MDwvaW50ZWdlcj4KPC9kaWN0Pgo8L3BsaXN0PgoBAAAAAAAAAAAA
> >
FLOATPOS 0 0 0 0 FLOATPOS 0 0 0 0
FXID {3568A34C-460C-D046-82F7-7D87378ABB20} FXID {3568A34C-460C-D046-82F7-7D87378ABB20}
WAK 0 WAK 0
> >
<MASTERPLAYSPEEDENV <MASTERPLAYSPEEDENV
ACT 0 ACT 0
VIS 0 1 1 VIS 0 1 1
LANEHEIGHT 0 0 LANEHEIGHT 0 0
ARM 0 ARM 0
DEFSHAPE 0 -1 -1 DEFSHAPE 0 -1 -1
> >
<TEMPOENVEX <TEMPOENVEX
ACT 0 ACT 0
VIS 1 0 1 VIS 1 0 1
LANEHEIGHT 0 0 LANEHEIGHT 0 0
ARM 0 ARM 0
DEFSHAPE 1 -1 -1 DEFSHAPE 1 -1 -1
> >
<PROJBAY <PROJBAY
> >
> <TRACK {0285AA2F-2341-854C-BBEE-985C6E7A9ADD}
NAME ""
PEAKCOL 16576
BEAT -1
AUTOMODE 0
VOLPAN 1 0 -1 -1 1
MUTESOLO 0 0 0
IPHASE 0
ISBUS 0 0
BUSCOMP 0 0
SHOWINMIX 1 0.6667 0.5 1 0.5 0 0 0
FREEMODE 0
SEL 0
REC 1 0 0 0 0 0 0
VU 2
TRACKHEIGHT 0 0
INQ 0 0 0 0.5 100 0 0 100
NCHAN 2
FX 1
TRACKID {0285AA2F-2341-854C-BBEE-985C6E7A9ADD}
PERF 0
MIDIOUT -1
MAINSEND 1 0
<FXCHAIN
WNDRECT 125 469 639 376
SHOW 0
LASTSEL 0
DOCKED 0
BYPASS 0 0 0
<VST "VST: lampshade (yourcompany)" lampshade.vst 0 "" 1382378611
c2xlUu5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAIAAAABAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAAABAA
776t3g3wrd4=
AAAQAAAA
>
FLOATPOS 0 0 0 0
FXID {B7DD42FB-8D0E-C24C-924A-407EC4334EB7}
WAK 0
>
>
>