Beeps - Audio synthesis and playback library

Ask DeepWiki License Build Status Gem Version

⚠️ Notice

This repository is a read-only mirror of our monorepo. We do not accept pull requests or direct contributions here.

🔄 Where to Contribute?

All development happens in our xord/all monorepo, which contains all our main libraries. If you'd like to contribute, please submit your changes there.

For more details, check out our Contribution Guidelines.

Thanks for your support! 🙌

🚀 About

Beeps is an audio library for Ruby. You build a processor graph — oscillators, file / mic input, filters, envelopes, effects — by wiring nodes together with the >> operator, then render the result to a Sound and play it back.

It is part of the xord/* family and underlies the audio support in Reflex, Processing, RubySketch, and Reight. Like the rest of the family, it is primarily developed for our own use, but it works as a standalone audio synthesis gem.

📋 Requirements

  • Ruby 3.0.0 or later
  • A C++ compiler with C++20 support
  • Xot and Rucy (declared as runtime dependencies)
  • Platform audio backend:
    • macOS — OpenAL and AVFoundation (bundled with the OS)
    • Windows — OpenAL (MINGW_PACKAGE_PREFIX-openal) and Media Foundation
    • Linuxlibopenal-dev

The following third-party DSP libraries are cloned from GitHub and statically linked while the native extension is being built, so you do not need to install them separately:

Library Role
STK Core synthesis primitives
AudioFile WAV / AIFF file I/O
r8brain-free-src High-quality sample-rate conversion
signalsmith-stretch Time stretching and pitch shifting

📦 Installation

Add this line to your Gemfile:

gem 'beeps'

Then install:

$ bundle install

Or install it directly:

$ gem install beeps

require 'beeps' automatically calls Beeps.init! and registers Beeps.fin! at exit. Set $BEEPS_NOAUTOINIT = true before requiring if you want to manage the lifetime yourself.

📚 What's Included

Generators (signal sources)

Class Purpose
Beeps::Oscillator Sine / triangle / square / sawtooth / noise / sample-playback oscillator
Beeps::Value Constant or linearly-interpolated control value over time
Beeps::Sequencer Schedule processors at given offsets and durations
Beeps::FileIn Stream audio from a WAV / AIFF / other supported file
Beeps::MicIn Capture audio from a microphone
Beeps::TextIn Synthesize speech from text

Filters (processors that take an input)

Class Purpose
Beeps::Gain Multiply the signal by a gain coefficient
Beeps::Mixer Sum multiple inputs
Beeps::Envelope Attack / Decay / Sustain / Release envelope with note_on / note_off
Beeps::LowPass Low-pass filter with cutoff frequency
Beeps::HighPass High-pass filter with cutoff frequency
Beeps::Reverb Reverb with mix, room_size, damping controls
Beeps::TimeStretch Change duration without affecting pitch
Beeps::PitchShift Change pitch without affecting duration
Beeps::Analyser FFT analyser — exposes time-domain and spectrum readings

Playback

Class Purpose
Beeps::Sound A finite, renderable audio asset (created from a processor or load_sound)
Beeps::SoundPlayer Returned by Sound#play; supports pause, stop, position, loop, ...

💡 Usage

Play a 440 Hz sine tone for one second

require 'beeps'

osc    = Beeps::Oscillator.new(:sine, frequency: 440)
sound  = Beeps::Sound.new(osc, 1)
player = sound.play

sleep 1   # keep the script alive while the sound plays

Build a processor chain with >>

require 'beeps'

# oscillator -> half-volume -> low-pass at 800 Hz -> reverb
chain =
  Beeps::Oscillator.new(:sawtooth, frequency: 220) >>
  Beeps::Gain.new(0.5) >>
  Beeps::LowPass.new(cutoff: 800) >>
  Beeps::Reverb.new(mix: 0.3, room_size: 0.7)

Beeps::Sound.new(chain, 2).play
sleep 2

a >> b calls b.add_input(a) and returns b, so the right-most node is the head of the chain you pass to Sound.new.

ADSR envelope

require 'beeps'

osc = Beeps::Oscillator.new(:sine, frequency: 440)
env = Beeps::Envelope.new(0.05, 0.1, 0.7, 0.3, input: osc)
env.note_on
env.note_off 0.5    # release after 0.5 s

Beeps::Sound.new(env, 1).play
sleep 1

Play and save a wave file

require 'beeps'

# play an existing file
player = Beeps.load_sound('drum.wav').play

# render a chain and save it to disk
sound = Beeps::Sound.new(Beeps::Oscillator.new(:square, frequency: 880), 0.5)
sound.save 'square.wav'

Capture from the microphone and analyse

require 'beeps'

mic      = Beeps::MicIn.new(1)            # 1 channel
analyser = Beeps::Analyser.new(1024, mic) # 1024-point FFT
mic.start

loop do
  sleep 0.1
  puts analyser.spectrum.first(8).map {|v| v.round 3 }.inspect
end

🛠️ Development

$ rake lib    # build the native C++ library (libbeeps)
$ rake ext    # build the Ruby C extension
$ rake test   # run the test suite
$ rake doc    # generate RDoc from C++ sources
$ rake       # default: builds the extension

In the xord/all monorepo you can scope by module, e.g. rake beeps test.

📜 License

Beeps is licensed under the MIT License. See the LICENSE file for details.

The third-party DSP libraries listed above retain their own licenses.