End of the year project list for 2021

Here’s a big list of stuff I’ve done this year. It’s not everything since I do a lot of smaller projects that I start on and never finish, or end up changing what i need out of them, but these are most of my completed projects.

left image uses middle image’s style to make the third image. I used some random generative pen plotter drawings for the first set, and some watercolor paintings in a colorfield style for the second set. I realize I need to align *everything* perfectly to get good results though.

Machine Learning and AI Art – experimented with StyleGan and style transfer scripts, I wrote a script to process lots of images in batch. I threw my art into StyleGan and got interesting results – see above. Better alignment and upgrading to StyleGan2 would probably get better results, but I need to make a good camera stand to make alignment easy

newoldmusic.com & discover.newoldmusic.com – my biggest projects for the year, my music discovery tool and a music blog that goes with it. I did a write up on my scrapers & server I wrote for the discovery site in this post: https://www.jasonrparadis.xyz/playlist-maker-random-song-recommendation-site/
I’ve found a lot of music I like with it so far.

Rhyming markov chain experiments, using social media posts as data to generate random sentences, then match those with other sentences that rhyme together

Migrated VPS from Windows server 2016 to Linux/Debian – first of 3 server setups this year. I use this one for most of my projects that need internet access, the other is for home/local stuff that doesn’t need internet access. Also migrated http://music.jasonrparadis.xyz to a docker container (It running slow was my main reason for upgrading)

Pigeon rescue site – bought http://www.pdxbirds.com after seeing a social media post about people not sure what to do with a hurt pigeon they found, I figure I should probably put my knowledge of the bird to use somehow. I need to do more work on it and figure out how to show it in search results for combinations of Portland / Vancouver + Pigeon.

home server rebuilt #1, Linux/Debian on a raspberry Pi: my old server was having overheating issues so I switched to a Pi, since I was also interested in dropping electricity costs. Didn’t quite work out as I like using GUIs for little idle games and I quickly ran out of CPU/RAM

I built up my collection of electronics supplies after getting my old box of electronics components out of the shed and realizing the container had leaked and ruined everything. I’ve got pretty much everything needed for synth & audio DIY other than niche parts for specific circuits.

Bytebeat generator – found an old python script I had wrote years ago about trying to make bytebeat (generative music using bitwise operators) work with Python, I always had issues with generating the audio properly, but it was just an issue with duck typing. I got it to work, but I don’t really have a use for it at the moment, but when I buy a Eurorack synthesizer case eventually, I’d like to use it in a module.

server rebuilt #2 – my old pc, I bought new thermal paste and cooler for it since it was overheating last time I used it. Power costs aren’t that big of a deal I guess, considering my hobbies.

Belgian Popcorn – a script to slowdown music like the Belgian music genre “Popcorn”. I’ve written up a big blog post about it, I just need to post examples, but I’m kind of afraid of copyright strikes if I don’t pick the right music.

Youtube history scanner – Makes a list of most played youtube videos, used for https://www.newoldmusic.com/2021/10/28/my-most-listened-tracks-over-the-years/

Youtube playlist creator – a tool to add items to a youtube playlist, I find it useful for creating playlists. Here are a few – https://www.youtube.com/channel/UCdVylbnspmm-1z46X2FtCSw/playlists – I’m currently using it to add lots of songs but I’m rate limited at 300 a day, it’s gonna take months until I’m done.

WS2811 leds controlled by ESP32 chips. I wired up my living room with RGB LEDs and used an ESP32 chip as a web server to control them, I also 3d printed a case. I’ve since switched this to my Raspberry PI since having to disconnect everything update got annoying quick. I need to do a write up of this and post my script, it uses lots of bitwise operator math to randomize patterns


Matrix mixer
3 input mixer
Lots of 40106 based oscillators
Multiple 4051 sequencers
386 amp
PAM3804 hooked up to some cheap speakers from goodwill –

I did a write up about most of these here:

Schematic for a flashy LED circuit – also works as an audio circuit. 40106 is an inverter, it flips a high voltage to ground, and ground to high at a rate related to r1 and c1. the 4040 takes the 40106 output and divides it, each output is a different division. I like to make r1 a variable resistor and a light variable resistor so you can manually adjust the rate, and have it related to how much light is in the room.

Lots of oscillators connected to frequency dividers, used for audio generation, sequencing, and to drive LEDs – I like to put them in mason jars with light variable resistors, they are a nice little decoration and if you put a few of them near each other, they flash in sequence.

Electronics kits:
function generator (can’t find link, I think I’ve had it for years but just never built it)
resistor/capacitor/transistor tester (https://www.amazon.com/gp/product/B07WT9VVZB) – I really like this, no need to read resistors by color code

I think that’s most of everything! Maybe my goal for this year should be to document my personal projects more.

Categorized as tech

Recent synth / audio diy circuits

Here’s a few synthesizer circuits I’ve made lately. There’s a lot of simple circuits for synth design that are ripe for experimentation, usually under the name of “lunetta” synthesizers or CMOS synthesizers on google, using common digital logic chips to make audio circuits and noisemakers.

small synthesizer modules, using header pins and small screwdriver controlled variable resistors / potentiometers instead of full size pots and jacks.

The largest is a hex inverter oscillator used as a clock, into a frequency divider, then the outputs of the divider ran into a multiplexer in a way that it counts through the 8 steps controlled by the tiny screwdriver controlled potentiometers. There’s a wiring issue making pots 2 and 3 control the entire pitch of the sequence, but I kinda like it. I just wish I knew why it was doing that – I don’t see anything wired incorrectly, but I used stranded wire with point to point board and it’s possible some of it got caught in the holes and might be shorting. but glitches is part of why I like this set up, I could do all of this in software and midi a lot easier, but it’s just not the same. for this one in particular, it being broken works as an advantage – if you speed the clock up to audio rate, the sequence pretty much turns into a basic wavetable synth. a coarse and fine pot for clock speed would make this a lot more useful.

The small one with 4 knobs is 4 oscillators and 2 inverters. This is too small and needs to be rebuilt, two of the oscillators don’t work and need to be rewired, but it’s all cramped together so close that I can’t reasonably fix it. It still works good enough to test the next two circuits.

The other two, with 9 and 3 pots, are two passive mixers: an experimental matrix mixer, and a normal 3 input mixer.

These all use tiny potentiometers and little header pins instead of full size pots and jacks, because it hardly takes up any room – full sized pots + a faceplate + jacks for output take up a lot of space. I crammed most of these into too small of an area, so troubleshooting them can be tough – but most of the issues are just newbie mistakes and the downsides of using the wrong type of board to put the circuit together. the large board was point to point and a huge headache, and uses waaaaay too many wires, but I kinda like it (I was in the mood of solder work = a form of art at the time, but now it just feels wasteful when a proper board is so much less wiring (and shorting issues related to it))

I’ve got lots more parts on the way, I knew getting back into this hobby was a bad idea, heh. I think I’ve spent at least 500 bucks in the past few months replacing all of my old electronics parts that got ruined in my leaky shed.

I’d really like to buy a eurorack modular synthesizer setup, they are super expensive for what they are but adapting these circuits to that format doesn’t seem like it’d be too tough. I’d also like to build an amp for my synth stuff (I don’t wanna destroy my Roland JC-77 with bleeps and bloops, I push it enough running a bass into it), and a chorus + flanger + phaser for my short scale 6 string bass thing.

BONUS PICTURE OF A DOG. This is Sophie, I got her a few months ago from a local rescue. She’s wonderful, I wish I knew more about little dogs long ago, I figured they were all just like chihuahuas or terriers. She’s more mellow than most cats I’ve met – as long as you aren’t a poodle, anyway, hah. She does not think highly of fancy poodles and will bark at them, it’s kinda funny really. I don’t know what they did to offend her.

Python script for scanning Docker logs

This is a simple docker container log scanner written in Python, I was trying to filter out real views from bots on my music discovery tools. It uses the docker python library – pip install docker should grab it.

a quick python script for accessing + searching Docker log files

I used it to try and sort real visitors from fake ones

import docker
client = docker.from_env()
containerlist = client.containers.list()
ignorelist = []
getlist = ['bestof', 'favicon', '/database', 'GET / ', '/update' ]
#getlist = ['GET /bestof']
for containername in containerlist:
    if containername.name not in ignorelist:
        logs = containername.logs().decode().split('\n')
        for containerlogs in logs:
            if any(word in containerlogs for word in getlist):
                newstr = containerlogs.split('"')
                if len(newstr) is 9:
                    ua = newstr[5][0:200]
                    ip = newstr[7]
                    ref = newstr[3]
                    visited = newstr[1]
                    if ip == '-':
                        ip = newstr[0].split(' ')[0]
                    print(f'possible non-bot visitor: {ip} visited {visited}, related: {ref}, {ua}')

WordPress code blocks don’t work with python, but you can still copy and paste. (edit: now they do~) Here are some example results:

possible non-bot visitor: visited GET / HTTP/1.1, related: -, Mozilla/5.0 (Linux; Android 7.0;) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; PetalBot;+https://webmaster.petalsearch.com/site/petalbot)
possible non-bot visitor: visited GET / HTTP/1.1, related: http://baidu.com/, Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; EML-AL00 Build/HUAWEIEML-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 baidu.sogo.uc.UCBrowser/ UWS/ Mob
possible non-bot visitor: visited GET /favicon.ico HTTP/1.1, related: -, Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4 240.111 Safari/537.36
a few results – of course, I mostly got bots.

I had a theory that favicon might only show up to real users, people using actual browsers – I guess that was wrong (selenium does exist, and google has it’s own favicon scraper). I’ve noticed less bots hit /database and /bestof, maybe I could filter it down from there. I notice they tend not to have a referral link (I think that’s what it is? I’ve labelled it as “related”).

I feel like I could have used this in the past, but now I can’t remember why I needed it.

Categorized as tech Tagged

Music list site update & overview of my scripts used for it

I updated newmusic.jasonrparadis.xyz with more lists – It now scrapes the following:

John Peel Festive 50 1976 – 2004
NME, Select, Sounds, The Face, The Wire – End of year lists
punk-disco.com – German/Swiss/Austrian punk/new wave lists
rateyourmusic.com – some DIY/80s Cassette Culture lists, and some other users best of lists.

Scraping the last one caused some issues – any issues with the URL would get your IP instantly banned and a manual request required to get unbanned. So far I’ve been banned for 3 days with no fix just because I forgot to add a user-agent to the headers ONE TIME. Silly. It’s not even their lists, it’s their users. Luckily I have some cheap VPN so I used that to get around my ban, and kept scraping times low so it didn’t happen again. Here’s my script:

import requests
from bs4 import BeautifulSoup
import time
import random

#url pattern is easy to figure out, just set range to the number of pages from the list you choose

pages = [f'https://rateyourmusic.com/list/king0elizabeth/king0elizabeths-obscure-music-recommendations/{x}/' for x in range(1,101)]

for each in pages:
    response = requests.get(each, headers= {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0'})
    soup = BeautifulSoup(response.text, 'lxml')
    trs = soup.find_all('tr')
    for td in trs:
        if td.h3 is None or td.h2 is None:
        bandname = td.h2.text
        albumname = td.h3.text.replace('\n',' ')
        print(f'?. {bandname} - {albumname}')

This will print the list on the site to console in the form of “?. Artist – Album / Single”. Since there’s so much checking that needs to be done, it’s easier to just copy and paste from the console into the file I use to create a database – some sites like rocklist are inconsistent in the format of the lists. I created another script to convert those to the proper format:

swaps format "<rank>. <song/album> - <artist>" to "<rank>. <artist> - <song/album>" so it will import
into the database the same as the other lists

with open('converter.txt', 'r', encoding='utf-8') as f:
    imports = f.readlines()

data = []
for each in imports:
    if '~' in each:
    each = each.replace("\n","")
    ranksplit = each.split('. ')
    rank = ranksplit[0]
    namesplit = str(ranksplit[1]).split(' - ')
    title = namesplit[0]
    artist = namesplit[1]
    print(f'{rank}. {artist} - {title}')
    data.append(f'{rank}. {artist} - {title}')

and this is the script I used for punk-disco.com – luckily they don’t care about scraping, the site looks like it’s from the angelfire/geocities era lmao

import requests
from bs4 import BeautifulSoup

scrapes and prints punk-disco.com for bands and album names to console in a format that works for my import script -
there's still some minor formatting errors, like odd spaces and some characters not encoding properly,
but I think that's just because it's an old site or something to do with it being in german. fixing it in notepad++ works good enough

germanlists = ['http://www.punk-disco.com/NDW%20A-E.htm',
for each in germanlists:
    print(f'~\n{each}') #used for splitting lists in import.py
    response = requests.get(each)
    soup = BeautifulSoup(response.text, 'lxml')
    trs = soup.find_all('table')
    for row in trs:
        if '<p>' in str(row):
            if row.text.strip() is '':
            bandalbum = row.find_all('b')[0].text.encode('utf-8').decode('utf-8')
            if '(' in str(bandalbum) and ')' in str(bandalbum):
                cleantext = bandalbum.split('(')[1].split(')')[0]
                bandalbum = str(bandalbum).replace(f"({cleantext})", '')
            bandalbum = bandalbum.strip().replace('\n','').replace(':','-').title()
            if '\n' in bandalbum:
                bandalbum = bandalbum.replace('\n','') 
            print(f"?. {bandalbum}")

WordPress code blocks really messed up Python formatting. Oh well. Something else to fix in the future, I guess.

This is my import script – it turns import.txt into a database, which is what I copy the result of the scrapers above into, then run this and fix any errors it gives until there’s none.

import sqlite3

with open('import.txt', 'r', encoding='utf-8') as f:
    imports = f.read()
sql = sqlite3.connect('musiclists.db')
cur = sql.cursor()

count = 0
for alist in imports.split('~\n'):
    table = alist.split('\n')
    tablename = table[0]
    cur.execute('CREATE TABLE IF NOT EXISTS "' + tablename + '"(rank TEXT, artist TEXT, albumorsong TEXT)')
    for albumsingle in table[1:]:
            if albumsingle == '':
                ranksplit = albumsingle.split('. ')
                rank = ranksplit[0]
                namesplit = ''.join(ranksplit[1:]).split(' - ')
                artist = ''.join(namesplit[0])
                title = namesplit[1]
                cur.execute(f'INSERT INTO "{tablename}" VALUES(?,?,?)',[rank,artist,title])
                #print (f"inserted {rank}, {artist}, {title}")
        except Exception as e:
            print(f'error in {table[0]}: {albumsingle}, {e}')
            count += 1
    print (f"{tablename} finished")
if count == 0:
    print ("success, all good format")

Originally I might have had an issue with a goofy SQL query here, but after ~reading the documentation~, I think I’ve got it sorted out as best I can without redoing table names.

from flask import Flask, render_template, request
import sqlite3
import random

app = Flask(__name__)

@app.route('/database', methods=['GET', 'POST'])
def main():
    sql = sqlite3.connect('musiclists.db')
    cur = sql.cursor()
    if request.method == 'POST':
        tablefix = f"{request.form.get('tables')}"

        data = cur.execute(f"SELECT * FROM '{tablefix}'").fetchall()
    elif request.method == 'GET':
        data = []
        tablefix = ''
    alltables = cur.execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall()
    return render_template('index.html', current=tablefix,output=data,

def makeplaylist():
    sql = sqlite3.connect('musiclists.db')
    cur = sql.cursor()
    alltables = cur.execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall()
    playlist = []
    for each in range(0,15):
        tablefix = random.choice((sum(alltables,())))
        data = cur.execute(f"SELECT * FROM '{tablefix}'").fetchall()
        playlist.append(list(random.choice(data)) + [tablefix])
    return render_template('playlist.html', data=playlist)

#just for local debugging    
if __name__ == '__main__':

This is my main Flask script that runs the whole thing. I should probably try making my own lists now, I already have https://music.jasonrparadis.xyz/bestof which could be turned into a list easy enough. Adding a button for favorites to the new site & a best of page from that might be another thing to add.

I run all this in a docker image and just rebuild the image every time I do an update. It works quite well, and it again reminds me of how great docker and containers are. I do occasionally seem to be getting some lag, I’m not sure if it’s my cheap VPS (it’s only 2gb of ram) or some type of hibernation thing, since it seems like it’s only after it hasn’t been used for a while, then it works fine. It’s still better than it was running on my old Windows VPS, that’s for sure.

here’s some more music I’ve found from using this tool:

I like how half these bands you can barely find anything about them on google. ~how mysterious~
this reminds me of Liliput / Kleenex
vaguely industrial / experimental electronic? I was going to say this sounds like Pyrolator or Der Plan, turns out it was released on that label so I guess I wasn’t that far off.
this is the kind of stuff I wouldn’t have liked 10-15 years ago hahaha. same with that Tim Wright song from the other blog post
post-punk / gothy music always has some pretty awesome guitars & bass. as someone who has played a lot of bass and really into Jaco Pastorius, playing a bass with a pick was always a sin, but it’s actually got the best tone

I really like music. All of it, with amateur/”folk” (i.e. talent is mostly irrelevant if it’s catchy or interesting) music being held in high regard. The only thing I really don’t like is sappy ballads & overproduced modern music – but that might be obvious considering I’m listening to digital rips of cassettes in 2021, haha. Switching my computer to 5.1 sound seems to help with the noise on some stuff, I’m not sure why that is.

Categorized as music, tech

Playlist maker / random song recommendation site

I’ve been meaning to format my VPS and switch to Linux / Debian + Docker for a while, and finally did after I noticed my old music recommendation site (music.jasonrparadis.xyz) occasionally having issues. I tried debugging a bit, but couldn’t find anything in the script causing, and restarting the server fixed it for a bit, so I formatted and reinstalled. I turned my python/flask site into a docker image, then set up Nginx Proxy Manager and used that to secure it with Let’s Encrypt and route it to the proper ports. That completely fixed it.

I’ve been wanting to redo the site anyway, so I made a new one based around other people’s music lists: newmusic.jasonrparadis.xyz – I picked a a bunch of lists from www.rocklistmusic.co.uk that seem interesting me – experimental / underground / etc stuff like from The Wire, misc punk era stuff – John Peel, NME, Sounds – or just things that randomly interest me

So far I’ve found some music I like from it:

I’d like to find more NDW / German punk and new wave to add to it, there’s a lot of really interesting and unique stuff from that time period – Der Plan, Pyrolator, Malaria!, etc. www.punk-disco.com seems to have a load of German/Swiss/Austrian bands and songs to search for, it might be worth building a script to parse that site a bit better since it looks like a geocities/angelfire site.

Categorized as music, tech

Designing brackets for connecting painting canvas panels to IKEA furniture

My code in OpenSCAD, a programming / scripting language for CAD / Computer-Aided Design.

I’ve been trying to figure out a good way to hang up my art but my house is kinda small and has funky thicc walls – drilling is always a pain, so putting things on the wall is annoying. I’ve been doing a lot of 3d design lately with OpenSCAD and have 3d printed a number of other brackets for holding electronics to shelves, and decided to make my own for the IKEA KALLAX shelving unit that my TV is on. after a few prototypes, this is what I came up with:

Both versions of my bracket
brackets in action, holding up plotted paintings done on canvas panel

If I print anymore then I’d like to increase the width of the parallel pieces, they seem like they could break if they take too much abuse.

I should probably paint them all in the same size / color but overall I am satisfied, this a lot better than drilling holes in my wall and trying to figure out other solutions that don’t damage artwork. I think I might have to use this in my kitchen as well for some shelves, putting light sensitive stuff behind a canvas panel would work pretty well I think.

a bonus: here’s my Christmas gift for my dad, he wanted a Ford Bronco logo mashed up with a T-Rex to possibly use for his 1st gen Bronco rebuild. He doesn’t know if he’s gonna use them since the vehicle is worth more stock, but it was fun to make them. I basically mashed up two pictures in paint, imported into Inkscape to fix lines, then imported into blender and extrude, then import into the 3d printing software and into my 3d printer.

It’s a family of Broncosaurus Rexes hanging out on my desk.

About the battery age switch reset in 2010 Ford Fusion Hybrids aka cars are really just fancy computers

a 2010 Ford Fusion Hybrid. This is someone else’s picture of a perfectly reasonable driving appliance.

I’ve had a 2010 Ford Fusion for about 40k of the 150k miles on it, and I’ve been satisfied with it for what it is – a midsize sedan that gets 40ish MPG but still has power comparable to a 6 cylinder. I have not done anything to it other than normal maintenance, until now anyway – my engine would not turn off at idle or drive in purely electric mode. I only noticed because I’ve been getting low MPG for a while, I figured it was just cause I haven’t driven very much this year, but I had to wait for a grocery pickup and it took 40 minutes and I knew it should have turned off after 20 minutes or so. So I started googling and reading. There’s a service advisory for some electronic issue, but I didn’t think it was that. I noticed this thread:


It says these cars have a switch that disables some electronic functionality around the 8th or 9th year and you can fix it with an OBD-II cable & laptop running FORscan. I had one for an old Subaru laying around, so I tried that – but I couldn’t connect. I took a chance on buying the cable recommended in that thread for around 30 dollars. It took me a while to get it recognize, first driver issues (and then issues finding them since they aren’t on their site), then issues getting it to connect with MS-CAN. Finally I get connected, and it says my battery is 10 years old? I’m not sure when it kicks in but I’ve barely driven at all this year so it’s possible it happened at the beginning of the year and haven’t noticed. I set it to 1 year old, hit the buttons, heard a click in the trunk, and drove. 10 minutes later I’m at a stop light and the engine turns off and the car is in EV mode again. Back to normal.

No check engine or anything comes up on the dashboard when this happens. It’s kind of silly, but maybe it’s a liability thing? I wonder how many people have gotten rid of these cars thinking something was bad when nothing was actually wrong.

I’m kinda bored of it and want to get a 3rd generation Mazda Miata, but I’m too reasonable to go from 40mpg and a bunch of power + space to a tiny noisy roadster just for fun when I don’t even drive much anymore. Maybe at 200k or a real issue happening to this car, or if I find a really good deal.

Categorized as cars, tech

Painting with a pen plotter

I realized that painting with the axidraw API and scanning SVG files was actually pretty easy, so I’ve been trying to rewrite some of my old plotter scripts to work with painting. It works okay for pointillism and long strokes, but short strokes don’t turn out well or just get painted over by the next lines.

The pen drawings near the bottom are mostly for testing https://github.com/jrparadis/plotplot which is a web interface for the axidraw CLI I wrote because I dislike using Inkscape or CLI for basic things like disabling motors.

A lot of these are bit op patterns layered and transformed multiple times. I think I’ve got a bit more experimentation to do – the only one that’s actually new and not adapted from old pen plotting scripts is #4, which is an abstract version of Louis Wain’s Early Irish-Indian Cat xy scanned for closest colors and plotted about 10 times (it’s not suppose to be very accurate, just the basis for something abstract). The current script only seems to get results from really colorful pictures though. Guess I need to keep on trying!

Categorized as art, tech