Skip to content

Commit ccec90d

Browse files
committed
Added PitchCorrect
1 parent 8d0b6d2 commit ccec90d

File tree

25 files changed

+2055
-0
lines changed

25 files changed

+2055
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright AudioKit. All Rights Reserved.
2+
3+
#include "SoundpipeDSPBase.h"
4+
#include "ParameterRamper.h"
5+
#include "Soundpipe.h"
6+
#include "autotune.h"
7+
8+
enum PitchCorrectParameter : AUParameterAddress {
9+
PitchCorrectParameterSpeed,
10+
PitchCorrectParameterAmount
11+
};
12+
13+
class PitchCorrectDSP : public SoundpipeDSPBase {
14+
private:
15+
sp_rms *rms_l;
16+
sp_rms *rms_r;
17+
autotune *autotune_l;
18+
autotune *autotune_r;
19+
ParameterRamper speedRamp;
20+
ParameterRamper amountRamp;
21+
22+
public:
23+
PitchCorrectDSP() {
24+
parameters[PitchCorrectParameterSpeed] = &speedRamp;
25+
parameters[PitchCorrectParameterAmount] = &amountRamp;
26+
}
27+
28+
void init(int channelCount, double sampleRate) override {
29+
SoundpipeDSPBase::init(channelCount, sampleRate);
30+
sp_rms_create(&rms_l);
31+
sp_rms_init(sp, rms_l);
32+
sp_rms_create(&rms_r);
33+
sp_rms_init(sp, rms_r);
34+
autotune_create(&autotune_l);
35+
autotune_init(sp, autotune_l);
36+
autotune_create(&autotune_r);
37+
autotune_init(sp, autotune_r);
38+
39+
// Create chromatic scale from A220 to A440
40+
float scale[13] = {
41+
220.0, // A
42+
233.08, // A#/Bb
43+
246.94, // B
44+
261.63, // C
45+
277.18, // C#/Db
46+
293.66, // D
47+
311.13, // D#/Eb
48+
329.63, // E
49+
349.23, // F
50+
369.99, // F#/Gb
51+
392.00, // G
52+
415.30, // G#/Ab
53+
440.00 // A
54+
};
55+
56+
autotune_set_scale_freqs(autotune_l, scale, 13);
57+
autotune_set_scale_freqs(autotune_r, scale, 13);
58+
}
59+
60+
void deinit() override {
61+
SoundpipeDSPBase::deinit();
62+
sp_rms_destroy(&rms_l);
63+
sp_rms_destroy(&rms_r);
64+
}
65+
66+
void reset() override {
67+
SoundpipeDSPBase::reset();
68+
if (!isInitialized) return;
69+
sp_rms_init(sp, rms_l);
70+
sp_rms_init(sp, rms_r);
71+
}
72+
73+
void process(FrameRange range) override {
74+
for (int i : range) {
75+
float speed = speedRamp.getAndStep();
76+
float amount = amountRamp.getAndStep();
77+
78+
float leftIn = inputSample(0, i);
79+
float rightIn = inputSample(1, i);
80+
81+
float rms_l_out = 0;
82+
float rms_r_out = 0;
83+
84+
float leftOut = 0, rightOut = 0;
85+
86+
autotune_set_speed(autotune_l, speed);
87+
autotune_set_amount(autotune_l, amount);
88+
89+
autotune_set_speed(autotune_r, speed);
90+
autotune_set_amount(autotune_r, amount);
91+
92+
sp_rms_compute(sp, rms_l, &leftIn, &rms_l_out);
93+
autotune_compute(sp, autotune_l, &leftIn, &leftOut, rms_l_out);
94+
95+
sp_rms_compute(sp, rms_r, &rightIn, &rms_r_out);
96+
autotune_compute(sp, autotune_r, &rightIn, &rightOut, rms_r_out);
97+
98+
outputSample(0, i) = leftOut;
99+
outputSample(1, i) = rightOut;
100+
}
101+
}
102+
};
103+
104+
AK_REGISTER_DSP(PitchCorrectDSP, "pcrt")
105+
AK_REGISTER_PARAMETER(PitchCorrectParameterSpeed)
106+
AK_REGISTER_PARAMETER(PitchCorrectParameterAmount)

Sources/Soundpipe/include/Yin.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef Yin_h
2+
#define Yin_h
3+
4+
#include <stdint.h>
5+
6+
#define YIN_DEFAULT_THRESHOLD 0.15
7+
8+
/**
9+
* @struct Yin
10+
* @breif Object to encapsulate the parameters for the Yin pitch detection algorithm
11+
*/
12+
typedef struct _Yin {
13+
int16_t bufferSize; /**< Size of the audio buffer to be analysed */
14+
int16_t halfBufferSize; /**< Half the buffer length */
15+
float* yinBuffer; /**< Buffer that stores the results of the intermediate processing steps of the algorithm */
16+
float probability; /**< Probability that the pitch found is correct as a decimal (i.e 0.85 is 85%) */
17+
float threshold; /**< Allowed uncertainty in the result as a decimal (i.e 0.15 is 15%) */
18+
float sampleRate;
19+
} Yin;
20+
21+
/**
22+
* Initialise the Yin pitch detection object
23+
* @param yin Yin pitch detection object to initialise
24+
* @param bufferSize Length of the audio buffer to analyse
25+
* @param threshold Allowed uncertainty (e.g 0.05 will return a pitch with ~95% probability)
26+
*/
27+
void Yin_init(Yin *yin, int16_t bufferSize, float threshold, int sampleRate);
28+
29+
/**
30+
* Runs the Yin pitch detection algortihm
31+
* @param yin Initialised Yin object
32+
* @param buffer Buffer of samples to analyse
33+
* @return Fundamental frequency of the signal in Hz. Returns -1 if pitch can't be found
34+
*/
35+
float Yin_getPitch(Yin *yin, int16_t* buffer);
36+
37+
/**
38+
* Certainty of the pitch found
39+
* @param yin Yin object that has been run over a buffer
40+
* @return Returns the certainty of the note found as a decimal (i.e 0.3 is 30%)
41+
*/
42+
float Yin_getProbability(Yin *yin);
43+
44+
45+
46+
#endif

Sources/Soundpipe/include/arp.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef arp_h
2+
#define arp_h
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <math.h>
7+
#include <string.h>
8+
#include "soundpipe.h"
9+
#include "pitchshift.h"
10+
11+
typedef struct {
12+
sp_delay *dels;
13+
sp_pshift *pshifts;
14+
int num_steps;
15+
} arp;
16+
17+
int arp_create(arp **p);
18+
int arp_init(sp_data *sp, arp *p);
19+
int arp_compute(sp_data *sp, arp *p, float *in, float autotune_freq, float *out);
20+
21+
#endif /* arp_h */
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef autotune_h
2+
#define autotune_h
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#include <stdio.h>
9+
#include <stdint.h>
10+
#include <stdbool.h>
11+
#include "soundpipe.h"
12+
#include "Yin.h"
13+
#include "circular_buffer.h"
14+
#include "pitchshift.h"
15+
#include "pitchshift2.h"
16+
#include "pitchcalculate.h"
17+
18+
typedef struct {
19+
pitchcalculate *pcalc;
20+
pitchshift2 *pshift2;
21+
Yin *yin;
22+
circular_buffer *buff;
23+
sp_butlp *lpf;
24+
sp_port *scale_freq_port;
25+
int16_t *intBuffer;
26+
int yin_downsample_acc;
27+
bool correction_mode_active;
28+
float detected_freq;
29+
float cur_correction_amt_cents;
30+
float base_freq;
31+
float target_freq;
32+
float pshift_freq_ratio;
33+
float cur_freq_ratio;
34+
int scale_freq_index_acc;
35+
int unknown_freq_acc;
36+
float nearest_scale_freq_index;
37+
float nearest_scale_freq;
38+
float amount;
39+
float speed;
40+
bool should_smooth_scale_idx;
41+
bool should_smooth_target_freq;
42+
43+
bool should_update_scale_freqs;
44+
float *autotune_scale_freqs;
45+
int autotune_scale_freqs_count;
46+
float *tmp_scale_freqs;
47+
int tmp_scale_freqs_count;
48+
} autotune;
49+
50+
int autotune_create(autotune **p);
51+
int autotune_init(sp_data *sp, autotune *p);
52+
int autotune_compute(sp_data *sp, autotune *p, float *in, float *out, float rms);
53+
int autotune_set_scale_freqs(autotune *p, float *frequencies, int count);
54+
int autotune_set_amount(autotune *p, float amount);
55+
int autotune_set_speed(autotune *p, float speed);
56+
57+
#ifdef __cplusplus
58+
}
59+
#endif
60+
61+
62+
#endif /* autotune_h */
63+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef circular_buffer_h
2+
#define circular_buffer_h
3+
4+
#include <stdio.h>
5+
6+
typedef struct circular_buffer {
7+
void *buffer; // data buffer
8+
void *buffer_end; // end of data buffer
9+
size_t capacity; // maximum number of items in the buffer
10+
size_t count; // number of items in the buffer
11+
size_t writePos; // the write position
12+
size_t readPos; // the read position
13+
size_t sz; // size of each item in the buffer
14+
void *head; // pointer to head
15+
void *tail; // pointer to tail
16+
} circular_buffer;
17+
18+
void cb_init(circular_buffer *cb, size_t capacity, size_t sz);
19+
void cb_free(circular_buffer *cb);
20+
void cb_push_back(circular_buffer *cb, const void *item);
21+
void cb_read_at_index_behind_write(circular_buffer *cb, int idx, void **value);
22+
void cb_pop_front(circular_buffer *cb, void *item);
23+
void cb_pop_multiple(circular_buffer *cb, int16_t *itemArray, int count, int moveReadheadBy);
24+
25+
#endif /* circular_buffer_h */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef equalizer_h
2+
#define equalizer_h
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <math.h>
7+
#include <string.h>
8+
#include "soundpipe.h"
9+
10+
typedef struct equalizer {
11+
sp_eqfil *eq1;
12+
sp_eqfil *eq2;
13+
sp_eqfil *eq3;
14+
sp_eqfil *eq4;
15+
} equalizer;
16+
17+
int equalizer_create(equalizer **eq);
18+
int equalizer_init(sp_data *sp, equalizer *eq);
19+
int equalizer_compute(sp_data *sp, equalizer *eq, float *in, float *out);
20+
21+
#endif /* equalizer_h */
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef harmonizer_h
2+
#define harmonizer_h
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <math.h>
7+
#include <string.h>
8+
#include "soundpipe.h"
9+
#include "pitchshift.h"
10+
11+
typedef struct {
12+
smbpitchshift *pshift1;
13+
smbpitchshift *pshift2;
14+
smbpitchshift *pshift3;
15+
smbpitchshift *pshift4;
16+
int scale_freq_index;
17+
int num_harmonies;
18+
int mode;
19+
} harmonizer;
20+
21+
int harmonizer_create(harmonizer **p);
22+
int harmonizer_init(sp_data *sp, harmonizer *p);
23+
int harmonizer_set_scale_freqs(float *frequencies, int count);
24+
int harmonizer_compute(sp_data *sp, harmonizer *p, float *in, int scale_freq_index, float *out);
25+
26+
#endif /* harmonizer_h */
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#ifndef interpolate_h
2+
#define interpolate_h
3+
4+
#include <math.h>
5+
6+
// This functions finds the determinant of Matrix
7+
double determinantOfMatrix(double mat[3][3]) {
8+
double ans;
9+
ans = mat[0][0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2])
10+
- mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0])
11+
+ mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]);
12+
return ans;
13+
}
14+
15+
// This function finds the solution of system of
16+
// linear equations using cramer's rule
17+
void findSolution(double coeff[3][4], double solution[3]) {
18+
// Matrix d using coeff as given in cramer's rule
19+
double d[3][3] = {
20+
{ coeff[0][0], coeff[0][1], coeff[0][2] },
21+
{ coeff[1][0], coeff[1][1], coeff[1][2] },
22+
{ coeff[2][0], coeff[2][1], coeff[2][2] },
23+
};
24+
// Matrix d1 using coeff as given in cramer's rule
25+
double d1[3][3] = {
26+
{ coeff[0][3], coeff[0][1], coeff[0][2] },
27+
{ coeff[1][3], coeff[1][1], coeff[1][2] },
28+
{ coeff[2][3], coeff[2][1], coeff[2][2] },
29+
};
30+
// Matrix d2 using coeff as given in cramer's rule
31+
double d2[3][3] = {
32+
{ coeff[0][0], coeff[0][3], coeff[0][2] },
33+
{ coeff[1][0], coeff[1][3], coeff[1][2] },
34+
{ coeff[2][0], coeff[2][3], coeff[2][2] },
35+
};
36+
// Matrix d3 using coeff as given in cramer's rule
37+
double d3[3][3] = {
38+
{ coeff[0][0], coeff[0][1], coeff[0][3] },
39+
{ coeff[1][0], coeff[1][1], coeff[1][3] },
40+
{ coeff[2][0], coeff[2][1], coeff[2][3] },
41+
};
42+
43+
// Calculating Determinant of Matrices d, d1, d2, d3
44+
double D = determinantOfMatrix(d);
45+
double D1 = determinantOfMatrix(d1);
46+
double D2 = determinantOfMatrix(d2);
47+
double D3 = determinantOfMatrix(d3);
48+
49+
// Case 1
50+
if (D != 0) {
51+
// Coeff have a unique solution. Apply Cramer's Rule
52+
double x = D1 / D;
53+
double y = D2 / D;
54+
double z = D3 / D;
55+
solution[0] = x;
56+
solution[1] = y;
57+
solution[2] = z;
58+
}
59+
// Case 2
60+
else {
61+
if (D1 == 0 && D2 == 0 && D3 == 0)
62+
printf("Infinite solutions\n");
63+
else if (D1 != 0 || D2 != 0 || D3 != 0)
64+
printf("No solutions\n");
65+
}
66+
}
67+
68+
void interpolate_min(float off1, float val1, float off2, float val2, float off3, float val3, float *min_out) {
69+
double coeff[3][4] = {
70+
{ powf(off1, 2), off1, 1, val1 },
71+
{ powf(off2, 2), off2, 1, val2 },
72+
{ powf(off3, 2), off3, 1, val3 },
73+
};
74+
75+
double solution[3] = { 0, 0, 0 };
76+
77+
findSolution(coeff, solution);
78+
79+
*min_out = (-1 * solution[1]) / (2 * solution[0]); // minimum of quadratic function (-b / 2a)
80+
}
81+
82+
#endif /* interpolate_h */

0 commit comments

Comments
 (0)