Realtime Weather Sonification
OpenWeatherMap
This first, simple Web Audio sonification application makes use of the Weather API for real-time, browser-based sonification of weather data. For fetching data, a free subscription is necessary: https://home.openweathermap.org
Once subscribed, the API key can be used to get current weather information in the browser:
https://api.openweathermap.org/data/2.5/weather?q=Potsdam&appid=eab7c410674e15bfdd841f66941a92c2
JSON Data Structure
The resulting output in JSON looks like this:
{ "coord": { "lon": 13.41, "lat": 52.52 }, "weather": [ { "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" } ], "base": "stations", "main": { "temp": 9.74, "feels_like": 6.57, "temp_min": 9, "temp_max": 10.56, "pressure": 1034, "humidity": 93 }, "visibility": 8000, "wind": { "speed": 4.1, "deg": 270 }, "clouds": { "all": 90 }, "dt": 1604655648, "sys": { "type": 1, "id": 1275, "country": "DE", "sunrise": 1604643143, "sunset": 1604676458 }, "timezone": 3600, "id": 2950159, "name": "Berlin", "cod": 200 }
All entries of this data structure can be used as synthesis parameters in a sonification system with Web Audio.
Temperatures to Frequencies
Mapping
In this example we are using a simple freuency modulation formula for turning temperature and humidity into more or less pleasing (annoying) sounds. The frequency of a first oscillator is derived from the temperature:
\(\displaystyle f_1 = 10 \frac{1}{{T^2 / C^{\circ} }}\)
The modulator frequency is controlled by the humidity \(H\):
\(y = sin(2 \pi (f_1 + 100*sin(2 \pi H t))t)\)
The Result
The resulting app fetches the weather data of a chosen city, extracts temperature and humidity and sets the parameters of the audio processes:
What does the weather sound like in ...?
Code
<!doctype html> <html> <head> <title>Where would you rather be?</title> </head> <blockquote style="border: 2px solid #122; padding: 10px; background-color: #ccc;"> <body> <p>What does the weather sound like in ...?</p> <p> <button onclick="myFunction()">Enter City Name</button> <button onclick="stop()">Stop</button> <p id="demo"></p> </p> </body> <div id="location"></div> <div id="weather"> <div id="description"></div> <h1 id="temp"></h1> <h1 id="humidity"></h1> </div> </blockquote> <script> var audioContext = new window.AudioContext var oscillator = audioContext.createOscillator() var modulator = audioContext.createOscillator() // the output gain var gainNode = audioContext.createGain() var modInd = audioContext.createGain(); modInd.gain.value = 100; gainNode.gain.value = 0 modulator.connect(modInd) modInd.connect(oscillator.detune) oscillator.connect(gainNode) gainNode.connect(audioContext.destination) oscillator.start(0) oscillator.frequency.setValueAtTime(100, audioContext.currentTime); modulator.start(0) modulator.frequency.setValueAtTime(100, audioContext.currentTime); function myFunction() { var city = prompt("Enter City Name", "Potsdam"); if (city != null) { get_weather(city) } } function stop() { gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 1); } function frequency(y) { oscillator.frequency.value = y } function get_weather( cityName ) { var key = 'eab7c410674e15bfdd841f66941a92c2'; fetch('https://api.openweathermap.org/data/2.5/weather?q=' + cityName+ '&appid=' + key) .then(function(resp) { return resp.json()}) // Convert data to json .then(function(data) { setSynth(data); }) .catch(function() { // catch any errors }); } function setSynth(d) { var celcius = Math.round(parseFloat(d.main.temp)-273.15); var fahrenheit = Math.round(((parseFloat(d.main.temp)-273.15)*1.8)+32); var humidity = d.main.humidity; oscillator.frequency.linearRampToValueAtTime(1000*(100/(celcius*celcius)), audioContext.currentTime + 1); modulator.frequency.linearRampToValueAtTime(humidity, audioContext.currentTime + 1); gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 1); document.getElementById('description').innerHTML = d.weather[0].description; document.getElementById('temp').innerHTML = celcius + '°'; document.getElementById('location').innerHTML = d.name; document.getElementById('humidity').innerHTML = 'Humidity: '+humidity; } </script> </html>
Links and More Examples
Using the API in JavaScript is thoroughly explained here: https://bithacker.dev/fetch-weather-openweathermap-api-javascript