Skip to content

Commit

Permalink
feat: add autoCorrelate method
Browse files Browse the repository at this point in the history
  • Loading branch information
yigithanyucedag committed Jul 27, 2024
1 parent 46adfb2 commit 85b5441
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 7 deletions.
73 changes: 71 additions & 2 deletions cpp/react-native-pitchy.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,76 @@
#include "react-native-pitchy.h"

namespace pitchy {
double multiply(double a, double b) {
#include <vector>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <limits>

namespace pitchy
{
double multiply(double a, double b)
{
return a * b;
}

double autoCorrelate(const std::vector<double> &buf, double sampleRate)
{
// Implements the ACF2+ algorithm
int SIZE = buf.size();
double rms = 0;

for (int i = 0; i < SIZE; ++i)
{
double val = buf[i];
rms += val * val;
}
rms = std::sqrt(rms / SIZE);
if (rms < 0.01) // not enough signal
return -1;

int r1 = 0, r2 = SIZE - 1;
double thres = 0.2;
for (int i = 0; i < SIZE / 2; ++i)
if (std::abs(buf[i]) < thres)
{
r1 = i;
break;
}
for (int i = 1; i < SIZE / 2; ++i)
if (std::abs(buf[SIZE - i]) < thres)
{
r2 = SIZE - i;
break;
}

std::vector<double> slicedBuf(buf.begin() + r1, buf.begin() + r2);
SIZE = slicedBuf.size();

std::vector<double> c(SIZE, 0);
for (int i = 0; i < SIZE; ++i)
for (int j = 0; j < SIZE - i; ++j)
c[i] += slicedBuf[j] * slicedBuf[j + i];

int d = 0;
while (c[d] > c[d + 1])
d++;
double maxval = -1, maxpos = -1;
for (int i = d; i < SIZE; ++i)
{
if (c[i] > maxval)
{
maxval = c[i];
maxpos = i;
}
}
double T0 = maxpos;

double x1 = c[T0 - 1], x2 = c[T0], x3 = c[T0 + 1];
double a = (x1 + x3 - 2 * x2) / 2;
double b = (x3 - x1) / 2;
if (a)
T0 = T0 - b / (2 * a);

return sampleRate / T0;
}
}
6 changes: 5 additions & 1 deletion cpp/react-native-pitchy.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#ifndef PITCHY_H
#define PITCHY_H

namespace pitchy {
#include <vector>

namespace pitchy
{
double multiply(double a, double b);
double autoCorrelate(const std::vector<double> &buf, double sampleRate);
}

#endif /* PITCHY_H */
13 changes: 9 additions & 4 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { useState, useEffect } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { multiply } from 'react-native-pitchy';
import { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { autoCorrelate } from 'react-native-pitchy';

export default function App() {
const [result, setResult] = useState<number | undefined>();

useEffect(() => {
multiply(3, 7).then(setResult);
// multiply(3, 7).then(setResult);
// 2048 length
const data = new Array(2048)
.fill(0)
.map((_, i) => Math.sin((i / 2048) * Math.PI * 2 * 440));
autoCorrelate(data, 44100).then(setResult);
}, []);

return (
Expand Down
23 changes: 23 additions & 0 deletions ios/Pitchy.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,28 @@ @implementation Pitchy
resolve(result);
}

// Method to expose autoCorrelate
RCT_EXPORT_METHOD(autoCorrelate:(NSArray<NSNumber *> *)buf
sampleRate:(double)sampleRate
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
// Convert NSArray<NSNumber *> to std::vector<double>
std::vector<double> cBuf;
for (NSNumber *num in buf) {
cBuf.push_back([num doubleValue]);
}

// Call the autoCorrelate function
double result = pitchy::autoCorrelate(cBuf, sampleRate);

if (result < 0) {
reject(@"autoCorrelate_error", @"Not enough signal", nil);
} else {
NSNumber *resultNumber = @(result);
resolve(resultNumber);
}
}


@end
7 changes: 7 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ const Pitchy = NativeModules.Pitchy
export function multiply(a: number, b: number): Promise<number> {
return Pitchy.multiply(a, b);
}

export function autoCorrelate(
buf: number[],
sampleRate: number
): Promise<number> {
return Pitchy.autoCorrelate(buf, sampleRate);
}

0 comments on commit 85b5441

Please sign in to comment.