-
Creating sound ambiences using exponential distribution
10/12/2025 at 20:06 • 0 commentsIn the previous log I made a sound amplifier that can be used to play a sound onto a speaker from line out of a controller or a similar device. Since the Halloween is approaching you could use it play some creepy sounds. Let say you have a crypt where you hear a scream of a tortured soul every minute. This is well-modeled by an exponential distribution with PDF (Probability Density Function):
Integrating this PDF from 0 to a, gives CDF (Cumulative Distribution Function):
The meaning of it is "what is the probability that I will wait a minutes for event to happen". In our case, what is probability that you will hear a scream after a minutes of not hearing anybody scream in the crypt.
Now, how do you turn that into a program?
The process is as follows, first you generate a uniformly distributed number U:
U = random.random()
Equate that to the CDF and solve for a
The intuition here is that we are sampling CDF using a uniform distribution, and converting from probability value to wait time by solving for a.
Here a is just a wait time in seconds (units don't matter) between playing sounds of different tortured souls. Python implementation using pygame for playing sounds shows below how to create a dismal atmosphere using sounds from Dark Messiah Of Might and Magic.
import pygame import time import random import math import os pygame.mixer.init() pygame.mixer.music.load("crypt_main_01.wav") pygame.mixer.music.play(-1) sound_fx = os.listdir("sounds") random.seed(18512158625243168) lmda = 1/60 # average rate of sound effects while pygame.mixer.music.get_busy(): dt = -(1/lmda)*math.log(1-random.random()) pygame.mixer.Sound(os.path.join("sounds", random.choice(sound_fx))).play() print("Sleeping for", dt, "seconds\n") time.sleep(dt)The result of that is that the sound effects are playing "at random", but on average they are spaced exactly 1 minute apart (lmda=1/60).
Playing sound effect talios_underground_drip_01.wav Sleeping for 128.69566205426352 seconds Playing sound effect womb_pit-spiders2.wav Sleeping for 77.31571960719558 seconds Playing sound effect crypt_main_01-voice02.wav Sleeping for 118.22675017236637 seconds Playing sound effect a_windgust03.wav Sleeping for 9.406140801162172 seconds Playing sound effect talios_underground_drip_05.wav Sleeping for 143.527373362454 seconds Playing sound effect karthal_city_interior_rndc_03.wav Sleeping for 233.31308460867473 seconds Playing sound effect boat_inside_rndb_03.wav Sleeping for 34.25852255619906 seconds Playing sound effect menelag_inside-violins05.wav Sleeping for 45.78918863544417 seconds Playing sound effect stonehelm_paokai_int_wind_02.wav Sleeping for 26.795201242341257 seconds Playing sound effect kharthal_roofs-thunder03.wav Sleeping for 40.608196333385564 seconds Playing sound effect boat_inside-creak01.wav Sleeping for 79.57805612346229 seconds Playing sound effect karthal_city_cellar_rndc_03.wav Sleeping for 7.086597576435293 seconds Playing sound effect stonehelm_paokai_ext_wind_02.wav Sleeping for 74.11938743159087 seconds Playing sound effect goblin_main-bat03.wav Sleeping for 19.494657143535072 seconds Playing sound effect talios_inside_no_wind.wav Sleeping for 56.11492592704442 seconds Playing sound effect talios_inside-creaks01.wav Sleeping for 65.92188091086814 seconds Playing sound effect orc_caves_02_creak_04.wav Sleeping for 114.70192969525529 seconds Playing sound effect kharthal_roofs-thunder03.wav Sleeping for 53.66492417273082 seconds Playing sound effect womb_03_3.wav Sleeping for 1.850743553746255 seconds Playing sound effect crypt_catacombs.wav Sleeping for 46.001320343673086 seconds Playing sound effect karthal_city_interior_rndb_02.wav Sleeping for 30.43711004687171 seconds Playing sound effect upper_temple_main.wav Sleeping for 6.600836081999313 seconds Playing sound effect karthal_gates-bird0204.wav Sleeping for 53.59866821050122 seconds Playing sound effect crypt_goddess.wav Sleeping for 101.2902363567874 seconds Playing sound effect orc_caves_02_wind_gust_04.wav Sleeping for 48.05731083376595 seconds Playing sound effect orc_caves_01_small_river_01.wav Sleeping for 42.116406568532575 seconds Playing sound effect karthal_gates-bird0101.wav Sleeping for 141.33458066209457 seconds Playing sound effect boat_outside_rndd_01.wav Sleeping for 23.410817717634007 seconds Playing sound effect boat_inside-creak02.wav Sleeping for 105.39932936049989 seconds Playing sound effect boat_inside_rnde_02.wav Sleeping for 15.517968358066575 seconds Playing sound effect crypt_main_03_02.wav Sleeping for 34.4874963559264 seconds Playing sound effect womb_03_2.wav Sleeping for 18.18784523134326 seconds Playing sound effect orc_caves_02_creak_02.wav Sleeping for 47.969406439382674 seconds Playing sound effect crypt_main_05_01.wav Sleeping for 49.53160356370553 seconds Playing sound effect temple_stairs_02-tone03.wav Sleeping for 17.15574922570256 seconds Playing sound effect a_rockfalling02.wav Sleeping for 8.342460896115393 seconds Playing sound effect karthal_gates-dog0202.wav Sleeping for 2.5383012869378447 seconds Playing sound effect orc_cyclops.wav Sleeping for 168.82321786938795 seconds Playing sound effect karthal_city_interior.wav Sleeping for 29.775608361974413 seconds Playing sound effect crypt_catacombs-drips02.wav Sleeping for 56.719310252147324 seconds Playing sound effect talios_inside-creaks02.wav Sleeping for 53.343953975100156 seconds Playing sound effect boat_outside_rndd_03.wav Sleeping for 1.9232440582360897 seconds Playing sound effect boat_inside_rnde_05.wav Sleeping for 52.789288080099446 seconds Playing sound effect boat_inside_rnde_02.wav Sleeping for 33.81348866316184 seconds Playing sound effect karthal_city_cellar_rnda_01.wav Sleeping for 108.5107399666818 seconds Playing sound effect orc_caves_01_small_river.wav Sleeping for 88.70394974369471 seconds Playing sound effect karthal_city_cellar_rndc_02.wav Sleeping for 46.65599424100057 seconds Playing sound effect karthal_city_cellar_rnda_02.wav Sleeping for 79.43392968844216 seconds Playing sound effect a_rockfalling02.wav Sleeping for 36.106667120965014 seconds Playing sound effect orc_caves_01_small_river_02.wav Sleeping for 15.475057283089406 seconds Playing sound effect temple_stairs_02-tone03.wav Sleeping for 95.70672679528789 seconds Playing sound effect karthal_gates-dog0102.wav Sleeping for 183.84268891105916 seconds Playing sound effect crypt_goddess.wav Sleeping for 28.177534459415273 seconds Playing sound effect necropolis_goddess_voices3.wav Sleeping for 7.271903475243708 seconds Playing sound effect stonehelm_fire_explowood_01.wav Sleeping for 85.2453587303634 seconds Playing sound effect stonehelm_fire_explowood_04.wav Sleeping for 7.432176949246249 seconds Playing sound effect temple_stairs_01.wav Sleeping for 75.08470818533749 seconds Playing sound effect karthal_gates-dog0304.wav Sleeping for 36.72286949890331 seconds -
Basic power amplifier circuit everyone should know
10/11/2025 at 01:48 • 0 commentsDesigning The Circuit
In this log I'm going to use my matrix router breadboard to put together a simple audio amplifier made of push-pull stage and a op amp in inverting amplifier configuration. If you ever tried building a push-pull stage without feedback you probably noted horrible distortion around zero due to transistors falling out of active region and starting to act non-linearly.
Note the flat regions of the waveform where input is crossing 0.6V.
If you were to connect an actual speaker it would look even worse due to inductance and dynamic nature of the load.
The op amp has a closed-loop gain of 500/100 = 5. And in the circuit above it is simply providing a linear gain before power stage as well as low impedance. The fix is surprisingly simple, just close op amp feedback around the output and it will do its best to keep it linear! In the next circuit, the op amp will become aware of the push-pull stage.
The magic of an op amp is that it is kind of a control system in itself working in a closed loop with feedback. By closing its feedback loop around a parameter you want it to control you can improve your circuit performance. In this case this circuit closed the feedback loop at output of the push-pull stage so that the op amp can maintain a gain of 5 despite non-linear behavior of the transistors around zero. I read about this trick in the Art Of Electronics, and this is the circuit we are going to build using a matrix router.
NOTE: The capacitor polarity in this circuit does not matter. This sometimes bothers people, they think they are hurting the poor thing. The purpose of capacitor is to block DC bias. If there's DC voltage across the capacitor you should orient it according to polarity. You may ask: but doesn't audio signal change polarity when zero-crossing? Yes, but for AC of large enough frequency the capacitor is considered to be a short circuit. Therefore the voltage drop across the capacitor for AC signal is zero and polarity does not matter. Bottom line, watch DC bias, don't worry about AC. If you got it wrong, it will explode and you will know you got it wrong. In my circuit I oriented negative side to the virtual ground node, because at DC inverting input of the op amp will try to be equal to whatever is connected to the non-inverting input (ground). So if there was a DC bias coming from some audio input, it would be on the positive side of capacitor.
Split The Circuit Into Nets
Since I'm going to use a matrix router breadboard, the first thing to do is to split the circuit into NETs. A NET is a just a group of connected pins. This is no different from the process that a PCB layout software or a circuit simulator would do, except we have to do it by hand. Below I colored and labeled all NETs.
Solder Parts Into Matrix Router Board
There's really no magic to it, you just put them anywhere you want, that's kind of the point of using a matrix router.
Implement The NETs
The next step is to close the jumpers. I go over each net's Y row and close the jumpers at X columns where the device pin is located. It is best to do it one Y row at a time to make sure you don't miss anything.
![]()
I also added connectors for power, audio input and audio output for external speaker and for probing. I usually use outer tracks Y15, Y14, Y13 for power distribution, similar to conventional breadboard (obviously conventional breadboard does not have a dual power supply rail, but here you can do whatever you want). The op amp that I used was LM324N (though mine had issues and I rewired it for LM412). I also replaced the resistors with a 1k potentiometer. Transistors are N23904 and N23906, they do the job, but I would like to replace them with something heftier.
Below, I also colored sections of Y rows using same colors as in schematic. In hindsight, I should've had the board made in white so I could use a color marker to draw on it.
![]()
The matrix breadboard is pretty intuitive to use. Each NET in a circuit is just a line running across horizontally. The rows with same Y numbers are connected via hidden tracks running on the left. This may be easier to understand if you look at the layout (Protomatrix 2x80x30 Layout), see also links below.
Results
The circuit worked, but was a bit quiet due to small transistors. There was no noticeable distortion at lower volumes. At higher volumes transistors would drop into saturation with my 4 Ohm speaker and start clipping. I think the greatest weak point of the board are vias, since all connections are made through them, but they should be able to handle about 1 A. This should be enough for a small speaker. Having so many vias on the board ensures board houses hate you and so you get your money's worth!
Links
KiCAD Layouts & Layout Scripts
-
What is matrix routing?
03/15/2025 at 01:36 • 0 commentsMatrix routing is one of those concepts that everyone claims to understand—until they actually face the challenge of routing something with a matrix and end up in a tangled mess. I first encountered matrix routing when exploring PXI-based matrix switching systems. In that world, the prevailing mindset is to spend a hefty amount each year on the "magic" routing software and to avoid reinventing the wheel. But honestly, what's so wrong with reinventing your own wheel every now and then? That's one of the things I love most about engineering: understanding how things work so you can put your own spin on them, combine ideas, remix, and integrate them into something new.
Matrix routing, at its core, is actually quite simple. Here’s a step-by-step guide to implement any arbitrary circuit using a matrix:
Matrix Routing Procedure
- Break your circuit into nets (groups of connected nodes).
- Attach the device nodes to X columns.
- Assign a unique Y row for each net in the circuit you want to route.
- To route a net, close the crosspoints where the X column of each node intersects with the Y row of that net.
It might take a little time to fully grasp why these steps work, but once you do, you'll have a powerful tool at your disposal.
I made some router boards to try the idea out. You can get them if you want to support my project: Protomatrix 2x30x80. More to come!
![]()
Vlad Shcherbakov

