A decentralized music tracking and discovery platform built on AT Protocol 馃幍
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
1import init, { AudioDecoder } from "../pkg/raichu";
2import consola from "consola";
3
4class AudioPlayer {
5 private audioContext: AudioContext | null = null;
6 private sourceNode: AudioBufferSourceNode | null = null;
7 private buffer: AudioBuffer | null = null;
8
9 async load(url: string, ext: string) {
10 const response = await fetch(url);
11 const arrayBuffer = await response.arrayBuffer();
12 const uint8Array = new Uint8Array(arrayBuffer);
13
14 await init(); // Initialize WASM
15 const decoder = new AudioDecoder();
16 decoder.decode(uint8Array, ext);
17
18 const pcmData = decoder.get_pcm_data();
19 const sampleRate = decoder.get_sample_rate();
20 const channels = decoder.get_channels();
21
22 this.audioContext = new window.AudioContext({ sampleRate });
23
24 this.buffer = this.audioContext.createBuffer(
25 channels,
26 pcmData.length / channels,
27 sampleRate,
28 );
29
30 for (let i = 0; i < channels; i++) {
31 const channelData = this.buffer.getChannelData(i);
32 for (let j = 0; j < channelData.length; j++) {
33 channelData[j] = pcmData[j * channels + i];
34 }
35 }
36
37 consola.info(">> Audio Loaded Successfully");
38 }
39
40 play(offset = 0) {
41 if (this.audioContext && this.buffer) {
42 this.sourceNode = this.audioContext.createBufferSource();
43 this.sourceNode.buffer = this.buffer;
44 this.sourceNode.connect(this.audioContext.destination);
45 this.sourceNode.start(0, offset);
46 this.sourceNode.loop = false;
47 }
48 }
49
50 pause() {
51 if (this.sourceNode) {
52 this.sourceNode.stop();
53 this.sourceNode = null;
54 }
55 }
56
57 stop() {
58 this.pause();
59 if (this.audioContext) {
60 this.audioContext.close();
61 this.audioContext = null;
62 }
63 }
64}
65export default AudioPlayer;