Platine etape 1
This commit is contained in:
97
app/platine-tools/sampler.ts
Normal file
97
app/platine-tools/sampler.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
class Sampler {
|
||||
public audioContext: AudioContext = new AudioContext();
|
||||
public gainNode: GainNode = new GainNode(this.audioContext);
|
||||
|
||||
public audioBuffer: AudioBuffer | null = null;
|
||||
public audioBufferReversed: AudioBuffer | null = null;
|
||||
public audioSource: AudioBufferSourceNode | null = null;
|
||||
|
||||
public duration: number = 0;
|
||||
public isReversed: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.gainNode.connect(this.audioContext.destination);
|
||||
}
|
||||
|
||||
async getAudioBuffer(audioUrl: string) {
|
||||
const response = await fetch(audioUrl);
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
|
||||
const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
|
||||
|
||||
return audioBuffer;
|
||||
}
|
||||
|
||||
async loadTrack(audioUrl: string) {
|
||||
this.audioBuffer = await this.getAudioBuffer(audioUrl);
|
||||
this.audioBufferReversed = this.getReversedAudioBuffer(this.audioBuffer);
|
||||
|
||||
this.duration = this.audioBuffer.duration;
|
||||
}
|
||||
|
||||
getReversedAudioBuffer(audioBuffer: AudioBuffer) {
|
||||
const bufferArray = audioBuffer.getChannelData(0).slice().reverse();
|
||||
|
||||
const audioBufferReversed = this.audioContext.createBuffer(
|
||||
1,
|
||||
audioBuffer.length,
|
||||
audioBuffer.sampleRate,
|
||||
);
|
||||
|
||||
audioBufferReversed.getChannelData(0).set(bufferArray);
|
||||
|
||||
return audioBufferReversed;
|
||||
}
|
||||
|
||||
changeDirection(isReversed: boolean, secondsPlayed: number) {
|
||||
this.isReversed = isReversed;
|
||||
this.play(secondsPlayed);
|
||||
}
|
||||
|
||||
play(offset = 0) {
|
||||
this.pause();
|
||||
|
||||
const buffer = this.isReversed
|
||||
? this.audioBufferReversed
|
||||
: this.audioBuffer;
|
||||
|
||||
const cueTime = this.isReversed ? this.duration - offset : offset;
|
||||
|
||||
this.audioSource = this.audioContext.createBufferSource();
|
||||
this.audioSource.buffer = buffer;
|
||||
this.audioSource.loop = false;
|
||||
|
||||
this.audioSource.connect(this.gainNode);
|
||||
|
||||
this.audioSource.start(0, cueTime);
|
||||
}
|
||||
|
||||
updateSpeed(speed: number, isReversed: boolean, secondsPlayed: number) {
|
||||
if (!this.audioSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isReversed !== this.isReversed) {
|
||||
this.changeDirection(isReversed, secondsPlayed);
|
||||
}
|
||||
|
||||
const { currentTime } = this.audioContext;
|
||||
const speedAbsolute = Math.abs(speed);
|
||||
|
||||
this.audioSource.playbackRate.cancelScheduledValues(currentTime);
|
||||
this.audioSource.playbackRate.linearRampToValueAtTime(
|
||||
Math.max(0.001, speedAbsolute),
|
||||
currentTime,
|
||||
);
|
||||
}
|
||||
|
||||
pause() {
|
||||
if (!this.audioSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.audioSource.stop();
|
||||
}
|
||||
}
|
||||
|
||||
export default Sampler;
|
||||
Reference in New Issue
Block a user