Friday, April 06, 2007

18X: waveform to pitch mapping

I just uploaded another 18X video. 1:22 long.

"Waveform to Pitch Mapping

A fun little setup. The output from ProTools is connected to an analogue input of the Picaxe. The Picaxe simply has a little program on it that says something like "take the voltage from the analogue in pin, and use that as the pitch of a beepy note". ProTools is running a signal generator RTAS plugin."

http://www.youtube.com/watch?v=ybQ69VkRkuM

Originally, I was going to have a pot to control the tempo of the notes (and therefore waveform sampling interval). But it is far more effective and direct to have it sampling and playing at a constant, quick speed. You can still see in the code that the pot can be connected; the value of adc 0 is being read into byte 0, which ends up as the length part of the sound command. I am sure that the sampling interval would be quicker if I got rid of that now superfluous readadc command... but whether it would sound better is another story entirely...

Here is the code for it:

' ************************************************************
' * using a waveform to control pitch *
' ************************************************************

let b1 = 1 ' set length of sound / sampling interval
main:
readadc 0,b0 ' read the value of pin 0: for tempo
readadc 1,b2 ' read the value of pin 1: for pitch val
let b0 = b0 / 3 min 1 ' set b0 for an appropriate value for note length
let b1 = b0 * 3 / 2 max 255 ' another appropriate note length value
sound 7,(b2,b0) ' play a sound
goto main ' loop forever


22 comments:

Martin said...

Hi Seb. I haven't done any picaxe coding myself, although I have written some BASIC on the ol' c64. In this code example it seems as though you don't use the variable b1 after assigning it. Is this correct?

Sebastian Tomczak said...

Mr Victory,
The variable b1 is a hangover from a previous version of this code.

Originally i had planned to use a pot to controller the sampling rate (read speed of pitch change of the sound).

After plugging in the pot, I realised that it sounded best if the pot was at zero - hence no need for the pot.

PS. Go listen to tack two of damo's milkcrate, it's just great.


- Seb

Jason Paterson said...

hey Seb. I seen this and realised it sounded quite relevant to my current uni project, i was wondering if you could help me out,

I'm using picaxe (18x) and i need to get my chip to reconginse a selection of frequencies and carry out corisponding actions. my programing knowledge is rather basic so i don't know how to do it. any help would be great,
thanks

Jp

Sebastian Tomczak said...

Hi Jason,
Okay, let us start off with a few simple questions:

• Are there specific frequencies you need to to be able to "hear" and react to?

• How many different frequencies do you need to be able to hear?

• Can you give me an action that you are supposed to perform?

• Are you allowed to use any external IC's to complete your task?

Also -- you may wish to look at this post...

http://little-scale.blogspot.com/2007/04/overview-so-far.html

It does things that may be getting closer to what you want it to do.

Regards,

Sebastian Tomczak

Jason Paterson said...

thanks for getting back to me, i require the chip to recognise the following octave of notes:

E: 329.63 hz
F: 349.23 hz
F#: 369.99 hz
G: 392.0 hz
G#: 415.30 hz
A: 440.00 hz
A#: 466.16 hz
B: 493.88 hz
C: 523.25 hz
C#: 554.37 hz
D: 587.33 hz
D#: 622.25 hz

i do not require it to be as acurate as the above frequencies, jus so long as it can recognise the diference between one note and another

i simply require it to make an output pin high for each note (i realise i may need a bigger chip for this)

i have no restrictions as to what type of chip i may use, however pbasic language is what i am used to

thanks

Jp

Sebastian Tomczak said...

Jason,
The way i see it is that you have two main options.

1) Investigate the use of DTMF decoders that rely on a single resistor to control the frequency that they react to. I have seen these chips, and they are reasonable cheap. They should also work very reliably and quickly.

or

2) Investigate how well the PULSIN command in Picaxe or Arduino or anything similar can differentiate between various frequencies.

Perhaps you will need to a) scale and approximate values and then b) compare these values to a predetermined lookup table.

This is what i might look into. If you need a hand with any of this, please let me know.

Cheers!

ps. you might need to run the signal through a preamp (think something like an LM386 circuit) and then buffer it through a double inversion (think a 74HC14 or similar IC).

Steve said...

Hi Seb,

Not sure if you can help me, but I am trying to reproduce real or near real aircraft sounds, and install this in my model radio control plane for realism playing through a small amp and speaker, I have tried using a Vmusic2 MP3 player module and control this via my picaxe 18x chip, this works ok except there is a gap between playing each track, I have recorded three sounds, one of the engine at idle, second file at mid throttle and the third sound is engine at full throttle, I can control this on my radio controls receiver and detecting the throttles stick position with pulsin to the picaxe.

I was intrigued on how much sound you got from using waveform to pitch mapping, although I have no idea what or how you done this, but it sounds very impressive. Can you think of a way to play a wav sound file (aircraft engine sound) and increase the pitch to simulate increase in throttle position, or you may have experimented with this in the past,

Love your work,

Kind regards
Steve
Western Australia

Sebastian Tomczak said...

Steve (from WA!),
Thanks for your message.

Okay, so with the waveform to pitch mapping, this is taking a waveform from ProTools and then reading this waveform as an analog voltage for the Picaxe. This data was then mapped to the parameters of playing a tone.

So, the variety was achieved by changing the waveform shape, amplitude and frequency of the signal from ProTools.

But, this is annoyingly complex.

So i was thinking there are a few ways of going about finding a solution. I am just brainstorming here, so yeah.

a) perhaps use some sort of integrated noise generator IC with a controllable filter or noise shaping parameters. Control such a chip with the picaxe

b) generate some noise with the picaxe using the digital output pins and then sending this output through a four or more bit r2r adc. Then, use an SPI pot and bit bang the SPI protocol. You can then create a filter for the noise by creating an RC filter with a fixed cap and the digital pot. (i have an example on this blog somewhere of bit banging SPI protocol in order to control a digital pot...=)


Okay that's all i've got for now! But i will write more ideas if i have any!

Hope this helps in some small way or it might give you some ideas.

Steve said...

Hi Sab,

Thanks for posting back in this regard Sab (-:

First of all, I most say I have never dabbled in audio projects, but have some digital IC experience (and, nand, nor and logic IC etc), but never touched analog or audio.

I did not respond straightaway as I did not know how to, but I have googled what you suggested and think I can understand what you was advising me on. If I send say eight bits through a DAC I will get a corresponding voltage on the analog side of the chip, 0000000 = -10V or 11111111 = +10v and anything in between as an example. But I am not sure at this stage if the picaxe chip will send binary data on all 8 outputs simultaneously too the DAC. I obtained a DAC0800LCN 8 bit DAC from Dick Smiths today (only $2.50), to experiment with and get some idea how this type of device works and see if I can get this to work. Can a picaxe send 8 simultaneously bits to the DAC and how would I take the voltage wave form and get this into an audio output through a amp and speaker?

I will set up the DAC and see if it comes alive, thanks again for helping with this,

Regards
Steve

Sebastian Tomczak said...

Ahh, i didn't realise DSE had these chips in their catalogue, i will have to go and get some too! Thanks for the info.

Anyway, with the 18x and above, what you will want to look at is the "let PINS =" command. This will let you represent an 8 bit byte, for example, in parallel along the outputs.

I do not think that the Picaxe chips are fast enough to generate 8 bit audio. However, you might like to try out calculating waveforms etc. using just 4 bits to begin with. I don't know though. Maybe 8 will work.

Regards,

Sebastian Tomczka

Steve said...

Thanks for the info on "let PINS=", now I can send parallel comands.

Dick Smith part number for the DAC is Z 6834 if that helps.

Even if the picaxe can not send the data fast enough, at least I can get some experience with DAC's and wave forms. I intend to use a very small wave sound file (loop), try and find a program that will convert this file into binary form in 8 bit segments (maybe 4 bit), I will then program the picaxe to send the data back to the DAC. Only problem now is how do I play this back through a speaker?

More googling coming up I think, I will show the results if successful Sab,

Regards

Steve

Sebastian Tomczak said...

Hi Steve,
I can make up a Max/MSP patch for you if you don't find a program. Let me know.

Sebastian Tomczak said...

Hi Steve,
I made a little Max/MSP patch for you which will perform such a conversion and save the output as a text file.

Get it here:
http://little-scale.blogspot.com/2008/03/audio2bits.html

You will need the Max/MSP runtime from cycling74.com (it's free)

Steve said...

Hi Sab,

I have come across a problem, I did not see that I needed a dual power supply for the DAC (Positive and negative volts), so this has set me back. I could use a 555 timer to give me the -V, but not sure if this will be stable enough for the DAC ............... bugger.

So will need to work out the power supply before I can go any further.

Is the Max/MSP for MAC computers only? As my system would not recognise the file format,

Steve

Steve said...

oops, I should of research that better, found the windows XP version now.

WOW that's what I wanted, your patch worked a treat, read the WAV sound file and it stored this to the text file, you are a king at this stuff Sab,

Steve

Sebastian Tomczak said...

Ha. Glad it worked. It was a quick thingo i made up tonight, sorry if it is buggy! Let me know if you do run into any problems.

Also -- in regards to the digital to analog conversion process, you might be interested in using an r2r ladder... for example:
http://en.wikipedia.org/wiki/Resistor_Ladder

I just use some 1% 0.25W resistors from DSE for this sort of stuff, works a treat. I have found this successful for playing back low bit audio waveforms.

And it is really cheap and easy too!!!

Steve said...

Hi again Sab,

Built the R2R and sent some binary code through from the picaxe ok, only tested with multimeter so far, but can see that I am get voltage wings ok.

You little program works just fine, but I am struggling to find (google) a program that will convert a string of decimal numbers to binary, have you come across on in your travels?

I am about to fire up a LM358 op amp and see if I can some some out of the R2R network sending some codes through it, still have to search to see what the basic commands are for sending lots of 8 bits as fast as the picaxe can, using your suggested let PINS,

Regards
Steve

Sebastian Tomczak said...

Hi there, i can easily whip up another Max/MSP patch that will convert decimals to bins. Please be specific: what sort of input (for example, do you want to do so from a text file, or from a user input, or what?)

And why do you require such a program?

Cheers!

Steve said...

Hi Dude,

From a text file, then copy and paste this into the basic code.

I'm new to programming the picaxe and have not used basic for over 25 years, so maybe I don't understand some of the picaxe statements. What I did last night was to send 8 bits (as per example below) through an R2R resistor network:

NOTE: I cut the program down in size here, just as an example,

#picaxe 18x ; set picaxe
init:
setfreq m8 ; double speed
main:
let pins = 000001
let pins = 000010
let pins = %11000011
let pins = 000100
let pins = 000111
let pins = 001111
goto main

This produced a wave like sound (more like a buzzer sound) through a small speaker and I tried different combinations of 8 bits.

So Sab, I think I need to either look at using your program with 8 bit binary number output, and convert my small sound WAV file and then put the results in a basic statement to send to the picaxe, or try and put the 8 bit binary string into an array.

Your little program worked very well, so if it is possible to change it would be good, or can I use decimal numbers to send the 8 output pins high or low?

Have you programmed an R2R network with strings of 8 bit binary numbers using the picaxe? An example would help me understand this better is you have some.

So to summarise:
convert small WAV sound file through your little program
cut and paste the results (numbers) from the text file into basic statements
Send binary 8 bit numbers from the picaxe to the R2R network
output sound through amp and speaker

Regards
Steve

Sebastian Tomczak said...

Hi Steve,
I will of course gladly try and make such a binary conversion program for you, no problems. But before I do, I have a feeling in the back of my mind that you should be able to set pins in Picaxe using a decimal number, not a binary number
With a binary number, 255 would look like this:

let pins = %11111111
(so, all pins set to HIGH)

With a decimal number, the same outcome would look like this:
let pins = 255

So I think that in your code, when you say for example:
let pins = 000111

you are actually saying:
let pins = 111
which can be written as
let pins = %01101111

I am quite sure about this, because all that this command is doing, is taking an 8 bit byte and setting the port output register. So it doesn't matter if it is in bin or dec or whatever. Could you just try this out, maybe write a simple program such as:

main
let pins = 000011
pause 1000
let pins = 0
pause 1000
let pins = 3
pause 1000
let pins = 0
pause 1000
goto main


make sense? and just connect LEDs to the appropriate pins to test, or whatever.

I don't have my picaxe stuff setup up at the moment, thats why i can't test it on a real world circuit right now :-(

Steve said...

Hi Sab,

Yep it did worked, I blew the dust off of my old logic probe and using the following:

Main:

let pins = 0

goto main

I then tested to make sure all pins were low, then went through the 8 bits, changing "let pins = 0" to 1, 2, 4,8 up to 255, it worked a treat. picaxe must see the statement %10010001 with the % sign in front and uses the binary system, but no "%" and it knows it is decimal numbers, very clever picaxe.

Now as you wonderful little program works ok, I now have to see if I can get all the numbers into an array of some kind, so I can loop the numbers (lots of numbers),

I will keep you posted Sab, thanks again dude,

Regards

Steve

Sebastian Tomczak said...

Hi Steve,
Yeah, the percent sign denotes the binary. Handy little symbol ;-)

I was thinking, maybe you don't need to store it in an array, maybe just have the bytes as a straight out block of code, you know?

like this:

sound1
let pins = sample_1_byte
let pins = sample_2_byte
...
let pins = sample_n_byte

(test for some condition to exit loop)
goto sound1

Know what i mean? Anyway, good luck man!