Transform Data into Sound
Data visualization charts cannot provide the same experience to non-visual users.
Now use @uturi/sonification to quickly and easily convey data changes through sound.
Interactive Demo
Basic Settings
Frequency Settings
Volume Settings
Rhythm Settings
Getting Started
Installation
Global Installation
npm install @uturi/sonification
# or
yarn add @uturi/sonification
# or
pnpm add @uturi/sonificationFramework-Specific Installation (RECOMMENDED)
// you can also install the particular framework version
npm install @uturi/sonification/react
# or
yarn add @uturi/sonification/react
# or
pnpm add @uturi/sonification/reactQuick Start
Vanilla JavaScript / TypeScript
import { Sonifier } from '@uturi/sonification';
const salesData = [100, 150, 80, 200, 175, 300];
const sonifier = new Sonifier();
sonifier.sonify(salesData, 'frequency', { autoPlay: true });React
import { useSonifier } from '@uturi/sonification/react';
import { useCallback } from 'react';
function ChartWithSound() {
const chartData = [10, 25, 15, 40, 35, 60];
const { sonify, isPlaying, error, result } = useSonifier({
duration: 2.0,
volume: 0.5,
});
const handlePlaySound = async () => {
try {
await sonify(chartData, 'melody', { autoPlay: true });
} catch (err) {
console.error('Error:', err);
}
};
return (
<div>
<button onClick={handlePlaySound} disabled={isPlaying}>
{isPlaying ? 'Playing...' : 'Play Chart Sound'}
</button>
{error && <div>Error: {error.message}</div>}
</div>
);
}Vue
import { useSonifier } from '@uturi/sonification/vue';
const chartData = [10, 25, 15, 40, 35, 60];
const { sonify, isPlaying, error, result } = useSonifier({
duration: 2.0,
volume: 0.5,
});
const handlePlaySound = async () => {
try {
await sonify(chartData, 'volume', { autoPlay: true });
} catch (err) {
console.error('Error:', err);
}
};
<template>
<div>
<button @click="handlePlaySound" :disabled="isPlaying">
{{ isPlaying ? 'Playing...' : 'Play Chart Sound' }}
</button>
<div v-if="error">Error: {{ error.message }}</div>
</div>
</template>Svelte
import { useSonifier } from '@uturi/sonification/svelte';
const chartData = [10, 25, 15, 40, 35, 60];
const { sonify, isPlaying, error, result } = useSonifier({
duration: 2.0,
volume: 0.5,
});
const handlePlaySound = async () => {
try {
await sonify(chartData, 'frequency', { autoPlay: true });
} catch (err) {
console.error('Error:', err);
}
};
<button on:click={handlePlaySound} disabled={$isPlaying}>
{$isPlaying ? 'Playing...' : 'Play Chart Sound'}
</button>
{#if $error}
<div>Error: {$error.message}</div>
{/if}Sonification Methods
1. Frequency - Pitch changes according to value
// Frequency: Pitch changes according to value
// Higher values produce higher pitches
const sonifier = new Sonifier();
const result = await sonifier.sonify(data, 'frequency', { autoPlay: true });2. Volume - Volume changes according to value
// Volume: Volume changes according to value
// Higher values produce louder sounds
const sonifier = new Sonifier();
const result = await sonifier.sonify(data, 'volume', { autoPlay: true });3. Rhythm - Rhythm pattern changes according to value
// Rhythm: Rhythm pattern changes according to value
// Higher values produce faster rhythms
const sonifier = new Sonifier();
const result = await sonifier.sonify(data, 'rhythm', { autoPlay: true });4. Melody - Musical scale using notes (C, D, E, F, G, A, B)
// Melody: Scale changes according to value
// Creates a musical melody using notes (C, D, E, F, G, A, B)
const sonifier = new Sonifier();
const result = await sonifier.sonify(data, 'melody', { autoPlay: true });Waveform Types
Notice
When choosing a Waveform Type, carefully consider both the acoustic characteristics of the sound and the nature of the data you want to convey. Each waveform has distinct auditory properties, and the appropriate waveform varies depending on the data characteristics.
| Waveform | Characteristics | Change Detection Accuracy | Auditory Fatigue | Suitable Use Cases |
|---|---|---|---|---|
| Sine | Smooth and pure tone | ★★★★★ | ★★★★★ | Common values, key data with slopes |
| Square | Strong attack, abrupt transitions | ★★★☆☆ | ★★☆☆☆ | Outliers, warnings, state transitions |
| Sawtooth | Clear rise/fall, strong harmonics | ★★☆☆☆ | ★★☆☆☆ | Enhanced slope/trend recognition |
Choose from three waveform types
// Three waveform types available
const sonifier = new Sonifier({
waveType: 'sine', // default
// waveType: 'square',
// waveType: 'sawtooth',
});
// Change waveform dynamically
sonifier.setConfig({
waveType: 'square', // Switch to square wave
});
await sonifier.sonify(data, 'frequency', { autoPlay: true });Custom Configuration
Initial Configuration
// Fine-tuned configuration customization
const sonifier = new Sonifier({
// Basic audio settings
duration: 3.0, // 3 seconds playback
sampleRate: 44100, // CD quality
waveType: 'square', // Waveform type: 'sine' | 'square' | 'sawtooth'
// Frequency range (Hz)
minFrequency: 200, // Lowest pitch
maxFrequency: 800, // Highest pitch
// Volume range (0-1)
minVolume: 0.1, // Minimum volume
maxVolume: 0.8, // Maximum volume
// Rhythm range (0-1)
minRhythm: 0.2, // Minimum rhythm
maxRhythm: 0.9, // Maximum rhythm
});
await sonifier.sonify(salesData, 'frequency', { autoPlay: true });Dynamic Configuration Update
// Update configuration dynamically
const sonifier = new Sonifier({
duration: 2.0,
volume: 0.3,
waveType: 'sine',
});
// Later, update the configuration
sonifier.setConfig({
duration: 4.0,
volume: 0.6,
waveType: 'square', // Change waveform type
});
// Get current configuration
const currentConfig = sonifier.getConfig();
console.log('Current config:', currentConfig);Manual Audio Playback
Generate audio and play later
// Generate audio without auto-playing
const sonifier = new Sonifier();
const result = await sonifier.sonify(data, 'melody', { autoPlay: false });
// Play later
await sonifier.play(result.audioBuffer);
// Or use with Web Audio API directly
const audioContext = new AudioContext();
const source = audioContext.createBufferSource();
source.buffer = result.audioBuffer;
source.connect(audioContext.destination);
source.start();Error Handling
SonificationError Class
// SonificationError Class
import { SonificationError, ERROR_CODES } from '@uturi/sonification';
// All errors thrown by the library are instances of SonificationError
class SonificationError extends Error {
readonly code: SonificationErrorCode; // Error code to distinguish error types
readonly cause?: Error; // Original error (if any)
readonly field?: string; // Field name (for validation errors)
}
// Error Codes
export const ERROR_CODES = {
WORKER_ERROR: 'WORKER_ERROR', // Web Worker initialization or execution error
VALIDATION_ERROR: 'VALIDATION_ERROR', // Input data or configuration validation failed
TIMEOUT_ERROR: 'TIMEOUT_ERROR', // Audio generation timeout
AUDIO_CONTEXT_ERROR: 'AUDIO_CONTEXT_ERROR', // AudioContext related error
UNKNOWN_ERROR: 'UNKNOWN_ERROR', // Unknown error
} as const;Basic Error Handling
import { Sonifier, SonificationError, ERROR_CODES } from '@uturi/sonification';
const sonifier = new Sonifier();
try {
const result = await sonifier.sonify(data, 'melody', { autoPlay: true });
console.log('Success:', result);
} catch (error) {
if (error instanceof SonificationError) {
switch (error.code) {
case ERROR_CODES.VALIDATION_ERROR:
console.error('Validation error:', error.message);
console.error('Field:', error.field);
break;
case ERROR_CODES.WORKER_ERROR:
console.error('Worker error:', error.message);
break;
case ERROR_CODES.TIMEOUT_ERROR:
console.error('Timeout error:', error.message);
break;
case ERROR_CODES.AUDIO_CONTEXT_ERROR:
console.error('AudioContext error:', error.message);
break;
default:
console.error('Unknown error:', error.message);
}
}
}