Skip to content

Commit d36987f

Browse files
authored
feat/fix: possibility of onended and positionChange events removal (#519)
* feat: possibility of onended and positionChange events removal * fix: misplacement of sending events
1 parent d331929 commit d36987f

File tree

9 files changed

+48
-17
lines changed

9 files changed

+48
-17
lines changed

apps/common-app/src/examples/AudioFile/AudioPlayer.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class AudioPlayer {
5151
this.offset = event.value;
5252
};
5353

54+
this.sourceNode.onended = (event) => {
55+
console.log("ended");
56+
}
57+
5458
this.sourceNode.start(this.audioContext.currentTime, this.offset);
5559

5660
AudioManager.setLockScreenInfo({
@@ -103,8 +107,12 @@ class AudioPlayer {
103107
};
104108

105109
reset = () => {
110+
if (this.sourceNode) {
111+
this.sourceNode.onended = null;
112+
this.sourceNode.onPositionChanged = null;
113+
this.sourceNode.stop(this.audioContext.currentTime);
114+
}
106115
this.audioBuffer = null;
107-
this.sourceNode?.stop(this.audioContext.currentTime);
108116
this.sourceNode = null;
109117
this.offset = 0;
110118
this.seekOffset = 0;

packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ std::mutex &AudioBufferBaseSourceNode::getBufferLock() {
4747
}
4848

4949
void AudioBufferBaseSourceNode::sendOnPositionChangedEvent() {
50-
if (onPositionChangedTime_ > onPositionChangedInterval_) {
50+
if (onPositionChangedCallbackId_ != 0 &&
51+
onPositionChangedTime_ > onPositionChangedInterval_) {
5152
std::unordered_map<std::string, EventValue> body = {
5253
{"value", getCurrentPosition()}};
5354

@@ -99,6 +100,7 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection(
99100
if (detune != 0.0f) {
100101
stretch_->setTransposeSemitones(detune);
101102
}
103+
sendOnPositionChangedEvent();
102104
}
103105

104106
} // namespace audioapi

packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
3434
// internal helper
3535
double vReadIndex_;
3636

37-
uint64_t onPositionChangedCallbackId_ = 0;
37+
uint64_t onPositionChangedCallbackId_ = 0; // 0 means no callback
3838
int onPositionChangedInterval_;
3939
int onPositionChangedTime_ = 0;
4040

packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ void AudioBufferQueueSourceNode::processNode(
7070
processWithPitchCorrection(processingBus, framesToProcess);
7171

7272
handleStopScheduled();
73-
sendOnPositionChangedEvent();
7473
} else {
7574
processingBus->zero();
7675
}

packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ void AudioBufferSourceNode::processNode(
141141
}
142142

143143
handleStopScheduled();
144-
sendOnPositionChangedEvent();
145144
} else {
146145
processingBus->zero();
147146
}
@@ -177,6 +176,8 @@ void AudioBufferSourceNode::processWithoutPitchCorrection(
177176
processWithInterpolation(
178177
processingBus, startOffset, offsetLength, computedPlaybackRate);
179178
}
179+
180+
sendOnPositionChangedEvent();
180181
}
181182

182183
void AudioBufferSourceNode::processWithoutInterpolation(

packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
7373
? std::numeric_limits<size_t>::max()
7474
: dsp::timeToSampleFrame(stopTime_, sampleRate);
7575

76-
if (isUnscheduled() || isFinished()) {
76+
if (isFinished()) {
7777
startOffset = 0;
7878
nonSilentFramesToProcess = 0;
7979
return;
@@ -135,6 +135,12 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
135135
return;
136136
}
137137

138+
if (isUnscheduled()) {
139+
startOffset = 0;
140+
nonSilentFramesToProcess = 0;
141+
return;
142+
}
143+
138144
// normal "mid-buffer" playback
139145
startOffset = 0;
140146
nonSilentFramesToProcess = framesToProcess;

packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ AudioEventHandlerRegistry::~AudioEventHandlerRegistry() {
2424
uint64_t AudioEventHandlerRegistry::registerHandler(
2525
const std::string &eventName,
2626
const std::shared_ptr<jsi::Function> &handler) {
27-
static uint64_t LISTENER_ID = 0;
27+
static uint64_t LISTENER_ID = 1;
2828

2929
eventHandlers_[eventName][LISTENER_ID] = handler;
3030

packages/react-native-audio-api/src/core/AudioBufferBaseSourceNode.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import AudioScheduledSourceNode from './AudioScheduledSourceNode';
33
import BaseAudioContext from './BaseAudioContext';
44
import AudioParam from './AudioParam';
55
import { EventTypeWithValue } from '../events/types';
6+
import { AudioEventSubscription } from '../events';
67

78
export default class AudioBufferBaseSourceNode extends AudioScheduledSourceNode {
89
readonly playbackRate: AudioParam;
910
readonly detune: AudioParam;
11+
private positionChangedSubscription?: AudioEventSubscription;
1012

1113
constructor(context: BaseAudioContext, node: IAudioBufferBaseSourceNode) {
1214
super(context, node);
@@ -16,14 +18,20 @@ export default class AudioBufferBaseSourceNode extends AudioScheduledSourceNode
1618
}
1719

1820
// eslint-disable-next-line accessor-pairs
19-
public set onPositionChanged(callback: (event: EventTypeWithValue) => void) {
20-
const subscription = this.audioEventEmitter.addAudioEventListener(
21-
'positionChanged',
22-
callback
23-
);
21+
public set onPositionChanged(
22+
callback: ((event: EventTypeWithValue) => void) | null
23+
) {
24+
if (!callback) {
25+
this.positionChangedSubscription?.remove();
26+
this.positionChangedSubscription = undefined;
27+
(this.node as IAudioBufferBaseSourceNode).onPositionChanged = '0';
28+
return;
29+
}
30+
this.positionChangedSubscription =
31+
this.audioEventEmitter.addAudioEventListener('positionChanged', callback);
2432

2533
(this.node as IAudioBufferBaseSourceNode).onPositionChanged =
26-
subscription.subscriptionId;
34+
this.positionChangedSubscription.subscriptionId;
2735
}
2836

2937
// eslint-disable-next-line accessor-pairs

packages/react-native-audio-api/src/core/AudioScheduledSourceNode.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import { IAudioScheduledSourceNode } from '../interfaces';
22
import AudioNode from './AudioNode';
33
import { InvalidStateError, RangeError } from '../errors';
44
import { EventEmptyType } from '../events/types';
5-
import { AudioEventEmitter } from '../events';
5+
import { AudioEventEmitter, AudioEventSubscription } from '../events';
66

77
export default class AudioScheduledSourceNode extends AudioNode {
88
protected hasBeenStarted: boolean = false;
99
protected readonly audioEventEmitter = new AudioEventEmitter(
1010
global.AudioEventEmitter
1111
);
1212

13+
private onendedSubscription?: AudioEventSubscription;
14+
1315
public start(when: number = 0): void {
1416
if (when < 0) {
1517
throw new RangeError(
@@ -42,13 +44,18 @@ export default class AudioScheduledSourceNode extends AudioNode {
4244
}
4345

4446
// eslint-disable-next-line accessor-pairs
45-
public set onended(callback: (event: EventEmptyType) => void) {
46-
const subscription = this.audioEventEmitter.addAudioEventListener(
47+
public set onended(callback: ((event: EventEmptyType) => void) | null) {
48+
if (!callback) {
49+
this.onendedSubscription?.remove();
50+
this.onendedSubscription = undefined;
51+
return;
52+
}
53+
this.onendedSubscription = this.audioEventEmitter.addAudioEventListener(
4754
'ended',
4855
callback
4956
);
5057

5158
(this.node as IAudioScheduledSourceNode).onended =
52-
subscription.subscriptionId;
59+
this.onendedSubscription.subscriptionId;
5360
}
5461
}

0 commit comments

Comments
 (0)