react-native-audio-api 0.8.3-nightly-ea268f4-20251006 → 0.9.0-nightly-96a5bcd-20251007
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp} +79 -75
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +99 -43
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +1 -101
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +0 -3
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +107 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +0 -2
- package/common/cpp/audioapi/core/AudioNode.cpp +3 -3
- package/common/cpp/audioapi/core/AudioNode.h +1 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +0 -35
- package/common/cpp/audioapi/core/BaseAudioContext.h +4 -12
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +0 -2
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +3 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
- package/common/cpp/audioapi/core/effects/GainNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +17 -12
- package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -2
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +2 -2
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +4 -2
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +4 -2
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +4 -2
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +7 -2
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +3 -1
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +9 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.h +1 -1
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +6 -4
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +2 -2
- package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -90
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +241 -282
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +57 -19
- package/common/cpp/test/CMakeLists.txt +2 -1
- package/common/cpp/test/GainTest.cpp +9 -9
- package/common/cpp/test/StereoPannerTest.cpp +129 -0
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +1 -2
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
- package/lib/commonjs/api.js +14 -1
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioDecoder.js +48 -0
- package/lib/commonjs/core/AudioDecoder.js.map +1 -0
- package/lib/commonjs/core/BaseAudioContext.js +11 -18
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/module/api.js +2 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioDecoder.js +42 -0
- package/lib/module/core/AudioDecoder.js.map +1 -0
- package/lib/module/core/BaseAudioContext.js +11 -18
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +3 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioDecoder.d.ts +4 -0
- package/lib/typescript/core/AudioDecoder.d.ts.map +1 -0
- package/lib/typescript/core/BaseAudioContext.d.ts +3 -6
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +6 -3
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +5 -0
- package/src/core/AudioDecoder.ts +78 -0
- package/src/core/BaseAudioContext.ts +26 -29
- package/src/interfaces.ts +18 -6
- package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* This file dynamically links to the FFmpeg library, which is licensed under
|
|
3
|
-
* GNU Lesser General Public License (LGPL) version 2.1 or later.
|
|
2
|
+
* This file dynamically links to the FFmpeg library, which is licensed under
|
|
3
|
+
* the GNU Lesser General Public License (LGPL) version 2.1 or later.
|
|
4
4
|
*
|
|
5
|
-
* Our own code in this file is licensed under the MIT License and dynamic
|
|
6
|
-
* allows you to use this code without your entire project being subject
|
|
7
|
-
* terms of the LGPL. However, note that if you link statically to
|
|
8
|
-
* comply with the terms of the LGPL for FFmpeg itself.
|
|
5
|
+
* Our own code in this file is licensed under the MIT License and dynamic
|
|
6
|
+
* linking allows you to use this code without your entire project being subject
|
|
7
|
+
* to the terms of the LGPL. However, note that if you link statically to
|
|
8
|
+
* FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
#include <audioapi/utils/AudioBus.h>
|
|
@@ -14,24 +14,62 @@
|
|
|
14
14
|
#include <vector>
|
|
15
15
|
|
|
16
16
|
extern "C" {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
#include <libavcodec/avcodec.h>
|
|
18
|
+
#include <libavformat/avformat.h>
|
|
19
|
+
#include <libavutil/opt.h>
|
|
20
|
+
#include <libswresample/swresample.h>
|
|
21
21
|
}
|
|
22
|
+
class AudioBuffer;
|
|
22
23
|
|
|
23
|
-
namespace audioapi::
|
|
24
|
+
namespace audioapi::ffmpegdecoder {
|
|
24
25
|
// Custom IO context for reading from memory
|
|
25
26
|
struct MemoryIOContext {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const uint8_t *data;
|
|
28
|
+
size_t size;
|
|
29
|
+
size_t pos;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
struct AudioStreamContext {
|
|
33
|
+
AVFormatContext *fmt_ctx = nullptr;
|
|
34
|
+
AVCodecContext *codec_ctx = nullptr;
|
|
35
|
+
int audio_stream_index = -1;
|
|
36
|
+
};
|
|
30
37
|
|
|
31
38
|
int read_packet(void *opaque, uint8_t *buf, int buf_size);
|
|
32
39
|
int64_t seek_packet(void *opaque, int64_t offset, int whence);
|
|
33
|
-
|
|
34
|
-
std::vector<
|
|
35
|
-
|
|
40
|
+
inline int findAudioStreamIndex(AVFormatContext *fmt_ctx);
|
|
41
|
+
std::vector<float> readAllPcmFrames(
|
|
42
|
+
AVFormatContext *fmt_ctx,
|
|
43
|
+
AVCodecContext *codec_ctx,
|
|
44
|
+
int out_sample_rate,
|
|
45
|
+
int output_channel_count,
|
|
46
|
+
int audio_stream_index,
|
|
47
|
+
size_t &framesRead);
|
|
48
|
+
|
|
49
|
+
void convertFrameToBuffer(
|
|
50
|
+
SwrContext *swr,
|
|
51
|
+
AVFrame *frame,
|
|
52
|
+
int output_channel_count,
|
|
53
|
+
std::vector<float> &buffer,
|
|
54
|
+
size_t &framesRead,
|
|
55
|
+
uint8_t **&resampled_data,
|
|
56
|
+
int &max_resampled_samples);
|
|
57
|
+
bool setupDecoderContext(
|
|
58
|
+
AVFormatContext *fmt_ctx,
|
|
59
|
+
int &audio_stream_index,
|
|
60
|
+
std::unique_ptr<AVCodecContext, decltype(&avcodec_free_context)>
|
|
61
|
+
&codec_ctx);
|
|
62
|
+
std::shared_ptr<AudioBuffer> decodeAudioFrames(
|
|
63
|
+
AVFormatContext *fmt_ctx,
|
|
64
|
+
AVCodecContext *codec_ctx,
|
|
65
|
+
int audio_stream_index,
|
|
66
|
+
int sample_rate);
|
|
67
|
+
|
|
68
|
+
std::shared_ptr<AudioBuffer>
|
|
69
|
+
decodeWithMemoryBlock(const void *data, size_t size, int sample_rate);
|
|
70
|
+
|
|
71
|
+
std::shared_ptr<AudioBuffer> decodeWithFilePath(
|
|
72
|
+
const std::string &path,
|
|
73
|
+
int sample_rate);
|
|
36
74
|
|
|
37
|
-
} // namespace audioapi::ffmpegdecoder
|
|
75
|
+
} // namespace audioapi::ffmpegdecoder
|
|
@@ -21,7 +21,7 @@ enable_testing()
|
|
|
21
21
|
file(GLOB_RECURSE RNAUDIOAPI_SRC
|
|
22
22
|
CONFIGURE_DEPENDS
|
|
23
23
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/*.cpp"
|
|
24
|
-
"${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp"
|
|
24
|
+
"${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp"
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
# exclude HostObjects from tests
|
|
@@ -67,6 +67,7 @@ add_executable(
|
|
|
67
67
|
OscillatorTest.cpp
|
|
68
68
|
GainTest.cpp
|
|
69
69
|
AudioParamTest.cpp
|
|
70
|
+
StereoPannerTest.cpp
|
|
70
71
|
)
|
|
71
72
|
|
|
72
73
|
add_compile_definitions(AUDIO_API_TEST_SUITE)
|
|
@@ -28,10 +28,10 @@ class TestableGainNode : public audioapi::GainNode {
|
|
|
28
28
|
getGainParam()->setValue(value);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
std::shared_ptr<audioapi::AudioBus> processNode(
|
|
32
32
|
const std::shared_ptr<audioapi::AudioBus> &processingBus,
|
|
33
33
|
int framesToProcess) override {
|
|
34
|
-
audioapi::GainNode::processNode(processingBus, framesToProcess);
|
|
34
|
+
return audioapi::GainNode::processNode(processingBus, framesToProcess);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -52,9 +52,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectly) {
|
|
|
52
52
|
bus->getChannel(0)->getData()[i] = i + 1;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
56
|
-
for (size_t i = 0; i <
|
|
57
|
-
EXPECT_FLOAT_EQ((*
|
|
55
|
+
auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
56
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
57
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -71,9 +71,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) {
|
|
|
71
71
|
bus->getChannel(1)->getData()[i] = -i - 1;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
75
|
-
for (size_t i = 0; i <
|
|
76
|
-
EXPECT_FLOAT_EQ((*
|
|
77
|
-
EXPECT_FLOAT_EQ((*
|
|
74
|
+
auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
75
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
76
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
|
|
77
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(1))[i], (-i - 1) * GAIN_VALUE);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#include <audioapi/core/OfflineAudioContext.h>
|
|
2
|
+
#include <audioapi/core/effects/StereoPannerNode.h>
|
|
3
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
4
|
+
#include <audioapi/utils/AudioArray.h>
|
|
5
|
+
#include <audioapi/utils/AudioBus.h>
|
|
6
|
+
#include <gtest/gtest.h>
|
|
7
|
+
#include "MockAudioEventHandlerRegistry.h"
|
|
8
|
+
|
|
9
|
+
using namespace audioapi;
|
|
10
|
+
|
|
11
|
+
class StereoPannerTest : public ::testing::Test {
|
|
12
|
+
protected:
|
|
13
|
+
std::shared_ptr<IAudioEventHandlerRegistry> eventRegistry;
|
|
14
|
+
std::unique_ptr<OfflineAudioContext> context;
|
|
15
|
+
static constexpr int sampleRate = 44100;
|
|
16
|
+
|
|
17
|
+
void SetUp() override {
|
|
18
|
+
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
|
|
19
|
+
context = std::make_unique<OfflineAudioContext>(
|
|
20
|
+
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class TestableStereoPannerNode : public StereoPannerNode {
|
|
25
|
+
public:
|
|
26
|
+
explicit TestableStereoPannerNode(BaseAudioContext *context)
|
|
27
|
+
: StereoPannerNode(context) {}
|
|
28
|
+
|
|
29
|
+
void setPanParam(float value) {
|
|
30
|
+
getPanParam()->setValue(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
std::shared_ptr<AudioBus> processNode(
|
|
34
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
35
|
+
int framesToProcess) override {
|
|
36
|
+
return StereoPannerNode::processNode(processingBus, framesToProcess);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
TEST_F(StereoPannerTest, StereoPannerCanBeCreated) {
|
|
41
|
+
auto panner = context->createStereoPanner();
|
|
42
|
+
ASSERT_NE(panner, nullptr);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) {
|
|
46
|
+
static constexpr float PAN_VALUE = 0.5;
|
|
47
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
48
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
49
|
+
panNode->setPanParam(PAN_VALUE);
|
|
50
|
+
|
|
51
|
+
auto bus =
|
|
52
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 1, sampleRate);
|
|
53
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
54
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
58
|
+
// x = (0.5 + 1) / 2 = 0.75
|
|
59
|
+
// gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
|
|
60
|
+
// gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
|
|
61
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
62
|
+
EXPECT_NEAR(
|
|
63
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
64
|
+
(i + 1) * 0.38268343236508984,
|
|
65
|
+
1e-4);
|
|
66
|
+
EXPECT_NEAR(
|
|
67
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
68
|
+
(i + 1) * 0.9238795325112867,
|
|
69
|
+
1e-4);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) {
|
|
74
|
+
static constexpr float PAN_VALUE = -0.5;
|
|
75
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
76
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
77
|
+
panNode->setPanParam(PAN_VALUE);
|
|
78
|
+
|
|
79
|
+
auto bus =
|
|
80
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
|
|
81
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
82
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
83
|
+
(*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
87
|
+
// x = -0.5 + 1 = 0.5
|
|
88
|
+
// gainL = cos(x * (π / 2)) = cos(0.5 * (π / 2)) = 0.7071067811865476
|
|
89
|
+
// gainR = sin(x * (π / 2)) = sin(0.5 * (π / 2)) = 0.7071067811865476
|
|
90
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
91
|
+
EXPECT_NEAR(
|
|
92
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
93
|
+
(i + 1) + (i + 1) * 0.7071067811865476,
|
|
94
|
+
1e-4);
|
|
95
|
+
EXPECT_NEAR(
|
|
96
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
97
|
+
(i + 1) * 0.7071067811865476,
|
|
98
|
+
1e-4);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) {
|
|
103
|
+
static constexpr float PAN_VALUE = 0.75;
|
|
104
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
105
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
106
|
+
panNode->setPanParam(PAN_VALUE);
|
|
107
|
+
|
|
108
|
+
auto bus =
|
|
109
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
|
|
110
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
111
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
112
|
+
(*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
116
|
+
// x = 0.75
|
|
117
|
+
// gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
|
|
118
|
+
// gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
|
|
119
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
120
|
+
EXPECT_NEAR(
|
|
121
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
122
|
+
(i + 1) * 0.38268343236508984,
|
|
123
|
+
1e-4);
|
|
124
|
+
EXPECT_NEAR(
|
|
125
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
126
|
+
(i + 1) + (i + 1) * 0.9238795325112867,
|
|
127
|
+
1e-4);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -18,8 +18,7 @@ class IOSAudioRecorder : public AudioRecorder {
|
|
|
18
18
|
IOSAudioRecorder(
|
|
19
19
|
float sampleRate,
|
|
20
20
|
int bufferLength,
|
|
21
|
-
const std::shared_ptr<AudioEventHandlerRegistry>
|
|
22
|
-
&audioEventHandlerRegistry);
|
|
21
|
+
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
|
|
23
22
|
|
|
24
23
|
~IOSAudioRecorder() override;
|
|
25
24
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#define MINIAUDIO_IMPLEMENTATION
|
|
2
|
+
#import <audioapi/libs/miniaudio/miniaudio.h>
|
|
3
|
+
|
|
4
|
+
#include <audioapi/libs/miniaudio/decoders/libopus/miniaudio_libopus.h>
|
|
5
|
+
#include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
|
|
6
|
+
|
|
7
|
+
#include <audioapi/core/sources/AudioBuffer.h>
|
|
8
|
+
#include <audioapi/core/utils/AudioDecoder.h>
|
|
9
|
+
#include <audioapi/dsp/VectorMath.h>
|
|
10
|
+
#include <audioapi/libs/audio-stretch/stretch.h>
|
|
11
|
+
#include <audioapi/libs/base64/base64.h>
|
|
12
|
+
#include <audioapi/libs/ffmpeg/FFmpegDecoding.h>
|
|
13
|
+
#include <audioapi/utils/AudioArray.h>
|
|
14
|
+
#include <audioapi/utils/AudioBus.h>
|
|
15
|
+
|
|
16
|
+
namespace audioapi {
|
|
17
|
+
|
|
18
|
+
// Decoding audio in fixed-size chunks because total frame count can't be
|
|
19
|
+
// determined in advance. Note: ma_decoder_get_length_in_pcm_frames() always
|
|
20
|
+
// returns 0 for Vorbis decoders.
|
|
21
|
+
std::vector<float> AudioDecoder::readAllPcmFrames(ma_decoder &decoder, int outputChannels)
|
|
22
|
+
{
|
|
23
|
+
std::vector<float> buffer;
|
|
24
|
+
std::vector<float> temp(CHUNK_SIZE * outputChannels);
|
|
25
|
+
ma_uint64 outFramesRead = 0;
|
|
26
|
+
|
|
27
|
+
while (true) {
|
|
28
|
+
ma_uint64 tempFramesDecoded = 0;
|
|
29
|
+
ma_decoder_read_pcm_frames(&decoder, temp.data(), CHUNK_SIZE, &tempFramesDecoded);
|
|
30
|
+
if (tempFramesDecoded == 0) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
buffer.insert(buffer.end(), temp.data(), temp.data() + tempFramesDecoded * outputChannels);
|
|
35
|
+
outFramesRead += tempFramesDecoded;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (outFramesRead == 0) {
|
|
39
|
+
NSLog(@"Failed to decode");
|
|
40
|
+
}
|
|
41
|
+
return buffer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::makeAudioBufferFromFloatBuffer(
|
|
45
|
+
const std::vector<float> &buffer,
|
|
46
|
+
float outputSampleRate,
|
|
47
|
+
int outputChannels)
|
|
48
|
+
{
|
|
49
|
+
if (buffer.empty()) {
|
|
50
|
+
return nullptr;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
auto outputFrames = buffer.size() / outputChannels;
|
|
54
|
+
auto audioBus = std::make_shared<AudioBus>(outputFrames, outputChannels, outputSampleRate);
|
|
55
|
+
|
|
56
|
+
for (int ch = 0; ch < outputChannels; ++ch) {
|
|
57
|
+
auto channelData = audioBus->getChannel(ch)->getData();
|
|
58
|
+
for (int i = 0; i < outputFrames; ++i) {
|
|
59
|
+
channelData[i] = buffer[i * outputChannels + ch];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return std::make_shared<AudioBuffer>(audioBus);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(const std::string &path, float sampleRate)
|
|
66
|
+
{
|
|
67
|
+
if (AudioDecoder::pathHasExtension(path, {".mp4", ".m4a", ".aac"})) {
|
|
68
|
+
auto buffer = ffmpegdecoder::decodeWithFilePath(path, static_cast<int>(sampleRate));
|
|
69
|
+
if (buffer == nullptr) {
|
|
70
|
+
NSLog(@"Failed to decode with FFmpeg: %s", path.c_str());
|
|
71
|
+
return nullptr;
|
|
72
|
+
}
|
|
73
|
+
return buffer;
|
|
74
|
+
}
|
|
75
|
+
ma_decoder decoder;
|
|
76
|
+
ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
|
|
77
|
+
ma_decoding_backend_vtable *customBackends[] = {ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
|
|
78
|
+
|
|
79
|
+
config.ppCustomBackendVTables = customBackends;
|
|
80
|
+
config.customBackendCount = sizeof(customBackends) / sizeof(customBackends[0]);
|
|
81
|
+
|
|
82
|
+
if (ma_decoder_init_file(path.c_str(), &config, &decoder) != MA_SUCCESS) {
|
|
83
|
+
NSLog(@"Failed to initialize decoder for file: %s", path.c_str());
|
|
84
|
+
ma_decoder_uninit(&decoder);
|
|
85
|
+
return nullptr;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
|
|
89
|
+
auto outputChannels = static_cast<int>(decoder.outputChannels);
|
|
90
|
+
|
|
91
|
+
std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
|
|
92
|
+
ma_decoder_uninit(&decoder);
|
|
93
|
+
return makeAudioBufferFromFloatBuffer(buffer, outputSampleRate, outputChannels);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithMemoryBlock(const void *data, size_t size, float sampleRate)
|
|
97
|
+
{
|
|
98
|
+
const AudioFormat format = AudioDecoder::detectAudioFormat(data, size);
|
|
99
|
+
if (format == AudioFormat::MP4 || format == AudioFormat::M4A || format == AudioFormat::AAC) {
|
|
100
|
+
auto buffer = ffmpegdecoder::decodeWithMemoryBlock(data, size, static_cast<int>(sampleRate));
|
|
101
|
+
if (buffer == nullptr) {
|
|
102
|
+
NSLog(@"Failed to decode with FFmpeg");
|
|
103
|
+
return nullptr;
|
|
104
|
+
}
|
|
105
|
+
return buffer;
|
|
106
|
+
}
|
|
107
|
+
ma_decoder decoder;
|
|
108
|
+
ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
|
|
109
|
+
|
|
110
|
+
ma_decoding_backend_vtable *customBackends[] = {ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
|
|
111
|
+
|
|
112
|
+
config.ppCustomBackendVTables = customBackends;
|
|
113
|
+
config.customBackendCount = sizeof(customBackends) / sizeof(customBackends[0]);
|
|
114
|
+
|
|
115
|
+
if (ma_decoder_init_memory(data, size, &config, &decoder) != MA_SUCCESS) {
|
|
116
|
+
NSLog(@"Failed to initialize decoder for memory block");
|
|
117
|
+
ma_decoder_uninit(&decoder);
|
|
118
|
+
return nullptr;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
|
|
122
|
+
auto outputChannels = static_cast<int>(decoder.outputChannels);
|
|
123
|
+
|
|
124
|
+
std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
|
|
125
|
+
ma_decoder_uninit(&decoder);
|
|
126
|
+
return makeAudioBufferFromFloatBuffer(buffer, outputSampleRate, outputChannels);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithPCMInBase64(
|
|
130
|
+
const std::string &data,
|
|
131
|
+
float inputSampleRate,
|
|
132
|
+
int inputChannelCount,
|
|
133
|
+
bool interleaved)
|
|
134
|
+
{
|
|
135
|
+
auto decodedData = base64_decode(data, false);
|
|
136
|
+
const auto uint8Data = reinterpret_cast<uint8_t *>(decodedData.data());
|
|
137
|
+
size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t));
|
|
138
|
+
|
|
139
|
+
auto audioBus = std::make_shared<AudioBus>(numFramesDecoded, inputChannelCount, inputSampleRate);
|
|
140
|
+
|
|
141
|
+
for (int ch = 0; ch < inputChannelCount; ++ch) {
|
|
142
|
+
auto channelData = audioBus->getChannel(ch)->getData();
|
|
143
|
+
|
|
144
|
+
for (size_t i = 0; i < numFramesDecoded; ++i) {
|
|
145
|
+
size_t offset;
|
|
146
|
+
if (interleaved) {
|
|
147
|
+
// Ch1, Ch2, Ch1, Ch2, ...
|
|
148
|
+
offset = (i * inputChannelCount + ch) * sizeof(int16_t);
|
|
149
|
+
} else {
|
|
150
|
+
// Ch1, Ch1, Ch1, ..., Ch2, Ch2, Ch2, ...
|
|
151
|
+
offset = (ch * numFramesDecoded + i) * sizeof(int16_t);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return std::make_shared<AudioBuffer>(audioBus);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
} // namespace audioapi
|
package/lib/commonjs/api.js
CHANGED
|
@@ -219,6 +219,18 @@ Object.defineProperty(exports, "WorkletSourceNode", {
|
|
|
219
219
|
return _WorkletSourceNode.default;
|
|
220
220
|
}
|
|
221
221
|
});
|
|
222
|
+
Object.defineProperty(exports, "decodeAudioData", {
|
|
223
|
+
enumerable: true,
|
|
224
|
+
get: function () {
|
|
225
|
+
return _AudioDecoder.decodeAudioData;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
Object.defineProperty(exports, "decodePCMInBase64", {
|
|
229
|
+
enumerable: true,
|
|
230
|
+
get: function () {
|
|
231
|
+
return _AudioDecoder.decodePCMInBase64;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
222
234
|
Object.defineProperty(exports, "useSystemVolume", {
|
|
223
235
|
enumerable: true,
|
|
224
236
|
get: function () {
|
|
@@ -250,6 +262,7 @@ var _StreamerNode = _interopRequireDefault(require("./core/StreamerNode"));
|
|
|
250
262
|
var _ConstantSourceNode = _interopRequireDefault(require("./core/ConstantSourceNode"));
|
|
251
263
|
var _system = _interopRequireDefault(require("./system"));
|
|
252
264
|
var _useSystemVolume = _interopRequireDefault(require("./hooks/useSystemVolume"));
|
|
265
|
+
var _AudioDecoder = require("./core/AudioDecoder");
|
|
253
266
|
var _types = require("./types");
|
|
254
267
|
var _errors = require("./errors");
|
|
255
268
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -257,7 +270,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
257
270
|
|
|
258
271
|
/* eslint-disable no-var */
|
|
259
272
|
|
|
260
|
-
if (global.createAudioContext == null || global.createOfflineAudioContext == null || global.createAudioRecorder == null || global.AudioEventEmitter == null) {
|
|
273
|
+
if (global.createAudioContext == null || global.createOfflineAudioContext == null || global.createAudioRecorder == null || global.createAudioDecoder == null || global.AudioEventEmitter == null) {
|
|
261
274
|
if (!_specs.NativeAudioAPIModule) {
|
|
262
275
|
throw new Error(`Failed to install react-native-audio-api: The native module could not be found.`);
|
|
263
276
|
}
|
package/lib/commonjs/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_specs","require","_WorkletNode","_interopRequireDefault","_WorkletSourceNode","_WorkletProcessingNode","_RecorderAdapterNode","_AudioBuffer","_AudioBufferSourceNode","_AudioBufferQueueSourceNode","_AudioContext","_OfflineAudioContext","_AudioDestinationNode","_AudioNode","_AnalyserNode","_AudioParam","_AudioScheduledSourceNode","_BaseAudioContext","_BiquadFilterNode","_GainNode","_OscillatorNode","_StereoPannerNode","_AudioRecorder","_StreamerNode","_ConstantSourceNode","_system","_useSystemVolume","_types","_errors","e","__esModule","default","global","createAudioContext","createOfflineAudioContext","createAudioRecorder","AudioEventEmitter","NativeAudioAPIModule","Error","install"],"sourceRoot":"../../src","sources":["api.ts"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_specs","require","_WorkletNode","_interopRequireDefault","_WorkletSourceNode","_WorkletProcessingNode","_RecorderAdapterNode","_AudioBuffer","_AudioBufferSourceNode","_AudioBufferQueueSourceNode","_AudioContext","_OfflineAudioContext","_AudioDestinationNode","_AudioNode","_AnalyserNode","_AudioParam","_AudioScheduledSourceNode","_BaseAudioContext","_BiquadFilterNode","_GainNode","_OscillatorNode","_StereoPannerNode","_AudioRecorder","_StreamerNode","_ConstantSourceNode","_system","_useSystemVolume","_AudioDecoder","_types","_errors","e","__esModule","default","global","createAudioContext","createOfflineAudioContext","createAudioRecorder","createAudioDecoder","AudioEventEmitter","NativeAudioAPIModule","Error","install"],"sourceRoot":"../../src","sources":["api.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAkDA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,kBAAA,GAAAD,sBAAA,CAAAF,OAAA;AACA,IAAAI,sBAAA,GAAAF,sBAAA,CAAAF,OAAA;AACA,IAAAK,oBAAA,GAAAH,sBAAA,CAAAF,OAAA;AACA,IAAAM,YAAA,GAAAJ,sBAAA,CAAAF,OAAA;AACA,IAAAO,sBAAA,GAAAL,sBAAA,CAAAF,OAAA;AACA,IAAAQ,2BAAA,GAAAN,sBAAA,CAAAF,OAAA;AACA,IAAAS,aAAA,GAAAP,sBAAA,CAAAF,OAAA;AACA,IAAAU,oBAAA,GAAAR,sBAAA,CAAAF,OAAA;AACA,IAAAW,qBAAA,GAAAT,sBAAA,CAAAF,OAAA;AACA,IAAAY,UAAA,GAAAV,sBAAA,CAAAF,OAAA;AACA,IAAAa,aAAA,GAAAX,sBAAA,CAAAF,OAAA;AACA,IAAAc,WAAA,GAAAZ,sBAAA,CAAAF,OAAA;AACA,IAAAe,yBAAA,GAAAb,sBAAA,CAAAF,OAAA;AACA,IAAAgB,iBAAA,GAAAd,sBAAA,CAAAF,OAAA;AACA,IAAAiB,iBAAA,GAAAf,sBAAA,CAAAF,OAAA;AACA,IAAAkB,SAAA,GAAAhB,sBAAA,CAAAF,OAAA;AACA,IAAAmB,eAAA,GAAAjB,sBAAA,CAAAF,OAAA;AACA,IAAAoB,iBAAA,GAAAlB,sBAAA,CAAAF,OAAA;AACA,IAAAqB,cAAA,GAAAnB,sBAAA,CAAAF,OAAA;AACA,IAAAsB,aAAA,GAAApB,sBAAA,CAAAF,OAAA;AACA,IAAAuB,mBAAA,GAAArB,sBAAA,CAAAF,OAAA;AACA,IAAAwB,OAAA,GAAAtB,sBAAA,CAAAF,OAAA;AACA,IAAAyB,gBAAA,GAAAvB,sBAAA,CAAAF,OAAA;AACA,IAAA0B,aAAA,GAAA1B,OAAA;AAEA,IAAA2B,MAAA,GAAA3B,OAAA;AAWA,IAAA4B,OAAA,GAAA5B,OAAA;AAMkB,SAAAE,uBAAA2B,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAnFlB;;AAsBA;;AAEA,IACEG,MAAM,CAACC,kBAAkB,IAAI,IAAI,IACjCD,MAAM,CAACE,yBAAyB,IAAI,IAAI,IACxCF,MAAM,CAACG,mBAAmB,IAAI,IAAI,IAClCH,MAAM,CAACI,kBAAkB,IAAI,IAAI,IACjCJ,MAAM,CAACK,iBAAiB,IAAI,IAAI,EAChC;EACA,IAAI,CAACC,2BAAoB,EAAE;IACzB,MAAM,IAAIC,KAAK,CACb,iFACF,CAAC;EACH;EAEAD,2BAAoB,CAACE,OAAO,CAAC,CAAC;AAChC","ignoreList":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.decodeAudioData = decodeAudioData;
|
|
7
|
+
exports.decodePCMInBase64 = decodePCMInBase64;
|
|
8
|
+
var _AudioBuffer = _interopRequireDefault(require("./AudioBuffer"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
class AudioDecoder {
|
|
11
|
+
static instance = null;
|
|
12
|
+
constructor() {
|
|
13
|
+
this.decoder = global.createAudioDecoder();
|
|
14
|
+
}
|
|
15
|
+
static getInstance() {
|
|
16
|
+
if (!AudioDecoder.instance) {
|
|
17
|
+
AudioDecoder.instance = new AudioDecoder();
|
|
18
|
+
}
|
|
19
|
+
return AudioDecoder.instance;
|
|
20
|
+
}
|
|
21
|
+
async decodeAudioDataInstance(input, sampleRate) {
|
|
22
|
+
let buffer;
|
|
23
|
+
if (typeof input === 'string') {
|
|
24
|
+
// Remove the file:// prefix if it exists
|
|
25
|
+
if (input.startsWith('file://')) {
|
|
26
|
+
input = input.replace('file://', '');
|
|
27
|
+
}
|
|
28
|
+
buffer = await this.decoder.decodeWithFilePath(input, sampleRate ?? 0);
|
|
29
|
+
} else if (input instanceof ArrayBuffer) {
|
|
30
|
+
buffer = await this.decoder.decodeWithMemoryBlock(new Uint8Array(input), sampleRate ?? 0);
|
|
31
|
+
}
|
|
32
|
+
if (!buffer) {
|
|
33
|
+
throw new Error('Unsupported input type or failed to decode audio');
|
|
34
|
+
}
|
|
35
|
+
return new _AudioBuffer.default(buffer);
|
|
36
|
+
}
|
|
37
|
+
async decodePCMInBase64Instance(base64String, inputSampleRate, inputChannelCount, interleaved) {
|
|
38
|
+
const buffer = await this.decoder.decodeWithPCMInBase64(base64String, inputSampleRate, inputChannelCount, interleaved);
|
|
39
|
+
return new _AudioBuffer.default(buffer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function decodeAudioData(input, sampleRate) {
|
|
43
|
+
return AudioDecoder.getInstance().decodeAudioDataInstance(input, sampleRate);
|
|
44
|
+
}
|
|
45
|
+
async function decodePCMInBase64(base64String, inputSampleRate, inputChannelCount, isInterleaved = true) {
|
|
46
|
+
return AudioDecoder.getInstance().decodePCMInBase64Instance(base64String, inputSampleRate, inputChannelCount, isInterleaved);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=AudioDecoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_AudioBuffer","_interopRequireDefault","require","e","__esModule","default","AudioDecoder","instance","constructor","decoder","global","createAudioDecoder","getInstance","decodeAudioDataInstance","input","sampleRate","buffer","startsWith","replace","decodeWithFilePath","ArrayBuffer","decodeWithMemoryBlock","Uint8Array","Error","AudioBuffer","decodePCMInBase64Instance","base64String","inputSampleRate","inputChannelCount","interleaved","decodeWithPCMInBase64","decodeAudioData","decodePCMInBase64","isInterleaved"],"sourceRoot":"../../../src","sources":["core/AudioDecoder.ts"],"mappings":";;;;;;;AACA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAwC,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExC,MAAMG,YAAY,CAAC;EACjB,OAAeC,QAAQ,GAAwB,IAAI;EAG3CC,WAAWA,CAAA,EAAG;IACpB,IAAI,CAACC,OAAO,GAAGC,MAAM,CAACC,kBAAkB,CAAC,CAAC;EAC5C;EAEA,OAAcC,WAAWA,CAAA,EAAiB;IACxC,IAAI,CAACN,YAAY,CAACC,QAAQ,EAAE;MAC1BD,YAAY,CAACC,QAAQ,GAAG,IAAID,YAAY,CAAC,CAAC;IAC5C;IACA,OAAOA,YAAY,CAACC,QAAQ;EAC9B;EAEA,MAAaM,uBAAuBA,CAClCC,KAA2B,EAC3BC,UAAmB,EACG;IACtB,IAAIC,MAAM;IACV,IAAI,OAAOF,KAAK,KAAK,QAAQ,EAAE;MAC7B;MACA,IAAIA,KAAK,CAACG,UAAU,CAAC,SAAS,CAAC,EAAE;QAC/BH,KAAK,GAAGA,KAAK,CAACI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;MACtC;MACAF,MAAM,GAAG,MAAM,IAAI,CAACP,OAAO,CAACU,kBAAkB,CAACL,KAAK,EAAEC,UAAU,IAAI,CAAC,CAAC;IACxE,CAAC,MAAM,IAAID,KAAK,YAAYM,WAAW,EAAE;MACvCJ,MAAM,GAAG,MAAM,IAAI,CAACP,OAAO,CAACY,qBAAqB,CAC/C,IAAIC,UAAU,CAACR,KAAK,CAAC,EACrBC,UAAU,IAAI,CAChB,CAAC;IACH;IAEA,IAAI,CAACC,MAAM,EAAE;MACX,MAAM,IAAIO,KAAK,CAAC,kDAAkD,CAAC;IACrE;IACA,OAAO,IAAIC,oBAAW,CAACR,MAAM,CAAC;EAChC;EAEA,MAAaS,yBAAyBA,CACpCC,YAAoB,EACpBC,eAAuB,EACvBC,iBAAyB,EACzBC,WAAoB,EACE;IACtB,MAAMb,MAAM,GAAG,MAAM,IAAI,CAACP,OAAO,CAACqB,qBAAqB,CACrDJ,YAAY,EACZC,eAAe,EACfC,iBAAiB,EACjBC,WACF,CAAC;IACD,OAAO,IAAIL,oBAAW,CAACR,MAAM,CAAC;EAChC;AACF;AAEO,eAAee,eAAeA,CACnCjB,KAA2B,EAC3BC,UAAmB,EACG;EACtB,OAAOT,YAAY,CAACM,WAAW,CAAC,CAAC,CAACC,uBAAuB,CAACC,KAAK,EAAEC,UAAU,CAAC;AAC9E;AAEO,eAAeiB,iBAAiBA,CACrCN,YAAoB,EACpBC,eAAuB,EACvBC,iBAAyB,EACzBK,aAAsB,GAAG,IAAI,EACP;EACtB,OAAO3B,YAAY,CAACM,WAAW,CAAC,CAAC,CAACa,yBAAyB,CACzDC,YAAY,EACZC,eAAe,EACfC,iBAAiB,EACjBK,aACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -14,6 +14,7 @@ var _AudioBufferQueueSourceNode = _interopRequireDefault(require("./AudioBufferQ
|
|
|
14
14
|
var _AudioBufferSourceNode = _interopRequireDefault(require("./AudioBufferSourceNode"));
|
|
15
15
|
var _AudioDestinationNode = _interopRequireDefault(require("./AudioDestinationNode"));
|
|
16
16
|
var _BiquadFilterNode = _interopRequireDefault(require("./BiquadFilterNode"));
|
|
17
|
+
var _ConstantSourceNode = _interopRequireDefault(require("./ConstantSourceNode"));
|
|
17
18
|
var _GainNode = _interopRequireDefault(require("./GainNode"));
|
|
18
19
|
var _OscillatorNode = _interopRequireDefault(require("./OscillatorNode"));
|
|
19
20
|
var _PeriodicWave = _interopRequireDefault(require("./PeriodicWave"));
|
|
@@ -21,7 +22,7 @@ var _RecorderAdapterNode = _interopRequireDefault(require("./RecorderAdapterNode
|
|
|
21
22
|
var _StereoPannerNode = _interopRequireDefault(require("./StereoPannerNode"));
|
|
22
23
|
var _StreamerNode = _interopRequireDefault(require("./StreamerNode"));
|
|
23
24
|
var _WorkletNode = _interopRequireDefault(require("./WorkletNode"));
|
|
24
|
-
var
|
|
25
|
+
var _AudioDecoder = require("./AudioDecoder");
|
|
25
26
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
26
27
|
class BaseAudioContext {
|
|
27
28
|
constructor(context) {
|
|
@@ -35,6 +36,15 @@ class BaseAudioContext {
|
|
|
35
36
|
get state() {
|
|
36
37
|
return this.context.state;
|
|
37
38
|
}
|
|
39
|
+
async decodeAudioData(input, sampleRate) {
|
|
40
|
+
if (!(typeof input === 'string' || input instanceof ArrayBuffer)) {
|
|
41
|
+
throw new TypeError('Input must be a string or ArrayBuffer');
|
|
42
|
+
}
|
|
43
|
+
return await (0, _AudioDecoder.decodeAudioData)(input, sampleRate ?? this.sampleRate);
|
|
44
|
+
}
|
|
45
|
+
async decodePCMInBase64(base64String, inputSampleRate, inputChannelCount, isInterleaved = true) {
|
|
46
|
+
return await (0, _AudioDecoder.decodePCMInBase64)(base64String, inputSampleRate, inputChannelCount, isInterleaved);
|
|
47
|
+
}
|
|
38
48
|
createWorkletNode(callback, bufferLength, inputChannelCount, workletRuntime = 'AudioRuntime') {
|
|
39
49
|
if (inputChannelCount < 1 || inputChannelCount > 32) {
|
|
40
50
|
throw new _errors.NotSupportedError(`The number of input channels provided (${inputChannelCount}) can not be less than 1 or greater than 32`);
|
|
@@ -132,23 +142,6 @@ class BaseAudioContext {
|
|
|
132
142
|
createAnalyser() {
|
|
133
143
|
return new _AnalyserNode.default(this, this.context.createAnalyser());
|
|
134
144
|
}
|
|
135
|
-
|
|
136
|
-
/** Decodes audio data from a local file path. */
|
|
137
|
-
async decodeAudioDataSource(sourcePath) {
|
|
138
|
-
// Remove the file:// prefix if it exists
|
|
139
|
-
if (sourcePath.startsWith('file://')) {
|
|
140
|
-
sourcePath = sourcePath.replace('file://', '');
|
|
141
|
-
}
|
|
142
|
-
return new _AudioBuffer.default(await this.context.decodeAudioDataSource(sourcePath));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** Decodes audio data from an ArrayBuffer. */
|
|
146
|
-
async decodeAudioData(data) {
|
|
147
|
-
return new _AudioBuffer.default(await this.context.decodeAudioData(new Uint8Array(data)));
|
|
148
|
-
}
|
|
149
|
-
async decodePCMInBase64Data(base64, playbackRate = 1.0) {
|
|
150
|
-
return new _AudioBuffer.default(await this.context.decodePCMAudioDataInBase64(base64, playbackRate));
|
|
151
|
-
}
|
|
152
145
|
}
|
|
153
146
|
exports.default = BaseAudioContext;
|
|
154
147
|
//# sourceMappingURL=BaseAudioContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_errors","require","_utils","_WorkletSourceNode","_interopRequireDefault","_WorkletProcessingNode","_AnalyserNode","_AudioBuffer","_AudioBufferQueueSourceNode","_AudioBufferSourceNode","_AudioDestinationNode","_BiquadFilterNode","_GainNode","_OscillatorNode","_PeriodicWave","_RecorderAdapterNode","_StereoPannerNode","_StreamerNode","_WorkletNode","
|
|
1
|
+
{"version":3,"names":["_errors","require","_utils","_WorkletSourceNode","_interopRequireDefault","_WorkletProcessingNode","_AnalyserNode","_AudioBuffer","_AudioBufferQueueSourceNode","_AudioBufferSourceNode","_AudioDestinationNode","_BiquadFilterNode","_ConstantSourceNode","_GainNode","_OscillatorNode","_PeriodicWave","_RecorderAdapterNode","_StereoPannerNode","_StreamerNode","_WorkletNode","_AudioDecoder","e","__esModule","default","BaseAudioContext","constructor","context","destination","AudioDestinationNode","sampleRate","currentTime","state","decodeAudioData","input","ArrayBuffer","TypeError","decodePCMInBase64","base64String","inputSampleRate","inputChannelCount","isInterleaved","createWorkletNode","callback","bufferLength","workletRuntime","NotSupportedError","isWorkletsAvailable","shareableWorklet","workletsModule","makeShareableCloneRecursive","audioBuffers","channelCount","floatAudioData","map","buffer","Float32Array","WorkletNode","Error","createWorkletProcessingNode","inputBuffers","outputBuffers","framesToProcess","inputData","outputData","WorkletProcessingNode","createWorkletSourceNode","startOffset","WorkletSourceNode","createRecorderAdapter","RecorderAdapterNode","createOscillator","OscillatorNode","createStreamer","StreamerNode","createConstantSource","ConstantSourceNode","createGain","GainNode","createStereoPanner","StereoPannerNode","createBiquadFilter","BiquadFilterNode","createBufferSource","options","pitchCorrection","AudioBufferSourceNode","createBufferQueueSource","AudioBufferQueueSourceNode","createBuffer","numOfChannels","length","AudioBuffer","createPeriodicWave","real","imag","constraints","InvalidAccessError","disableNormalization","PeriodicWave","createAnalyser","AnalyserNode","exports"],"sourceRoot":"../../../src","sources":["core/BaseAudioContext.ts"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAQA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,kBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,sBAAA,GAAAD,sBAAA,CAAAH,OAAA;AACA,IAAAK,aAAA,GAAAF,sBAAA,CAAAH,OAAA;AACA,IAAAM,YAAA,GAAAH,sBAAA,CAAAH,OAAA;AACA,IAAAO,2BAAA,GAAAJ,sBAAA,CAAAH,OAAA;AACA,IAAAQ,sBAAA,GAAAL,sBAAA,CAAAH,OAAA;AACA,IAAAS,qBAAA,GAAAN,sBAAA,CAAAH,OAAA;AACA,IAAAU,iBAAA,GAAAP,sBAAA,CAAAH,OAAA;AACA,IAAAW,mBAAA,GAAAR,sBAAA,CAAAH,OAAA;AACA,IAAAY,SAAA,GAAAT,sBAAA,CAAAH,OAAA;AACA,IAAAa,eAAA,GAAAV,sBAAA,CAAAH,OAAA;AACA,IAAAc,aAAA,GAAAX,sBAAA,CAAAH,OAAA;AACA,IAAAe,oBAAA,GAAAZ,sBAAA,CAAAH,OAAA;AACA,IAAAgB,iBAAA,GAAAb,sBAAA,CAAAH,OAAA;AACA,IAAAiB,aAAA,GAAAd,sBAAA,CAAAH,OAAA;AACA,IAAAkB,YAAA,GAAAf,sBAAA,CAAAH,OAAA;AACA,IAAAmB,aAAA,GAAAnB,OAAA;AAAoE,SAAAG,uBAAAiB,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAErD,MAAMG,gBAAgB,CAAC;EAKpCC,WAAWA,CAACC,OAA0B,EAAE;IACtC,IAAI,CAACA,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACC,WAAW,GAAG,IAAIC,6BAAoB,CAAC,IAAI,EAAEF,OAAO,CAACC,WAAW,CAAC;IACtE,IAAI,CAACE,UAAU,GAAGH,OAAO,CAACG,UAAU;EACtC;EAEA,IAAWC,WAAWA,CAAA,EAAW;IAC/B,OAAO,IAAI,CAACJ,OAAO,CAACI,WAAW;EACjC;EAEA,IAAWC,KAAKA,CAAA,EAAiB;IAC/B,OAAO,IAAI,CAACL,OAAO,CAACK,KAAK;EAC3B;EAEA,MAAaC,eAAeA,CAC1BC,KAA2B,EAC3BJ,UAAmB,EACG;IACtB,IAAI,EAAE,OAAOI,KAAK,KAAK,QAAQ,IAAIA,KAAK,YAAYC,WAAW,CAAC,EAAE;MAChE,MAAM,IAAIC,SAAS,CAAC,uCAAuC,CAAC;IAC9D;IACA,OAAO,MAAM,IAAAH,6BAAe,EAACC,KAAK,EAAEJ,UAAU,IAAI,IAAI,CAACA,UAAU,CAAC;EACpE;EAEA,MAAaO,iBAAiBA,CAC5BC,YAAoB,EACpBC,eAAuB,EACvBC,iBAAyB,EACzBC,aAAsB,GAAG,IAAI,EACP;IACtB,OAAO,MAAM,IAAAJ,+BAAiB,EAC5BC,YAAY,EACZC,eAAe,EACfC,iBAAiB,EACjBC,aACF,CAAC;EACH;EAEAC,iBAAiBA,CACfC,QAAwE,EACxEC,YAAoB,EACpBJ,iBAAyB,EACzBK,cAAmC,GAAG,cAAc,EACvC;IACb,IAAIL,iBAAiB,GAAG,CAAC,IAAIA,iBAAiB,GAAG,EAAE,EAAE;MACnD,MAAM,IAAIM,yBAAiB,CACzB,0CAA0CN,iBAAiB,6CAC7D,CAAC;IACH;IACA,IAAII,YAAY,GAAG,CAAC,EAAE;MACpB,MAAM,IAAIE,yBAAiB,CACzB,+BAA+BF,YAAY,0BAC7C,CAAC;IACH;IAEA,IAAIG,0BAAmB,EAAE;MACvB,MAAMC,gBAAgB,GAAGC,qBAAc,CAACC,2BAA2B,CACjE,CAACC,YAAgC,EAAEC,YAAoB,KAAK;QAC1D,SAAS;;QACT,MAAMC,cAAmC,GAAGF,YAAY,CAACG,GAAG,CACzDC,MAAM,IAAK,IAAIC,YAAY,CAACD,MAAM,CACrC,CAAC;QACDZ,QAAQ,CAACU,cAAc,EAAED,YAAY,CAAC;MACxC,CACF,CAAC;MACD,OAAO,IAAIK,oBAAW,CACpB,IAAI,EACJ,IAAI,CAAC9B,OAAO,CAACe,iBAAiB,CAC5BM,gBAAgB,EAChBH,cAAc,KAAK,WAAW,EAC9BD,YAAY,EACZJ,iBACF,CACF,CAAC;IACH;IACA;IACA,MAAM,IAAIkB,KAAK,CACb,yIACF,CAAC;EACH;EAEAC,2BAA2BA,CACzBhB,QAKS,EACTE,cAAmC,GAAG,cAAc,EAC7B;IACvB,IAAIE,0BAAmB,EAAE;MACvB,MAAMC,gBAAgB,GAAGC,qBAAc,CAACC,2BAA2B,CACjE,CACEU,YAAgC,EAChCC,aAAiC,EACjCC,eAAuB,EACvB/B,WAAmB,KAChB;QACH,SAAS;;QACT,MAAMgC,SAA8B,GAAGH,YAAY,CAACN,GAAG,CACpDC,MAAM,IAAK,IAAIC,YAAY,CAACD,MAAM,EAAE,CAAC,EAAEO,eAAe,CACzD,CAAC;QACD,MAAME,UAA+B,GAAGH,aAAa,CAACP,GAAG,CACtDC,MAAM,IAAK,IAAIC,YAAY,CAACD,MAAM,EAAE,CAAC,EAAEO,eAAe,CACzD,CAAC;QACDnB,QAAQ,CAACoB,SAAS,EAAEC,UAAU,EAAEF,eAAe,EAAE/B,WAAW,CAAC;MAC/D,CACF,CAAC;MACD,OAAO,IAAIkC,8BAAqB,CAC9B,IAAI,EACJ,IAAI,CAACtC,OAAO,CAACgC,2BAA2B,CACtCX,gBAAgB,EAChBH,cAAc,KAAK,WACrB,CACF,CAAC;IACH;IACA;IACA,MAAM,IAAIa,KAAK,CACb,yIACF,CAAC;EACH;EAEAQ,uBAAuBA,CACrBvB,QAKS,EACTE,cAAmC,GAAG,cAAc,EACjC;IACnB,IAAI,CAACE,0BAAmB,EAAE;MACxB;MACA,MAAM,IAAIW,KAAK,CACb,yIACF,CAAC;IACH;IACA,MAAMV,gBAAgB,GAAGC,qBAAc,CAACC,2BAA2B,CACjE,CACEC,YAAgC,EAChCW,eAAuB,EACvB/B,WAAmB,EACnBoC,WAAmB,KAChB;MACH,SAAS;;MACT,MAAMd,cAAmC,GAAGF,YAAY,CAACG,GAAG,CACzDC,MAAM,IAAK,IAAIC,YAAY,CAACD,MAAM,CACrC,CAAC;MACDZ,QAAQ,CAACU,cAAc,EAAES,eAAe,EAAE/B,WAAW,EAAEoC,WAAW,CAAC;IACrE,CACF,CAAC;IACD,OAAO,IAAIC,0BAAiB,CAC1B,IAAI,EACJ,IAAI,CAACzC,OAAO,CAACuC,uBAAuB,CAClClB,gBAAgB,EAChBH,cAAc,KAAK,WACrB,CACF,CAAC;EACH;EAEAwB,qBAAqBA,CAAA,EAAwB;IAC3C,OAAO,IAAIC,4BAAmB,CAAC,IAAI,EAAE,IAAI,CAAC3C,OAAO,CAAC0C,qBAAqB,CAAC,CAAC,CAAC;EAC5E;EAEAE,gBAAgBA,CAAA,EAAmB;IACjC,OAAO,IAAIC,uBAAc,CAAC,IAAI,EAAE,IAAI,CAAC7C,OAAO,CAAC4C,gBAAgB,CAAC,CAAC,CAAC;EAClE;EAEAE,cAAcA,CAAA,EAAiB;IAC7B,OAAO,IAAIC,qBAAY,CAAC,IAAI,EAAE,IAAI,CAAC/C,OAAO,CAAC8C,cAAc,CAAC,CAAC,CAAC;EAC9D;EAEAE,oBAAoBA,CAAA,EAAuB;IACzC,OAAO,IAAIC,2BAAkB,CAAC,IAAI,EAAE,IAAI,CAACjD,OAAO,CAACgD,oBAAoB,CAAC,CAAC,CAAC;EAC1E;EAEAE,UAAUA,CAAA,EAAa;IACrB,OAAO,IAAIC,iBAAQ,CAAC,IAAI,EAAE,IAAI,CAACnD,OAAO,CAACkD,UAAU,CAAC,CAAC,CAAC;EACtD;EAEAE,kBAAkBA,CAAA,EAAqB;IACrC,OAAO,IAAIC,yBAAgB,CAAC,IAAI,EAAE,IAAI,CAACrD,OAAO,CAACoD,kBAAkB,CAAC,CAAC,CAAC;EACtE;EAEAE,kBAAkBA,CAAA,EAAqB;IACrC,OAAO,IAAIC,yBAAgB,CAAC,IAAI,EAAE,IAAI,CAACvD,OAAO,CAACsD,kBAAkB,CAAC,CAAC,CAAC;EACtE;EAEAE,kBAAkBA,CAChBC,OAA0C,EACnB;IACvB,MAAMC,eAAe,GAAGD,OAAO,EAAEC,eAAe,IAAI,KAAK;IAEzD,OAAO,IAAIC,8BAAqB,CAC9B,IAAI,EACJ,IAAI,CAAC3D,OAAO,CAACwD,kBAAkB,CAACE,eAAe,CACjD,CAAC;EACH;EAEAE,uBAAuBA,CACrBH,OAA0C,EACd;IAC5B,MAAMC,eAAe,GAAGD,OAAO,EAAEC,eAAe,IAAI,KAAK;IAEzD,OAAO,IAAIG,mCAA0B,CACnC,IAAI,EACJ,IAAI,CAAC7D,OAAO,CAAC4D,uBAAuB,CAACF,eAAe,CACtD,CAAC;EACH;EAEAI,YAAYA,CACVC,aAAqB,EACrBC,MAAc,EACd7D,UAAkB,EACL;IACb,IAAI4D,aAAa,GAAG,CAAC,IAAIA,aAAa,IAAI,EAAE,EAAE;MAC5C,MAAM,IAAI5C,yBAAiB,CACzB,oCAAoC4C,aAAa,gCACnD,CAAC;IACH;IAEA,IAAIC,MAAM,IAAI,CAAC,EAAE;MACf,MAAM,IAAI7C,yBAAiB,CACzB,kCAAkC6C,MAAM,kDAC1C,CAAC;IACH;IAEA,IAAI7D,UAAU,GAAG,IAAI,IAAIA,UAAU,GAAG,KAAK,EAAE;MAC3C,MAAM,IAAIgB,yBAAiB,CACzB,6BAA6BhB,UAAU,sCACzC,CAAC;IACH;IAEA,OAAO,IAAI8D,oBAAW,CACpB,IAAI,CAACjE,OAAO,CAAC8D,YAAY,CAACC,aAAa,EAAEC,MAAM,EAAE7D,UAAU,CAC7D,CAAC;EACH;EAEA+D,kBAAkBA,CAChBC,IAAkB,EAClBC,IAAkB,EAClBC,WAAqC,EACvB;IACd,IAAIF,IAAI,CAACH,MAAM,KAAKI,IAAI,CAACJ,MAAM,EAAE;MAC/B,MAAM,IAAIM,0BAAkB,CAC1B,4BAA4BH,IAAI,CAACH,MAAM,oBAAoBI,IAAI,CAACJ,MAAM,sBACxE,CAAC;IACH;IAEA,MAAMO,oBAAoB,GAAGF,WAAW,EAAEE,oBAAoB,IAAI,KAAK;IAEvE,OAAO,IAAIC,qBAAY,CACrB,IAAI,CAACxE,OAAO,CAACkE,kBAAkB,CAACC,IAAI,EAAEC,IAAI,EAAEG,oBAAoB,CAClE,CAAC;EACH;EAEAE,cAAcA,CAAA,EAAiB;IAC7B,OAAO,IAAIC,qBAAY,CAAC,IAAI,EAAE,IAAI,CAAC1E,OAAO,CAACyE,cAAc,CAAC,CAAC,CAAC;EAC9D;AACF;AAACE,OAAA,CAAA9E,OAAA,GAAAC,gBAAA","ignoreList":[]}
|