Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions .claude/skills/utilities/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,22 @@ Higher-level DSP blocks. Read each header before use.

---

### `WsolaTimeStretcher.h` — pitch-preserving time stretch

Needs ~`getRequiredInputFrames()` of PCM in its internal queue before the first OLA
iteration.

- **File / AudioTag:** early `SeekDecoderDaemon` fills the SPSC; construction
`primeWsolaInputFromDecoder()` waits until the analysis queue is full (no wall-clock
deadline). No first-quantum warmup — process only feeds the current quantum.
- **Buffer sources:** `AudioBufferSourceNode::start` calls `primeWsolaInput()` after
setting `vReadIndex_` (advances cursor by frames fed). Prefill happens only there;
`processWithPitchCorrection` feeds one quantum's input. Compare cold-start with DC
ones sample + abs/relative first-sound logs in `WsolaTimeStretcher`. Scratch sized
with `scratchBufferFrames(sampleRate)`.

---

### `SpectrumAnalyser.h` — shared windowed-FFT magnitude spectrum

Owns FFT scratch state (Blackman window, temp array, complex scratch, magnitude
Expand Down
49 changes: 16 additions & 33 deletions apps/common-app/src/examples/AudioTag/AudioTag.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { Text, useWindowDimensions, View } from 'react-native';
import { useWindowDimensions, View } from 'react-native';
import {
Audio,
AudioTagHandle,
Expand Down Expand Up @@ -97,41 +96,25 @@ const AudioTag: React.FC = () => {
// console.log('onVolumeChange', volume);
}, []);

const audioTagElement = useMemo(
() => (
<Audio
source={DEMO_AUDIO_URL}
ref={audioRef}
context={audioContextRef.current}
loop
controls
onLoadStart={handleLoadStart}
onLoad={handleLoad}
onError={handleError}
onPositionChange={handlePositionChange}
onEnded={handleEnded}
onPlay={handlePlay}
onPause={handlePause}
onVolumeChange={handleVolumeEvent}
/>
),
[
handleEnded,
handleError,
handleLoad,
handleLoadStart,
handlePause,
handlePlay,
handlePositionChange,
handleVolumeEvent,
]
);

return (
<Container disablePadding>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{ width: '90%' }}>
{audioTagElement}
<Audio
source={DEMO_AUDIO_URL}
ref={audioRef}
context={audioContextRef.current}
loop
controls
onLoadStart={handleLoadStart}
onLoad={handleLoad}
onError={handleError}
onPositionChange={handlePositionChange}
onEnded={handleEnded}
onPlay={handlePlay}
onPause={handlePause}
onVolumeChange={handleVolumeEvent}
/>
<Spacer.Vertical size={20} />
<Slider
label="Volume"
Expand Down
Loading