Skip to content

Commit

Permalink
Fix/audio converter (#245)
Browse files Browse the repository at this point in the history
* refactor: refactored ios audio decoding

* refactor: refactored native folders structure

* refactor: removed unused prop from AudioParam

* refactor: share AudioDecoder header between ios and android

* refactor: refactored FFtFrame impl per platform

* ci: yarn lint fix

* fix: fixed .clang-format

* fix: fixed cpplint version

---------

Co-authored-by: Maciej Makowski <[email protected]>
  • Loading branch information
maciejmakowski2003 and Maciej Makowski authored Jan 8, 2025
1 parent 4233887 commit 4746fbf
Show file tree
Hide file tree
Showing 38 changed files with 112 additions and 302 deletions.
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ runs:

- name: Install cpplint
shell: bash
run: pip install 'cpplint==1.6.1'
run: pip install 'cpplint==2.0.0'

- name: Install ktlint
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion apps/fabric-example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2152,7 +2152,7 @@ SPEC CHECKSUMS:
React-utils: e74516d5b9483c5530ec61e249e28b88729321d2
ReactCodegen: ff7512e124e3dc1363a4930a209d033354d2042a
ReactCommon: cde69a75746e8d7131f61c27155ee9dc42117003
RNAudioAPI: edc2f2460642e089af187b2a8e44fd750155c70f
RNAudioAPI: 6910ec8d0609b3dc4072a8d6aafa9b8bfdd28406
RNGestureHandler: e1dcb274c17ca0680a04d7ff357e35e37c384185
RNReanimated: 4335a2d4b358c01a28fe1881db59d897e8724681
RNScreens: 74536418fef8086457d39df36a55b36efd5329c9
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-audio-api/.clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
Standard: Cpp17
TabWidth: 4
UseTab: Never
---
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-audio-api/RNAudioAPI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |s|

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

s.ios.frameworks = 'Accelerate'
s.ios.frameworks = 'CoreFoundation', 'CoreAudio', 'AudioToolbox', 'Accelerate'
s.xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) HAVE_ACCELERATE=1'
}
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-audio-api/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ file(GLOB_RECURSE SOURCE_FILES
"../common/cpp/jsi/*.h"
"../common/cpp/jsi/*.cpp"
"../common/cpp/types/*.h"
"../common/cpp/libs/*.h"
)

add_library(react-native-audio-api SHARED ${SOURCE_FILES})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

namespace audioapi {

AudioDecoder::AudioDecoder(int sampleRate) : sampleRate_(sampleRate) {}

AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {
ma_decoder decoder;
ma_decoder_config config =
Expand Down Expand Up @@ -55,10 +53,4 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {

return audioBus;
}

AudioBus *AudioDecoder::decodeWithArrayBuffer() const {
// TODO: implement this
return new AudioBus(1, 1, 1);
}

} // namespace audioapi
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context)
numberOfInputs_ = 0;
buffer_ = std::shared_ptr<AudioBuffer>(nullptr);

detuneParam_ =
std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
playbackRateParam_ = std::make_shared<AudioParam>(
context, 1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);

isInitialized_ = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ class AudioBus;

class AudioDecoder {
public:
explicit AudioDecoder(int sampleRate);
explicit AudioDecoder(int sampleRate) : sampleRate_(sampleRate) {}

[[nodiscard]] AudioBus *decodeWithFilePath(const std::string &path) const;
// TODO: implement this
[[nodiscard]] AudioBus *decodeWithArrayBuffer() const;

private:
int sampleRate_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@

namespace audioapi {

AudioParam::AudioParam(
BaseAudioContext *context,
float defaultValue,
float minValue,
float maxValue)
AudioParam::AudioParam(float defaultValue, float minValue, float maxValue)
: value_(defaultValue),
defaultValue_(defaultValue),
minValue_(minValue),
maxValue_(maxValue),
context_(context) {
maxValue_(maxValue) {
startTime_ = 0;
endTime_ = 0;
startValue_ = value_;
Expand Down
9 changes: 1 addition & 8 deletions packages/react-native-audio-api/common/cpp/core/AudioParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,9 @@

namespace audioapi {

class BaseAudioContext;

class AudioParam {
public:
explicit AudioParam(
BaseAudioContext *context,
float defaultValue,
float minValue,
float maxValue);
explicit AudioParam(float defaultValue, float minValue, float maxValue);

[[nodiscard]] float getValue() const;
float getValueAtTime(double time);
Expand All @@ -44,7 +38,6 @@ class AudioParam {
float defaultValue_;
float minValue_;
float maxValue_;
BaseAudioContext *context_;
std::deque<ParamChangeEvent> eventsQueue_;

double startTime_;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#ifdef ANDROID
#include "AudioDecoder.h"
#include "AudioPlayer.h"
#else
#include "IOSAudioDecoder.h"
#include "IOSAudioPlayer.h"
#endif

Expand All @@ -12,6 +10,7 @@
#include "AudioBuffer.h"
#include "AudioBufferSourceNode.h"
#include "AudioBus.h"
#include "AudioDecoder.h"
#include "AudioDestinationNode.h"
#include "AudioNodeManager.h"
#include "BiquadFilterNode.h"
Expand All @@ -25,13 +24,12 @@ namespace audioapi {
BaseAudioContext::BaseAudioContext() {
#ifdef ANDROID
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
#else
audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
audioDecoder_ =
std::make_shared<IOSAudioDecoder>(audioPlayer_->getSampleRate());
#endif

audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());

sampleRate_ = audioPlayer_->getSampleRate();
bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();

Expand Down Expand Up @@ -108,19 +106,11 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
sampleRate_, real, imag, length, disableNormalization);
}

#ifdef ANDROID
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
const std::string &path) {
auto audioBus = audioDecoder_->decodeWithFilePath(path);
return std::make_shared<AudioBuffer>(audioBus);
}
#else
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
const std::string &path) {
auto audioBus = audioDecoder_->decodeWithFilePath(path);
return std::make_shared<AudioBuffer>(audioBus);
}
#endif

std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
if (!isRunning()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ class AudioNodeManager;
class BiquadFilterNode;
class AudioDestinationNode;
class AudioBufferSourceNode;
class AudioDecoder;

#ifdef ANDROID
class AudioPlayer;
class AudioDecoder;
#else
class IOSAudioPlayer;
class IOSAudioDecoder;
#endif

class BaseAudioContext {
Expand Down Expand Up @@ -65,13 +64,12 @@ class BaseAudioContext {
protected:
static std::string toString(ContextState state);
std::shared_ptr<AudioDestinationNode> destination_;
std::shared_ptr<AudioDecoder> audioDecoder_;

#ifdef ANDROID
std::shared_ptr<AudioPlayer> audioPlayer_;
std::shared_ptr<AudioDecoder> audioDecoder_;
#else
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
std::shared_ptr<IOSAudioDecoder> audioDecoder_;
#endif

int sampleRate_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ namespace audioapi {
BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
: AudioNode(context) {
frequencyParam_ = std::make_shared<AudioParam>(
context, 350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
detuneParam_ =
std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
QParam_ =
std::make_shared<AudioParam>(context, 1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
gainParam_ = std::make_shared<AudioParam>(
context, 0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
QParam_ = std::make_shared<AudioParam>(1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
gainParam_ =
std::make_shared<AudioParam>(0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
type_ = BiquadFilterType::LOWPASS;
isInitialized_ = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
namespace audioapi {
constexpr int SAMPLE_RATE = 44100;
constexpr int CHANNEL_COUNT = 2;
constexpr float MOST_POSITIVE_SINGLE_FLOAT =
static_cast<float>(std::numeric_limits<float>::max());
constexpr float MOST_NEGATIVE_SINGLE_FLOAT =
static_cast<float>(std::numeric_limits<float>::lowest());
constexpr float MOST_POSITIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::max());
constexpr float MOST_NEGATIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::lowest());
constexpr float NYQUIST_FREQUENCY = SAMPLE_RATE / 2.0;
static float MAX_DETUNE = 1200 * std::log2(MOST_POSITIVE_SINGLE_FLOAT);
constexpr float MAX_GAIN = MOST_POSITIVE_SINGLE_FLOAT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace audioapi {

GainNode::GainNode(BaseAudioContext *context) : AudioNode(context) {
gainParam_ = std::make_shared<AudioParam>(context, 1.0, -MAX_GAIN, MAX_GAIN);
gainParam_ = std::make_shared<AudioParam>(1.0, -MAX_GAIN, MAX_GAIN);
isInitialized_ = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ namespace audioapi {
OscillatorNode::OscillatorNode(BaseAudioContext *context)
: AudioScheduledSourceNode(context) {
frequencyParam_ = std::make_shared<AudioParam>(
context, 444.0, -NYQUIST_FREQUENCY, NYQUIST_FREQUENCY);
detuneParam_ =
std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
444.0, -NYQUIST_FREQUENCY, NYQUIST_FREQUENCY);
detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
type_ = OscillatorType::SINE;
periodicWave_ = context_->getBasicWaveForm(type_);
isInitialized_ = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace audioapi {
StereoPannerNode::StereoPannerNode(BaseAudioContext *context)
: AudioNode(context) {
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
panParam_ = std::make_shared<AudioParam>(context, 0.0, -MAX_PAN, MAX_PAN);
panParam_ = std::make_shared<AudioParam>(0.0, -MAX_PAN, MAX_PAN);
isInitialized_ = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ size_t timeToSampleFrame(double time, int sampleRate);

double sampleFrameToTime(int sampleFrame, int sampleRate);

float linearInterpolate(
const float *source,
size_t firstIndex,
size_t secondIndex,
float factor);
float linearInterpolate(const float *source, size_t firstIndex, size_t secondIndex, float factor);

} // namespace audioapi::AudioUtils
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#if defined(HAVE_ACCELERATE)
#include "FFTFrame.h"
#include "Accelerate/Accelerate.h"

#if defined(HAVE_ACCELERATE)
#include <Accelerate/Accelerate.h>
#endif

#if defined(ANDROID)
#include <fftw3.h>
#endif

namespace audioapi {
#if defined(HAVE_ACCELERATE)

void FFTFrame::inverse(float *timeDomainData) {
FFTSetup fftSetup_ = vDSP_create_fftsetup(log2Size_, FFT_RADIX2);
Expand All @@ -25,5 +32,25 @@ void FFTFrame::inverse(float *timeDomainData) {

vDSP_destroy_fftsetup(fftSetup_);
}
} // namespace audioapi

#elif defined(ANDROID)

void FFTFrame::inverse(float *timeDomainData) {
fftwf_complex *freqDomainData = fftwf_alloc_complex(size_ / 2);
for (int i = 0; i < size_ / 2; i++) {
freqDomainData[i][0] = realData_[i];
freqDomainData[i][1] = imaginaryData_[i];
}

auto plan = fftwf_plan_dft_c2r_1d(
size_, freqDomainData, timeDomainData, FFTW_ESTIMATE);
fftwf_execute(plan);
fftwf_destroy_plan(plan);
fftwf_free(freqDomainData);

VectorMath::multiplyByScalar(
timeDomainData, 1.0f / static_cast<float>(size_), timeDomainData, size_);
}

#endif
} // namespace audioapi
40 changes: 7 additions & 33 deletions packages/react-native-audio-api/common/cpp/utils/VectorMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,14 @@

namespace audioapi::VectorMath {

void multiplyByScalarThenAddToOutput(
const float *inputVector,
float scalar,
float *outputVector,
size_t numberOfElementsToProcess);
void multiplyByScalarThenAddToOutput(const float *inputVector, float scalar, float *outputVector, size_t numberOfElementsToProcess);

void multiplyByScalar(
const float *inputVector,
float scalar,
float *outputVector,
size_t numberOfElementsToProcess);
void addScalar(
const float *inputVector,
float scalar,
float *outputVector,
size_t numberOfElementsToProcess);
void add(
const float *inputVector1,
const float *inputVector2,
float *outputVector,
size_t numberOfElementsToProcess);
void subtract(
const float *inputVector1,
const float *inputVector2,
float *outputVector,
size_t numberOfElementsToProcess);
void multiply(
const float *inputVector1,
const float *inputVector2,
float *outputVector,
size_t numberOfElementsToProcess);
void multiplyByScalar(const float *inputVector, float scalar, float *outputVector, size_t numberOfElementsToProcess);
void addScalar(const float *inputVector, float scalar, float *outputVector, size_t numberOfElementsToProcess);
void add(const float *inputVector1, const float *inputVector2, float *outputVector, size_t numberOfElementsToProcess);
void subtract(const float *inputVector1, const float *inputVector2, float *outputVector, size_t numberOfElementsToProcess);
void multiply(const float *inputVector1, const float *inputVector2, float *outputVector, size_t numberOfElementsToProcess);

// Finds the maximum magnitude of a float vector.
float maximumMagnitude(
const float *inputVector,
size_t numberOfElementsToProcess);
float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProcess);
} // namespace audioapi::VectorMath
Loading

0 comments on commit 4746fbf

Please sign in to comment.