Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Floppy Drive Music

Wed Feb 19, 2014 2:03 pm

I watched some YouTube videos of people making music with old floppy drives and decided to try this myself. I wanted to do it from first principles without using anything that others have produced and wanted it to be as simple as possible. This is what I came up with in only 12 hours using nothing other than Gordon's excellent wiringPi library and some reasonably compact C code:

https://plus.google.com/110265018208679 ... jh5SC8Dh9D

Note: It looks like the head isn't moving in the video but I discovered the notes were louder if I just vibrated the head back and forth rather than moved it in the same direction. This also simplifies the code because you don't need to worry about the head hitting one end.

All I used was my Raspberry Pi, a single floppy drive, a 5v 2a supply to power both the Pi and the floppy drive and a couple of transistors to convert the Pi's 3.3v outputs into 5v outputs to drive the stepper motor and change its direction.

I was very pleased with the result and surprised I could get such a large range of notes out of a single drive (almost 4 octaves).

If anybody wants more details I will be happy to provide them.

This is my C source code:

Code: Select all

/* --------------------------------------
 * Written by Scott Vincent
 * 16 Feb 2014
 * --------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>

// pin 11 = wiringPi Pin 0. Use this for motor direction.
const int dirPin = 0;

// pin 12 supports pwm mode but it turns out I didn't need pwm mode in the end!
// pin 12 = wiringPi Pin 1. Use this for stepper motor.
const int stepPin = 1;

// Define an octave with naturals and sharps (Zz = rest)
enum { Cn, Cs, Dn, Ds, En, Fn, Fs, Gn, Gs, An, As, Bn, Zz };

// Define another one with flats and remaining sharps
enum { Bs, Df, Dn2, Ef, En2, Es, Gf, Gn2, Af, An2, Bf, Bn2, Zz2 };

/**
 * Frequencies in hundredths of Hz, e.g. middle A = 44000
 * 4 Octaves with 12 notes per octave, i.e. C to B
 */
const int freq[4][12] = {
	{ 13081,13859,14683,15556,16481,17461,18500,19600,20765,22000,23308,24694 },
	{ 26163,27718,29366,31113,32963,34923,36999,39200,41530,44000,46616,49388 },
	{ 52325,55437,58733,62225,65925,69846,73999,78399,83061,88000,93233,98777 },
	{ 104650,110873,117466,124451,131851,139691,147998,156798,166122,176000,186466,197553 }
};

/**
 * Frequency (in Hz) is converted to Floppy Delay using the formula:
 *   314000 / frequency = floppy delay
 * so middle A = 314000 / 440 = 714
 *
 * Lowest realistic note is delay = 1550
 * Highest realistic note is delay = 210
 */
const int floppyConv = 31400000;

// Calculate all our floppy delays at the start
int floppyDelay[4][12];

// Song1 is the C major scale (note, octave, length)
const int song1_tempo = 120;
const int song1[][3] = {
	{ Cn, 1, 1 },
	{ Dn, 1, 1 },
	{ En, 1, 1 },
	{ Fn, 1, 1 },
	{ Gn, 1, 1 },
	{ An, 1, 1 },
	{ Bn, 1, 1 },
	{ Cn, 2, 1 },
	{ -1, -1, -1 }
};


// Song2 is The Imperial March from Star Wars (note, octave, length)
const int song2_tempo = 104 * 8;
const int song2[][3] = {
	{ Gn, 1, 8 },		// Bar 1
	{ Gn, 1, 8 },
	{ Gn, 1, 8 },
	{ Ef, 1, 6 },
	{ Bf, 1, 2 },

	{ Gn, 1, 8 },
	{ Ef, 1, 6 },
	{ Bf, 1, 2 },
	{ Gn, 1, 16 },

	{ Dn, 2, 8 },
	{ Dn, 2, 8 },
	{ Dn, 2, 8 },
	{ Ef, 2, 6 },
	{ Bf, 1, 2 },

	{ Gf, 1, 8 },		// Bar 4
	{ Ef, 1, 6 },
	{ Bf, 1, 2 },
	{ Gn, 1, 16 },

	{ Gn, 2, 8 },
	{ Gn, 1, 6 },
	{ Gn, 1, 2 },
	{ Gn, 2, 8 },
	{ Gf, 2, 6 },
	{ Fn, 2, 2 },

	{ En, 2, 2 },
	{ Ds, 2, 2 },
	{ En, 2, 4 },
	{ Zz, 0, 4 },
	{ Gs, 1, 4 },
	{ Cs, 2, 8 },
	{ Bs, 2, 6 },
	{ Bn, 1, 2 },

	{ Bf, 1, 2 },		// Bar 7
	{ An, 1, 2 },
	{ Bf, 1, 4 },
	{ Zz, 0, 4 },
	{ Ef, 1, 4 },
	{ Gf, 1, 8 },
	{ Ef, 1, 6 },
	{ Gf, 1, 2 },

	{ Bf, 1, 8 },
	{ Gn, 1, 6 },
	{ Bf, 1, 2 },
	{ Dn, 2, 16 },

	{ Gn, 2, 8 },
	{ Gn, 1, 6 },
	{ Gn, 1, 2 },
	{ Gn, 2, 8 },
	{ Gf, 2, 6 },
	{ Fn, 2, 2 },

	{ En, 2, 2 },		// Bar 10
	{ Ds, 2, 2 },
	{ En, 2, 4 },
	{ Zz, 0, 4 },
	{ Gs, 1, 4 },
	{ Cs, 2, 8 },
	{ Bs, 2, 6 },
	{ Bn, 1, 2 },

	{ Bf, 1, 2 },
	{ An, 1, 2 },
	{ Bf, 1, 4 },
	{ Zz, 0, 4 },
	{ Ef, 1, 4 },
	{ Gf, 1, 8 },
	{ Ef, 1, 6 },
	{ Bf, 1, 2 },

	{ Gn, 1, 8 },
	{ Ef, 1, 6 },
	{ Bf, 1, 2 },
	{ Gn, 1, 16 },

	{ -1, -1, -1 }
};


/**
 *
 */
static void resetMotor()
{
	// To reset head position move back 10 then forward 5
	digitalWrite(dirPin, LOW);
	for (int i=0; i < 10; i++){
		digitalWrite(stepPin, HIGH);
		digitalWrite(stepPin, LOW);
		delay(1);
	}

	digitalWrite(dirPin, HIGH);
	for (int i=0; i < 5; i++){
		digitalWrite(stepPin, HIGH);
		digitalWrite(stepPin, LOW);
		delay(1);
	}

	delay(400);
}


/**
 *
 */
static int init()
{
	if (wiringPiSetup() == -1){
		printf("Failed to initialize wiringPi\n");
		return 1;
	}

	pinMode(stepPin, OUTPUT);
	pinMode(dirPin, OUTPUT);

	resetMotor();

	for (int octave = 0; octave < 4; octave++){
		for (int note = 0; note < 12; note++){
			floppyDelay[octave][note] = floppyConv / freq[octave][note];
		}
	}

	return 0;
}


/**
 *
 */
static void playNote(int note, int octave, int length)
{
	static int dir = 1;
	int pause = floppyDelay[octave][note] * 10;

	int endTime = millis() + length;
	while (millis() < endTime){
		digitalWrite(dirPin, dir);
		if (dir == 0)
			dir = 1;
		else
			dir = 0;

		digitalWrite(stepPin, HIGH);
		digitalWrite(stepPin, LOW);
		delayMicroseconds(pause);
	}
}


/**
 *
 */
static void rest(int length)
{
	int endTime = millis() + length;
	while (millis() < endTime){
		delay(5);
	}
}


/**
 * song[note_num][note, octave, length]
 */
static void playSong(const int song[][3], const int tempo)
{
	// Convert tempo in BPM to millisecs
	int noteLen = 60000 / tempo;

	for (int i = 0; song[i][0] != -1; i++){
		int length = song[i][2] * noteLen;
		if (song[i][0] == Zz){
			rest(length);
		}
		else {
			playNote(song[i][0], song[i][1], (7 * length) / 8);
			rest(length / 8);
		}
	}
}


/**
 *
 */
int main()
{
	if (init() != 0){
		printf("init failed - Exiting\n");
		return 1;
	}

	playSong(song2, song2_tempo);

	return 0;
}
Last edited by Orange on Mon Jan 05, 2015 11:41 am, edited 1 time in total.

crobs808
Posts: 3
Joined: Thu Apr 10, 2014 7:46 pm

Re: Floppy Drive Music

Thu Apr 10, 2014 7:48 pm

Yes, I am VERY interested in doing this from the ground up. Do you have a full How-To guide? I know I simply do not compile this and run it on the Raspberry Pi. What else do I need to do? Needing some help with the end-to-end logistics here.

Thank you!

crobs808
Posts: 3
Joined: Thu Apr 10, 2014 7:46 pm

Re: Floppy Drive Music

Thu Apr 10, 2014 8:02 pm

What IDE did you use? I am getting a lot of compilation errors using CodeBlocks, and I have already specified the necessary dependencies for WiringPi libraries. The compilation errors I am getting are basic code logic/structure problems (infinite for loops, redefining variables, etc.)

Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Re: Floppy Drive Music

Thu Apr 10, 2014 9:43 pm

crobs808 wrote:What IDE did you use? I am getting a lot of compilation errors using CodeBlocks, and I have already specified the necessary dependencies for WiringPi libraries. The compilation errors I am getting are basic code logic/structure problems (infinite for loops, redefining variables, etc.)
I didn't use an IDE. I just wrote it in on the pi using vi and compiled it with GCC.

All you need to do is go to Gordon's wiringPi website and follow his install instructions. Then type: gcc -o floppy_music floppy_music.c to build my program. Then type: ./floppy_music to run it.

crobs808
Posts: 3
Joined: Thu Apr 10, 2014 7:46 pm

Re: Floppy Drive Music

Mon Apr 14, 2014 4:56 am

Bummer, I was hoping to not have to code/compile this on the Pi itself. My ultimate goal was to have a windows binary I could run, so that I could make this work on a standard windows machine. My ultimate goal is a re-distributable that will work for anyone, as long as they have the floppy hardware wired up. Trying to make this turn-key.

Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Re: Floppy Drive Music

Mon Apr 14, 2014 5:04 am

I'm not sure I understand what you're trying to do. The whole point of this project is that it uses the GPIO pins on the Pi. If you build and run the binary on a Windows machine how is it supposed to control the GPIO pins on the Pi?

XPerianer
Posts: 1
Joined: Mon Aug 11, 2014 1:05 pm
Contact: Website

Re: Floppy Drive Music

Mon Aug 11, 2014 2:12 pm

For all who are interested:

I made a tutorial on how to make music with the Raspberry,
using the code posted above, because it's so easy to use and also to understand.
Theres a text version on my Blog, http://domj.happyforever.com/?p=99
but theres also a video version which maybe gives you more clues on how to do it.
Link to youtube: https://www.youtube.com/watch?v=yvM-eNblI84

I hope i can help some people struggling to connect everything like i did first.

Sincerly,
XPerianer

Blog: http://domj.happyforever.com
Youtube: https://www.youtube.com/user/XtraPerianer/videos

dpeach
Posts: 7
Joined: Sun Jan 04, 2015 8:55 pm

Re: Floppy Drive Music

Sun Jan 04, 2015 9:02 pm

Not knowing C++ I had a little trouble compiling the code as it is written.

The first 4 lines that are intended to be a comment are actually not properly formed. I got this error when trying to compile:

Code: Select all

main.cpp:1:3: error: invalid preprocessing directive #--
main.cpp:2:3: error: invalid preprocessing directive #Written
main.cpp:3:6: error: "Feb" is not a valid filename
main.cpp:4:3: error: invalid preprocessing directive #--
I didn't know what any of it meant, but searching the file with VIM from the command line I searched for 'Feb' and saw the only instance was in those first commented lines. I just deleted the first lines and everything compiled fine.

I then showed the project to some of my programmer friends and they noticed that the # used as comment indicators in those lines are not correct for C++. You can either delete them like I did, or comment those lines out with

Code: Select all

/* comment */
or

Code: Select all

//
at the beginning.

Hope that helps someone else.

Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Re: Floppy Drive Music

Mon Jan 05, 2015 11:43 am

Sorry about that, not sure how it happened. I've fixed the original code now so comments are correctly marked with /* ... */

kernelrain
Posts: 1
Joined: Mon Aug 10, 2015 11:21 am

Re: Floppy Drive Music

Mon Aug 10, 2015 11:26 am

Sorry for reviving this old thread, but while studying your source code, I noticed that you use the following formula to determine the delay between to motor pulses:

Code: Select all

/**
 * Frequency (in Hz) is converted to Floppy Delay using the formula:
 *   314000 / frequency = floppy delay
 * so middle A = 314000 / 440 = 714
 *
 * Lowest realistic note is delay = 1550
 * Highest realistic note is delay = 210
 */
const int floppyConv = 31400000;
Are the 314000 some magical value? Or did you determine that value experimentally?
Thank you for your reply in advance

User avatar
experix
Posts: 204
Joined: Mon Nov 10, 2014 7:39 pm
Location: Coquille OR
Contact: Website

Re: Floppy Drive Music

Mon Aug 10, 2015 2:40 pm

Can you make music with a 500 MB hard disk drive from a VAX system? It has a **heavy** aluminum case measuring about 40 x 30 x 20 cm and inside there are very strong magnets, big platters and so on. Every detail seems to have been made in the most expensive way possible.

Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Re: Floppy Drive Music

Tue Aug 11, 2015 10:31 am

kernelrain wrote:Sorry for reviving this old thread, but while studying your source code, I noticed that you use the following formula to determine the delay between to motor pulses:

Code: Select all

/**
 * Frequency (in Hz) is converted to Floppy Delay using the formula:
 *   314000 / frequency = floppy delay
 * so middle A = 314000 / 440 = 714
 *
 * Lowest realistic note is delay = 1550
 * Highest realistic note is delay = 210
 */
const int floppyConv = 31400000;
Are the 314000 some magical value? Or did you determine that value experimentally?
Thank you for your reply in advance
I believe I came up with that number by trial and error. It was the best value for the drive I was using where the lowest and highest note sounded ok.

x2110311x
Posts: 1
Joined: Wed Jun 15, 2016 2:32 am

Re: Floppy Drive Music

Wed Jun 15, 2016 3:02 pm

Sorry to revive this old thread, but I need some advice with this.
So your code works great for me, but I want to be able to use multiple floppy drives, but I'm not familiar with C.
I tried writing my own code in Python, even using WiringPi, but for some reason it's extremely quiet.
Also, I'm still working on length of notes

Code: Select all

import wiringpi 
import time

wiringpi.wiringPiSetupGpio() # For GPIO pin numbering

wiringpi.pinMode(17,1)
wiringpi.pinMode(18,1)
wiringpi.pinMode(27,1)
wiringpi.pinMode(22,1)
def playnote (step, dir, note, length):   #Play note (step pin, direction pin, note, length)
        wiringpi.digitalWrite(dir ,1)
	for num in range(1, length*10):
                wiringpi.digitalWrite(step,1)
                time.sleep(note)
                wiringpi.digitalWrite(step,0)
                time.sleep(note)
        wiringpi.digitalWrite(dir, 0)
        for num in range(1, length*10):
                wiringpi.digitalWrite(step,1)
                time.sleep(note)
                wiringpi.digitalWrite(step,0)
                time.sleep(note)
        return


#Notes
C2 = 1 / 65.41
Db2 = 1 / 69.30
D2 = 1 / 73.42
Eb2 = 1 / 77.78
E2 = 1 / 82.41
F2 = 1 / 87.31
Gb2 = 1 / 92.50
G2 = 1 / 98.00
Ab2 = 1 / 103.83
A2 = 1 / 110.00
Bb2= 1 / 116.54
B2 = 1 / 123.47
C3 = 1 / 130.81
Db3 = 1 / 138.59
D3 = 1 / 146.83
Eb3 = 1 / 155.56
E3 = 1 / 164.81
F3 = 1 / 174.61
Gb3 = 1 / 185.00
G3 = 1 / 196.00
Ab3 = 1 / 207.65
A3 = 1 / 220.00
Bb3 = 1 / 233.08
B3 = 1 / 246.94
C4 = 1 / 261.63
Db4 = 1 / 277.18
D4 = 1 / 293.66
Eb4 = 1 / 311.13
E4 = 1 / 329.63
F4 = 1 / 349.23
Gb4 = 1 / 369.99
G4 = 1 / 392.00
Ab4 = 1 / 415.30
A4 = 1 / 440.00
Bb4 = 1 / 466.16
B4 = 1 /  493.88
C5 = 1 / 523.25

def scale(step, dir):
        playnote(step, dir, C4, 10)
        playnote(step, dir, D4, 10)
        playnote(step, dir, E4, 10)
        playnote(step, dir, F4, 10)
        playnote(step, dir, G4, 10)
        playnote(step, dir, A4, 10)
        playnote(step, dir, B4, 10)
        playnote(step, dir, C5, 10)
        return

scale(22,27)

thataintworking
Posts: 2
Joined: Tue Nov 18, 2014 4:12 am

Re: Floppy Drive Music

Thu Sep 29, 2016 5:31 am

One thing I noticed is that your code moves the head forward but never moves it back. This affects the sound quality/volume.

Orange
Posts: 36
Joined: Tue Jan 24, 2012 6:41 am

Re: Floppy Drive Music

Fri Oct 07, 2016 7:20 am

Sorry, I should have given instructions on how to compile the above code.
Paste the source code into a file called floppymusic.c using nano, then compile it using this command:

gcc -o floppymusic -std=c99 -lwiringPi floppymusic.c

This creates an executable file called floppymusic. To run it just type:

./floppymusic

Return to “Other projects”

Who is online

Users browsing this forum: Martin Frezman and 13 guests