This is a snippet showing the concept of event loudness density (ELD) proposed in [1]. This toy example combines a Gaussian ELD with synthetic bubble sound model [2][3].
Changing the value of the grain density or the STD of Gaussian ELD leads to different acoustic textures.
Reference:
import numpy as np
import random
# paramter configuration
# Duration of the clip
Duration = 5.0
# Sampling rate
sr = 20000.0
# total number of samples
NumSamples = int(Duration * sr / 2.0) * 2 + 1
# range of sampled bubble oscillation frequency
fmin = 500.0
fmax = 10000.0
# Temporal density of grains
Density = 10000.0
# std of Gaussian ELD in dB scale
stdValueSmall = 0.5
stdValueMid = 4.0
stdValueLarge = 8.0
signalSTDSmall = np.zeros(NumSamples)
signalSTDMid = np.zeros(NumSamples)
signalSTDLarge = np.zeros(NumSamples)
# probability that an event is placed within a discrete time sample
perSampleProbability = Density / sr
def ComputeBubbleSound(frequency, duration, decayTime, samplingRate):
"""Return the signal of a single oscillating bubble sound"""
NumSteps = int(duration * samplingRate / 2.0) * 2 + 1
s = np.zeros(NumSteps)
decayFactorPerStep = np.exp(-1.0 / samplingRate / decayTime)
decay = 1.0
for iTime in range(0, NumSteps):
t = float(iTime) / samplingRate
s[iTime] = np.sin(2.0 * np.pi * frequency * iTime / samplingRate)
s[iTime] = s[iTime] * decay
decay *= decayFactorPerStep
return s
# snippet of drawing the progress bar
from IPython.display import clear_output
def update_progress(progress):
bar_length = 20
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
if progress < 0:
progress = 0
if progress >= 1:
progress = 1
block = int(round(bar_length * progress))
clear_output(wait = True)
text = "Progress: [{0}] {1:.1f}%".format( "#" * block + "-" * (bar_length - block), progress * 100)
print(text)
# overlap-add
fmin_sqrt = np.sqrt(fmin)
fmax_sqrt = np.sqrt(fmax)
for iTime in range(0, NumSamples):
if random.random() < perSampleProbability:
AmplitudeSTDSmall = np.power(10.0, random.gauss(-30.0, stdValueSmall) / 20.0)
AmplitudeSTDMid = np.power(10.0, random.gauss(-30.0, stdValueMid) / 20.0)
AmplitudeSTDLarge = np.power(10.0, random.gauss(-30.0, stdValueLarge) / 20.0)
frequency = (random.random() * (fmax_sqrt - fmin_sqrt) + fmin_sqrt)**2
decayTime = 1.0 / (0.043 * frequency + 0.0014 * np.power(frequency, 1.5))
Bubble = ComputeBubbleSound(frequency, 0.2, decayTime, sr)
NBubble = Bubble.size
if iTime + NBubble - 1 < NumSamples:
for iTBubble in range(0, NBubble):
signalSTDSmall[iTime + iTBubble] += Bubble[iTBubble] * AmplitudeSTDSmall
signalSTDMid[iTime + iTBubble] += Bubble[iTBubble] * AmplitudeSTDMid
signalSTDLarge[iTime + iTBubble] += Bubble[iTBubble] * AmplitudeSTDLarge
update_progress(iTime / NumSamples)
Progress: [####################] 100.0%
# visualize the results
import matplotlib.pyplot as plt
import IPython
plt.plot(np.arange(NumSamples) / sr, signalSTDSmall)
plt.xlabel('time (s)')
plt.ylabel('signal')
plt.show()
IPython.display.Audio(signalSTDSmall, rate=sr)
plt.plot(np.arange(NumSamples) / sr, signalSTDMid)
plt.xlabel('time (s)')
plt.ylabel('signal')
plt.show()
IPython.display.Audio(signalSTDMid, rate=sr)
plt.plot(np.arange(NumSamples) / sr, signalSTDLarge)
plt.xlabel('time (s)')
plt.ylabel('signal')
plt.show()
IPython.display.Audio(signalSTDLarge, rate=sr)