import numpy as np
import matplotlib.pyplot as plt
import sys
from sonipy.sonify import SonifyTool
# % matplotlib inline
First, let's create some x and y data to sonify.
x = np.linspace(0,5,50)
y = np.sin(x**2)
plt.figure(figsize=(4,2))
plt.scatter(x,y);
Here is the simpliest way to sonify an audio file. The tone can then be played in a jupyter notebook.
Tone = SonifyTool(x, y)
Tone.play(autoplay=False)
multitones created
SonifyTool takes a bliplength
parameter to change the time length of each blip in seconds.
You can also save the tone as follows:
Tone.save(path='.')
Writing .\tones/multitone.wav Saved multitone as .\tones/multitone.wav.
Saving the tone creates a folder called "tones" in the current directory.
If you want your tones saved elsewhere, change path to your desired directory.
There are three inputs that help you change how x scales with time, which SonifyTool
will take inside a durations_args
dictionary.
time_total
: Total time difference between first and last blip (in ms).dtime_min
: Minimum allowed time difference between blips (in ms).dtime_max
: Maximum allowed time difference between blips (in ms).# choose 1 of 3
duration_args = {
"time_total": 1000, # 10 seconds or 10,000 ms
# "dtime_min": 50, # .2 second or 200 ms
# "dtime_max": 100, # .1 second or 500 ms
}
Tone = SonifyTool(x,y, duration_args=duration_args)
Tone.play(autoplay=False)
multitones created
Alternately, you can simply pass a duration_scale
(in units of x value per ms).
duration_scale = 1. / 200. # x value / time (ms)
Tone = SonifyTool(x, y, duration_scale=duration_scale)
Tone.play(autoplay=False)
multitones created
Here's how to change how frequency scales with y. SonifyTool
will take frequency_args
with the following options for inputs:
frequency_min
: the minimum frequency that the y values hit.frequency_max
: the maximum frequency that the y values hit.cents_per_value
: a y scale parameter, in units of "pitch" per y value (cents/y).Cents are a logarithmic unit of tone intervals.
C4 = 261.6 # Hz
# choose 2 of 3
frequency_args = {
# "frequency_min": 2 * C4,
"frequency_max": 10 * C4,
"cents_per_value": 1400.,
}
Tone = SonifyTool(x, y, frequency_args=frequency_args)
Tone.play(autoplay=False)
multitones created
The same information that is contained inside the audio file can be visualized in the following plot formats. The beauty of the soundfile is not having to deal with these, hence why I've left them for last.
As a plot, x and y would look like this.
from sonipy.visualisation import plotData
fig, axes = plotData(Tone)
Tone.plotTone()
Tone.plotSpectrogram();
Tone.plotSpectrum()
Note the blip plot below is not supported in python 3.7:
pythonversion = (sys.version.split(' ')[0])
pythonversion
'3.11.5'
if pythonversion[:3] != "3.7":
Tone.plotBlips()
The details of the sonification can be found inside Tone. These include details like the y frequency scale (cent / y value), the x durations scale (x value / ms), total time (ms), or any of the following:
Tone.keys
['bliplength', 'multitone', 'multitones', 'x', 'x_dtime_max', 'x_dtime_min', 'x_durations', 'x_dx', 'x_dx_max', 'x_dx_min', 'x_scale', 'x_starttimes', 'x_time_total', 'y', 'y_cents_per_value', 'y_freq_translate_to_range', 'y_frequencies', 'y_frequency_max', 'y_frequency_min', 'y_input_frequency_args', 'y_inputs', 'y_n_inputs', 'y_value_max', 'y_value_min', 'y_values']
from platform import python_version
python_version()
'3.11.5'
print(sum(Tone.multitones))
0
Tone.play(autoplay=False)
If you'd like to compare multiple soundfiles consistently, I'd recommend passing the same cents_per_value
for each soundfile. You will also pass a frequency_min
or frequency_max
. If you'd like the maximum frequencies or minimum frequencies to match to values that aren't the maximum or minimum in your input data, you may pass a value_min
or value_max
to force the corresponding minimum/maximum frequency to the same y value, grounding the scale across differnt Tones.
To save you the calculation, you can find a cent_per_value function inside sonipy.scales.frequency
.
Here's some basic code to do just that.
C4 = 261.6 # Hz
frequency_min = 2 * C4
frequency_max = 10 * C4
value_min = min(y)
value_max = max(y)
from sonipy.scales.frequency import cent_per_value
myscale = cent_per_value(f_min = frequency_min, f_max = frequency_max,
v_min = value_min, v_max = value_max)
frequency_args = {
"frequency_min": frequency_min,
"cents_per_value" : myscale/2,
"value_min" : min(y),
}
Tone = SonifyTool(x,y, frequency_args=frequency_args)
Tone.play(autoplay=False)
multitones created
Contributions and collaborations are welcomed and awesome! Here is a great place to start. This project is perfect to people learning to work with packages so give it a try. Feel free to open an issue/pull request here on github, send us a tweet at @Astro_Locke or email locke.patton@cfa.harvard.edu if you have questions or would like to brainstorm your ideas.