Skip to content

Commit 89f8193

Browse files
exzosexzos
authored andcommitted
chore: return helper functions for data scaling and sampling
1 parent 22fac3f commit 89f8193

File tree

3 files changed

+155
-13
lines changed

3 files changed

+155
-13
lines changed

example/src/App.tsx

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { useCallback, useEffect, useState } from 'react';
2-
import { View, StyleSheet, ScrollView } from 'react-native';
2+
3+
import { ScrollView, StyleSheet, Text, View } from 'react-native';
34
import { computeAmplitude } from 'react-native-audio-analyzer';
5+
import { robustScale, sample, scale, trimmedScale } from '../../src/helpers';
46

5-
export default function Index() {
7+
export default function App() {
68
const [data, setData] = useState<number[]>([]);
9+
710
const run = useCallback(async () => {
811
try {
912
const result = computeAmplitude(
1013
'/data/data/audioanalyzer.example/files/sample.mp3',
11-
1000
14+
100
1215
);
1316
setData(result);
1417
} catch (raw) {
@@ -21,29 +24,80 @@ export default function Index() {
2124
run();
2225
}, [run]);
2326

27+
const results = [
28+
{
29+
title: 'Original:',
30+
data: data.map((value, index) => (
31+
<View key={index} style={[styles.item, { height: value * 100 }]} />
32+
)),
33+
},
34+
{
35+
title: 'Trimmed scale:',
36+
data: trimmedScale(data, 0, 1).map((value, index) => (
37+
<View key={index} style={[styles.item, { height: value * 100 }]} />
38+
)),
39+
},
40+
{
41+
title: 'Robust scale:',
42+
data: robustScale(data, 0, 1).map((value, index) => (
43+
<View key={index} style={[styles.item, { height: value * 100 }]} />
44+
)),
45+
},
46+
{
47+
title: 'Scale + sample:',
48+
data: scale(sample(data, 35)).map((value, index) => (
49+
<View key={index} style={[styles.item, { height: value * 100 }]} />
50+
)),
51+
},
52+
{
53+
title: 'Scale:',
54+
data: scale(data).map((value, index) => (
55+
<View key={index} style={[styles.item, { height: value * 100 }]} />
56+
)),
57+
},
58+
];
59+
2460
return (
25-
<ScrollView horizontal contentContainerStyle={styles.root}>
26-
<View style={styles.container}>
27-
{data.map((item, index) => (
28-
<View key={index} style={[styles.item, { height: 500 * item }]} />
61+
<View style={styles.container}>
62+
<View>
63+
{results.map((_, index) => (
64+
<View style={styles.example} key={index}>
65+
<Text style={styles.title}>{_.title}</Text>
66+
<ScrollView horizontal style={styles.scroll}>
67+
<View style={styles.row}>{_.data}</View>
68+
</ScrollView>
69+
</View>
2970
))}
3071
</View>
31-
</ScrollView>
72+
</View>
3273
);
3374
}
3475

3576
const styles = StyleSheet.create({
36-
root: {
37-
flexGrow: 1,
38-
},
3977
container: {
4078
flex: 1,
41-
columnGap: 1,
79+
justifyContent: 'center',
80+
backgroundColor: '#ffffff',
81+
},
82+
loader: {
83+
padding: 30,
84+
},
85+
row: {
4286
flexDirection: 'row',
4387
alignItems: 'center',
4488
},
89+
title: {
90+
marginBottom: 5,
91+
},
92+
example: {
93+
padding: 10,
94+
},
95+
scroll: {
96+
maxHeight: 200,
97+
},
4598
item: {
4699
width: 3,
47-
backgroundColor: 'red',
100+
backgroundColor: 'blue',
101+
marginHorizontal: 2,
48102
},
49103
});

src/helpers.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
export function scale(arr: number[]) {
2+
if (arr.length === 0) {
3+
return [];
4+
}
5+
6+
const min = Math.min(...arr);
7+
const max = Math.max(...arr);
8+
const diff = max - min;
9+
10+
if (diff === 0) {
11+
// If diff is 0, all elements in the array are the same.
12+
// To avoid division by zero, return an array of the same length with 0 values.
13+
return arr.map(() => 0);
14+
}
15+
16+
return arr.map((value) => (value - min) / diff);
17+
}
18+
19+
export function sample(arr: number[], newSize: number) {
20+
const originalSize = arr.length;
21+
22+
if (newSize === 0) {
23+
return [];
24+
}
25+
26+
const result: number[] = [];
27+
28+
for (let i = 0; i < newSize; i++) {
29+
const index = Math.floor((i / newSize) * originalSize);
30+
result.push(arr[index] ?? 0);
31+
}
32+
33+
return result;
34+
}
35+
36+
export function robustScale(arr: number[], q1 = 0.05, q3 = 0.75) {
37+
if (arr.length === 0) {
38+
return [];
39+
}
40+
41+
const sortedArr = [...arr].sort((a, b) => a - b);
42+
43+
const q1Index = Math.floor((sortedArr.length - 1) * q1);
44+
const q3Index = Math.floor((sortedArr.length - 1) * q3);
45+
46+
const q1_ = sortedArr[q1Index];
47+
const q3_ = sortedArr[q3Index];
48+
49+
if (q1_ === undefined || q3_ === undefined || q1_ === q3_) {
50+
return arr.map(() => 0);
51+
}
52+
53+
const iqr = q3_ - q1_; // Interquartile Range
54+
55+
return arr.map((value) => {
56+
const scaledValue = (value - q1_) / iqr;
57+
58+
if (scaledValue < 0) return 0;
59+
if (scaledValue > 1) return 1;
60+
return scaledValue;
61+
});
62+
}
63+
64+
export function trimmedScale(
65+
arr: number[],
66+
lowerPercentile = 0.03,
67+
upperPercentile = 0.95
68+
) {
69+
if (arr.length === 0) {
70+
return [];
71+
}
72+
73+
const sortedArr = [...arr].sort((a, b) => a - b);
74+
75+
const lowerIndex = Math.floor((sortedArr.length - 1) * lowerPercentile);
76+
const upperIndex = Math.ceil((sortedArr.length - 1) * upperPercentile);
77+
78+
const min = sortedArr[lowerIndex];
79+
const max = sortedArr[upperIndex];
80+
81+
if (min === undefined || max === undefined || min === max) {
82+
return arr.map(() => 0);
83+
}
84+
85+
const diff = max - min;
86+
87+
return arr.map((value) => (value - min) / diff);
88+
}
File renamed without changes.

0 commit comments

Comments
 (0)