Generative Soundscape Synthesis from Satellite Imagery and Open Geospatial Data
Generative Soundscape Synthesis from Satellite Imagery and Open Geospatial Data
Photo by Maxim Berg on Unsplash
A satellite image is a strangely quiet thing. It shows you everything — the river bending through the fields, the motorway slicing a forest in half, the neat grid of a residential district — and unfortunately tells you absolutely nothing about what it feels like to stand there.
I spent a good part of the last three years recording soundscapes along the Pilica River, dragging AudioMoths through wetlands and analyzing acoustic diversity. And every time I looked at the satellite view or an orthophoto of a recording site, the same thought kept coming back:
I already know what this pixel sounds like. Could a machine guess it too?
Silly? A little. Useful? Surprisingly, maybe. Nevertheless, I am currently sitting in a small cottage near the lake; it's heavily raining, and generative sounds are a nice holiday project idea, so let me walk you through it.
The problem
Sound is a genuinely informative dimension of a landscape. Ecologists use it to monitor biodiversity, urban planners use it to assess noise exposure, and the rest of us use it, mostly unconsciously, to decide whether a place feels calm or hostile. The catch is that acoustic data is expensive to collect. You need hardware in the field, permissions, batteries, weatherproofing, and a lot of patience. Satellite imagery, on the other hand, is free, global, and refreshed every few days.
[embed]Soundscapes Unveiled A Study of Acoustic Diversity in the Pilica River Basinmedium.com
So the question becomes: how much of a soundscape can we infer purely from what a place looks like from above, plus a bit of context we can fetch for free? This is obviously not a substitute for real bioacoustic monitoring — a generative model will never tell you whether the corncrake came back this spring. But as a way of sonifying land cover, it turns a silent raster into something you can experience.
The idea
The recipe has four ingredients:
- A satellite scene. Sentinel-2 L2A, fetched from the Copernicus Data Space STAC catalog. We select the least-cloudy scene within a date range, clip it to the area of interest, and build a proper RGB composite.
- A land cover estimate. What fraction of the image is forest, river, road, cropland? Two sources answer this: OpenStreetMap, which is precise but incomplete, and a small vision-language model, which is complete but imprecise. We merge them.
- Context. A soundscape is not just land cover. A January scene should not sound like a July one. So we pull historical weather data for the exact acquisition date from Open-Meteo and derive the season from the date and the hemisphere.
- A text-to-audio model. AudioLDM2 generates one clip per land-cover type from a handwritten acoustic prompt, and we mix the clips in proportion to their share of the scene.
In other words: the satellite tells us what is there, OSM and the VLM tell us how much of it there is, the weather archive tells us under what conditions, and the audio model performs the whole thing like an orchestra reading a score.
The method
Everything runs locally, in a single Python script. The imagery part is standard pystac-client + stackstac plumbing — search the catalog, stack the 10 m RGB bands, and stretch to something a vision model can actually look at:
def load_rgb(item, aoi):
stack = (
stackstac.stack(
[item],
bounds_latlon=tuple(aoi.to_crs('EPSG:4326').total_bounds),
fill_value=np.uint16(0),
epsg=aoi.crs.to_epsg(),
rescale=False,
properties=False,
chunksize=(1, 1, 256, 256),
dtype=np.uint16,
gdal_env=GDAL_ENV,
assets=RGB_BANDS,
)
.rio.write_nodata(0)
.isel(time=0)
.compute()
)
return stack.data.astype(np.float32) / 10000.0
The land cover estimation is where it gets interesting. Qwen3-VL-4B receives the composite and a strict prompt: pick from a fixed vocabulary of 25 land cover types, one per line, percentages summing to 100.
LANDCOVER_VISION_PROMPT: Final[str] = (
'Look at this satellite image. Identify the land cover and land use types '
'visible and estimate the percentage of the image each one covers. '
'Choose types from: forest, water, river, lake, wetland, '
'urban, residential, industrial, road, highway, airport, port, field, '
'cropland, vineyard, grassland, shrubland, bare, beach, desert, mountain, '
'snow, quarry, greenhouse, solar. '
'Respond with one type per line in the format "type: percentage". '
'Percentages must sum to 100. Only include types you can clearly see. '
'Example:\nforest: 60\nriver: 25\nroad: 15'
)
Small VLMs are decent at recognizing land cover but mediocre at quantifying it, so we do not trust them blindly. In parallel, OSM polygons (via osmnx) are clipped to the AOI, and their areas are computed exactly; roads, being lines, are buffered with a plausible width for each road class — 20 meters for a motorway, 5 meters for a residential street.
OSM_TAG_MAP: Final[list[tuple[str, str, str]]] = [
('water', 'river', 'river'),
('water', 'stream', 'river'),
('water', 'lake', 'lake'),
('water', 'reservoir', 'lake'),
('water', 'pond', 'lake'),
('natural', 'wood', 'forest'),
('natural', 'water', 'water'),
...
Then the merge, and this is the whole trick: OSM is authoritative where it has data, and the VLM only fills the leftover space. If OSM reports that 40% of the AOI is mapped as forest and water, the vision model is only allowed to argue about the remaining 60%. Crowdsourced ground truth first, hallucination-prone model second.
def merge_fractions(osm_fractions, vision_fractions):
merged = dict(osm_fractions)
remaining = max(0.0, 1.0 - sum(merged.values()))
if remaining > 0.01 and vision_fractions:
vision_only = {t: v for t, v in vision_fractions.items() if t not in merged}
if vision_only:
vtotal = sum(vision_only.values())
for t, v in vision_only.items():
merged[t] = (v / vtotal) * remaining
...
The weather layer is old-school. Open-Meteo returns the WMO weather code, temperature, wind, and precipitation for the acquisition date, and a handful of if statements turn that into a prompt prefix: 'snowfall, snow falling quietly, freezing cold, winter' .
Finally, each land cover type carries a hand-crafted acoustic description. This turned out to be the part I enjoyed writing the most. A wetland is 'frogs croaking loudly, water birds calling, reeds and cattails rustling in wind'; a quarry is 'rock crusher running, distant controlled explosion rumble, dump trucks reversing'. The weather prefix is glued in front, AudioLDM2 renders each clip, and a weighted mixdown produces the final stereo file
AUDIO_PROMPTS: Final[dict[str, str]] = {
'forest': (
'dense forest ambience, birds chirping and calling in tree canopy, '
'wind rustling through leaves, woodpecker drumming in distance, '
'insects buzzing, twigs snapping underfoot, deep natural quiet'
),
'water': (
'water flowing and splashing, continuous water sound, '
'gentle waves or stream gurgling, frogs and insects near water, '
'close perspective next to open water body'
),
'river': (
'river flowing over rocks, water rushing and gurgling, '
'stream babbling continuously, larger splashes over boulders, '
'frogs croaking at river bank, dragonfly wings, wet stones'
),
...
The results
The default AOI is a stretch of the Sulejów reservoir on the Pilica — the same river from which the real recordings in my acoustic diversity study came, which makes for an honest comparison. For a January scene, the pipeline found mostly water, forest, and wetland, fetched the weather for that day (below zero, light snow), and produced thirty seconds of muffled winter shoreline: soft wind, lapping water, a distant bird song.
[embed]
Is it accurate? In the bioacoustic sense, absolutely not :D — the model invents birds that were certainly not calling in January. But as an impression of a place derived entirely from open data, it is uncannily plausible. Change the date range to July and the same coordinates thaw into insects, songbirds and reeds. Move the bounding box a few kilometers onto the motorway and the idyll is gone.
[embed]
For me, as a geographer, this raises some interesting hypotheses. Even though this is all a hallucination, does it mean that some notion of geographical space — one of the core concepts of geography — has emerged somewhere in the pipeline?
That’s my small TerraTune demo: a satellite image, an OSM extract, some weather data, and a couple of diffusion models mixed together to form a soundscape. The code is available here:
Have a nice listen!
메타데이터
- post_id
- bb3473e231a6
- slug
- generative-soundscape-synthesis-from-satellite-imagery-and-open-geospatial-data-bb3473e231a6
- url
- https://medium.com/@maciej.adamiak/generative-soundscape-synthesis-from-satellite-imagery-and-open-geospatial-data-bb3473e231a6
- canonical_url
- https://medium.com/@maciej.adamiak/generative-soundscape-synthesis-from-satellite-imagery-and-open-geospatial-data-bb3473e231a6
- author_url
- https://medium.com/@maciej.adamiak
- status
- ok
- fetched_at
- 2026-08-12 01:04:34