Download - It's so quiet. Let's make music
It’s so quiet.Let’s make music.
Loren Segal RubyConf 2014
@lsegal
WARNING: MUSIC AHEAD🚨 🚨
What ismusic even?
S + R = Mound
hythm
usic
S + R = Mound
hythm
usic
S + R = Mound
uby
usic
S + R =ound
uby
S + R =ound
uby
This talk.
dSoundd boop.
beep.
Analog Audio
Good Vibrations
Continuous Signal
DIGITAL AUDIO
💻 🔊?
Discrete Signal (not continuous)
187 198
-84 -84
not continuous,
Just Samples
Discrete Signal (not continuous)
Discrete Signal (not continuous)
Discrete Signal (sampling)
Discrete Signal (sampling)
Discrete Signal (sampling)
Audio Vocabulary[Sample Rate]⇒
“Number of data values for each second of audio”
Measured in Hertz (Hz)
[0, 214, 231, 35, -193, -245, -72, 167, 252, 105, -139, -255, -137, 107, 252, 165, -74, -246, -192, 38]
20.times.map {|i| (Math.sin(i) * 255).floor }
20 Samples
Common Sample Rates
44,100 Hz 44,800 Hz 96,000 Hz
used by VHS, CDs
💻 🔊
WAVESfundamental
SINEsin(x)
#math
f(t) = A sin(2πΩt)s
f(t) = A sin(2πΩt)Amplitude
Frequency
s
Ampl
itude
Frequency* …ish
Audio Vocabulary[Amplitude]⇒
“Loudness” Measured in Decibels (dB)
Audio Vocabulary[Frequency]⇒
“Pitch” Measured in Hertz (Hz)
s = Sample Rate
Ωs
= e.g., 44100
Frequency?
Ω = 440 Hz [A3]
f(t) = sin(0.0627t)
SQUARE
f(t) = A ((Ωt) < 0.5 ? -1 : 1)s
Triangle
f(t) = A(1 - 4(Ωt - Ωt ))ss
SAW(tooth)
f(t) = 2A (Ωt - Ωt )s s
NOISE
f(t) = A rand()rand() = some evenly distributed random fn
Show, Don’t Tell
Processing Audio
From synthesis
To analysis
Fourier Transform
It’s Complex
Literally.
SIDE VIEW OF f(t)!
thefouriertransform.com
“All waveforms, no matter what you scribble or observe in the universe, are actually just the sum of simple sinusoids of different frequencies.”
Analysis Applications
1. Pitch Detection: Instrument Tuner, Visualization
2. Wave Shaping: Equalizer, Autotune
Let’s see it.
RUBY TIME
ruby-audio$ gem install
libsndfile wrapper
require 'ruby-‐audio' include RubyAudio sample_rate, len, freq, amp = 48000, 10, 440, 0.9 buf = Buffer.float(sample_rate * len) buf.size.times do |i| sine_rad = ((freq * Math::PI * 2) / sample_rate) * i buf[i] = amp * Math.sin(sine_rad) end format = FORMAT_WAV | FORMAT_PCM_16 info = SoundInfo.new(channels: 1, samplerate: sample_rate, format: format) snd = Sound.new('out.wav', 'w', info) snd.write(buf) snd.close
Write a Sine Wave
easy_audio$ gem install
portaudio wrapper
require 'easy_audio'
EasyAudio.easy_open(&EasyAudio::Waveforms::SINE) sleep 2 # play for 2 seconds
Play a Sine Wave
require 'easy_audio'
triangle = EasyAudio::Waveforms::TRIANGLE stream = EasyAudio.easy_open(freq: 220, &triangle) Thread.new { loop { stream.frequency += 50; sleep 0.2 } } sleep 3
Increase Frequency / Time
Audio Plugins
VST
github.com/lsegal/ easy_vst
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { ruby_init(); ruby_init_loadpath(); rb_require("drb/drb"); rb_eval_string("DRb.start_service"); return new SampleVST(audioMaster); } // ... server = rb_eval_string( "DRbObject.new_with_uri('druby://localhost:9090')");
Embedding DRb - C++
rb_funcall( server, // the DRb object rb_intern(“process”), // the remote method 1, // one argument INT2FIX(sampleFrames)); // number of samples
Call Distributed Method
Fun Time!
Summary
1. Audio is samples!
2. Making waves!Sine, Square, Saw, Triangle, Noise
3. Fourier = analysis
4. Ruby libraries!ruby-audio
easy_audio easy_vst
5. Music!
💾gnuu.org
github.com/lsegal
@lsegal
Thanks! Questions?