Skip to content

Commit

Permalink
added eq to audio
Browse files Browse the repository at this point in the history
  • Loading branch information
0PandaDEV committed Apr 12, 2024
1 parent c8c5677 commit 6de099a
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 26 deletions.
66 changes: 62 additions & 4 deletions lib/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,53 @@ class Player {
private static instance: Player;
public audio: HTMLAudioElement;
public currentSongId: string;
private audioContext: AudioContext;
private sourceNode: MediaElementAudioSourceNode;
private eqFilters: BiquadFilterNode[];

private constructor() {
if (!Player.instance) {
this.audio = new Audio();
this.audio.volume = 1;
this.audio.preload = 'auto';
this.currentSongId = '';
this.audioContext = new AudioContext();
this.sourceNode = this.audioContext.createMediaElementSource(this.audio);
this.eqFilters = this.createEqFilters();
this.connectEqFilters();
Player.instance = this;
}
return Player.instance;
}

private createEqFilters(): BiquadFilterNode[] {
const frequencies = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
const filters = frequencies.map(freq => {
const filter = this.audioContext.createBiquadFilter();
filter.type = 'peaking';
filter.frequency.value = freq;
filter.Q.value = 1;
filter.gain.value = 0;
return filter;
});
return filters;
}

private connectEqFilters(): void {
let lastNode = this.sourceNode;
this.eqFilters.forEach(filter => {
lastNode.connect(filter);
lastNode = filter;
});
lastNode.connect(this.audioContext.destination);
}

public setEqGain(filterIndex: number, gain: number): void {
if (this.eqFilters[filterIndex]) {
this.eqFilters[filterIndex].gain.value = gain;
}
}

public async setSong(id: string) {
this.currentSongId = id;
const songsData = (await readSongs()).songs;
Expand Down Expand Up @@ -44,7 +79,13 @@ class Player {
}

public play() {
this.audio.play();
if (this.audioContext.state === 'suspended') {
this.audioContext.resume().then(() => {
this.audio.play();
});
} else {
this.audio.play();
}
}

public pause() {
Expand All @@ -67,8 +108,25 @@ class Player {
await this.setSong(songIds[prevIndex]);
}

public setVolume(value: number) {
this.audio.volume = value;
public setVolume(volume: number) {
if (volume == 0) {
this.audio.volume = 0;
return;
}

const minVolume = 1;
const maxVolume = 100;
volume = Math.max(minVolume, Math.min(maxVolume, volume));

const minp = 0;
const maxp = 100;

const minv = Math.log(0.01);
const maxv = Math.log(1);

const scale = (maxv - minv) / (maxp - minp);

this.audio.volume = Math.exp(minv + scale * (volume - minp));
}

public seek(percentage: number) {
Expand Down Expand Up @@ -123,4 +181,4 @@ class Player {
}
}

export default Player;
export default Player;
70 changes: 48 additions & 22 deletions pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
<template>
<div>
<div class="eq-controls">
<div v-for="(freq, index) in frequencies" :key="freq" class="eq-control">
<input
type="range"
min="-12"
max="12"
step="1"
v-model="eqGains[index]"
@input="updateEqGain(index, $event.target.value)"
/>
<label>{{ freq }} Hz</label>
<span>{{ eqGains[index] }}</span>
</div>
</div>
<li v-for="song in songs" :key="song.id" class="song-item">
<img :src="song.cover" :alt="song.title" class="song-cover">
<img :src="song.cover" :alt="song.title" class="song-cover" />
<p v-if="!song.id" class="error">Song ID is missing</p>
<div class="song-info">
<h2>{{ song.title }}</h2>
Expand All @@ -15,28 +29,38 @@
</template>

<script setup>
import { onMounted, ref } from 'vue';
import { readSongs } from '~/lib/Config.ts';
import Player from '~/lib/Player.ts';
import { onMounted, ref } from "vue";
import { readSongs } from "~/lib/Config.ts";
import Player from "~/lib/Player.ts";
const songs = ref([]);
const player = new Player();
const path = await window.__TAURI__.core.invoke("get_path")
const player = Player.getInstance();
const frequencies = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
const eqGains = reactive(new Array(frequencies.length).fill(0));
function updateEqGain(filterIndex, gain) {
player.setEqGain(filterIndex, parseFloat(gain));
}
onMounted(async () => {
try {
const songsConfig = await readSongs();
songs.value = await Promise.all(Object.entries(songsConfig.songs).map(async ([id, song]) => {
const coverBase64 = await window.__TAURI__.core.invoke('get_cover_base64', { id: song.id });
const coverBlob = base64ToBlob(coverBase64, 'image/jpeg');
const coverObjectURL = URL.createObjectURL(coverBlob);
return {
...song,
cover: coverObjectURL,
length: formatDuration(song.length),
date_added: formatDate(song.date_added),
};
}));
songs.value = await Promise.all(
Object.entries(songsConfig.songs).map(async ([id, song]) => {
const coverBase64 = await window.__TAURI__.core.invoke(
"get_cover_base64",
{ id: song.id }
);
const coverBlob = base64ToBlob(coverBase64, "image/jpeg");
const coverObjectURL = URL.createObjectURL(coverBlob);
return {
...song,
cover: coverObjectURL,
length: formatDuration(song.length),
date_added: formatDate(song.date_added),
};
})
);
} catch (error) {
console.error("Error during mounted hook:", error);
}
Expand All @@ -45,20 +69,22 @@ onMounted(async () => {
function formatDuration(duration) {
const minutes = Math.floor(duration / 60);
const seconds = duration % 60;
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
}
function formatDate(dateString) {
const date = new Date(dateString);
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
return `${day < 10 ? '0' : ''}${day}.${month < 10 ? '0' : ''}${month}.${year}`;
return `${day < 10 ? "0" : ""}${day}.${
month < 10 ? "0" : ""
}${month}.${year}`;
}
const playSong = async (song) => {
await player.setSong(song.id);
player.play()
player.play();
};
function base64ToBlob(base64, mimeType) {
Expand All @@ -73,7 +99,7 @@ function base64ToBlob(base64, mimeType) {
</script>

<style lang="scss">
@import '~/assets/styles/pages/index.scss';
@import "~/assets/styles/pages/index.scss";
.song-item {
display: flex;
Expand All @@ -97,4 +123,4 @@ function base64ToBlob(base64, mimeType) {
margin: 5px 0;
font-size: 16px;
}
</style>
</style>

0 comments on commit 6de099a

Please sign in to comment.