Skip to content

Commit f20410e

Browse files
maciejmakowski2003Maciej Makowski
andauthored
Feat/audio from url (#217)
* refactor: refactored AudioArray and AudioBus * feat: added playing audio file example * feat: added lib for mp3 decoding * feat: added sample mp3 file * feat: implemented decodeAudioData * refactor: yarn format * feat: added rn-fs and audio file * feat: added AudioSource type * feat: implemented decodeAudioDataSource * ci: yarn format * fix: fix after merge * feat: added playing audio file from url on IOS * feat: added support for require based audio source * refactor: pass source by cont ref * refactor: removed rn-fs --------- Co-authored-by: Maciej Makowski <[email protected]>
1 parent 261b8ac commit f20410e

Some content is hidden

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

51 files changed

+1044
-359
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React from 'react';
2+
import { useState, useRef, useEffect, FC } from 'react';
3+
import { Container, Button } from '../../components';
4+
5+
import {
6+
AudioContext,
7+
AudioBufferSourceNode,
8+
AudioBuffer,
9+
} from 'react-native-audio-api';
10+
11+
const AudioFile: FC = () => {
12+
const [isPlaying, setIsPlaying] = useState(false);
13+
14+
const audioContextRef = useRef<AudioContext | null>(null);
15+
const audioBufferSourceNodeRef = useRef<AudioBufferSourceNode | null>(null);
16+
const [audioBuffer, setAudioBuffer] = useState<AudioBuffer | null>(null);
17+
18+
const setup = () => {
19+
if (!audioContextRef.current) {
20+
audioContextRef.current = new AudioContext();
21+
}
22+
23+
audioBufferSourceNodeRef.current =
24+
audioContextRef.current.createBufferSource();
25+
audioBufferSourceNodeRef.current.buffer;
26+
audioBufferSourceNodeRef.current.connect(
27+
audioContextRef.current.destination
28+
);
29+
};
30+
31+
const fetchAudioBuffer = async () => {
32+
if (!audioContextRef.current) {
33+
audioContextRef.current = new AudioContext();
34+
}
35+
36+
setAudioBuffer(
37+
// audioContextRef.current.decodeAudioDataSource(
38+
// '/Users/maciejmakowski/projects/react-native-audio-api/apps/common-app/src/examples/AudioFile/runaway_kanye_west.mp3'
39+
// )
40+
audioContextRef.current.decodeAudioDataSource(
41+
'https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a'
42+
)
43+
);
44+
};
45+
46+
const handlePress = () => {
47+
if (isPlaying) {
48+
audioBufferSourceNodeRef.current?.stop();
49+
} else {
50+
setup();
51+
audioBufferSourceNodeRef.current!.buffer = audioBuffer;
52+
audioBufferSourceNodeRef.current?.start();
53+
}
54+
55+
setIsPlaying(!isPlaying);
56+
};
57+
58+
useEffect(() => {
59+
if (!audioContextRef.current) {
60+
audioContextRef.current = new AudioContext();
61+
}
62+
63+
fetchAudioBuffer();
64+
65+
return () => {
66+
audioContextRef.current?.close();
67+
};
68+
}, []);
69+
70+
return (
71+
<Container centered>
72+
<Button title={isPlaying ? 'Stop' : 'Play'} onPress={handlePress} />
73+
</Container>
74+
);
75+
};
76+
77+
export default AudioFile;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './AudioFile';
10.7 MB
Binary file not shown.

apps/common-app/src/examples/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import Piano from './Piano';
44
import Metronome from './Metronome';
55
import Oscillator from './Oscillator';
66
import DrumMachine from './DrumMachine';
7+
import AudioFile from './AudioFile';
78

89
type NavigationParamList = {
910
Oscillator: undefined;
1011
Metronome: undefined;
1112
DrumMachine: undefined;
1213
Piano: undefined;
14+
AudioFile: undefined;
1315
};
1416

1517
export type ExampleKey = keyof NavigationParamList;
@@ -47,4 +49,10 @@ export const Examples: Example[] = [
4749
subtitle: 'Generate sound waves',
4850
screen: Oscillator,
4951
},
52+
{
53+
key: 'AudioFile',
54+
title: 'Audio File',
55+
subtitle: 'Play an audio file',
56+
screen: AudioFile,
57+
},
5058
] as const;

apps/fabric-example/ios/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,7 +1598,7 @@ PODS:
15981598
- React-logger (= 0.76.0)
15991599
- React-perflogger (= 0.76.0)
16001600
- React-utils (= 0.76.0)
1601-
- RNAudioAPI (0.1.0):
1601+
- RNAudioAPI (0.2.0):
16021602
- DoubleConversion
16031603
- glog
16041604
- hermes-engine
@@ -2058,13 +2058,13 @@ SPEC CHECKSUMS:
20582058
React-utils: d9624101245ebaab39c9f1bd786132da0b4f27ff
20592059
ReactCodegen: dbfef1fef26f42c900bb1884fa149d49d501d64d
20602060
ReactCommon: 429ca28cd813c31359c73ffac6dc24f93347d522
2061-
RNAudioAPI: a4068f739b4e80e636ac6110d70858ea89ac4835
2061+
RNAudioAPI: adb400fcab1b85cafaff4e0880be5d4616fd4727
20622062
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

packages/react-native-audio-api/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11

2-
#include "AudioBus.h"
3-
#include "Constants.h"
4-
#include "AudioArray.h"
52
#include "AudioPlayer.h"
3+
#include "AudioArray.h"
4+
#include "AudioBus.h"
65
#include "AudioContext.h"
6+
#include "Constants.h"
77

88
namespace audioapi {
99

10-
AudioPlayer::AudioPlayer(const std::function<void(AudioBus*, int)> &renderAudio)
10+
AudioPlayer::AudioPlayer(
11+
const std::function<void(AudioBus *, int)> &renderAudio)
1112
: renderAudio_(renderAudio) {
1213
AudioStreamBuilder builder;
1314

@@ -20,7 +21,8 @@ AudioPlayer::AudioPlayer(const std::function<void(AudioBus*, int)> &renderAudio)
2021
->setDataCallback(this)
2122
->openStream(mStream_);
2223

23-
mBus_ = std::make_shared<AudioBus>(getSampleRate(), getBufferSizeInFrames(), CHANNEL_COUNT);
24+
mBus_ = std::make_shared<AudioBus>(
25+
getSampleRate(), getBufferSizeInFrames(), CHANNEL_COUNT);
2426
isInitialized_ = true;
2527
}
2628

@@ -62,7 +64,8 @@ DataCallbackResult AudioPlayer::onAudioReady(
6264
// TODO: optimize this with SIMD?
6365
for (int32_t i = 0; i < numFrames; i += 1) {
6466
for (int channel = 0; channel < CHANNEL_COUNT; channel += 1) {
65-
buffer[i * CHANNEL_COUNT + channel] = mBus_->getChannel(channel)->getData()[i];
67+
buffer[i * CHANNEL_COUNT + channel] =
68+
mBus_->getChannel(channel)->getData()[i];
6669
}
6770
}
6871

packages/react-native-audio-api/android/src/main/cpp/AudioPlayer/AudioPlayer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class AudioBus;
1212

1313
class AudioPlayer : public AudioStreamDataCallback {
1414
public:
15-
explicit AudioPlayer(const std::function<void(AudioBus*, int)> &renderAudio);
15+
explicit AudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio);
1616

1717
int getSampleRate() const;
1818
int getBufferSizeInFrames() const;
@@ -25,7 +25,7 @@ class AudioPlayer : public AudioStreamDataCallback {
2525
int32_t numFrames) override;
2626

2727
private:
28-
std::function<void(AudioBus*, int)> renderAudio_;
28+
std::function<void(AudioBus *, int)> renderAudio_;
2929
std::shared_ptr<AudioStream> mStream_;
3030
std::shared_ptr<AudioBus> mBus_;
3131
bool isInitialized_ = false;

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ std::vector<jsi::PropNameID> BaseAudioContextHostObject::getPropertyNames(
3030
propertyNames.push_back(jsi::PropNameID::forUtf8(runtime, "createBuffer"));
3131
propertyNames.push_back(
3232
jsi::PropNameID::forUtf8(runtime, "createPeriodicWave"));
33+
propertyNames.push_back(
34+
jsi::PropNameID::forUtf8(runtime, "decodeAudioDataSource"));
3335
return propertyNames;
3436
}
3537

@@ -200,6 +202,25 @@ jsi::Value BaseAudioContextHostObject::get(
200202
});
201203
}
202204

205+
if (propName == "decodeAudioDataSource") {
206+
return jsi::Function::createFromHostFunction(
207+
runtime,
208+
propNameId,
209+
1,
210+
[this](
211+
jsi::Runtime &runtime,
212+
const jsi::Value &thisValue,
213+
const jsi::Value *arguments,
214+
size_t count) -> jsi::Value {
215+
std::string source = arguments[0].getString(runtime).utf8(runtime);
216+
auto buffer = wrapper_->decodeAudioDataSource(source);
217+
auto audioBufferHostObject =
218+
AudioBufferHostObject::createFromWrapper(buffer);
219+
return jsi::Object::createFromHostObject(
220+
runtime, audioBufferHostObject);
221+
});
222+
}
223+
203224
throw std::runtime_error("Not yet implemented!");
204225
}
205226

packages/react-native-audio-api/common/cpp/core/AudioArray.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@
55

66
namespace audioapi {
77

8-
AudioArray::AudioArray(int size) : size_(size), data_(0) {
8+
AudioArray::AudioArray(int size) : data_(nullptr), size_(size) {
99
resize(size);
1010
}
1111

1212
AudioArray::~AudioArray() {
1313
if (data_) {
1414
delete[] data_;
15-
data_ = 0;
15+
data_ = nullptr;
1616
}
1717
}
1818

1919
int AudioArray::getSize() const {
2020
return size_;
2121
}
2222

23-
float* AudioArray::getData() const {
23+
float *AudioArray::getData() const {
2424
return data_;
2525
}
2626

27-
float& AudioArray::operator[](int index) {
27+
float &AudioArray::operator[](int index) {
2828
return data_[index];
2929
}
3030

31-
const float& AudioArray::operator[](int index) const {
31+
const float &AudioArray::operator[](int index) const {
3232
return data_[index];
3333
}
3434

@@ -75,29 +75,43 @@ void AudioArray::zero(int start, int length) {
7575
memset(data_ + start, 0, length * sizeof(float));
7676
}
7777

78-
void AudioArray::sum(const AudioArray* source) {
78+
void AudioArray::sum(const AudioArray *source) {
7979
sum(source, 0, 0, size_);
8080
}
8181

82-
void AudioArray::sum(const AudioArray* source, int start, int length) {
82+
void AudioArray::sum(const AudioArray *source, int start, int length) {
8383
sum(source, start, start, length);
8484
}
8585

86-
void AudioArray::sum(const AudioArray* source, int sourceStart, int destinationStart, int length) {
87-
VectorMath::add(data_ + destinationStart, source->getData() + sourceStart, data_ + destinationStart, length);
86+
void AudioArray::sum(
87+
const AudioArray *source,
88+
int sourceStart,
89+
int destinationStart,
90+
int length) {
91+
VectorMath::add(
92+
data_ + destinationStart,
93+
source->getData() + sourceStart,
94+
data_ + destinationStart,
95+
length);
8896
}
8997

90-
void AudioArray::copy(const AudioArray* source) {
98+
void AudioArray::copy(const AudioArray *source) {
9199
copy(source, 0, size_);
92100
}
93101

94-
void AudioArray::copy(const AudioArray* source, int start, int length) {
102+
void AudioArray::copy(const AudioArray *source, int start, int length) {
95103
copy(source, start, start, length);
96104
}
97105

98-
void AudioArray::copy(const AudioArray* source, int sourceStart, int destinationStart, int length) {
99-
memcpy(data_ + destinationStart, source->getData() + sourceStart, length * sizeof(float));
106+
void AudioArray::copy(
107+
const AudioArray *source,
108+
int sourceStart,
109+
int destinationStart,
110+
int length) {
111+
memcpy(
112+
data_ + destinationStart,
113+
source->getData() + sourceStart,
114+
length * sizeof(float));
100115
}
101116

102117
} // namespace audioapi
103-

packages/react-native-audio-api/common/cpp/core/AudioArray.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

3-
#include <memory>
43
#include <algorithm>
4+
#include <memory>
55

66
namespace audioapi {
77

@@ -11,28 +11,34 @@ class AudioArray {
1111
~AudioArray();
1212

1313
[[nodiscard]] int getSize() const;
14-
float* getData() const;
15-
14+
[[nodiscard]] float *getData() const;
1615

17-
float& operator[](int index);
18-
const float& operator[](int index) const;
16+
float &operator[](int index);
17+
const float &operator[](int index) const;
1918

2019
void normalize();
2120
void resize(int size);
2221
void scale(float value);
23-
float getMaxAbsValue() const;
22+
[[nodiscard]] float getMaxAbsValue() const;
2423

2524
void zero();
2625
void zero(int start, int length);
2726

28-
void sum(const AudioArray* source);
29-
void sum(const AudioArray* source, int start, int length);
30-
void sum(const AudioArray* source, int sourceStart, int destinationStart, int length);
31-
32-
void copy(const AudioArray* source);
33-
void copy(const AudioArray* source, int start, int length);
34-
void copy(const AudioArray* source, int sourceStart, int destinationStart, int length);
35-
27+
void sum(const AudioArray *source);
28+
void sum(const AudioArray *source, int start, int length);
29+
void sum(
30+
const AudioArray *source,
31+
int sourceStart,
32+
int destinationStart,
33+
int length);
34+
35+
void copy(const AudioArray *source);
36+
void copy(const AudioArray *source, int start, int length);
37+
void copy(
38+
const AudioArray *source,
39+
int sourceStart,
40+
int destinationStart,
41+
int length);
3642

3743
private:
3844
float *data_;

0 commit comments

Comments
 (0)