Making Noise in Python

| Comments

I’ve been working with PyAudio lately, on a project to synchronize sound streams across multiple devices. Nothing to say on that front yet, but I do have a nice snippet for programatically generating a tone:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import math
import numpy
import pyaudio


def sine(frequency, length, rate):
    length = int(length * rate)
    factor = float(frequency) * (math.pi * 2) / rate
    return numpy.sin(numpy.arange(length) * factor)


def play_tone(stream, frequency=440, length=1, rate=44100):
    chunks = []
    chunks.append(sine(frequency, length, rate))

    chunk = numpy.concatenate(chunks) * 0.25

    stream.write(chunk.astype(numpy.float32).tostring())


if __name__ == '__main__':
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paFloat32,
                    channels=1, rate=44100, output=1)

    play_tone(stream)

    stream.close()
    p.terminate()

This simply generates a sine wave of a specified frequency and length, and writes it out to an already open PyAudio stream. A pleasant tone is produced. It’s not too fancy, but it beats loading a wave file from disk.

Simple ‘Workon’ Command for Fish Shell

| Comments

I put together a quick workon clone for the fish’s fish shell. Definitely nothing as complete or useful as virtualenvwrapper, but it fixes my need: switching simply between virtualenv’s and projects.

Installation

First, create a function file ~/.config/fish/functions/workon.fish with this defintion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function workon -d "Activate virtual environment in $WORKON_HOME"
  set tgt {$WORKON_HOME}/$argv[1]
  if [ -d $tgt ]
    cd $tgt

    # deactivate any active venv, and activate the target
    # this needs to be rewritten with the `type` fish command
    if test -n "$VIRTUAL_ENV"
      deactivate
    end

    . bin/activate.fish

    if test (count $argv) -gt 1
      if test $argv[2] = "open"
        set -gx WORKON_OPEN_SUBLIME True
      end
    else
      set -ge WORKON_OPEN_SUBLIME
    end

    # open sublime text
    if test -n "$WORKON_OPEN_SUBLIME"
      open {$WORKON_SRC_DIR}/{$argv[1]}.sublime-project
    end

    # change to working dir
    if test -n "$WORKON_SRC_DIR"
      cd {$WORKON_SRC_DIR}/{$argv[1]}
    end
  else
    echo "$tgt not found"
  end
end

complete -c workon -a "(cd $WORKON_HOME; ls -d *)"

Then, define the necessary environment variables in your ~/.config/fish/config.fish file:

1
2
3
set -gx WORKON_HOME ~/Documents/virtual_environments
set -gx WORKON_SRC_DIR ~/Documents/code
set -gx WORKON_OPEN_SUBLIME True

As you might imagine, this is set up for how I work, but it wouldn’t be difficult to customize for your needs. Since this uses the virtualenv-provided activate.fish script, the deactivate command works as expected, as well as any other usual functions.

Is This Daylight Saving Time?

| Comments

Is this Daylight Saving Time? is a single-page site to determine your DST status. You can check out the source on GitHub.

It’s an overblown build—using Django for such a small site isn’t necessary—but it was more of an exercise than anything. The implementation is my first attempt at some best practices, namely fabric for automated deployment out of git, and pipeline for css/script minification.

Other packages used include pytz for timezone calculations and boto for automated upload of static assets to S3. Zurb Foundation was used for the frontend.

Geolocation is done using the City and Country IP databases from MaxMind and uses the Django-included django.contrib.gis.geoip to read them. That resolves the lat/long, which I then send to GeoNames for to get the timezone. That result is cached in a local SQLite database to minimize lookups to GeoNames.

Overall, it was a great learning experience. Like all great learning experiences it took entirely longer than I’d originally intended; all part of the fun.

Fixing a Famicom Disk System

| Comments

Update 2013-10-08: There is now a great article available at the Famicom Disk System site, which I’d highly recommend. See my addendum for more info.

This isn’t the usual fare from this blog, but this is good information that took me quite some time to find. I’m also an avid video game collector, and i recently picked up a Sharp Twin Famicom and a few Famicom Disk System games; notably Kid Icarus and the infamous Doki Doki Panic!, which later became the USA/World Super Mario Brothers 2.

Anyhow, my Twin Famicom came with Super Mario Brothers 2 (known as the Lost Worlds outside of Japan) which works perfectly, but the game on the back (some sort of Tennis game) wouldn’t ever work. I didn’t think much of it, until both of my new games didn’t work either. I would receive an Err.21 or Err.22 message each time I attempted to load the games. The drive would attempt to read, come to a full stop (note: this is important!) and then attempt to read again, shortly before throwing the error message.

So, my Twin Famicom came with a broken belt, which is very common, and the seller shipped the system with a new belt that would have to be installed. This part went swell, but apparently there’s more to be done. There’s a lot of random forum posts out there, telling you to adjust the potentiometer on the motor to adjust the drive speed, or the read head on the disk drive. Adjusting the pot was simple, but didn’t give me any results, and the read head is factory set (and thoroughly waxed/glued in) and seemed a little too dangerous to adjust, so I didn’t want to try.

I found a lot of passing mentions to aligning the spindle, but no real good information on how to do so, until I came across this forum post by “Zach”:

The tough part (for me, at least) comes when you have to phyiscally align the drive. The first time I replaced a belt, the drive worked (without any alignment) for most of my games, but not some others.
[…]
So what you have to do is reach in from the front of the drive, loosen the SMALL black allen head set screw that holds the grey metal block to the spindle, then rotate the big gear with the belt slot around until it clicks (you’ll see the spring-loaded piece snap into place, dropping down a steep notch). At that point, you have to rotate the big gear another quarter turn. This is the position where you want the assembly to be when you have the little, black set screw pointing straight out the front of the drive, so line up the smal, grey metal disk pickup block (which should be free to spin around the spindle since the set screw is loose) , and tighten the set screw with your little allen wrench. Try it out and see if more disks are loading (or see if you’ve messed up the drive even more!)

I followed his instructions by performing the following:

  1. Remove the FDS drive from the system, and disassemble the following:
    • Front faceplate and drive door
    • Bottom Plate
  2. Look inside the drive from the front (where the drive door was), and spin the spindle (from the gear at the bottom of the drive) until the small allen screw faces you.
  3. Loosen the screw, and keep the allen key in the screw to hold the spindle still.
  4. Spin the drive pulley clockwise until you hear a small click (clockwise should be observed by looking at the bottom of the drive. The spindle (if you were looking straight down at the top, would be moving counter-clockwise).
  5. Once you hear the small click, spin one quarter turn clockwise, and tighten down the spindle (allen screw).

I half reassembled things to see if the trick worked, and I was getting a new behavior! Now, the drive would spin up, attempt to read, and go to a black screen! The drive would continue spinning (and wouldn’t come to a full stop mid read, very important!), and then eventually the Famicom BIOS screen would return, with Err.27. I was on the way!

From here, I did the following:

  1. Loosen spindle, and turn the pulley 5 degrees or so clockwise, then retighten the spindle.
  2. Try a disk again.

I repeated those steps until the drive began exhibiting somewhat similar behavior as before (coming to a full stop during the read operation). Then I did the same, only moving 5 degrees counter-clockwise instead; and you know what?

IT WORKED.

Stupid thing loaded. It turns out that the systems are aware of the spindle position, and if it isn’t correct it will cause them to read the header data incorrectly, causing the games to fail. Afterwards, I reassembled the system and all of my games have been loading flawlessly.

Someday in the future maybe I’ll turn this into a guide with pretty pictures and everything, but for now hopefully this’ll help someone get their FDS working.

For reference, here’s a list of FDS Error Codes:

ERROR 01 Disk not correctly inserted. (No Disk Card)
ERROR 02 Battery error. Check power adaptor or batteries.
ERROR 03 Broken prong on disk card.
ERROR 04 Wrong gamemaker ID.
ERROR 05 Wrong game name.
ERROR 06 Wrong version name.
ERROR 07 A, B side error (eject disk, turn and insert disk again).
ERROR 08 Disk #1 wrong.
ERROR 09 Disk #2 wrong.
ERROR 10 Disk #3 wrong.
ERROR 20 screen data differs.
ERROR 21 Disk header block(NINTENDO-HVC) part is wrong.
ERROR 22 Disk header block reecognition #$01 isn’t read and cant be ignored.
ERROR 23 File recognition block #$02 can’t read for several reasons and cant be ignored.
ERROR 24 File header block recognition #$03 can’t read and cant be ignored.
ERROR 25 File data block recognition #$04 can’t read and cant be ignored.
ERROR 26 Can’t save properly to disk card.
ERROR 27 Block end mark seen and ends prematurely.
ERROR 28 The disk unit and the same period can’t take it.
ERROR 29 The disk unit and the same period can’t take it.
ERROR 30 Disk card too full to save.
ERROR 31 Data number of a disk card doesn’t match up.

Then, a commenter named “Jon” posted the following:

Thanks for posting this! When I got a “broken” FDS recently this helped direct me towards the cure.

I did find a much more direct & accurate way to align these though. It can be done during belt replacement & should eliminate the need for fine-tuning afterward.

How? When the gear assembly retainer (triangular piece) is removed for belt replacement, simply point the rectangular notch in the large white gear to the largest notch in the metal cam below it.

Maintain those positions during reinstall & you should be good to go. No need to hunt for a hex key (1.5mm BTW) to adjust the disk catch on the spindle & all positioning remains at original factory settings.