Skip to content

Commit c7acb44

Browse files
maciejmakowski2003Maciej Makowski
and
Maciej Makowski
authored
Feat/periodic wave (#205)
* feat: added periodic wave cpp files * feat: added props * refactor: enums refactoring * feat: declared different constructor of PeriodicWave * ci: yarn format * feat: added generating coeffs for basic wave forms function * feat: added fft implementation for ios * feat: added creating band limited tables * feat: defined preprocessor macro for using Accelerate on ios * feat: implemented getWaveDataTableForFundamentalFrequency function and fixed some nitpicks * feat: implemented interpolation and gettingSample * feat: added getRateScale * feat: introduced PeriodicWave into OscillatorNode * feat: added caching for periodicWave * feat: added createPeriodicWave BaseAudioContext method * feat: implemented setPeriodicWave method * feat: implemented PeriodicWave wrapper and HostObject * feat: updated interfaces * docs: updated API coverage * ci: spell-checker checks only .md files * ci: added rnaa to allowed words * refactor: yarn lint fixes * refactor: enhanced modulo operation, fixed small nitpicks and added comments * fix: fixed interfaces and errors connected with PeriodicWave * feat: added disableNormalization PeriodicWave constraint * fix: removed commented code * refactor: changed bufferIndex param name to phase * feat: added kfr lib but it does not work * fix: fixed buildi kfr * fix: finally works on Android * ci: yarn format * feat: added kfr as submodule * ci: yarn lint * refactor: moved kfr to external/kfr * fix: fixed kfr submodule --------- Co-authored-by: Maciej Makowski <maciej.makowski@swmansion.com>
1 parent 4d11298 commit c7acb44

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1460
-2014
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ shopify
2424
skia
2525
swm
2626
swmansion
27+
rnaa
2728

2829
tada
2930
vec

.github/actions/spelling/only.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
\.ts$
2-
\.tsx$
3-
41
\.md$

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ android/keystores/debug.keystore
7777
# Turborepo
7878
.turbo/
7979

80-
# generated by bob
81-
lib/
80+
packages/react-native-audio-api/lib
8281

8382
# Android
8483
.kotlin

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "packages/react-native-audio-api/external/kfr"]
2+
path = packages/react-native-audio-api/external/kfr
3+
url = https://github.com/kfrlib/kfr.git

apps/common-app/src/examples/Oscillator/Oscillator.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
GainNode,
77
OscillatorNode,
88
StereoPannerNode,
9-
type WaveType,
9+
type OscillatorType,
1010
} from 'react-native-audio-api';
1111

1212
import { Container, Slider, Spacer, Button } from '../../components';
@@ -26,7 +26,7 @@ const Oscillator: FC = () => {
2626
const [frequency, setFrequency] = useState(INITIAL_FREQUENCY);
2727
const [detune, setDetune] = useState(INITIAL_DETUNE);
2828
const [pan, setPan] = useState(INITIAL_PAN);
29-
const [oscillatorType, setOscillatorType] = useState<WaveType>('sine');
29+
const [oscillatorType, setOscillatorType] = useState<OscillatorType>('sine');
3030

3131
const audioContextRef = useRef<AudioContext | null>(null);
3232
const oscillatorRef = useRef<OscillatorNode | null>(null);
@@ -97,7 +97,7 @@ const Oscillator: FC = () => {
9797
setIsPlaying((prev) => !prev);
9898
};
9999

100-
const handleOscillatorTypeChange = (type: WaveType) => {
100+
const handleOscillatorTypeChange = (type: OscillatorType) => {
101101
setOscillatorType(type);
102102
if (oscillatorRef.current) {
103103
oscillatorRef.current.type = type;
@@ -159,7 +159,7 @@ const Oscillator: FC = () => {
159159
/>
160160
<Spacer.Vertical size={40} />
161161
<View style={styles.oscillatorTypeContainer}>
162-
{OSCILLATOR_TYPES.map((type: WaveType) => (
162+
{OSCILLATOR_TYPES.map((type: OscillatorType) => (
163163
<Pressable
164164
key={type}
165165
style={({ pressed }) => [

apps/fabric-example/ios/Podfile.lock

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@ PODS:
13081308
- ReactCommon/turbomodule/bridging
13091309
- ReactCommon/turbomodule/core
13101310
- Yoga
1311-
- react-native-skia (1.5.1):
1311+
- react-native-skia (1.5.3):
13121312
- DoubleConversion
13131313
- glog
13141314
- hermes-engine
@@ -1619,7 +1619,7 @@ PODS:
16191619
- ReactCommon/turbomodule/bridging
16201620
- ReactCommon/turbomodule/core
16211621
- Yoga
1622-
- RNGestureHandler (2.20.2):
1622+
- RNGestureHandler (2.21.1):
16231623
- DoubleConversion
16241624
- glog
16251625
- hermes-engine
@@ -2030,7 +2030,7 @@ SPEC CHECKSUMS:
20302030
React-Mapbuffer: b0b4ace5b62b269f3838df26ba2d8b4f39f90783
20312031
React-microtasksnativemodule: 0b7db04c18f6bb01ef5b1f9007c3229abecc35dd
20322032
react-native-safe-area-context: 2500e4fe998caad50ad3bc51ec23ef951308569e
2033-
react-native-skia: 7346a82f02bd8c318611ea22b78ae9ebfba97bb4
2033+
react-native-skia: b5216ffad62ec47294094cb25630332bb8f96493
20342034
React-nativeconfig: 72c10ff34863148ef90df9c9c8eacba99d2faaaa
20352035
React-NativeModulesApple: 5ec49182fa000b2215ee1bed03e2867f8323ccf5
20362036
React-perflogger: 073c7a8a436b3fe724f1df34e9d1f3db1d25fe74
@@ -2058,13 +2058,13 @@ SPEC CHECKSUMS:
20582058
React-utils: d9624101245ebaab39c9f1bd786132da0b4f27ff
20592059
ReactCodegen: dbfef1fef26f42c900bb1884fa149d49d501d64d
20602060
ReactCommon: 429ca28cd813c31359c73ffac6dc24f93347d522
2061-
RNAudioAPI: c2c7e844f9245985fca7b1ae9c872d23e7528837
2062-
RNGestureHandler: fc5ce5bf284640d3af6431c3a5c3bc121e98d045
2061+
RNAudioAPI: a4068f739b4e80e636ac6110d70858ea89ac4835
2062+
RNGestureHandler: a3822e519fd1e9885b92d8c9bd82a7a0be305fe3
20632063
RNReanimated: 77242c6d67416988a2fd9f5cf574bb3e60016362
20642064
RNScreens: e389d6a6a66a4f0d3662924ecae803073ccce8ec
20652065
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
2066-
Yoga: 1d66db49f38fd9e576a1d7c3b081e46ab4c28b9e
2066+
Yoga: f8ec45ce98bba1bc93dd28f2ee37215180e6d2b6
20672067

20682068
PODFILE CHECKSUM: 75ad38075e71875257a2590065853ea6a608b897
20692069

2070-
COCOAPODS: 1.16.2
2070+
COCOAPODS: 1.15.2

docs/web-audio-coverage.md

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Some of the noticeable implementation details that are still in progress or not
77
- Support of different number of channels (current approach in most of the audio-graph nodes assumes working with two channel audio)
88
- Multi-input for each node and input mixing (Although specification suggests that most of the nodes can cave only one input or output, common use-cases proves otherwise). Only node that mixes multiple inputs is `DestinationNode`.
99

10-
## ✅ Completed (**7** out of 33)
10+
## ✅ Completed (**9** out of 33)
1111

1212
<details>
1313
<summary><b>AudioBuffer</b></summary>
@@ -27,11 +27,17 @@ Some of the noticeable implementation details that are still in progress or not
2727
<details>
2828
<summary><b>GainNode</b></summary>
2929
</details>
30+
<details>
31+
<summary><b>OscillatorNode</b></summary>
32+
</details>
33+
<details>
34+
<summary><b>PeriodicWave</b></summary>
35+
</details>
3036
<details>
3137
<summary><b>StereoPannerNode</b></summary>
3238
</details>
3339

34-
## 🚧 In Progress (**5** out of 33)
40+
## 🚧 In Progress (**4** out of 33)
3541

3642
<details>
3743
<summary><b>AudioContext</b></summary>
@@ -123,7 +129,7 @@ Some of the noticeable implementation details that are still in progress or not
123129
| 🔘 createIIRFilter ||
124130
| 🔘 createOscillator ||
125131
| 🔘 createPanner ||
126-
| 🔘 createPeriodicWave | |
132+
| 🔘 createPeriodicWave | |
127133
| 🔘 createStereoPanner ||
128134
| 🔘 createWaveShaper ||
129135
| 🔘 decodeAudioData ||
@@ -132,23 +138,7 @@ Some of the noticeable implementation details that are still in progress or not
132138

133139
</details>
134140

135-
<details>
136-
<summary><b>OscillatorNode</b></summary>
137-
138-
<div style="padding: 16px; padding-left: 42px;">
139-
140-
| Property 🔹/ Method 🔘 | state |
141-
| ---------------------- | ----- |
142-
| 🔹 frequency ||
143-
| 🔹 detune ||
144-
| 🔹 type ||
145-
| 🔘 setPeriodicWave ||
146-
147-
</div>
148-
149-
</details>
150-
151-
## ❌ Not yet available (**21** out of 33)
141+
## ❌ Not yet available (**20** out of 33)
152142

153143
<details>
154144
<summary><b>AudioParamMap</b></summary>
@@ -174,9 +164,6 @@ Some of the noticeable implementation details that are still in progress or not
174164
<details>
175165
<summary><b>WaveShaperNode</b></summary>
176166
</details>
177-
<details>
178-
<summary><b>PeriodicWave</b></summary>
179-
</details>
180167
<details>
181168
<summary><b>IIRFilterNode</b></summary>
182169
</details>

packages/react-native-audio-api/RNAudioAPI.podspec

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ Pod::Spec.new do |s|
1616

1717
s.source_files = "ios/**/*.{h,m,mm}", "common/cpp/**/*.{hpp,cpp,c,h}"
1818

19+
s.ios.frameworks = 'Accelerate'
20+
s.xcconfig = {
21+
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) HAVE_ACCELERATE=1'
22+
}
23+
1924
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
2025
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
2126
if respond_to?(:install_modules_dependencies, true)

packages/react-native-audio-api/android/CMakeLists.txt

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.9.0)
1+
cmake_minimum_required(VERSION 3.12.0)
22
project(react-native-audio-api)
33

44
set(CMAKE_VERBOSE_MAKEFILE ON)
@@ -32,8 +32,11 @@ file(GLOB_RECURSE SOURCE_FILES
3232
"../common/cpp/HostObjects/*.h"
3333
"../common/cpp/utils/*.cpp"
3434
"../common/cpp/utils/*.h"
35+
"../common/cpp/types/*.h"
3536
)
3637

38+
add_subdirectory(../external/kfr ${CMAKE_CURRENT_BINARY_DIR}/kfr-build)
39+
3740
add_library(react-native-audio-api SHARED ${SOURCE_FILES})
3841

3942
file(GLOB DIRS CONFIGURE_DEPENDS "src/main/cpp/**" "../common/cpp/**")
@@ -49,25 +52,18 @@ target_include_directories(
4952

5053
find_package(ReactAndroid REQUIRED CONFIG)
5154
find_package(fbjni REQUIRED CONFIG)
52-
find_package (oboe REQUIRED CONFIG)
53-
54-
# set(LINK_LIBRARIES
55-
# ReactAndroid::reactnative
56-
# ReactAndroid::jsi
57-
# fbjni::fbjni
58-
# android
59-
# log
60-
# oboe::oboe
61-
# )
62-
63-
# target_link_libraries(react-native-audio-api ${LINK_LIBRARIES})
55+
find_package(oboe REQUIRED CONFIG)
6456

6557
set(LINK_LIBRARIES
6658
ReactAndroid::jsi
6759
fbjni::fbjni
6860
android
6961
log
7062
oboe::oboe
63+
kfr
64+
kfr_dsp
65+
kfr_dft
66+
kfr_io
7167
)
7268

7369
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
@@ -83,4 +79,3 @@ else()
8379
endif()
8480

8581
target_link_libraries(react-native-audio-api ${LINK_LIBRARIES} ${RN_VERSION_LINK_LIBRARIES})
86-

packages/react-native-audio-api/common/cpp/HostObjects/BaseAudioContextHostObject.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ std::vector<jsi::PropNameID> BaseAudioContextHostObject::getPropertyNames(
2828
propertyNames.push_back(
2929
jsi::PropNameID::forUtf8(runtime, "createBufferSource"));
3030
propertyNames.push_back(jsi::PropNameID::forUtf8(runtime, "createBuffer"));
31+
propertyNames.push_back(
32+
jsi::PropNameID::forUtf8(runtime, "createPeriodicWave"));
3133
return propertyNames;
3234
}
3335

@@ -161,6 +163,43 @@ jsi::Value BaseAudioContextHostObject::get(
161163
});
162164
}
163165

166+
if (propName == "createPeriodicWave") {
167+
return jsi::Function::createFromHostFunction(
168+
runtime,
169+
propNameId,
170+
3,
171+
[this](
172+
jsi::Runtime &runtime,
173+
const jsi::Value &thisValue,
174+
const jsi::Value *arguments,
175+
size_t count) -> jsi::Value {
176+
auto real = arguments[0].getObject(runtime).getArray(runtime);
177+
auto imag = arguments[1].getObject(runtime).getArray(runtime);
178+
auto disableNormalization = arguments[2].getBool();
179+
auto length =
180+
static_cast<int>(real.getProperty(runtime, "length").asNumber());
181+
182+
auto *realData = new float[length];
183+
auto *imagData = new float[length];
184+
185+
for (size_t i = 0; i < real.length(runtime); i++) {
186+
realData[i] = static_cast<float>(
187+
real.getValueAtIndex(runtime, i).getNumber());
188+
}
189+
for (size_t i = 0; i < imag.length(runtime); i++) {
190+
realData[i] = static_cast<float>(
191+
imag.getValueAtIndex(runtime, i).getNumber());
192+
}
193+
194+
auto periodicWave = wrapper_->createPeriodicWave(
195+
realData, imagData, disableNormalization, length);
196+
auto periodicWaveHostObject =
197+
PeriodicWaveHostObject::createFromWrapper(periodicWave);
198+
return jsi::Object::createFromHostObject(
199+
runtime, periodicWaveHostObject);
200+
});
201+
}
202+
164203
throw std::runtime_error("Not yet implemented!");
165204
}
166205

packages/react-native-audio-api/common/cpp/HostObjects/BaseAudioContextHostObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "BiquadFilterNodeHostObject.h"
1313
#include "GainNodeHostObject.h"
1414
#include "OscillatorNodeHostObject.h"
15+
#include "PeriodicWaveHostObject.h"
1516
#include "StereoPannerNodeHostObject.h"
1617

1718
namespace audioapi {

packages/react-native-audio-api/common/cpp/HostObjects/OscillatorNodeHostObject.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ std::vector<jsi::PropNameID> OscillatorNodeHostObject::getPropertyNames(
2424
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "frequency"));
2525
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "detune"));
2626
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "type"));
27+
propertyNames.push_back(
28+
jsi::PropNameID::forAscii(runtime, "setPeriodicWave"));
2729
return propertyNames;
2830
}
2931

@@ -46,6 +48,25 @@ jsi::Value OscillatorNodeHostObject::get(
4648
return jsi::String::createFromUtf8(runtime, waveType);
4749
}
4850

51+
if (propName == "setPeriodicWave") {
52+
return jsi::Function::createFromHostFunction(
53+
runtime,
54+
propNameId,
55+
1,
56+
[this](
57+
jsi::Runtime &rt,
58+
const jsi::Value &thisVal,
59+
const jsi::Value *args,
60+
size_t count) -> jsi::Value {
61+
auto wrapper = getOscillatorNodeWrapperFromAudioNodeWrapper();
62+
auto periodicWaveHostObject =
63+
args[0].getObject(rt).asHostObject<PeriodicWaveHostObject>(rt);
64+
65+
wrapper->setPeriodicWave(periodicWaveHostObject->wrapper_);
66+
return jsi::Value::undefined();
67+
});
68+
}
69+
4970
return AudioScheduledSourceNodeHostObject::get(runtime, propNameId);
5071
}
5172

packages/react-native-audio-api/common/cpp/HostObjects/OscillatorNodeHostObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "AudioParamHostObject.h"
88
#include "AudioScheduledSourceNodeHostObject.h"
99
#include "OscillatorNodeWrapper.h"
10+
#include "PeriodicWaveHostObject.h"
1011

1112
namespace audioapi {
1213
using namespace facebook;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "PeriodicWaveHostObject.h"
2+
3+
namespace audioapi {
4+
using namespace facebook;
5+
6+
PeriodicWaveHostObject::PeriodicWaveHostObject(
7+
const std::shared_ptr<PeriodicWaveWrapper> &wrapper)
8+
: wrapper_(wrapper) {}
9+
10+
std::vector<jsi::PropNameID> PeriodicWaveHostObject::getPropertyNames(
11+
jsi::Runtime &runtime) {
12+
std::vector<jsi::PropNameID> propertyNames;
13+
return propertyNames;
14+
}
15+
16+
jsi::Value PeriodicWaveHostObject::get(
17+
jsi::Runtime &runtime,
18+
const jsi::PropNameID &propNameId) {
19+
auto propName = propNameId.utf8(runtime);
20+
21+
throw std::runtime_error("Not yet implemented!");
22+
}
23+
24+
void PeriodicWaveHostObject::set(
25+
jsi::Runtime &runtime,
26+
const jsi::PropNameID &propNameId,
27+
const jsi::Value &value) {
28+
auto propName = propNameId.utf8(runtime);
29+
30+
throw std::runtime_error("Not yet implemented!");
31+
}
32+
33+
} // namespace audioapi

0 commit comments

Comments
 (0)