react-native-audio-api 0.9.0 → 0.10.0-nightly-971a6b4-20251010
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 +124 -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 +133 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +58 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.h +26 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +0 -2
- 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/sources/AudioBufferBaseSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +0 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +0 -2
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +0 -1
- package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -91
- package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +75 -0
- package/common/cpp/audioapi/core/utils/AudioStretcher.h +30 -0
- package/common/cpp/audioapi/core/utils/Constants.h +4 -0
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +5 -1
- 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 +1 -1
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
- package/lib/commonjs/api.js +21 -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/AudioStretcher.js +31 -0
- package/lib/commonjs/core/AudioStretcher.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 +3 -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/AudioStretcher.js +26 -0
- package/lib/module/core/AudioStretcher.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 +5 -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/AudioStretcher.d.ts +3 -0
- package/lib/typescript/core/AudioStretcher.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 +10 -3
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +10 -0
- package/src/core/AudioDecoder.ts +78 -0
- package/src/core/AudioStretcher.ts +43 -0
- package/src/core/BaseAudioContext.ts +26 -29
- package/src/interfaces.ts +26 -6
- package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
|
|
4
|
+
#include <audioapi/HostObjects/utils/AudioDecoderHostObject.h>
|
|
5
|
+
#include <audioapi/core/utils/AudioDecoder.h>
|
|
6
|
+
#include <audioapi/jsi/JsiPromise.h>
|
|
7
|
+
|
|
8
|
+
#include <jsi/jsi.h>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <thread>
|
|
12
|
+
#include <utility>
|
|
13
|
+
|
|
14
|
+
namespace audioapi {
|
|
15
|
+
AudioDecoderHostObject::AudioDecoderHostObject(
|
|
16
|
+
jsi::Runtime *runtime,
|
|
17
|
+
const std::shared_ptr<react::CallInvoker> &callInvoker) {
|
|
18
|
+
promiseVendor_ = std::make_shared<PromiseVendor>(runtime, callInvoker);
|
|
19
|
+
addFunctions(
|
|
20
|
+
JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithPCMInBase64),
|
|
21
|
+
JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithFilePath),
|
|
22
|
+
JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithMemoryBlock));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithMemoryBlock) {
|
|
26
|
+
auto arrayBuffer = args[0]
|
|
27
|
+
.getObject(runtime)
|
|
28
|
+
.getPropertyAsObject(runtime, "buffer")
|
|
29
|
+
.getArrayBuffer(runtime);
|
|
30
|
+
auto data = arrayBuffer.data(runtime);
|
|
31
|
+
auto size = static_cast<int>(arrayBuffer.size(runtime));
|
|
32
|
+
|
|
33
|
+
auto sampleRate = args[1].getNumber();
|
|
34
|
+
|
|
35
|
+
auto promise = promiseVendor_->createPromise(
|
|
36
|
+
[data, size, sampleRate](std::shared_ptr<Promise> promise) {
|
|
37
|
+
std::thread([data, size, sampleRate, promise = std::move(promise)]() {
|
|
38
|
+
auto result =
|
|
39
|
+
AudioDecoder::decodeWithMemoryBlock(data, size, sampleRate);
|
|
40
|
+
|
|
41
|
+
if (!result) {
|
|
42
|
+
promise->reject("Failed to decode audio data.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
auto audioBufferHostObject =
|
|
47
|
+
std::make_shared<AudioBufferHostObject>(result);
|
|
48
|
+
|
|
49
|
+
promise->resolve([audioBufferHostObject = std::move(
|
|
50
|
+
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
51
|
+
auto jsiObject = jsi::Object::createFromHostObject(
|
|
52
|
+
runtime, audioBufferHostObject);
|
|
53
|
+
jsiObject.setExternalMemoryPressure(
|
|
54
|
+
runtime, audioBufferHostObject->getSizeInBytes());
|
|
55
|
+
return jsiObject;
|
|
56
|
+
});
|
|
57
|
+
}).detach();
|
|
58
|
+
});
|
|
59
|
+
return promise;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithFilePath) {
|
|
63
|
+
auto sourcePath = args[0].getString(runtime).utf8(runtime);
|
|
64
|
+
auto sampleRate = args[1].getNumber();
|
|
65
|
+
|
|
66
|
+
auto promise = promiseVendor_->createPromise(
|
|
67
|
+
[sourcePath, sampleRate](std::shared_ptr<Promise> promise) {
|
|
68
|
+
std::thread([sourcePath, sampleRate, promise = std::move(promise)]() {
|
|
69
|
+
auto result =
|
|
70
|
+
AudioDecoder::decodeWithFilePath(sourcePath, sampleRate);
|
|
71
|
+
|
|
72
|
+
if (!result) {
|
|
73
|
+
promise->reject("Failed to decode audio data source.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
auto audioBufferHostObject =
|
|
78
|
+
std::make_shared<AudioBufferHostObject>(result);
|
|
79
|
+
|
|
80
|
+
promise->resolve([audioBufferHostObject = std::move(
|
|
81
|
+
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
82
|
+
auto jsiObject = jsi::Object::createFromHostObject(
|
|
83
|
+
runtime, audioBufferHostObject);
|
|
84
|
+
jsiObject.setExternalMemoryPressure(
|
|
85
|
+
runtime, audioBufferHostObject->getSizeInBytes());
|
|
86
|
+
return jsiObject;
|
|
87
|
+
});
|
|
88
|
+
}).detach();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return promise;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithPCMInBase64) {
|
|
95
|
+
auto b64 = args[0].getString(runtime).utf8(runtime);
|
|
96
|
+
auto inputSampleRate = args[1].getNumber();
|
|
97
|
+
auto inputChannelCount = args[2].getNumber();
|
|
98
|
+
auto interleaved = args[3].getBool();
|
|
99
|
+
|
|
100
|
+
auto promise = promiseVendor_->createPromise(
|
|
101
|
+
[b64, inputSampleRate, inputChannelCount, interleaved](
|
|
102
|
+
std::shared_ptr<Promise> promise) {
|
|
103
|
+
std::thread([b64,
|
|
104
|
+
inputSampleRate,
|
|
105
|
+
inputChannelCount,
|
|
106
|
+
interleaved,
|
|
107
|
+
promise = std::move(promise)]() {
|
|
108
|
+
auto result = AudioDecoder::decodeWithPCMInBase64(
|
|
109
|
+
b64, inputSampleRate, inputChannelCount, interleaved);
|
|
110
|
+
|
|
111
|
+
if (!result) {
|
|
112
|
+
promise->reject("Failed to decode audio data source.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
auto audioBufferHostObject =
|
|
117
|
+
std::make_shared<AudioBufferHostObject>(result);
|
|
118
|
+
|
|
119
|
+
promise->resolve([audioBufferHostObject = std::move(
|
|
120
|
+
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
121
|
+
auto jsiObject = jsi::Object::createFromHostObject(
|
|
122
|
+
runtime, audioBufferHostObject);
|
|
123
|
+
jsiObject.setExternalMemoryPressure(
|
|
124
|
+
runtime, audioBufferHostObject->getSizeInBytes());
|
|
125
|
+
return jsiObject;
|
|
126
|
+
});
|
|
127
|
+
}).detach();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return promise;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
|
|
4
|
+
#include <audioapi/core/utils/AudioDecoder.h>
|
|
5
|
+
#include <audioapi/jsi/JsiPromise.h>
|
|
6
|
+
|
|
7
|
+
#include <jsi/jsi.h>
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <thread>
|
|
11
|
+
#include <utility>
|
|
12
|
+
|
|
13
|
+
namespace audioapi {
|
|
14
|
+
using namespace facebook;
|
|
15
|
+
|
|
16
|
+
class AudioDecoderHostObject : public JsiHostObject {
|
|
17
|
+
public:
|
|
18
|
+
explicit AudioDecoderHostObject(
|
|
19
|
+
jsi::Runtime *runtime,
|
|
20
|
+
const std::shared_ptr<react::CallInvoker> &callInvoker);
|
|
21
|
+
JSI_HOST_FUNCTION_DECL(decodeWithMemoryBlock);
|
|
22
|
+
JSI_HOST_FUNCTION_DECL(decodeWithFilePath);
|
|
23
|
+
JSI_HOST_FUNCTION_DECL(decodeWithPCMInBase64);
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
std::shared_ptr<PromiseVendor> promiseVendor_;
|
|
27
|
+
};
|
|
28
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
|
|
4
|
+
#include <audioapi/HostObjects/utils/AudioStretcherHostObject.h>
|
|
5
|
+
#include <audioapi/core/utils/AudioStretcher.h>
|
|
6
|
+
#include <audioapi/jsi/JsiPromise.h>
|
|
7
|
+
|
|
8
|
+
#include <jsi/jsi.h>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <thread>
|
|
12
|
+
#include <utility>
|
|
13
|
+
|
|
14
|
+
namespace audioapi {
|
|
15
|
+
|
|
16
|
+
AudioStretcherHostObject::AudioStretcherHostObject(
|
|
17
|
+
jsi::Runtime *runtime,
|
|
18
|
+
const std::shared_ptr<react::CallInvoker> &callInvoker) {
|
|
19
|
+
promiseVendor_ = std::make_shared<PromiseVendor>(runtime, callInvoker);
|
|
20
|
+
addFunctions(
|
|
21
|
+
JSI_EXPORT_FUNCTION(AudioStretcherHostObject, changePlaybackSpeed));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
JSI_HOST_FUNCTION_IMPL(AudioStretcherHostObject, changePlaybackSpeed) {
|
|
25
|
+
auto audioBuffer =
|
|
26
|
+
args[0].getObject(runtime).asHostObject<AudioBufferHostObject>(runtime);
|
|
27
|
+
auto playbackSpeed = static_cast<float>(args[1].asNumber());
|
|
28
|
+
|
|
29
|
+
auto promise = promiseVendor_->createPromise(
|
|
30
|
+
[audioBuffer, playbackSpeed](std::shared_ptr<Promise> promise) {
|
|
31
|
+
std::thread([audioBuffer,
|
|
32
|
+
playbackSpeed,
|
|
33
|
+
promise = std::move(promise)]() {
|
|
34
|
+
auto result = AudioStretcher::changePlaybackSpeed(
|
|
35
|
+
*audioBuffer->audioBuffer_, playbackSpeed);
|
|
36
|
+
|
|
37
|
+
if (!result) {
|
|
38
|
+
promise->reject("Failed to change audio playback speed.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
auto audioBufferHostObject =
|
|
43
|
+
std::make_shared<AudioBufferHostObject>(result);
|
|
44
|
+
|
|
45
|
+
promise->resolve([audioBufferHostObject = std::move(
|
|
46
|
+
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
47
|
+
auto jsiObject = jsi::Object::createFromHostObject(
|
|
48
|
+
runtime, audioBufferHostObject);
|
|
49
|
+
jsiObject.setExternalMemoryPressure(
|
|
50
|
+
runtime, audioBufferHostObject->getSizeInBytes());
|
|
51
|
+
return jsiObject;
|
|
52
|
+
});
|
|
53
|
+
}).detach();
|
|
54
|
+
});
|
|
55
|
+
return promise;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
|
|
4
|
+
#include <audioapi/core/utils/AudioStretcher.h>
|
|
5
|
+
#include <audioapi/jsi/JsiPromise.h>
|
|
6
|
+
|
|
7
|
+
#include <jsi/jsi.h>
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <thread>
|
|
11
|
+
#include <utility>
|
|
12
|
+
|
|
13
|
+
namespace audioapi {
|
|
14
|
+
using namespace facebook;
|
|
15
|
+
|
|
16
|
+
class AudioStretcherHostObject : public JsiHostObject {
|
|
17
|
+
public:
|
|
18
|
+
explicit AudioStretcherHostObject(
|
|
19
|
+
jsi::Runtime *runtime,
|
|
20
|
+
const std::shared_ptr<react::CallInvoker> &callInvoker);
|
|
21
|
+
JSI_HOST_FUNCTION_DECL(changePlaybackSpeed);
|
|
22
|
+
|
|
23
|
+
private:
|
|
24
|
+
std::shared_ptr<PromiseVendor> promiseVendor_;
|
|
25
|
+
};
|
|
26
|
+
} // namespace audioapi
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
#include <audioapi/core/AudioContext.h>
|
|
8
8
|
#include <audioapi/core/destinations/AudioDestinationNode.h>
|
|
9
|
-
#include <audioapi/core/utils/AudioDecoder.h>
|
|
10
9
|
#include <audioapi/core/utils/AudioNodeManager.h>
|
|
11
10
|
|
|
12
11
|
namespace audioapi {
|
|
@@ -26,7 +25,6 @@ AudioContext::AudioContext(
|
|
|
26
25
|
#endif
|
|
27
26
|
|
|
28
27
|
sampleRate_ = sampleRate;
|
|
29
|
-
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate);
|
|
30
28
|
|
|
31
29
|
if (initSuspended) {
|
|
32
30
|
playerHasBeenStarted_ = false;
|
|
@@ -176,41 +176,6 @@ std::shared_ptr<AnalyserNode> BaseAudioContext::createAnalyser() {
|
|
|
176
176
|
return analyser;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
|
|
180
|
-
const std::string &path) {
|
|
181
|
-
auto audioBus = audioDecoder_->decodeWithFilePath(path);
|
|
182
|
-
|
|
183
|
-
if (!audioBus) {
|
|
184
|
-
return nullptr;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return std::make_shared<AudioBuffer>(audioBus);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioData(
|
|
191
|
-
const void *data,
|
|
192
|
-
size_t size) {
|
|
193
|
-
auto audioBus = audioDecoder_->decodeWithMemoryBlock(data, size);
|
|
194
|
-
|
|
195
|
-
if (!audioBus) {
|
|
196
|
-
return nullptr;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return std::make_shared<AudioBuffer>(audioBus);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeWithPCMInBase64(
|
|
203
|
-
const std::string &data,
|
|
204
|
-
float playbackSpeed) {
|
|
205
|
-
auto audioBus = audioDecoder_->decodeWithPCMInBase64(data, playbackSpeed);
|
|
206
|
-
|
|
207
|
-
if (!audioBus) {
|
|
208
|
-
return nullptr;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return std::make_shared<AudioBuffer>(audioBus);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
179
|
AudioNodeManager *BaseAudioContext::getNodeManager() {
|
|
215
180
|
return nodeManager_.get();
|
|
216
181
|
}
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
#include <audioapi/core/types/ContextState.h>
|
|
4
4
|
#include <audioapi/core/types/OscillatorType.h>
|
|
5
5
|
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
6
|
-
|
|
6
|
+
#include <cassert>
|
|
7
|
+
#include <complex>
|
|
8
|
+
#include <cstddef>
|
|
7
9
|
#include <functional>
|
|
8
10
|
#include <memory>
|
|
9
11
|
#include <string>
|
|
10
12
|
#include <utility>
|
|
11
13
|
#include <vector>
|
|
12
|
-
#include <complex>
|
|
13
|
-
#include <cstddef>
|
|
14
|
-
#include <cassert>
|
|
15
14
|
|
|
16
15
|
namespace audioapi {
|
|
17
16
|
|
|
@@ -27,7 +26,6 @@ class BiquadFilterNode;
|
|
|
27
26
|
class AudioDestinationNode;
|
|
28
27
|
class AudioBufferSourceNode;
|
|
29
28
|
class AudioBufferQueueSourceNode;
|
|
30
|
-
class AudioDecoder;
|
|
31
29
|
class AnalyserNode;
|
|
32
30
|
class AudioEventHandlerRegistry;
|
|
33
31
|
class IAudioEventHandlerRegistry;
|
|
@@ -68,10 +66,6 @@ class BaseAudioContext {
|
|
|
68
66
|
int length);
|
|
69
67
|
std::shared_ptr<AnalyserNode> createAnalyser();
|
|
70
68
|
|
|
71
|
-
std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
|
|
72
|
-
std::shared_ptr<AudioBuffer> decodeAudioData(const void *data, size_t size);
|
|
73
|
-
std::shared_ptr<AudioBuffer> decodeWithPCMInBase64(const std::string &data, float playbackSpeed);
|
|
74
|
-
|
|
75
69
|
std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
|
|
76
70
|
[[nodiscard]] float getNyquistFrequency() const;
|
|
77
71
|
AudioNodeManager *getNodeManager();
|
|
@@ -85,9 +79,7 @@ class BaseAudioContext {
|
|
|
85
79
|
|
|
86
80
|
std::shared_ptr<AudioDestinationNode> destination_;
|
|
87
81
|
// init in AudioContext or OfflineContext constructor
|
|
88
|
-
|
|
89
|
-
// init in AudioContext or OfflineContext constructor
|
|
90
|
-
float sampleRate_ {};
|
|
82
|
+
float sampleRate_{};
|
|
91
83
|
ContextState state_ = ContextState::RUNNING;
|
|
92
84
|
std::shared_ptr<AudioNodeManager> nodeManager_;
|
|
93
85
|
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
#include <audioapi/core/AudioContext.h>
|
|
4
4
|
#include <audioapi/core/destinations/AudioDestinationNode.h>
|
|
5
5
|
#include <audioapi/core/sources/AudioBuffer.h>
|
|
6
|
-
#include <audioapi/core/utils/AudioDecoder.h>
|
|
7
6
|
#include <audioapi/core/utils/AudioNodeManager.h>
|
|
8
7
|
#include <audioapi/core/utils/Constants.h>
|
|
9
8
|
#include <audioapi/core/utils/Locker.h>
|
|
@@ -30,7 +29,6 @@ OfflineAudioContext::OfflineAudioContext(
|
|
|
30
29
|
numberOfChannels_(numberOfChannels),
|
|
31
30
|
currentSampleFrame_(0) {
|
|
32
31
|
sampleRate_ = sampleRate;
|
|
33
|
-
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate_);
|
|
34
32
|
resultBus_ = std::make_shared<AudioBus>(
|
|
35
33
|
static_cast<int>(length_), numberOfChannels_, sampleRate_);
|
|
36
34
|
}
|
|
@@ -27,10 +27,6 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode(
|
|
|
27
27
|
std::make_shared<signalsmith::stretch::SignalsmithStretch<float>>();
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
AudioBufferBaseSourceNode::~AudioBufferBaseSourceNode() {
|
|
31
|
-
clearOnPositionChangedCallback();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
30
|
std::shared_ptr<AudioParam> AudioBufferBaseSourceNode::getDetuneParam() const {
|
|
35
31
|
return detuneParam_;
|
|
36
32
|
}
|
|
@@ -15,7 +15,6 @@ class AudioParam;
|
|
|
15
15
|
class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
|
|
16
16
|
public:
|
|
17
17
|
explicit AudioBufferBaseSourceNode(BaseAudioContext *context, bool pitchCorrection);
|
|
18
|
-
~AudioBufferBaseSourceNode() override;
|
|
19
18
|
|
|
20
19
|
[[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
|
|
21
20
|
[[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
|
|
@@ -16,10 +16,6 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
|
|
|
16
16
|
numberOfInputs_ = 0;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
AudioScheduledSourceNode::~AudioScheduledSourceNode() {
|
|
20
|
-
clearOnEndedCallback();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
19
|
void AudioScheduledSourceNode::start(double when) {
|
|
24
20
|
playbackState_ = PlaybackState::SCHEDULED;
|
|
25
21
|
startTime_ = when;
|
|
@@ -27,7 +27,6 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
27
27
|
// FINISHED: The node has finished playing.
|
|
28
28
|
enum class PlaybackState { UNSCHEDULED, SCHEDULED, PLAYING, STOP_SCHEDULED, FINISHED };
|
|
29
29
|
explicit AudioScheduledSourceNode(BaseAudioContext *context);
|
|
30
|
-
~AudioScheduledSourceNode() override;
|
|
31
30
|
|
|
32
31
|
void start(double when);
|
|
33
32
|
virtual void stop(double when);
|
|
@@ -1,124 +1,67 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <audioapi/
|
|
3
|
+
#include <audioapi/core/types/AudioFormat.h>
|
|
4
4
|
#include <audioapi/libs/miniaudio/miniaudio.h>
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
#include <cstring>
|
|
5
7
|
#include <memory>
|
|
6
8
|
#include <string>
|
|
7
9
|
#include <vector>
|
|
8
|
-
#include <cstring>
|
|
9
|
-
#include <algorithm>
|
|
10
10
|
|
|
11
11
|
namespace audioapi {
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
UNKNOWN,
|
|
15
|
-
WAV,
|
|
16
|
-
OGG,
|
|
17
|
-
FLAC,
|
|
18
|
-
AAC,
|
|
19
|
-
MP3,
|
|
20
|
-
M4A,
|
|
21
|
-
MP4,
|
|
22
|
-
MOV
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
class AudioBus;
|
|
13
|
+
class AudioBuffer;
|
|
26
14
|
|
|
27
15
|
static constexpr int CHUNK_SIZE = 4096;
|
|
28
16
|
|
|
29
17
|
class AudioDecoder {
|
|
30
18
|
public:
|
|
31
|
-
|
|
19
|
+
AudioDecoder() = delete;
|
|
32
20
|
|
|
33
|
-
[[nodiscard]] std::shared_ptr<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
[[nodiscard]] std::shared_ptr<AudioBus> decodeWithPCMInBase64(
|
|
39
|
-
const std::string &data,
|
|
40
|
-
float playbackSpeed) const;
|
|
21
|
+
[[nodiscard]] static std::shared_ptr<AudioBuffer> decodeWithFilePath(const std::string &path, float sampleRate);
|
|
22
|
+
[[nodiscard]] static std::shared_ptr<AudioBuffer>
|
|
23
|
+
decodeWithMemoryBlock(const void *data, size_t size, float sampleRate);
|
|
24
|
+
[[nodiscard]] static std::shared_ptr<AudioBuffer>
|
|
25
|
+
decodeWithPCMInBase64(const std::string &data, float inputSampleRate, int inputChannelCount, bool interleaved);
|
|
41
26
|
|
|
42
27
|
private:
|
|
43
|
-
float
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
static std::vector<int16_t> readAllPcmFrames(
|
|
47
|
-
ma_decoder &decoder,
|
|
48
|
-
int numChannels,
|
|
49
|
-
ma_uint64 &outFramesRead);
|
|
50
|
-
static std::shared_ptr<AudioBus> makeAudioBusFromInt16Buffer(
|
|
51
|
-
const std::vector<int16_t> &buffer,
|
|
52
|
-
int numChannels,
|
|
53
|
-
float sampleRate);
|
|
54
|
-
|
|
55
|
-
void changePlaybackSpeedIfNeeded(
|
|
56
|
-
std::vector<int16_t> &buffer,
|
|
57
|
-
size_t framesDecoded,
|
|
58
|
-
int numChannels,
|
|
59
|
-
float playbackSpeed) const {
|
|
60
|
-
if (playbackSpeed == 1.0f) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
auto stretcher = stretch_init(
|
|
65
|
-
static_cast<int>(sampleRate_ / 333.0f),
|
|
66
|
-
static_cast<int>(sampleRate_ / 55.0f),
|
|
67
|
-
numChannels,
|
|
68
|
-
0x1);
|
|
28
|
+
static std::vector<float> readAllPcmFrames(ma_decoder &decoder, int outputChannels);
|
|
29
|
+
static std::shared_ptr<AudioBuffer>
|
|
30
|
+
makeAudioBufferFromFloatBuffer(const std::vector<float> &buffer, float outputSampleRate, int outputChannels);
|
|
69
31
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
int outputFrames = stretch_samples(
|
|
75
|
-
stretcher,
|
|
76
|
-
buffer.data(),
|
|
77
|
-
static_cast<int>(framesDecoded),
|
|
78
|
-
stretchedBuffer.data(),
|
|
79
|
-
1 / playbackSpeed);
|
|
80
|
-
|
|
81
|
-
outputFrames +=
|
|
82
|
-
stretch_flush(stretcher, stretchedBuffer.data() + (outputFrames));
|
|
83
|
-
stretchedBuffer.resize(outputFrames);
|
|
84
|
-
|
|
85
|
-
buffer = stretchedBuffer;
|
|
86
|
-
|
|
87
|
-
stretch_deinit(stretcher);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
static AudioFormat detectAudioFormat(const void* data, size_t size) {
|
|
91
|
-
if (size < 12) return AudioFormat::UNKNOWN;
|
|
92
|
-
const auto* bytes = static_cast<const unsigned char*>(data);
|
|
32
|
+
static AudioFormat detectAudioFormat(const void *data, size_t size) {
|
|
33
|
+
if (size < 12)
|
|
34
|
+
return AudioFormat::UNKNOWN;
|
|
35
|
+
const auto *bytes = static_cast<const unsigned char *>(data);
|
|
93
36
|
|
|
94
37
|
// WAV/RIFF
|
|
95
38
|
if (std::memcmp(bytes, "RIFF", 4) == 0 && std::memcmp(bytes + 8, "WAVE", 4) == 0)
|
|
96
|
-
|
|
39
|
+
return AudioFormat::WAV;
|
|
97
40
|
|
|
98
41
|
// OGG
|
|
99
42
|
if (std::memcmp(bytes, "OggS", 4) == 0)
|
|
100
|
-
|
|
43
|
+
return AudioFormat::OGG;
|
|
101
44
|
|
|
102
45
|
// FLAC
|
|
103
46
|
if (std::memcmp(bytes, "fLaC", 4) == 0)
|
|
104
|
-
|
|
47
|
+
return AudioFormat::FLAC;
|
|
105
48
|
|
|
106
49
|
// AAC starts with 0xFF 0xF1 or 0xFF 0xF9
|
|
107
50
|
if (bytes[0] == 0xFF && (bytes[1] & 0xF6) == 0xF0)
|
|
108
|
-
|
|
51
|
+
return AudioFormat::AAC;
|
|
109
52
|
|
|
110
53
|
// MP3: "ID3" or 11-bit frame sync (0xFF 0xE0)
|
|
111
54
|
if (std::memcmp(bytes, "ID3", 3) == 0)
|
|
112
|
-
|
|
55
|
+
return AudioFormat::MP3;
|
|
113
56
|
if (bytes[0] == 0xFF && (bytes[1] & 0xE0) == 0xE0)
|
|
114
|
-
|
|
57
|
+
return AudioFormat::MP3;
|
|
115
58
|
|
|
116
59
|
if (std::memcmp(bytes + 4, "ftyp", 4) == 0) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
60
|
+
if (std::memcmp(bytes + 8, "M4A ", 4) == 0)
|
|
61
|
+
return AudioFormat::M4A;
|
|
62
|
+
else if (std::memcmp(bytes + 8, "qt ", 4) == 0)
|
|
63
|
+
return AudioFormat::MOV;
|
|
64
|
+
return AudioFormat::MP4;
|
|
122
65
|
}
|
|
123
66
|
return AudioFormat::UNKNOWN;
|
|
124
67
|
}
|
|
@@ -126,19 +69,21 @@ class AudioDecoder {
|
|
|
126
69
|
static inline bool pathHasExtension(const std::string &path, const std::vector<std::string> &extensions) {
|
|
127
70
|
std::string pathLower = path;
|
|
128
71
|
std::transform(pathLower.begin(), pathLower.end(), pathLower.begin(), ::tolower);
|
|
129
|
-
for (const auto&
|
|
130
|
-
|
|
131
|
-
|
|
72
|
+
for (const auto &ext : extensions) {
|
|
73
|
+
if (pathLower.ends_with(ext))
|
|
74
|
+
return true;
|
|
132
75
|
}
|
|
133
76
|
return false;
|
|
134
77
|
}
|
|
135
78
|
|
|
136
|
-
|
|
137
79
|
[[nodiscard]] static inline int16_t floatToInt16(float sample) {
|
|
138
|
-
return static_cast<int16_t>(sample *
|
|
80
|
+
return static_cast<int16_t>(sample * INT16_MAX);
|
|
139
81
|
}
|
|
140
82
|
[[nodiscard]] static inline float int16ToFloat(int16_t sample) {
|
|
141
|
-
return static_cast<float>(sample) /
|
|
83
|
+
return static_cast<float>(sample) / INT16_MAX;
|
|
84
|
+
}
|
|
85
|
+
[[nodiscard]] static inline float uint8ToFloat(uint8_t byte1, uint8_t byte2) {
|
|
86
|
+
return static_cast<float>(static_cast<int16_t>((byte2 << 8) | byte1)) / INT16_MAX;
|
|
142
87
|
}
|
|
143
88
|
};
|
|
144
89
|
|