# Drum Maschine in single line

Hey Guys/Girls

I just wanna share my ideas about the drum machine.
The idea is to create something like real drum machine in a single line.

And so I wrote a simple function like this

``````##| define :maschine do |s_name, beats, amp, humanize, stretch|
define :maschine do |var|
##| set default values in case they if they are not set
_sample = !var[0].nil? ? var[0] : "bd_house"
_beats = !var[1].nil? ? var[1].ring : [1]
_n = _beats.length ? _beats.length : 1
_amp = !var[2].nil? ? var[2] : 1
_humanize = !var[3].nil? ? var[3] : 0
_stretch = !var[4].nil? ? var[4] : 1

_n.times do
if(_beats.tick == 1)
sample _sample, amp: _amp, start: rrand(0, _humanize), rate: rrand(1, _stretch)
end
sleep 1.0 / _beats.length
end
end
``````

this is the way how to use it

``````  live_loop :beat do
maschine [ "bd_haus",  [1, 0, 0, 0 ], 0.5, 0.002, 1.1]
end
``````

What you do is that you call the function it self, you tell it what sample you wanna play, you give it bunch of 1 & 0 (the number depends completely on you). The next 3 numbers are: amp, random start position (which gives the groove bit of human like feel), and the rate for funky transpositions

You can even do this
`maschine [ "bd_haus"]`
this will play one beat per a measure

maschine [ “bd_haus”, [1, 0, 0, 0 ]]
this will play one beat on the beginning with the time/measure equally divided by number of beats in this case it is equal to this

``````sample :bd_house
sleep 0.25
sleep 0.25
sleep 0.25
sleep 0.25
``````

and so this

`````` live_loop :beat do
maschine [ "bd_haus",  [1, 0, 0, 0 ]]
end
live_loop :beat2 do
maschine [ "elec_blip",  [0, 1, 0 ]]
end
``````

will create 4/3 beat
You see that it’s even more powerful than normal beat maschine as you can use as many beats per measure as you like 1, 4, 5, 6, 19876,… if you will
(yes I have not use any of other features like: amp, start, rate that are part of the function, I just wanted to simplify the example)

Although I like the what it does in a code of “one line” I feel it has flaws. Mainly the most elementary flaw is that - while I write the line it does not autocomplete for the sample type.

If you look at it… it is basically a simple extension of the sample it self… only enhanced by the repetition.

Something like we have
`play_pattern [:d3, :c1, :Eb5]`

But the play_pattern is able to play melodical pattern but not rhythmical.

The ideal implementation I can think of would be:
sample :bd_ada, pattern: [1,0,0,0,1,0,1,0], amp: 1, start: 0.02, …

See that?
If the sample or synth, whatever will be extended for the “pattern” option, we will be able to create a drum maschine from every sample/synth right away… I just don’t know how to patch the sample implementation it self…
Plus My question is, if you feel anything other/better approach to that?

3 Likes

I like the idea and I expanded on it a little - but you can achieve the same thing already:

E.G.

``````use_bpm 100

define :maschine do |var|
_sample = !var["sample"].nil? ? var["sample"] : "bd_house"
_pattern = !var["pattern"].nil? ? var["pattern"].ring : [1]
_patternlength = _pattern.length ? _pattern.length : 1
_amp = !var["amp"].nil? ? var["amp"] : 1
_swing = !var["swing"].nil? ? var["swing"] : 0
_rate = !var["rate"].nil? ? var["rate"] : 1
_bars = !var["bars"].nil? ? var["bars"] : 1

_patternlength.times do
if(_pattern.tick == 1)
with_swing rrand(0, _swing), pulse: 8 do
sample _sample, amp: _amp, rate: _rate
end
end

sleep 1.0 / _pattern.length * _bars
end
end

live_loop :kicks do
8.times do
maschine "sample" => :bd_haus, "pattern" => [1], "bars" => 4
end

32.times do
maschine "sample" => :bd_haus, "pattern" => [1]
end
end

live_loop :snares do
maschine "sample" => :sn_dub, "pattern" => [0, 1], "swing" => 0.05
end

live_loop :synths do
with_synth :growl do
play [:a3, :cs4], attack: 0.25, sustain: 0.1, decay: (line 0.1, 0.5, steps: 32).mirror.tick, release: 0.1, amp: 0.8
end

sleep 1
end
``````

V.S (does the same thing):

``````use_bpm 100

live_loop :kicks do
8.times do
sample :bd_haus, amp: 0.8, rate: 0.8 if (ring 1,0,0,0).tick == 1
sleep 1
end

32.times do
sample :bd_haus, amp: 0.8, rate: 0.8 if (ring 1,1,1,1).tick == 1
sleep 1
end
end

live_loop :snares do
sample :sn_dub, amp: 0.8, rate: 1 if (ring 0,1,0,1).tick == 1
sleep 0.5
end

live_loop :synths do
with_synth :growl do
play [:a3, :cs4], attack: 0.25, sustain: 0.1, decay: (line 0.1, 0.5, steps: 32).mirror.tick, release: 0.1, amp: 0.8
end

sleep 1
end``````
1 Like

Thats a lot of code, really, for a drum machine…

I didn’t write this, I think it was posted elsewhere in the
forums, so I liked it, and saved it away safe…

Eli…

``````  use_bpm 120

cycle = (ring 2, 4, 6,8)

live_loop :drums do
tick
sample :bd_tek if 5[look%4] >0
sample :bd_klub if 3[look%5] >0
sample :bd_boom if cycle.look[look%4] >0
sample :elec_cymbal, rate: 3 if 10[look%4] >0
sleep 0.5
end
end
``````
2 Likes

I was thinking the same thing. Here is another derivative version from yours @Eli

``````live_loop :drums2 do ; tick
sample :bd_tek if bools(1, 0, 1, 0).look
sample :elec_cymbal, rate: 3 if bools(0, 1).look

sleep 0.5
end
``````

Using two different techniques, `bools` and `spread`.

And Ring samples ^^

``````live_loop :drums2 do ; tick
sample (ring :bd_tek,:elec_cymbal).look
sample (ring :bd_klub, :bd_boom).look if spread(4, 11).look
sleep 0.5
end
``````

Hmmm… you know…

@notinflight posted a nice little snippet in this post…

If you jazz it up a little and trigger it off the drums, you’ve
got the basics of a dance track…

``````use_bpm 120
cycle = (ring 2, 4, 6,8)

live_loop :drums do
tick
sample :bd_tek if 5[look%4] >0
sample :bd_klub if 3[look%5] >0
sample :bd_boom if cycle.look[look%4] >0
sample :elec_cymbal, rate: 3 if 10[look%4] >0
sleep 0.5

live_loop :looper do
sync :drums
if rand() > 0.65 then
with_fx :ixi_techno do
with_fx :wobble do
play :Gs3, attack: 0.25, sustain: 0.1, decay: 0.1, release: 0.1
sleep 0.25
play :Fs3, attack: 0.25, sustain: 0.1, decay: 0.1, release: 0.1
sleep 0.25
play :A3, attack: 0.25, sustain: 0.1, decay: 0.1, release: 0.1
sleep 0.25
play :B3, attack: 0.25, sustain: 0.1, decay: 0.1, release: 0.1
sleep 0.5
end
end
end
end
end
``````

thanks for all the tips, I’ll go thru it definitely more in depth soon.

…sure we can program machine like pattern many ways… the point here is I guess to come up with the most important features for a single line function similar to play_pattern_timed used for tone based approach but this time for rhythm.
I think the rhythm deserves a simple function for fast rhythm sketches and
I found the rhythm machines and their logic a perfect example of what to achieve.
What I’m suggesting is to come up with ideas and narrow them down to a most useful functions that can be hopefully later implemented straight to the Sonic Pi.

If you look on many kinds of music and how it is programmed MPC, Push 1-2, Maschine, and the like they all use grids of samples with more or less grove. And if that will be implemented it’ll speed up our workflow a lot. Same like the play_pattern_timed does for us in melody.

so my proposal of attributes are:

• sample name
• amplification
• sample start definition
• stretch
• beat pattern
• automatic or/and manual time definition connected with the beat pattern

(It would be nice if anybody knows how to patch the Sonic Pi and hacked that in .) one day.

How about something like this? The numbers in the strings represent amplitudes so that you can easily vary each drum hit…

``````define :str_to_amps do |s|
s.sub("-", "0").chars.map{ |c| c.to_f / 9 }
end

define :phrase do |inst, beat, amps|
if amps.is_a? String then
amps = str_to_amps amps
end

beat_num = 0
amps.each { |a|
sample inst, amp: a
sleep beat
beat_num += 1
}
end
end

use_bpm 140

live_loop :bdrums do
phrase :drum_bass_soft, 0.5, "7-5-6---"
phrase :drum_cymbal_closed, 0.5, "35234336"
phrase :drum_snare_soft, 0.5, "-1-2-8-2"
sleep 4
tick
end``````
1 Like