<p>The problem lies in your reference &quot;ref=np.max&quot;, which tells the amplitude_to_db() to scale all data to the maximum power level.</p>
<p>As you wanted to compare the different datasets you must use the same reference level.</p>
<p>My suggestion:</p>
<p>take the data that are ambient noise only (typically the quietest data without any bombs/fish sound etc) estimate the rms value of this dataset und use this value as reference.</p>
<p>let &quot;y_noise&quot; be such dataset and &quot;noise = np.sqrt(np.mean(y_noise**2))&quot;</p>
<p>then use &quot;ref=noise&quot;</p>
<p>Edit: above procedure ensures that the spectrogram values are all referenced to the same background noise level. If, additionally the specshow() normalizes the colorscale, then image maybe unchanged but colorbar will be different, reflecting the correct different values.</p>
<p>Update (removing previous edit2,3):
in specshow() add a keyword &quot;clim = (-20,100)&quot; to fix the conversion from dB values to color scale. Play with lower and upper limits to catch both background and foreground sound.</p>

CC BY-SA 4.0
2023-01-13T18:44:52.117Z
hanks, I tried playing with 'ref=' previously. If I adjust my code for an ambient track as such:

y_noise = librosa.stft(y)  # STFT of y |
noise = np.sqrt(np.mean(y_noise **2)) |
S_db = librosa.amplitude_to_db(np.abs(D), ref=noise ) 

Then make sure to set 'ref=noise' for the bomb tracks using the 'noise' value from the ambient track I still get the same problem. Am I approaching this correctly?
Fish and things
CC BY-SA 4.0
2023-01-13T20:21:36.523Z
I guess, the plot look similar but the colorbars on the right side show different values. It the seems that specshow always normalize the colors.
WMXZ
CC BY-SA 4.0
2023-01-14T11:52:44.830Z
Is there another function or packge you could recommend where I can achieve what I'm looking for?
Fish and things
CC BY-SA 4.0
2023-01-15T16:07:28.483Z
Is there a way you can define the min and max of the color bar? That is how I would do it in matlab but I’m not familiar with librosa/Python.
selene
CC BY-SA 4.0
2023-01-15T20:29:58.917Z
@selene, it is "clim=(min,max)" as indicated in the updated answer
WMXZ
CC BY-SA 4.0
2023-01-17T23:13:20.683Z
@WMXZ very nice!
selene
CC BY-SA 4.0
2023-01-22T14:13:28.160Z
ANSWER: Clim didn't appear to change anything, however, I found using the **kwargs vmin and vmax in the specshow() function woked. e.g: librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='hz', vmin = -30, vmax = 50)
Fish and things
CC BY-SA 4.0
2023-01-22T14:58:22.440Z
just tried it again, and clim=(min,max) worked, so does vmin=min, vmax=max. Using Python 3.10.8, librosa 0.9.2 and matplotlib 3.5.1
WMXZ
CC BY-SA 4.0
2023-01-13T13:09:58.583Z
2023-01-14T08:03:39.570Z
2023-01-14T08:03:39.570Z
WMXZ
<p>I'm trying to plot the spectrogram of blast fishing sounds. The level of background sound is relatively similar across all recordings.</p>
<p>When I plot files with bombs the background sound shows as quiet, whereas in all files without this its much louder (see examples) - apologies I don't know the right terminology, would appreciate insight on this.</p>
<p>I suspect this is because the blast sound is a loud event which raises the amplitude of the file. How can I standardise this across all spectrograms? e.g is there a parameter I can extract from a bomb file which I can use as a reference for all others.</p>
<p>I am using the following Python code. Pointers to a function/package that would enable this would be a real bonus:</p>
<pre><code>import librosa.display
file_path = '.../trial_audio/YB00015_M2_20220901_082000.wav'

y, sr = librosa.load(file_path)

D = librosa.stft(y)  # STFT of y
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

plt.figure(figsize=(3, 5))
librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='hz')#, y_axis='log')
plt.colorbar()
plt.xticks(np.arange(0, len(y)/sr, 1)) # xticks every second
plt.ylim(0,8000)
</code></pre>
<p>Examples: left = bomb, right = no bomb</p>
<p><a href="https://i.sstatic.net/ghtga.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/ghtga.png" alt="enter image description here" /></a>
<a href="https://i.sstatic.net/NdaQz.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/NdaQz.png" alt="enter image description here" /></a></p>

<decibels><spectrogram><amplitude><python><gunshot>
Standardising spectrogram amplitude
# Standardising spectrogram amplitude

(Asked by: username_0 on 2023-01-13)

I'm trying to plot the spectrogram of blast fishing sounds. The level of background sound is relatively similar across all recordings.

When I plot files with bombs the background sound shows as quiet, whereas in all files without this its much louder (see examples) - apologies I don't know the right terminology, would appreciate insight on this.

I suspect this is because the blast sound is a loud event which raises the amplitude of the file. How can I standardise this across all spectrograms? e.g is there a parameter I can extract from a bomb file which I can use as a reference for all others.

I am using the following Python code. Pointers to a function/package that would enable this would be a real bonus:

```
import librosa.display
file_path = '.../trial_audio/YB00015_M2_20220901_082000.wav'

y, sr = librosa.load(file_path)

D = librosa.stft(y)  # STFT of y
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

plt.figure(figsize=(3, 5))
librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='hz')#, y_axis='log')
plt.colorbar()
plt.xticks(np.arange(0, len(y)/sr, 1)) # xticks every second
plt.ylim(0,8000)

```

Examples: left = bomb, right = no bomb

[![enter image description here](https://i.sstatic.net/ghtga.png)](https://i.sstatic.net/ghtga.png)
[![enter image description here](https://i.sstatic.net/NdaQz.png)](https://i.sstatic.net/NdaQz.png)

**Tags:** decibels, spectrogram, amplitude, python, gunshot


---

## 1 answers

### Answer by username_1 on 2023-01-13. Score: 2 | Accepted answer

The problem lies in your reference "ref=np.max", which tells the amplitude\_to\_db() to scale all data to the maximum power level.

As you wanted to compare the different datasets you must use the same reference level.

My suggestion:

take the data that are ambient noise only (typically the quietest data without any bombs/username_0 sound etc) estimate the rms value of this dataset und use this value as reference.

let "y\_noise" be such dataset and "noise = np.sqrt(np.mean(y\_noise\*\*2))"

then use "ref=noise"

Edit: above procedure ensures that the spectrogram values are all referenced to the same background noise level. If, additionally the specshow() normalizes the colorscale, then image maybe unchanged but colorbar will be different, reflecting the correct different values.

Update (removing previous edit2,3):
in specshow() add a keyword "clim = (-20,100)" to fix the conversion from dB values to color scale. Play with lower and upper limits to catch both background and foreground sound.

> **Comments:**
> **username_0**: hanks, I tried playing with 'ref=' previously. If I adjust my code for an ambient track as such:  y_noise = librosa.stft(y)  # STFT of y | noise = np.sqrt(np.mean(y_noise **2)) | S_db = librosa.amplitude_to_db(np.abs(D), ref=noise )   Then make sure to set 'ref=noise' for the bomb tracks using the 'noise' value from the ambient track I still get the same problem. Am I approaching this correctly?  
> **username_1**: I guess, the plot look similar but the colorbars on the right side show different values. It the seems that specshow always normalize the colors.  
> **username_0**: Is there another function or packge you could recommend where I can achieve what I'm looking for?  
> **username_2**: Is there a way you can define the min and max of the color bar? That is how I would do it in matlab but I’m not familiar with librosa/Python.  
> **username_1**: @username_2, it is "clim=(min,max)" as indicated in the updated answer  
> **username_2**: @username_1 very nice!  
> **username_0**: ANSWER: Clim didn't appear to change anything, however, I found using the **kwargs vmin and vmax in the specshow() function woked. e.g: librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='hz', vmin = -30, vmax = 50)  
> **username_1**: just tried it again, and clim=(min,max) worked, so does vmin=min, vmax=max. Using Python 3.10.8, librosa 0.9.2 and matplotlib 3.5.1  

---

