Skip to content

merge main to docsprod #529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
e17ddc7
chore: released 0.6.1 (#485)
maciejmakowski2003 Jun 2, 2025
1f57794
feat: add haptics support for iOS audio sessions
tiramisuuuu Jun 4, 2025
897b6fb
revert changes to audio-manager.mdx
tiramisuuuu Jun 4, 2025
e0c8bab
refactor: change haptics configuration from iosOptions to dedicated i…
tiramisuuuu Jun 4, 2025
fd0f1cb
Merge pull request #487 from tiramisuuuu/main
michalsek Jun 4, 2025
cc693f5
fix: remove explicit base class destructor calls in AudioRecorder sub…
tiramisuuuu Jun 4, 2025
fa68804
Merge pull request #488 from tiramisuuuu/main
michalsek Jun 5, 2025
3e6627a
Merge pull request #489 from software-mansion/michalsek-patch-1
michalsek Jun 5, 2025
56a353b
Update README.md (#490)
michalsek Jun 5, 2025
c70c467
feat: implemented decoding pcm in base64 (#486)
maciejmakowski2003 Jun 5, 2025
f8042cd
Cant wait to do that - PAUSE in RN-Audio-API (#491)
maciejmakowski2003 Jun 5, 2025
3c9d773
fix: fixed stop (#492)
maciejmakowski2003 Jun 5, 2025
cddba01
fix: fixed spec alignment on android (#493)
maciejmakowski2003 Jun 5, 2025
3d0221d
feat: position event in audio buffer
mdydek Jun 10, 2025
68f7d41
fix: refactor param processing
mdydek Jun 10, 2025
8ab7213
feat: position event in audio buffer
mdydek Jun 10, 2025
27c61fc
fix: additional conditions to if that handled looping
mdydek Jun 10, 2025
1f1c27b
fix: typo
mdydek Jun 10, 2025
36a8ddc
feat: added parameter to steer skipping track if setting loopStart
mdydek Jun 11, 2025
3a014a9
fix: format
mdydek Jun 11, 2025
0c9db2b
fix: refactor param processing
mdydek Jun 11, 2025
49db066
Merge pull request #499 from software-mansion/fix/incorrect-looping-i…
mdydek Jun 11, 2025
2cb0662
docs: integrated few-line pages into their main objects (#501)
mdydek Jun 12, 2025
0c6ba16
docs: added docs for audio recorder (#502)
mdydek Jun 12, 2025
6b5efc6
Fix/android/lock screen info (#503)
maciejmakowski2003 Jun 12, 2025
3758918
fix: fixed order in ctor (#508)
maciejmakowski2003 Jun 17, 2025
7ade531
Refactor/audio buffer base source node (#504)
maciejmakowski2003 Jun 17, 2025
fb32708
Enable Native External Audio Processing via TurboModules (#469)
jerryseigle Jun 18, 2025
60b0309
fix: iOS restart engine after AVAudioSessionMediaServicesWereResetNot…
maxpotemkin Jun 23, 2025
a3b3c53
fix: fixed lock screen skip commands for android above 12 (#514)
maciejmakowski2003 Jun 23, 2025
aacea1e
fix: defining memory pressure in host object (#515)
mdydek Jun 23, 2025
d331929
chore: released 0.6.2 (#516)
maciejmakowski2003 Jun 23, 2025
d36987f
feat/fix: possibility of onended and positionChange events removal (#…
mdydek Jun 24, 2025
cac3bc4
feat/fix: update to react native 0.80.0 and fix android (#511)
itsramiel Jun 25, 2025
36c619f
docs: updated compatibility table and web audio mapi coverage (#521)
maciejmakowski2003 Jun 25, 2025
b7431a1
chore: released 0.6.3 (#524)
maciejmakowski2003 Jun 25, 2025
b51cc7b
Fix/android/runtime import (#527)
maciejmakowski2003 Jun 25, 2025
c7d5abc
docs: updated compatibility table (#528)
maciejmakowski2003 Jun 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Closes #

## ⚠️ Breaking changes ⚠️

<!-- A brief description of the breaking changes -->

-

## Introduced changes

<!-- A brief description of the changes -->
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ check out the [Getting Started](https://docs.swmansion.com/react-native-audio-ap
Ability to modify playback speed without affecting pitch of the sound
<br />

- <sub>[![Released in 0.6.0](https://img.shields.io/badge/Released_in-0.6.0-green)](https://github.com/software-mansion/react-native-audio-api/releases/tag/0.6.0)</sub> <br/> **System configuration** 🛠️ <br />
- <sub>[![Released in 0.6.0](https://img.shields.io/badge/Released_in-0.6.0-green)](https://github.com/software-mansion/react-native-audio-api/releases/tag/0.6.0)</sub> **System configuration** 🛠️ <br />
Full control of system audio settings, remote controls, lock screen integration and most importantly configurable background modes <br />
<br /> **Microphone support** 🎙️ <br />

- **Microphone support** 🎙️ <br />
Grab audio data from device microphone or connected device, connect it to the audio graph or stream through the internet <br />
<br /> **Connect audio param** 🤞 <br />

- **Connect audio param** 🤞 <br />
Ability to connect Audio nodes to audio params, which will allow for powerful and efficient modulation of audio parameters, creating effects like tremolo, vibrato or complex envelope followers. <br />

- **JS Audio Worklets** 🐎 <br />
Expand Down
38 changes: 19 additions & 19 deletions apps/common-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@
"react-native": "*"
},
"dependencies": {
"@react-native-vector-icons/common": "^11.0.0",
"@react-native-vector-icons/icomoon": "^0.0.1",
"@react-navigation/native": "^7.0.15",
"@react-navigation/native-stack": "^7.2.1",
"@react-navigation/stack": "^7.1.2",
"@shopify/react-native-skia": "1.11.11",
"@react-native-vector-icons/common": "12.0.1",
"@react-native-vector-icons/icomoon": "12.0.1",
"@react-navigation/native": "7.1.13",
"@react-navigation/native-stack": "7.3.18",
"@react-navigation/stack": "7.3.6",
"@shopify/react-native-skia": "2.0.5",
"react-native-audio-api": "workspace:*",
"react-native-dotenv": "3.4.11",
"react-native-gesture-handler": "2.24.0",
"react-native-reanimated": "3.17.1",
"react-native-safe-area-context": "5.3.0",
"react-native-screens": "4.9.1"
"react-native-gesture-handler": "2.26.0",
"react-native-reanimated": "3.18.0",
"react-native-safe-area-context": "5.4.1",
"react-native-screens": "4.11.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.2",
"@babel/runtime": "^7.25.0",
"@react-native/babel-preset": "0.77.1",
"@react-native/eslint-config": "0.77.1",
"@react-native/metro-config": "0.77.1",
"@react-native/typescript-config": "0.77.1",
"@react-native/babel-preset": "0.80.0",
"@react-native/eslint-config": "0.80.0",
"@react-native/metro-config": "0.80.0",
"@react-native/typescript-config": "0.80.0",
"@types/jest": "^29.5.13",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"@types/react": "^19.1.0",
"@types/react-test-renderer": "^19.1.0",
"eslint": "^8.57.0",
"jest": "^29.6.3",
"prettier": "^3.3.3",
"react": "18.3.1",
"react-native": "0.77.1",
"react-test-renderer": "18.3.1",
"react": "19.1.0",
"react-native": "0.80.0",
"react-test-renderer": "19.1.0",
"typescript": "~5.3.0"
}
}
158 changes: 31 additions & 127 deletions apps/common-app/src/examples/AudioFile/AudioFile.tsx
Original file line number Diff line number Diff line change
@@ -1,93 +1,23 @@
import React, { useCallback, useEffect, useRef, useState, FC } from 'react';
import React, { useCallback, useEffect, useState, FC } from 'react';
import { ActivityIndicator } from 'react-native';
import {
AudioBuffer,
AudioContext,
AudioBufferSourceNode,
AudioManager,
} from 'react-native-audio-api';

import { Container, Button, Spacer, Slider } from '../../components';
import { AudioManager } from 'react-native-audio-api';
import { Container, Button } from '../../components';
import AudioPlayer from './AudioPlayer';

const URL =
'https://software-mansion.github.io/react-native-audio-api/audio/voice/example-voice-01.mp3';

const INITIAL_RATE = 1;
const INITIAL_DETUNE = 0;

const labelWidth = 80;

const AudioFile: FC = () => {
const [isPlaying, setIsPlaying] = useState(false);
const [isLoading, setIsLoading] = useState(false);

const [offset, setOffset] = useState(0);
const [playbackRate, setPlaybackRate] = useState(INITIAL_RATE);
const [detune, setDetune] = useState(INITIAL_DETUNE);

const [audioBuffer, setAudioBuffer] = useState<AudioBuffer | null>(null);

const audioContextRef = useRef<AudioContext | null>(null);
const bufferSourceRef = useRef<AudioBufferSourceNode | null>(null);

const handlePlaybackRateChange = (newValue: number) => {
setPlaybackRate(newValue);

if (bufferSourceRef.current) {
bufferSourceRef.current.playbackRate.value = newValue;
}
};

const handleDetuneChange = (newValue: number) => {
setDetune(newValue);

if (bufferSourceRef.current) {
bufferSourceRef.current.detune.value = newValue;
}
};

const handlePress = async () => {
if (!audioContextRef.current) {
return;
}

const togglePlayPause = async () => {
if (isPlaying) {
bufferSourceRef.current?.stop(audioContextRef.current.currentTime);
AudioManager.setLockScreenInfo({
state: 'state_paused',
});

setTimeout(async () => {
await audioContextRef.current?.suspend();
}, 5);
await AudioPlayer.pause();
} else {
if (!audioBuffer) {
fetchAudioBuffer();
}

await audioContextRef.current.resume();

AudioManager.setLockScreenInfo({
state: 'state_playing',
});
await AudioPlayer.play();

AudioManager.observeAudioInterruptions(true);

bufferSourceRef.current = audioContextRef.current.createBufferSource({
pitchCorrection: true,
});
bufferSourceRef.current.buffer = audioBuffer;
bufferSourceRef.current.onended = (event) => {
setOffset((_prev) => event.value || 0);
};
bufferSourceRef.current.playbackRate.value = playbackRate;
bufferSourceRef.current.detune.value = detune;
bufferSourceRef.current.connect(audioContextRef.current.destination);

bufferSourceRef.current.start(
audioContextRef.current.currentTime,
offset
);
}

setIsPlaying((prev) => !prev);
Expand All @@ -96,26 +26,12 @@ const AudioFile: FC = () => {
const fetchAudioBuffer = useCallback(async () => {
setIsLoading(true);

const buffer = await fetch(URL)
.then((response) => response.arrayBuffer())
.then((arrayBuffer) =>
audioContextRef.current!.decodeAudioData(arrayBuffer)
)
.catch((error) => {
console.error('Error decoding audio data source:', error);
return null;
});

setAudioBuffer(buffer);
await AudioPlayer.loadBuffer(URL);

setIsLoading(false);
}, []);

useEffect(() => {
if (!audioContextRef.current) {
audioContextRef.current = new AudioContext({ initSuspended: true });
}

AudioManager.setLockScreenInfo({
title: 'Audio file',
artist: 'Software Mansion',
Expand All @@ -125,30 +41,37 @@ const AudioFile: FC = () => {

AudioManager.enableRemoteCommand('remotePlay', true);
AudioManager.enableRemoteCommand('remotePause', true);
AudioManager.enableRemoteCommand('remoteChangePlaybackPosition', true);
AudioManager.enableRemoteCommand('remoteSkipForward', true);
AudioManager.enableRemoteCommand('remoteSkipBackward', true);
AudioManager.observeAudioInterruptions(true);

const remotePlaySubscription = AudioManager.addSystemEventListener(
'remotePlay',
(event) => {
console.log('remotePlay event:', event);
() => {
AudioPlayer.play();
}
);

const remotePauseSubscription = AudioManager.addSystemEventListener(
'remotePause',
() => {
AudioPlayer.pause();
}
);

const remoteSkipForwardSubscription = AudioManager.addSystemEventListener(
'remoteSkipForward',
(event) => {
console.log('remotePause event:', event);
AudioPlayer.seekBy(event.value);
}
);

const remoteChangePlaybackPositionSubscription =
AudioManager.addSystemEventListener(
'remoteChangePlaybackPosition',
(event) => {
console.log('remoteChangePlaybackPosition event:', event);
}
);
const remoteSkipBackwardSubscription = AudioManager.addSystemEventListener(
'remoteSkipBackward',
(event) => {
AudioPlayer.seekBy(-event.value);
}
);

const interruptionSubscription = AudioManager.addSystemEventListener(
'interruption',
Expand All @@ -162,10 +85,11 @@ const AudioFile: FC = () => {
return () => {
remotePlaySubscription?.remove();
remotePauseSubscription?.remove();
remoteChangePlaybackPositionSubscription?.remove();
remoteSkipForwardSubscription?.remove();
remoteSkipBackwardSubscription?.remove();
interruptionSubscription?.remove();
audioContextRef.current?.close();
AudioManager.resetLockScreenInfo();
AudioPlayer.reset();
};
}, [fetchAudioBuffer]);

Expand All @@ -174,28 +98,8 @@ const AudioFile: FC = () => {
{isLoading && <ActivityIndicator color="#FFFFFF" />}
<Button
title={isPlaying ? 'Stop' : 'Play'}
onPress={handlePress}
disabled={!audioBuffer}
/>
<Spacer.Vertical size={49} />
<Slider
label="Playback rate"
value={playbackRate}
onValueChange={handlePlaybackRateChange}
min={0.0}
max={2.0}
step={0.25}
minLabelWidth={labelWidth}
/>
<Spacer.Vertical size={20} />
<Slider
label="Detune"
value={detune}
onValueChange={handleDetuneChange}
min={-1200}
max={1200}
step={100}
minLabelWidth={labelWidth}
onPress={togglePlayPause}
disabled={isLoading}
/>
</Container>
);
Expand Down
Loading
Loading